【发布时间】:2010-04-12 19:08:11
【问题描述】:
我有一个 RDL 报告文件,我想以某种方式“运行”报告并获取将用于填充报告的数据集。我想要做的是从用于填充报告的数据中提取原始数据,而不是实际向用户显示报告。这可能吗?
【问题讨论】:
-
这是 Report Builder 2.0 还是 3.0 RDL 文件?
标签: c# .net reporting business-intelligence rdl
我有一个 RDL 报告文件,我想以某种方式“运行”报告并获取将用于填充报告的数据集。我想要做的是从用于填充报告的数据中提取原始数据,而不是实际向用户显示报告。这可能吗?
【问题讨论】:
标签: c# .net reporting business-intelligence rdl
如果我了解您想要做什么,那么是的,这是可能的,但这有点痛苦。我为 Report Builder 2.0 报表的各种快照(在报表管理器中拍摄)执行此操作。
如果您使用报表服务器的内置 Web 服务,则可以以编程方式生成报表。有关一些示例代码,请参阅ReportExecutionService.Render Method(请注意,即使使用 SQL Server 2008,我也使用 ReportExecution2005 Web 服务)。您可以将报表呈现为各种格式,例如 XML、MHTML 或 PDF,然后尝试从中提取数据。您应该将您关心的数据表添加到报表中,通过将其 Visibility 更改为 Hide 来隐藏该表,但将其 DataElementOutput 属性设置为 Output,以便在呈现报表时,该表将被包含在内。为表格起一个独特的名称(例如,将“Tablix1”替换为“FlatData”)。然后,您可以将报告呈现为 XML 格式并使用 XSLT 仅提取该表中的行。以下是我之前用来从呈现的 Report Builder 2.0 报告中提取数据的一些 XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:variable name="reportID" select="*[local-name()='Report']/@Name"/>
<!-- Uppercase and lowercase alphabets for case-insensitive string comparisons -->
<xsl:variable name="up" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="lo" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:template match="/">
<xsl:element name="ContainerElementOfMyData">
<xsl:attribute name="ReportID">
<xsl:value-of select="$reportID"/>
</xsl:attribute>
<xsl:for-each select="*[local-name()='Report']/*[local-name()='FlatData']">
<!-- If the FlatData node has attributes on its tag, insert all of those
attributes in a single node -->
<xsl:if test="count(@*) > 0">
<MyNode>
<xsl:for-each select="@*">
<xsl:variable name="parentAttrName" select="name(.)"/>
<xsl:element name="{$parentAttrName}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</MyNode>
</xsl:if>
<!-- Go through each tag in FlatData that starts with 'Details' -->
<xsl:for-each select="//*[substring(local-name(), 1, 7)='Details']">
<xsl:if test="count(@*) > 0">
<MyNode>
<!-- For each attribute of the Details tag: -->
<xsl:for-each select="@*">
<xsl:variable name="attrName" select="name(.)"/>
<xsl:variable name="lowerAttrName" select="translate($attrName,$up,$lo)"/>
<xsl:variable name="attrValue" select="."/>
<!-- Write the attribute name as its own tag -->
<xsl:element name="{$attrName}">
<xsl:choose>
<xsl:when test="$attrValue = ''">
<!-- Do nothing because no value to output and we don't want empty CDATA tags -->
</xsl:when>
<!-- When field might have HTML tags, we want to wrap it in CDATA tags: -->
<xsl:when test="$lowerAttrName = 'my_first_text_field' or $lowerAttrName = 'my_other_text_field'">
<xsl:text disable-output-escaping="yes"><![CDATA[<![CDATA[]]></xsl:text>
<xsl:value-of select="$attrValue"/>
<xsl:text disable-output-escaping="yes">]]</xsl:text>
<xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:when>
<!-- When field will not have HTML tags, just output its value as normal -->
<xsl:otherwise>
<xsl:value-of select="$attrValue"/>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:for-each>
</MyNode>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:element><!--End of ContainerElementOfMyData-->
</xsl:template>
</xsl:stylesheet>
请注意,此 XSLT 取决于您将报表中隐藏的数据表命名为“FlatData”。如果您知道报告中的某些数据将包含 HTML 标记或其他如果放置在两个 XML 标记之间将不是有效 XML 的内容,请更改上面的 XSLT 以将该数据包装在 CDATA 标记中(例如,将 my_first_text_field 替换为其值需要 CDATA 标记的字段名称)。
将此 XSLT 应用于报表的呈现 XML 版本将生成更多 XML,这一次只包含您关心的报表中的数据。仅使用呈现的 XML 版本的报告的问题在于它包含所有图表、外观信息等,而不仅仅是您的数据。尝试以 XML 格式呈现您的一份报告并查看源代码;它有各种你可能不想要的疯狂。
对于将 XSLT 转换应用于 XML 的命令行工具,我推荐xalan。这是一个示例用法:
PS C:\Program Files\xalan-j_2_7_0> java org.apache.xalan.xslt.Process -IN rdl_rendered_to_xml.xml -XSL xsl_shown_above.xsl -OUT transformed.xml
生成的transformed.xml 将具有如下格式:
<?xml version="1.0" encoding="utf-8"?>
<ContainerElementOfMyData ReportID="MyReportName">
<MyNode>
<Key1>Value 1</Key1>
<Key2>Second value of your data</Key2>
</MyNode>
</ContainerElementOfMyData>
【讨论】:
正如 Sarah Vessels 在她的回答中已经提到的那样,您可以推送报表服务器来呈现数据, 在许多格式中,也许 EXCEL 是不错的选择,这取决于您的报表设计的复杂性。 I asked similar qestion 并且经过许多托盘后,我最终在 Mssql 中使用了 #TempTaples,它在报告被撕裂之前被添加,在我看来,报告服务器是作业处理的最后一个实例,所有数据和存储都应该在渲染的后端完成报告
【讨论】:
这是一个有趣的问题。当我不得不解决它时(用于 rdl 文件的单元测试),我编写了一个简单的 xml 解析器,它将从 rdl 文件中提取 sql 语句并执行它。这很简单,但如果你的语句有很多参数,当然会变得更复杂。但是,文件中也提供了参数信息,因此您应该能够编写通用解决方案(但您当然需要为参数提供值)。
【讨论】: