【问题标题】:Excel Insists that my OpenXml file has errorsExcel 坚持认为我的 OpenXml 文件有错误
【发布时间】:2019-08-15 20:11:27
【问题描述】:

好的,我正在从 DataTable 生成一个 Excel 文件。我生成文件并保存它,没有编译或运行时错误。但是,当我在 Excel 中打开文件时,它会弹出消息:

我们发现“filename.xlsx”中的某些内容存在问题。你想让我们尽可能多地恢复吗?如果您信任此工作簿的来源,请单击“是”。

所以我点击Yes。一两秒钟后,它会出现以下消息:

Excel 能够通过修复或删除不可读的内容来打开文件。
修复的记录:格式来自 /xl/styles.xml(样式)
点击查看日志文件列表修复:C:\file\path\filename.xml

但是如果你点击打开日志,它基本上只是说同样的话,没有额外的细节。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <logFileName>error336080_01.xml</logFileName>
    <summary>Errors were detected in file 'C:\my\file\path\data.xlsx'</summary>
    <repairedRecords>
        <repairedRecord>Repaired Records: Format from /xl/styles.xml part (Styles)</repairedRecord>
    </repairedRecords>
</recoveryLog>

所以,我想好吧...我刚刚找到了微软漂亮的小 OOXML SDK 验证器/比较工具。所以我在其中打开了“坏”文件,然后运行Validate。它完全成功返回,并表明文件中没有错误。所以我不太确定 Excel 在抱怨什么。

此外,在允许 Excel“修复”,然后完成打开文件后,工作表的样式和显示都正确,所有数据都已填写,看起来与预期的完全一样。

这是我用来生成 OOXML 样式表的代码...
(是的,它是 VB.NET,它是一个遗留应用程序。)

Private Function ConstructStyleSheet() As Stylesheet
    Dim rv As Stylesheet = New Stylesheet()

    rv.AppendChild(New NumberingFormats(
        New NumberingFormat() With {.NumberFormatId = 0, .FormatCode = "General"},
        New NumberingFormat() With {.NumberFormatId = 5, .FormatCode = "MM/dd/yyyy HH:mm:ss"}
    ))

    rv.AppendChild(New Fonts(
        New Font(),
        New Font(New Bold())
    ))

    rv.AppendChild(New Borders(
        New Border(),
        New Border(New BottomBorder(New Color() With {.Auto = True}) With {.Style = BorderStyleValues.Thin})
    ))

    '// COMMENTING OUT THIS BLOCK (BUT LEAVING ALL ABOVE) YIELDS AN XLSX WITH NO ERRORS
    '// BUT OF COURSE, NO STYLING ON ANY CELLS, EITHER
    rv.AppendChild(New CellFormats(
        New CellFormat() With {.FontId = 0, .ApplyFont = True},
        New CellFormat() With {.FontId = 1, .BorderId = 1, .ApplyFont = True, .ApplyBorder = True},
        New CellFormat() With {.FontId = 0, .ApplyFont = True, .NumberFormatId = 5, .ApplyNumberFormat = True}
    ))

    Return rv
End Function

这是/xl/styles.xml 样式表的内容...

<?xml version="1.0" encoding="utf-8"?>
<x:styleSheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <x:numFmts>
        <x:numFmt numFmtId="0" formatCode="General" />
        <x:numFmt numFmtId="5" formatCode="MM/dd/yyyy HH:mm:ss" />
    </x:numFmts>
    <x:fonts>
        <x:font />
        <x:font>
            <x:b />
        </x:font>
    </x:fonts>
    <x:borders>
        <x:border />
        <x:border>
            <x:bottom style="thin">
                <x:color auto="1" />
            </x:bottom>
        </x:border>
    </x:borders>
    <x:cellXfs>
        <x:xf fontId="0" applyFont="1" />
        <x:xf fontId="1" borderId="1" applyFont="1" applyBorder="1" />
        <x:xf numFmtId="5" fontId="0" applyNumberFormat="1" applyFont="1" />
    </x:cellXfs>
</x:styleSheet>

【问题讨论】:

  • 这个问题与您的其他问题stackoverflow.com/questions/57502096/… 是否相关或不同? FWIW 通常,一个很好的故障排除步骤是将修复的文件保存为不同的名称。在 Open XML SDK Productivity Tool 中打开原始文件。使用“比较”功能打开修复的文件。这将生成与原始文件不同的和生成修复文件的代码。这通常足以告诉您解决问题。
  • 它是相关的,但不同的问题。我最终找到了那个并修复了它(并回答了这个问题)。嗯...我看过比较,修复后将其保存在 Excel 中,但它有很大的不同。 Excel添加了很多其他东西,并将东西移动到SDK在生成文件时没有放出的所有不同地方。没想到通过比较可能只为 Styles 部分生成代码。我得看看那个。可能会让我靠近一点。
  • 特别令人沮丧的是 SDK Validator 说输出文件是 100% 完全有效的。
  • 是的,在这种情况下,我首先会专注于比较两个文件中样式的 xml。一旦您看到 XML 的不同之处,就可能更容易追踪。我对 Excel Open XML 不是很熟悉,我的领域更多的是 Word,但我在另一个问题中注意到的一点是 也许 您在“严格性”方面遇到了差异 - 一种变化在较旧版本的 Office 应用程序可能遇到问题的较新版本的 Open XML 中。这不是验证器会捕捉到的东西。我不记得究竟是什么让我这么想,虽然......
  • @CindyMeister - 终于找到了;谢谢。有很多不同之处,一个一个地添加它们直到它起作用。将添加一个详细说明修复的答案。

标签: excel openxml openxml-sdk spreadsheetml


【解决方案1】:

在一些工作之后也追踪了这个,并将答案发布在这里以供后代使用。

结果表明 Excel 需要您将填充样式放入输出文件中,即使您没有在任何单元格中使用任何填充样式。

    Private Function ConstructStyleSheet() As Stylesheet
        Dim rv As Stylesheet = New Stylesheet()

        rv.AppendChild(New NumberingFormats(
            New NumberingFormat() With {.NumberFormatId = 5, .FormatCode = "mm/dd/yyyy hh:mm:ss"}
        ) With {.Count = 1})

        rv.AppendChild(New Fonts(
            New Font(),
            New Font(New Bold())
        ) With {.Count = 2})

        '// ===== NEW SECTION =====
        rv.AppendChild(New Fills(
            New Fill(New PatternFill() With {.PatternType = PatternValues.None}),
            New Fill(New PatternFill() With {.PatternType = PatternValues.Gray125})
        ) With {.Count = 2})
        '\\ =======================

        rv.AppendChild(New Borders(
            New Border(),
            New Border(New BottomBorder(New Color() With {.Auto = True}) With {.Style = BorderStyleValues.Thin})
        ) With {.Count = 2})

        '// ===== THEN ALSO ADD THE .FillId = 0 ON ALL OF THE CellFormats
        rv.AppendChild(New CellFormats(
            New CellFormat() With {.FillId = 0, .BorderId = 0, .FontId = 0, .NumberFormatId = 0},
            New CellFormat() With {.FillId = 0, .ApplyBorder = True, .ApplyFont = True, .BorderId = 1, .FontId = 1, .NumberFormatId = 0},
            New CellFormat() With {.FillId = 0, .ApplyNumberFormat = True, .BorderId = 0, .NumberFormatId = 5, .FontId = 0, .ApplyFont = True}
        ) With {.Count = 3})

        Return rv
    End Function

在这两个问题之后,故事的明确寓意是 Excel(我猜其他 Office 应用程序也是如此?)对 XML 放置极度挑剔在 XLSX 文件中,您需要花费大量时间调试和追踪此类愚蠢的小东西,即使它们是您文件中实际上不需要的东西。

【讨论】:

  • FWIW Word 在某些方面更加宽容。 zip 包肯定不那么复杂。我知道使用 Excel,他们遇到了很多文件大小(以及效率/速度)的问题,这就是事情如此神秘和复杂的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-14
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多