代码之家  ›  专栏  ›  技术社区  ›  NotDan

如何从RDL文件中获取要填充的数据集?

  •  4
  • NotDan  · 技术社区  · 14 年前

    我有一个RDL报告文件,我想以某种方式“运行”该报告,并获取用于填充该报告的数据集。我要做的是从数据中提取一个原始数据,用于填充报表,而不实际向用户显示报表。这可能吗?

    3 回复  |  直到 14 年前
        1
  •  3
  •   Sarah Vessels    13 年前

    如果我明白你想做什么,那么是的,这是可能的,但这是一种痛苦。我对报表生成器2.0报表的各种快照(如在报表管理器中拍摄的)执行了此操作。

    如果使用报表服务器的内置web服务,则可以通过编程方式生成报表。见 ReportExecutionService.Render Method 对于一些示例代码(请注意,我甚至在使用SQL Server 2008时也使用ReportExecution2005 web服务)。您可以将报表呈现为多种格式,如XML、MHTML或PDF,然后尝试从中提取数据。您应该向报表中添加所关心的数据表,通过将其可见性更改为hide来隐藏该表,但将其DataElementOutput属性设置为Output,以便在呈现报表时包含该表。为表指定一些独特的名称(例如,将“Tablix1”替换为“FlatData”)。然后,可以将报表呈现为XML格式,并使用XSLT只提取该表中的行。以下是我以前使用过的一些XSLT,用于从呈现的报表生成器2.0报表中提取数据:

    <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(@*) &gt; 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(@*) &gt; 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>
    
        2
  •  1
  •   Community Mr_and_Mrs_D    7 年前

    正如Sarah Vesses在她的回答中已经提到的,您可以推动报表服务器来呈现数据, 在许多格式中,也许EXCEL是不错的选择,这取决于报表设计的复杂性。 I asked similar qestion 在许多托盘之后,我在Mssql中找到了在报表生成之前制作的试探性应用程序,在我看来报表服务器是作业处理的最后一个实例,所有数据和存储都应该在呈现报表的后端完成

        3
  •  0
  •   Klaus Byskov Pedersen    14 年前

    这是个有趣的问题。当我不得不解决这个问题(对于rdl文件的单元测试)时,我编写了一个简单的xml解析器,从rdl文件中提取sql语句并执行它。这很简单,但是如果你的语句有很多参数,当然会变得更复杂。但是,文件中也提供了参数信息,因此您应该能够编写通用解决方案(但您当然需要为参数提供值)。