我目前正在开发一个C#程序,允许我们的用户运行,查看和导出一批Crystal Reports。报告是使用Crystal Reports 2008 GUI完成的。这样做的主要原因之一是允许我们在Crystal Report导出为PDF时保留超链接。我的程序通过导出到rtf,然后将rtf转换为pdf来完成此操作。如果有人知道在转换为PDf时保留超链接的方法不那么复杂,我很乐意听到它,但这不是我当前的问题。
我已经做了很多关于如何优化程序的测试,以便尽可能少地导出导出。从我所看到的,对数据进行应用程序查询,然后将结果集绑定到Crystal Report是迄今为止最快的方法。我的问题是我无法将查询硬编码到程序中,需要从Crystal Report本身中进行检索。
在Crystal Reports 2008中,“数据库”菜单下有一个名为“显示SQL查询”的选项。这将打开一个窗口,其中包含用于给定报告的SQL查询。这正是我需要从我的应用程序中获取的东西。我已经加载了一个水晶报告,并在调试时遍历了ReportDocument对象,试图查找查询,但没有运气。
所以,我的问题是;是否有任何方法可以让我提取给定Crystal报表使用的查询?
答案 0 :(得分:3)
我意识到这是一个非常古老的问题,但我认为我会为那些偶然发现但需要3.5的框架目标的人提供替代方案(动态在3.5中不可用)。
您需要以下参考资料才能使用此解决方案。
using CrystalDecisions.ReportAppServer.DataDefModel;
using CrystalDecisions.CrystalReports.Engine;
然后只需使用以下内容访问ClientDoc
接口,并返回一个Command Text字符串列表。
private static List<string> GetCommandText(CrystalDecisions.CrystalReports.Engine.ReportDocument report)
{
var rptClientDoc = report.ReportClientDocument;
return rptClientDoc.DatabaseController.Database.Tables.OfType<CommandTable>()
.Select(cmdTbl => cmdTbl.CommandText).ToList();
}
答案 1 :(得分:2)
好吧,所以dotjoe给了我解决这个问题所需的所有提示。以下代码可用于从水晶报表中提取命令文本。
public string getCommandText(ReportDocument rd)
{
if (!rd.IsLoaded)
throw new ArgumentException("Please ensure that the reportDocument has been loaded before being passed to getCommandText");
PropertyInfo pi = rd.Database.Tables.GetType().GetProperty("RasTables", BindingFlags.NonPublic | BindingFlags.Instance);
return ((dynamic)pi.GetValue(rd.Database.Tables, pi.GetIndexParameters()))[0].CommandText;
}
它看起来有点乱,但是当你开始涉水时,它会有些道理。基本上,它使用反射来获取CommandText属性的值,并引入一点动态以通过ReportDocument中的动态属性。
这是我的命令文本,但我没有时间对代码进行任何测试。一旦我有时间处理这个问题,我相信我会做一些调整。我不知道不使用“SQL命令”的报告会发生什么。一旦我进一步测试,我会发表评论。
P.S。这要求您引用标准的反射/动态库以及以下Crystal Report库:
crystaldecisions.reportappserver.datadefmodel
crystaldecisions.crystalreports.engine
crystaldecisions.shared