本主题演示如何使用 Open XML SDK for Office 中的类以编程方式从流中打开电子表格文档。
何时从流中打开
如果你有一个应用程序(如 Microsoft SharePoint Foundation 2010),它通过使用流输入/输出来处理文档,并且你希望使用 Open XML SDK 来处理其中一个文档,则这样做很容易实现。 如果文档存在,并且可以使用 Open XML SDK 打开文档,则尤其如此。 但是,假设在您的代码中此时的文档为打开流,那么您必须在何处利用 SDK 来处理文档? 这就是本主题要讨论的方案。 示例代码中的示例方法接受开放流作为参数,然后使用 Open XML SDK 向流后面的文档添加文本。
SpreadsheetDocument 对象
SpreadsheetML 文档的基本文档结构由 和 Sheet 元素组成Sheets,这些元素引用 中的Workbook工作表。 为每个 Worksheet创建单独的 XML 文件。 例如,具有 MySheet1 和 MySheet2 这两张工作表的工作簿的 SpreadsheetML 位于 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">
        <sheets>
            <sheet name="MySheet1" sheetId="1" r:id="rId1" />
            <sheet name="MySheet2" sheetId="2" r:id="rId2" />
        </sheets>
    </workbook>
工作表 XML 文件包含一个或多个块级元素,例如 SheetData。 
              sheetData 表示单元格表,并包含一个或多个 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 这些类。 下表列出了对应于 、、sheets、 worksheetsheet和 sheetData 元素的类的workbook类名。
| SpreadsheetML 元素 | Open XML SDK 类 | 说明 | |
|---|---|---|---|
<workbook/> | 
Workbook | 主文档部件的根元素。 | |
<sheets/> | 
Sheets | 块级结构(例如 sheet、fileVersion 和)的容器 | ISO/IEC 29500 规范中指定的其他项。 | 
<sheet/> | 
Sheet | 指向工作表定义文件的工作表。 | |
<worksheet/> | 
Worksheet | 包含工作表数据的工作表定义文件。 | |
<sheetData/> | 
SheetData | 按行分组在一起的单元格表。 | |
<row/> | 
Row | 单元格表中的行。 | |
<c/> | 
Cell | 行中的单元格。 | |
<v/> | 
CellValue | 单元格的值。 | 
生成用于添加工作表的 SpreadsheetML 标记
当您有权访问 main 文档部件的正文时,可通过调用 AddNewPart 方法来添加工作表以创建新的 WorksheetPart。 下面的代码示例添加新的 WorksheetPart。
// Add a new worksheet.
WorksheetPart newWorksheetPart = workbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(new SheetData());
示例代码
在此示例中, OpenAndAddToSpreadsheetStream 方法可用于从已打开的流中打开电子表格文档,并在其中追加一些文本。 以下是使用 C# 和 Visual Basic 编写的完整示例代码。
using (FileStream fileStream = new FileStream(args[0], FileMode.Open, FileAccess.ReadWrite))
{
    OpenAndAddToSpreadsheetStream(fileStream);
}
请注意, OpenAddAndAddToSpreadsheetStream 方法不会关闭传递给它的流。 调用代码必须手动或使用 using 语句执行此操作。
以下是使用 C# 和 Visual Basic 编写的完整示例代码。
static void OpenAndAddToSpreadsheetStream(Stream stream)
{
    // Open a SpreadsheetDocument based on a stream.
    using (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());
            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);
        }
    }
}