打开电子表格文档以进行只读访问

本主题演示如何使用 Open XML SDK for Office 中的类以编程方式打开电子表格文档进行只读访问。


何时打开文档以进行只读访问

有时,您需要打开文档以检查或检索某些信息,并且希望以一种可确保文档保持未更改的方式执行此操作。 在此类情况下,您希望打开文档以进行只读访问。 本操作方法主题讨论几种以编程方式打开只读电子表格文档的方法。


获取 SpreadsheetDocument 对象

在 Open XML SDK 中,SpreadsheetDocument 类表示 Excel 文档包。 若要创建 Excel 文档,请创建 SpreadsheetDocument 类的一个实例并用部件填充该实例。 该文档至少必须具有一个充当文档容器的工作簿部件和至少一个工作表部件。 在此包中,将使用 SpreadsheetML 标记将文本表示为 XML 形式。

若要从文档中创建类实例,请调用 Open() 重载方法之一。 提供了多个 Open 方法,每个方法具有不同的签名。 下表中列出了允许您指定文档是否可编辑的方法。

打开 类库参考主题 说明
Open(String, Boolean) Open(String, Boolean) 从指定的文件创建 SpreadsheetDocument 类的实例。
Open(Stream, Boolean) 打开 (流,布尔值 从指定的 IO 流创建 SpreadsheetDocument 类的实例。
Open(String, Boolean, OpenSettings) Open(String, Boolean, OpenSettings) 从指定的文件创建 SpreadsheetDocument 类的实例。
Open(Stream, Boolean, OpenSettings) Open(Stream, Boolean, OpenSettings) 从指定的 I/O 流创建 SpreadsheetDocument 类的实例。

本主题中前面的表只列出了那些接受布尔值作为第二个参数以指定文档是否可编辑的 Open 方法。 若要打开文档以进行只读访问,请为此参数指定 False

请注意,其中两个 Open 方法会基于作为第一个参数的字符串创建 SpreadsheetDocument 类的实例。 代码示例中的第一个示例使用此技术。 它使用本主题中前面表中的第一个 Open 方法;此方法的签名需要两个参数。 第一个参数采用表示要从中打开文档的完整路径文件名的字符串。 第二个参数是 truefalse。 此示例使用 false 并指示您希望以只读方式打开文件。

以下代码示例调用 Open 方法。

// Open a SpreadsheetDocument based on a file path.
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false))

其他两个 Open 方法基于输入/输出流创建 SpreadsheetDocument 类的实例。 例如,如果有一个使用流输入/输出的Microsoft SharePoint Foundation 2010应用程序,并且想要使用 Open XML SDK 来处理文档,则可以使用此方法。

以下代码示例基于流打开文档。

// Open a SpreadsheetDocument based on a stream.
Stream stream = File.Open(filePath, FileMode.Open);

using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(stream, false))

假设你有一个应用程序,该应用程序使用 .NET Framework 类库的 System.IO.Packaging 命名空间中的 Open XML 支持,并且你希望使用 Open XML SDK 以只读方式处理包。 虽然 Open XML SDK 包含接受 Package 作为第一个参数的方法重载,但没有一个重载将布尔值作为第二个参数来指示是否应打开文档进行编辑。

建议的方法是首先以只读方式打开包,然后再创建 SpreadsheetDocument 类的实例,如代码示例中的第二个示例所示。 下面的代码示例执行此操作。

// Open System.IO.Packaging.Package.
Package spreadsheetPackage = Package.Open(filePath, FileMode.Open, FileAccess.Read);

// Open a SpreadsheetDocument based on a package.
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(spreadsheetPackage))

基本文档结构

SpreadsheetML 文档的基本文档结构由 SheetsSheet 元素组成,这些元素引用工作簿中的工作表。 为每个工作表创建一个单独的 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 单元格的值。

示例代码

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

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

static void OpenSpreadsheetDocumentReadonly(string filePath)
{
    // Open a SpreadsheetDocument based on a file path.
    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false))
    {
        if (spreadsheetDocument.WorkbookPart is not null)
        {
            // Attempt to add a new WorksheetPart.
            // The call to AddNewPart generates an exception because the file is read-only.
            WorksheetPart newWorksheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();

            // The rest of the code will not be called.
        }
    }

    // Open a SpreadsheetDocument based on a stream.
    Stream stream = File.Open(filePath, FileMode.Open);

    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(stream, false))
    {
        if (spreadsheetDocument.WorkbookPart is not null)
        {
            // Attempt to add a new WorksheetPart.
            // The call to AddNewPart generates an exception because the file is read-only.
            WorksheetPart newWorksheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();

            // The rest of the code will not be called.
        }
    }

    // Open System.IO.Packaging.Package.
    Package spreadsheetPackage = Package.Open(filePath, FileMode.Open, FileAccess.Read);

    // Open a SpreadsheetDocument based on a package.
    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(spreadsheetPackage))
    {
        if (spreadsheetDocument.WorkbookPart is not null)
        {
            // Attempt to add a new WorksheetPart.
            // The call to AddNewPart generates an exception because the file is read-only.
            WorksheetPart newWorksheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();

            // The rest of the code will not be called.
        }
    }
}

另请参阅