使用Java API更新Crystal Reports

2020-09-10 09:56发布

点击此处---> 群内免费提供SAP练习系统(在群公告中)加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)我一直在努力找出与各种Cryst...

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


我一直在努力找出与各种Crystal Reports Java API所出现的不一致之处,并且在线帮助在寻找明确的解决方案方面相当模糊或不确定。 所以我想在这里问

请原谅,但要有一些背景知识……

我们的BOE 4.1 FP11服务器管理着约1500个左右的Crystal Reports,这些服务器针对我们的数据仓库。 由于正在进行仓库迁移到另一个供应商的平台,我们需要使用新的DSN更新这些报告,并且一部分报告将需要对其CommandTable对象进行一些SQL调整。 我正在尝试使用您的Java SDK之一来自动执行此过程。 请记住,无论如何我都不是BOE或Crystal用户或专家,我只是一个在使用SDK和API进行集成/自动化方面具有丰富经验的编码人员。

仓库供应商正在协助我们进行此迁移,他们要求从受影响的报告中转储所有自定义SQL(CommandTable.CommandText),以便他们可以对其进行检查并进行任何必需的更改。 我能够使用Crystal Reports for Eclipse(CR4E)API并直接在BOE文件系统上的.RPT文件之后轻松提供此功能。 即使这些是托管报告,也可以直接查询RPT文件。 我能够遍历文件系统以收集所有RPT文件,识别受影响的文件,并将包括CommandTable自定义SQL在内的报告元数据转储到提供给供应商的文本文件中。 到目前为止很好...

然后,供应商获取了此文本转储,并对其运行了工具以验证SQL并进行任何必需的更新。 他们向我们返回了更新的文件,现在我应该阅读这些文件,然后为这些报告更新DSN和修改后的SQL(CommantTable.CommandText)。

所以现在我们可以解决当前的困境:

我意识到CR4E SDK不适用于托管报告,但是我认为我已经抓取了其中一些托管RPT并将其作为本地副本删除,只是为了尝试使用更新代码,然后再尝试远程访问它们 通过托管的API。 我编写了一些非常简单的代码来计算更新动态,并且代码运行无误。 但是,当我调用ReportClientDocument.save()和.close()时,实际上没有任何更改被写回到文件中。 文件时间戳确实发生更改,表明文件已更新,但是文件大小相同,表明内容未更改。 我还尝试了使用不同文件名的ReportClientDocument.saveAs()-也写入了新文件,但再次与原始文件相同。

在逐步调试时,我可以在内存的CommandTable.CommandText字段中看到SQL更改,因此我知道CommandTable.setCommandText()调用正在工作。 但是为什么它从不进入目标文件?该文件不是只读的,因为我检查ReportClientDocument.isReadOnly()会返回false。 再一次,saveAs()写入一个文件,但包含原始内容。

是因为CR4E SDK知道这实际上是一个托管报告并且拒绝更改它吗? 如果是这样,为什么不抛出异常而不是默默地失败并暗示成功?我希望保持这种过程既快速,简单又可行,因此首先尝试使用与我相同的CR4E API。 我还提供了RAS SDK和BIP41 SDK,可以尝试通过托管API,大约一半的人希望我必须这样做以确保正确更新元数据数据库。 但是在我再次追尾之前,我有什么想念的地方吗?

下面的代码片段显示了一个非常快速且肮脏的示例,该示例使用具有3个CommandTable对象的本地硬编码报告文件,并且我尝试将第一个CommandTable.CommandText更改为虚拟SQL字符串。

 File rptFile = new File(" test/update_test1.rpt");
 ReportClientDocument clientDoc = ReportClientDocument.openReport(rptFile);
 如果(clientDoc.isReadOnly())
   抛出新的异常("报告是只读的!");
 IDatabase数据库= clientDoc.getDatabaseController()。getDatabase();
 字符串cmdName = null;
 CommandTable cmdTable = null;
 对于(ITable t:database.getTables())
 {
   if(t instanceof CommandTable)
   {
     cmdTable =(CommandTable)t;
     cmdName = cmdTable.getAlias();
     cmdTable.setCommandText(" SELECT * FROM TEST_CRYSTAL_UPDATE;");
     打破;
   }
 }
 clientDoc.save();
 System.out.println("更改了命令'"的SQL'+报告中的cmdName +"'+ clientDoc.displayName()+"'));
 clientDoc.close();
 

上面的代码中没有显示它,但是周围有一个try/catch块可以捕获所有异常。 不会抛出任何异常,并且文件时间戳会再次更新,就像写了 something 。 这是调试器的前后截图,显示.setCommandText()调用实际上更改了CommandTable对象中的SQL。

之前:

之后:

感谢您提供的任何帮助。 我想接下来我将开始深入研究RAS API ...

(10.0 kB)
8条回答
一只江湖小虾
2020-09-10 10:31

我尝试将现有的SQL重新格式化为 更新测试。 这样,我不会更改功能性SQL,只需更改其周围的空格即可。 除非CR足够聪明地认识到除了空格以外没有实质性变化并且忽略了它,否则它仍然无法正常工作。

此外,verify()也不是Database对象上的方法。 父DatabaseController对象上有一个verifyTableConnectivity()方法,该方法将ITable作为其参数。 不知道它是否可以与CommandTable一起使用,但是它的读取方式听起来好像可以验证与数据库的连接。 我宁愿避免这种情况,因为我不打算实时连接每个报告以更新它们。 这实际上是否只是更新报告文件的要求,还是我正确阅读了此文件?

一周热门 更多>