使用 XMLSS 进行 Excel 报表生成






3.50/5 (5投票s)
本文探讨了 XMLSS 及其转换为 XL 的概念。
引言
定义:XSLT
(eXtensible Stylesheet Language Transformation) 将 XML 文档转换为其他格式,如 HTML、PDF、文本或 XL。它还可以用于将 XML 文档转换为具有不同 XML 标签(不同模式)的另一个 XML 文档。
本文包含 XMLSS 及其使用 XML 和 XSLT 转换为 XL 的概念。XSL 是一种用于格式化 XML 文档的语言。本文背后的基本思想是通过 XMLSS 转换轻松生成Excel 报表。使用 Excel 对象库进行 Excel 报表格式设置是一项繁琐的工作。但在这里,我们可以通过简单地更改 XSLT 文件来生成任何 Excel 报表格式。是不是一个很有趣的概念?
背景
在我当前的项目中,我需要生成一个指定格式的 Excel 报表。起初,我尝试使用 Excel 对象库。但这工作非常繁琐,而且不是很成功。经过广泛研究,我发现了 XMLSS 转换的概念。通过 XMLSS,我们可以生成任何指定格式的 Excel。这个概念非常简单。
XML (数据) + XSLT (样式格式化器) > XMLSS -> [转换后] -> XL [Excel]
使用代码
项目的核心功能描述如下。GetTransformedXL()
方法用于生成 Excel 文件。我们需要为该方法传递两个参数:一个是文件名,另一个是 dtReport DataTable
。首先,我们需要设置所有临时文件存储路径,然后创建一个 DataSet
来创建 XML 文件(数据)。将 DataSet
和 DataTable
的名称设置为与 *Transform.xslt* 文件中指定的名称相同。对 XML 文件进行适当的缩进和其他格式设置。将 XML 文件加载到 XmlDataDocument
对象中。接下来,我们需要将 XSLT 文件 *Transform.xslt* 加载到 XslCompiledTransform
对象中。之后,我们需要执行 XSLT 转换过程并获取建议的 XMLSS。将 XMLSS 注入 FileStream
。最后,从 FileStream
下载建议的 XL。
//-----------------------------------------------------------------
//To transform XMLSS to Excel
//-----------------------------------------------------------------
public void GetTransformedXL(string fileName, DataTable dtReport)
{
string procInfo = "type='text/xsl' href='" + "\\transform.xslt" +
"'";//Processing info for XSLT
string TempPath = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache);
string XMLPath = TempPath + "\\Transform.xml"; //temp path to store the XML file
string XLSPath = TempPath + "\\Transform.xls";//temp path to store the XLS file
//Getting the dataset.
DataSet dsReport = new DataSet("ExcelDS");
//Set the table name as specified in the xslt file:
dtReport.TableName = "ExcelTbl";
//Add the copy of table to the above dataset.
dsReport.Tables.Add(dtReport.Copy());
//Write the dataset as XML file with some XSLT processing information
using (XmlTextWriter tw = new XmlTextWriter(XMLPath, null))
{
tw.Formatting = Formatting.Indented;
tw.Indentation = 3;
tw.WriteStartDocument();
DataSet ds = dsReport;
tw.WriteProcessingInstruction("xml-stylesheet", procInfo);
ds.WriteXml(tw);
}
//Create XML Data Document.
XmlDataDocument xmldoc = new XmlDataDocument();
xmldoc.Load(XMLPath);
XslCompiledTransform xsl = new XslCompiledTransform();
//Load the XSLT file.
xsl.Load(XSLTFile);
using (XmlTextWriter tw = new XmlTextWriter(XLSPath, System.Text.Encoding.UTF8))
{
tw.Formatting = Formatting.Indented;
tw.Indentation = 3;
tw.WriteStartDocument();
//Perform a XSLT transformation.
xsl.Transform(xmldoc, null, tw);
}
//Streams the generated XLS file to the user
byte[] Buffer = null;
using (FileStream MyFileStream = new FileStream(XLSPath, FileMode.Open))
{
// Total bytes to read:
long size;
size = MyFileStream.Length;
Buffer = new byte[size];
MyFileStream.Read(Buffer, 0, int.Parse(MyFileStream.Length.ToString()));
}
//Section for Excel File Download
//Will show the forced download dialog.
HttpContext.Current.Response.ContentType = "application/xls";
string header = "attachment; filename=" + fileName;
HttpContext.Current.Response.AddHeader("content-disposition", header);
HttpContext.Current.Response.BinaryWrite(Buffer);
HttpContext.Current.Response.End();
HttpContext.Current.Response.Flush();
}
XSLT 部分
创建 XSLT 文件是一项困难的工作。尤其是在 XSLT 中进行样式设置。我发现了一种简单生成 Excel 模板的方法,只需将 Excel 文件 [建议的模板] 导出为 XML 电子表格文件即可。要进行高级 XSLT 格式设置,您需要熟练掌握其语法。
<xsl:stylesheet version="1.0"
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:my-scripts"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" >
<xsl:template match="ExcelDS">
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>Sujith</Author>
<LastAuthor>Sujith</LastAuthor>
<LastPrinted>2007-08-31T16:24:29Z</LastPrinted>
<Created>2007-08-31T16:12:42Z</Created>
<LastSaved>2007-11-02T04:11:41Z</LastSaved>
<Company>Company</Company>
<Version>11.5606</Version>
</DocumentProperties>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>7935</WindowHeight>
<WindowWidth>15195</WindowWidth>
<WindowTopX>0</WindowTopX>
<WindowTopY>75</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
<Style ss:ID="m22638596">
<Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
<Borders>
<Border ss:Position="Bottom"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top"
ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="Tahoma" x:Family="Swiss"
ss:Size="8" ss:Bold="1"/>
<Interior ss:Color="#C0C0C0" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="s64">
<Alignment ss:Horizontal="Center"
ss:Vertical="Bottom" ss:WrapText="1"/>
<Borders>
<Border ss:Position="Bottom"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top"
ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="Tahoma" x:Family="Swiss"
ss:Size="8" ss:Bold="1"/>
<Interior ss:Color="#C0C0C0" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="s65">
<Alignment ss:Horizontal="Center"
ss:Vertical="Center" ss:WrapText="1"/>
<Borders/>
<Font ss:FontName="Tahoma"
x:Family="Swiss" ss:Size="9"/>
</Style>
<Style ss:ID="s66">
<Borders/>
<Font ss:FontName="Tahoma"
x:Family="Swiss" ss:Size="9"/>
</Style>
<Style ss:ID="s67">
<Borders/>
<Font ss:FontName="Tahoma"
x:Family="Swiss" ss:Size="9"/>
<NumberFormat ss:Format="Fixed"/>
</Style>
<Style ss:ID="s68">
<Alignment ss:Horizontal="Center"
ss:Vertical="Center" ss:WrapText="1"/>
<Borders/>
<Font ss:FontName="Tahoma" x:Family="Swiss" ss:Size="9"/>
<Interior ss:Color="#C0C0C0" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="s69">
<Borders/>
<Font ss:FontName="Tahoma" x:Family="Swiss" ss:Size="9"/>
<Interior ss:Color="#C0C0C0" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="s70">
<Borders/>
<Font ss:FontName="Tahoma" x:Family="Swiss" ss:Size="9"/>
<Interior ss:Color="#C0C0C0" ss:Pattern="Solid"/>
<NumberFormat ss:Format="Fixed"/>
</Style>
<Style ss:ID="s81">
<Alignment ss:Horizontal="Center"
ss:Vertical="Center" ss:WrapText="1"/>
<Borders/>
<Font ss:FontName="Tahoma" x:Family="Swiss" ss:Size="9"/>
<NumberFormat/>
</Style>
<Style ss:ID="s82">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders/>
<Font ss:FontName="Tahoma" x:Family="Swiss" ss:Size="9"/>
</Style>
<Style ss:ID="s83">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders/>
<Font ss:FontName="Tahoma" x:Family="Swiss" ss:Size="9"/>
<NumberFormat ss:Format="Fixed"/>
</Style>
<Style ss:ID="s87">
<Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
<Borders>
<Border ss:Position="Top"
ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="Tahoma" x:Family="Swiss"
ss:Size="8" ss:Bold="1"/>
</Style>
<Style ss:ID="s89">
<Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
<Borders>
<Border ss:Position="Bottom"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right"
ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top"
ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="Tahoma" x:Family="Swiss"
ss:Size="8" ss:Bold="1"/>
<Interior ss:Color="#C0C0C0" ss:Pattern="Solid"/>
</Style>
</Styles>
<Worksheet>
<xsl:attribute name="ss:Name">ExcelTbl</xsl:attribute>
<!--<Table ss:ExpandedColumnCount="29"
x:FullColumns="1" x:FullRows="1">-->
<Table>
<xsl:apply-templates select="ExcelTbl"/>
<Column ss:AutoFitWidth="0" ss:Width="18"/>
<Row ss:Index="2">
<Cell ss:Index="2" ss:MergeAcross="16" ss:StyleID="m22638596"/>
<Cell ss:MergeAcross="1" ss:StyleID="s89">
<Data ss:Type="String">Q1</Data>
</Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s89">
<Data ss:Type="String">Q2</Data>
</Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s89">
<Data ss:Type="String">Q3</Data>
</Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s89">
<Data ss:Type="String">Q4</Data>
</Cell>
<Cell ss:MergeAcross="2" ss:StyleID="s89">
<Data ss:Type="String">Customer</Data>
</Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell ss:Index="2" ss:StyleID="s64">
<Data ss:Type="String">Lane #</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">O-City</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">O-State</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">O-ZIP</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">D-City</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">D-State</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">D-ZIP</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Miles</Data>
</Cell>
<Cell ss:StyleID="s64"/>
<Cell ss:StyleID="s64">
<Data ss:Type="String">RPM</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Flat</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Flat All-in</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">All-in RPM</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Min.</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">1 yr. Lds</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Margin - RPM</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Margin - Flat</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Margin - RPM - Allin</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Margin - Flat - Allin</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String"># Loads</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">High Cost</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String"># Loads</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">High Cost</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String"># Loads</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">High Cost</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String"># Loads</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">High Cost</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Line Haul</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Fuel</Data>
</Cell>
<Cell ss:StyleID="s64">
<Data ss:Type="String">Exp. Date</Data>
</Cell>
</Row>
<xsl:for-each select="ExcelTbl">
<Row >
<Cell ss:Index="2" ss:StyleID="s65" ss:MergeDown="1">
<Data ss:Type="Number">
<xsl:value-of select="Laneno"/>
</Data>
</Cell>
<Cell ss:StyleID="s65" ss:MergeDown="1">
<Data ss:Type="String">
<xsl:value-of select="Ocity"/>
</Data>
</Cell>
<Cell ss:StyleID="s65" ss:MergeDown="1">
<Data ss:Type="String">
<xsl:value-of select="Ostate"/>
</Data>
</Cell>
<Cell ss:StyleID="s81" ss:MergeDown="1">
<Data ss:Type="Number">
<xsl:value-of select="Ozip"/>
</Data>
</Cell>
<Cell ss:StyleID="s65" ss:MergeDown="1">
<Data ss:Type="String">
<xsl:value-of select="Dcity"/>
</Data>
</Cell>
<Cell ss:StyleID="s65" ss:MergeDown="1">
<Data ss:Type="String">
<xsl:value-of select="Dstate"/>
</Data>
</Cell>
<Cell ss:StyleID="s81" ss:MergeDown="1">
<Data ss:Type="Number">
<xsl:value-of select="Dzip"/>
</Data>
</Cell>
<Cell ss:StyleID="s65" ss:MergeDown="1">
<Data ss:Type="String">
<xsl:value-of select="Miles"/>
</Data>
</Cell>
<Cell ss:StyleID="s65">
<Data ss:Type="String">Price</Data>
</Cell>
<Cell ss:StyleID="s66">
<Data ss:Type="Number">
<xsl:value-of select="PRPM"/>
</Data>
</Cell>
<Cell ss:StyleID="s66">
<Data ss:Type="Number">
<xsl:value-of select="Pflat"/>
</Data>
</Cell>
<Cell ss:StyleID="s67">
<Data ss:Type="Number">
<xsl:value-of select="Pflatallin"/>
</Data>
</Cell>
<Cell ss:StyleID="s67">
<Data ss:Type="Number">
<xsl:value-of select="PRPMallin"/>
</Data>
</Cell>
<!--regular cols-->
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Minimum"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Lcount"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="MarginRPM"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s83">
<Data ss:Type="Number">
<xsl:value-of select="Mflat"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="MarginRPMallin"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s83">
<Data ss:Type="Number">
<xsl:value-of select="Mflatallin"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Q1Lcount"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Q1Hcost"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Q2Lcount"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Q2Hcost"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Q3Lcount"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Q3Hcost"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Q4Lcount"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Q4Hcost"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Linehaul"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="Number">
<xsl:value-of select="Fuel"/>
</Data>
</Cell>
<Cell ss:MergeDown="1" ss:StyleID="s82">
<Data ss:Type="String">
<xsl:value-of select="Expiredate"/>
</Data>
</Cell>
</Row>
<Row>
<!-- with out merging rows-->
<Cell ss:Index="10" ss:StyleID="s68">
<Data ss:Type="String">Cost</Data>
</Cell>
<Cell ss:StyleID="s69">
<Data ss:Type="Number">
<xsl:value-of select="CRPM"/>
</Data>
</Cell>
<Cell ss:StyleID="s69">
<Data ss:Type="Number">
<xsl:value-of select="Cflat"/>
</Data>
</Cell>
<Cell ss:StyleID="s70">
<Data ss:Type="Number">
<xsl:value-of select="Cflatallin"/>
</Data>
</Cell>
<Cell ss:StyleID="s70">
<Data ss:Type="Number">
<xsl:value-of select="CRPMallin"/>
</Data>
</Cell>
</Row>
</xsl:for-each>
<Row>
<Cell ss:Index="2" ss:MergeAcross="27" ss:StyleID="s87">
<Data ss:Type="String"
x:Ticked="1">-- End of Report --</Data>
</Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Layout x:Orientation="Landscape"/>
<PageMargins x:Left="0.17" x:Right="0.23"/>
</PageSetup>
<FitToPage/>
<Print>
<ValidPrinterInfo/>
<Scale>92</Scale>
<HorizontalResolution>600</HorizontalResolution>
<VerticalResolution>600</VerticalResolution>
</Print>
<Selected/>
<LeftColumnVisible>6</LeftColumnVisible>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>29</ActiveRow>
<ActiveCol>10</ActiveCol>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</Workbook>
</xsl:template>
</xsl:stylesheet>
创建报表 DS
以下方法将返回一个用于动态 XML 生成的 DataSet
。首先,您需要创建一个新的 DataSet
。从 *web.config* 分配连接字符串。设置连接对象并通过存储过程 "usp_GetReportDetails
" 执行命令。填充 DataSet ds
并返回 DataSet
。
//----------------------------------------------------------
//Returns the Report DataSet
//----------------------------------------------------------
public DataSet GetReportDS()
{
DataSet ds = new DataSet();
string connectionString =
System.Configuration.ConfigurationManager.ConnectionStrings[1].ConnectionString;
try
{
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "usp_GetReportDetails";
command.Connection = connection;
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(ds);
}
catch { }
return ds;
}
问题与解决方案
- 标记解析器错误
- 在以下对象中发生错误:Table
有时您会遇到标记解析器错误。这是由于 XSLT 文件无效或 XSLT 文件中的语法错误引起的。
这是由 XSLT 语法错误引起的。
运行演示项目
下载并解压项目 zip 文件。为了运行项目,您需要安装 Visual Studio 2005 和 SQL Server 2005。恢复数据库备份并在 *web.config* 文件中设置连接字符串。现在项目已准备就绪。祝您编码愉快。