从流中打开电子表格文档

本主题演示如何使用 Open XML SDK for Office 中的类以编程方式从流中打开电子表格文档。


何时从流中打开

如果你有一个应用程序(如 Microsoft SharePoint Foundation 2010),它通过使用流输入/输出来处理文档,并且你希望使用 Open XML SDK 来处理其中一个文档,则这样做很容易实现。 如果文档存在,并且可以使用 Open XML SDK 打开文档,则尤其如此。 但是,假设在您的代码中此时的文档为打开流,那么您必须在何处利用 SDK 来处理文档? 这就是本主题要讨论的方案。 示例代码中的示例方法接受开放流作为参数,然后使用 Open XML SDK 向流后面的文档添加文本。


SpreadsheetDocument 对象

SpreadsheetML 文档的基本文档结构由 工作表工作表 元素组成,它们引用工作簿中的工作表。 将为每张工作表创建单独的 XML 文件。 例如,具有 MySheet1 和 MySheet2 这两张工作表的工作簿的 SpreadsheetML 位于 Workbook.xml 文件中,并且显示在以下代码示例中。

    <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
    <workbook xmlns=https://schemas.openxmlformats.org/spreadsheetml/2006/main xmlns:r="https://schemas.openxmlformats.org/officeDocument/2006/relationships">
        <sheets>
            <sheet name="MySheet1" sheetId="1" r:id="rId1" /> 
            <sheet name="MySheet2" sheetId="2" r:id="rId2" /> 
        </sheets>
    </workbook>

工作表 XML 文件包含一个或多个块级元素,如 SheetDatasheetData 表示单元格表,并包含一个或多个 Row 元素。 row 包含一个或多个 Cell 元素。 每个单元格包含一个表示单元格的值的 CellValue 元素。 例如,工作簿中只在单元格 A1 中具有值 100 的第一张工作表的 SpreadsheetML 位于 Sheet1.xml 文件中,并且显示在以下代码示例中。

    <?xml version="1.0" encoding="UTF-8" ?> 
    <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
        <sheetData>
            <row r="1">
                <c r="A1">
                    <v>100</v> 
                </c>
            </row>
        </sheetData>
    </worksheet>

使用 Open XML SDK,可以创建使用与 SpreadsheetML 元素对应的强类型类的文档结构和内容。 可以在 DocumentFormat.OpenXML.Spreadsheet 命名空间中找到这些类。 下表列出了与 workbooksheetssheetworksheetsheetData 元素所对应类的类名称。

SpreadsheetML 元素 Open XML SDK 类 说明
workbook DocumentFormat.OpenXml.Spreadsheet.Workbook 主文档部件的根元素。
sheets DocumentFormat.OpenXml.Spreadsheet.Sheets 块级结构(如工作表、文件版本和 ISO/IEC 29500 规范中指定的其他项)的容器。
sheet DocumentFormat.OpenXml.Spreadsheet.Sheet 指向工作表定义文件的工作表。
worksheet DocumentFormat.OpenXml.Spreadsheet.Worksheet 包含工作表数据的工作表定义文件。
sheetData DocumentFormat.OpenXml.Spreadsheet.SheetData 按行分组在一起的单元格表。
row DocumentFormat.OpenXml.Spreadsheet.Row 单元格表中的行。
c DocumentFormat.OpenXml.Spreadsheet.Cell 行中的单元格。
v DocumentFormat.OpenXml.Spreadsheet.CellValue 单元格的值。

生成用于添加工作表的 SpreadsheetML 标记

当您有权访问main文档部件的正文时,可通过调用 AddNewPart<T> (String、String) 方法来添加工作表,以创建新的 WorksheetPart。 下面的代码示例添加新的 WorksheetPart


// Add a new worksheet.
WorksheetPart newWorksheetPart = workbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(new SheetData());
newWorksheetPart.Worksheet.Save();


示例代码

在该示例中, OpenAndAddToSpreadsheetStream 方法可用于从已打开的流中打开电子表格文档,并向其中追加一些文本。 以下是使用 C# 和 Visual Basic 编写的完整示例代码。

var fileStream = File.Open(args[0], FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
OpenAndAddToSpreadsheetStream(fileStream);

请注意, OpenAddAndAddToSpreadsheetStream 方法不会关闭传给它的流。 调用代码必须执行此操作。

以下是使用 C# 和 Visual Basic 编写的完整示例代码。

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.IO;
using System.Linq;

static void OpenAndAddToSpreadsheetStream(Stream stream)
{
    // Open a SpreadsheetDocument based on a stream.
    SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(stream, true);

    if (spreadsheetDocument is not null)
    {
        // Get or create the WorkbookPart
        WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart ?? spreadsheetDocument.AddWorkbookPart();

        
        // Add a new worksheet.
        WorksheetPart newWorksheetPart = workbookPart.AddNewPart<WorksheetPart>();
        newWorksheetPart.Worksheet = new Worksheet(new SheetData());
        newWorksheetPart.Worksheet.Save();
        

        Workbook workbook = workbookPart.Workbook ?? new Workbook();

        if (workbookPart.Workbook is null)
        {
            workbookPart.Workbook = workbook;
        }

        Sheets sheets = workbook.GetFirstChild<Sheets>() ?? workbook.AppendChild(new Sheets());
        string relationshipId = workbookPart.GetIdOfPart(newWorksheetPart);

        // Get a unique ID for the new worksheet.
        uint sheetId = 1;

        if (sheets.Elements<Sheet>().Count() > 0)
        {
            sheetId = (sheets.Elements<Sheet>().Select(s => s.SheetId?.Value).Max() + 1) ?? (uint)sheets.Elements<Sheet>().Count() + 1;
        }

        // Give the new worksheet a name.
        string sheetName = "Sheet" + sheetId;

        // Append the new worksheet and associate it with the workbook.
        Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = sheetName };
        sheets.Append(sheet);
        workbookPart.Workbook.Save();

        // Dispose the document handle.
        spreadsheetDocument.Dispose();
    }
}

另请参阅