在Excel中编辑后,OpenXML无法读取电子表格数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Excel中编辑后,OpenXML无法读取电子表格数据相关的知识,希望对你有一定的参考价值。

我正在使用OpenXML将一些翻译数据导出到Excel电子表格,然后将相同的电子表格导回到我的程序中。

现在,如果我只是直接导出和导入,这可以正常工作,但是,如果我在excel中打开电子表格并编辑它或只是保存它,我的程序无法读取数据,就好像它已损坏一样。但是,如果我再次打开它,Excel会查看它,所以该文件实际上并没有损坏。

导出数据

using (SpreadsheetDocument document = SpreadsheetDocument.Create(saveLocation, SpreadsheetDocumentType.Workbook))
...

//Add a WorkbookPart to the document
WorkbookPart workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();

//Add a WorksheetPart to the WorkbookPart
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();

//Add style
WorkbookStylesPart stylePart = workbookPart.AddNewPart<WorkbookStylesPart>();
stylePart.Stylesheet = GenerateStylesheet();
stylePart.Stylesheet.Save();
...

SheetData sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());
//Append some rows
...

worksheetPart.Worksheet.Save();

阅读电子表格

using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileStream, false))
        {
            WorkbookPart workbookPart = document.WorkbookPart;
            WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
            SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

            var headerRow = sheetData.Elements<Row>().FirstOrDefault();
            ...

            //All data here are numbers

所以最初我想也许更多的工作表是由excel创建的,我只是错误地假设.First()会产生正确的,但是在调试时查看对象表明数据在某种程度上是正确的。所以显然这里有问题,所以我决定查看.xlsx文件的存档内容。

这是在我的程序导出并创建文件之后。您可以看到xml文件中有一些实际数据(字符串)。

enter image description here

这是在我在Excel中打开电子表格并保存它而不进行任何编辑之后。

enter image description here

我不知道为什么会发生这种情况,如果它是某种意图的行为。我发现OpenXML充满了奇怪的设计选择,但在完成迷宫后,这是第一件真正阻止我进步的事情。

我在macOS上构建Netcore 2.0,显然Excel也在macOS上运行。

如果有人能帮我解决这个问题,我会非常高兴。

答案

有两种方法可以在Excel文件中存储字符串;正如您在创建中所做的那样使用内联字符串,或者正如评论中指出的那样,使用名为SharedStringTable的单独XML文件。 Excel碰巧使用后一种方法,因此直接包含字符串的每个单元格,它们包含SharedStringTable中条目的索引。

幸运的是,您可以使用OpenXML读取SharedStringTable,就像您可以使用文档的任何其他部分一样。例如:

using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileStream, false))
    {
        WorkbookPart workbookPart = document.WorkbookPart;
        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
        SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

        SharedStringTablePart stringTable = workbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();

        var headerRow = sheetData.Elements<Row>().FirstOrDefault();

        foreach (Cell c in headerRow.Elements<Cell>())
        {
            string cellText;

            if (c.DataType == CellValues.SharedString)
            {
                //the value will be a number which is an index into the shared strings table
                int index = int.Parse(c.CellValue.InnerText);
                cellText = stringTable.SharedStringTable.ElementAt(index).InnerText;
            }
            else
            {
                //just take the value from the cell (note this won't work for some types e.g. dates)
                cellText = c.CellValue.InnerText;
            }

            Console.WriteLine(cellText);
        }

    }
}

对于大文件,您可能需要考虑缓存共享字符串,如本问答中所述。

How can I improve the performance of retrieving values from SharedStringTable in OpenXml Excel spreadsheet tools?

以上是关于在Excel中编辑后,OpenXML无法读取电子表格数据的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft Excel 中的 OpenXML 用于注释

dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息

dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息

dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息

打开从excel文件读取的xml

使用“Openxml writer”合并 Excel 中的单元格