如何读取和写入 .xlsx (Excel 2007) 文件 - 第二部分
如何通过 C# 读取和写入 .xlsx (Excel 2007) 文件 - 第二部分
引言
在第一部分中,我们讨论了 Excel 2007 文件背后的事实和逻辑。在本文中,我们将了解如何写入 Excel 2007 文件。
正如我们已经看到的,sharedString.xml 和 Sheet1.xml,现在让我们探索 Excel 2007 文件写入中一些其他重要的文件。
1. [ContentType].xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Override PartName="/xl/theme/theme1.xml"
ContentType="application/vnd.openxmlformats-officedocument.theme+xml" />
<Override PartName="/xl/styles.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" />
<Default Extension="rels"
ContentType="application/vnd.openxmlformats-package.relationships+xml" />
<Default Extension="xml" ContentType="application/xml" />
<Override PartName="/xl/workbook.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" />
<Override PartName="/docProps/app.xml"
ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" />
<Override PartName="/xl/worksheets/sheet2.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />
<!-- Sheet Information -->
<Override PartName="/xl/worksheets/sheet3.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />
<!-- Sheet Information -->
<Override PartName="/xl/worksheets/sheet1.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />
<!-- Sheet Information -->
<Override PartName="/xl/sharedStrings.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml" />
<Override PartName="/docProps/core.xml"
ContentType="application/vnd.openxmlformats-package.core-properties+xml" />
</Types>
顾名思义,此文件包含每个文件的内容类型信息。当我们写入 Excel 文件时,其余文件保持不变,但是与工作表信息相关的部分将会改变,因为它取决于 Excel 文件包含的工作表的数量。例如,如果 Excel 文件仅包含一个工作表,则它仅包含一行,该行将表示工作表内容信息。
2. App.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/
extended-properties"
xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
<Application>Microsoft Excel</Application>
<DocSecurity>0</DocSecurity>
<ScaleCrop>false</ScaleCrop>
<HeadingPairs>
<vt:vector size="2" baseType="variant">
<vt:variant>
<vt:lpstr>Worksheets</vt:lpstr>
</vt:variant>
<vt:variant>
<vt:i4>3</vt:i4> <!-- Total number of Sheets -->
</vt:variant>
</vt:vector>
</HeadingPairs>
<TitlesOfParts>
<vt:vector size="3" baseType="lpstr"> <!-- size attribute contains the
value of the total number of sheets -->
<vt:lpstr>Sheet1</vt:lpstr> <!-- Sheet Reference -->
<vt:lpstr>Sheet2</vt:lpstr> <!-- Sheet Reference -->
<vt:lpstr>Sheet3</vt:lpstr> <!-- Sheet Reference -->
</vt:vector>
</TitlesOfParts>
<LinksUpToDate>false</LinksUpToDate>
<SharedDoc>false</SharedDoc>
<HyperlinksChanged>false</HyperlinksChanged>
<AppVersion>12.0000</AppVersion>
</Properties>
它位于 docProp\app.xml,此文件包含工作表的数量和名称。正如您在上面的代码注释中看到的,当我们写入此文件时,我们需要根据我们的 Excel 文件更改工作表的数量和工作表名称的值。假设我们在一个 Excel 文件中有 **两个** 工作表,它们的名称是 **SampleSheet1** 和 **SampleSheet2**,那么此文件将如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/
2006/extended-properties"
xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
<Application>Microsoft Excel</Application>
<DocSecurity>0</DocSecurity>
<ScaleCrop>false</ScaleCrop>
<HeadingPairs>
<vt:vector size="2" baseType="variant">
<vt:variant>
<vt:lpstr>Worksheets</vt:lpstr>
</vt:variant>
<vt:variant>
<vt:i4>2</vt:i4>
</vt:variant>
</vt:vector>
</HeadingPairs>
<TitlesOfParts>
<vt:vector size="2" baseType="lpstr">
<vt:lpstr>SampleSheet1</vt:lpstr>
<vt:lpstr>SampleSheet2</vt:lpstr>
</vt:vector>
</TitlesOfParts>
<Company />
<LinksUpToDate>false</LinksUpToDate>
<SharedDoc>false</SharedDoc>
<HyperlinksChanged>false</HyperlinksChanged>
<AppVersion>12.0000</AppVersion>
</Properties>
在这里我们可以看到这两个 XML 文件之间的区别,首先 **工作表的总数** 从 3 更改为 2,其次 **工作表名称** 更改了。
3. WorkBook.xml.rels
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId3"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet
Target="worksheets/sheet3.xml" />
<Relationship Id="rId2"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet
Target="worksheets/sheet2.xml" />
<Relationship Id="rId1"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet
Target="worksheets/sheet1.xml" />
<Relationship Id="rId6"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings
Target="sharedStrings.xml" />
<Relationship Id="rId5"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles
Target="styles.xml" />
<Relationship Id="rId4"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme
Target="theme/theme1.xml" />
</Relationships>
您可以在 xl\_rels\workbook.xml.rels 中找到此文件。它包含 WorkBook 包含的所有关系信息,并且每个关系都分配了一个唯一的 Id,该 Id 设置在 Id 属性的值中。让我们考虑包含两个工作表的 Excel 文件,那么该文件将如何?
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId3"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme
Target="theme/theme1.xml" />
<Relationship Id="rId2"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet
Target="worksheets/sheet2.xml" />
<Relationship Id="rId1"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet
Target="worksheets/sheet1.xml" />
<Relationship Id="rId5"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings
Target="sharedStrings.xml" />
<Relationship Id="rId4"
Type=http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles
Target="styles.xml" />
</Relationships>
如果您比较这两个 XML,您得到的区别是,第二个 XML 仅包含两个工作表的信息,而第一个 XML 包含三个工作表的信息,当然,关系 ID 也发生了变化。因此,当我们写入此文件时,我们应该注意 Id 的生成,并且应该根据 Excel 文件包含的工作表的数量生成工作表关系。
4. WorkBook.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<workbook xmlns=http://schemas.openxmlformats.org/spreadsheetml/2006/main
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<fileVersion appName="xl" lastEdited="4" lowestEdited="4" rupBuild="4505" />
<workbookPr defaultThemeVersion="124226" />
<bookViews>
<workbookView xWindow="120" yWindow="105" windowWidth="14295" windowHeight="5130" />
</bookViews>
<sheets>
<sheet name="Sheet1" sheetId="1" r:id="rId1" />
<sheet name="Sheet2" sheetId="2" r:id="rId2" />
<sheet name="Sheet3" sheetId="3" r:id="rId3" />
</sheets>
<calcPr calcId="124519" />
</workbook>
Workbook 包含有关工作表的信息。这是定义工作表名称的文件,其余文件使用这些工作表名称。此文件还通过定义属性 r:Id 的值来包含关系和工作表名称之间的映射。生成此文件时,我们必须小心,因为我们必须为工作表映射正确的关系 ID,否则 Excel 文件将被损坏。
逻辑
因此,逻辑非常简单,如果我们根据我们的数据正确地写入所有这些文件并将这些文件压缩到一个文件中,那么 Excel 2007 引擎可以读取它。
Using the Code
众所周知,Excel 文件是一个 WorkBook,它包含多个工作表,每个工作表包含行和列的集合,而行和列的交集称为单元格。
因此,为了使我们的代码易于适应,让我们将代码分解为三个主要类:
WorkBook
(它是根类,就像包含有关工作表和数据的所有信息的 Excel 文件一样。)WorkSheet
(此类表示 Excel 文件的单个 WorkSheet)。Cell
(此类表示 Excel 文件的 Cell 信息)。
让我们看看我们如何使用代码
Excel2007.WorkBook workBook = new Excel2007.WorkBook();
Response.Clear();
Response.BufferOutput = false;
string archiveName = "test.xlsx"; //setting name of Excel File
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "filename=" +
archiveName); //header information to export as zip.
workBook.WorkSheets.Add("FirstSheet"); //add sheet
workBook.WorkSheets["FirstSheet"].Cells[0, 0].Value =
"first value"; //set value on first cell of Sheet
workBook.WorkSheets["FirstSheet"].Cells[0, 1].Value = "second value";
workBook.WorkSheets.Add("SecondSheet");
workBook.WorkSheets["SecondSheet"].Cells[0, 0].Value = "third value";
workBook.Save(Response.OutputStream); //writing content of sheet on Response
Response.End();
因此,我们的代码所做的是,首先它获取有关数据和工作表的所有信息并将其保存在内存中,并且当调用 WorkBook.Save
方法时,它将所有信息写入所需的 XML 文件,然后通过 DotNetZip 库将这些文件压缩成一个文件。
因此,这是一个非常简单的库,可以编写基本的 Excel 2007 文件。
更多解决方案
对于复杂的 Excel 写入,您可以使用不同的免费解决方案。一些如下:
Microsoft 还提供了 System.IO.Packaging
库,您可以从中写入 Excel 文件,您只需在项目中添加 WindowsBase DLL 引用即可使用该库。
历史
- 2011 年 7 月 27 日:初始版本