Excel 坚持认为我的 OpenXml 文件有错误
Excel Insists that my OpenXml file has errors
好的,我正在从 DataTable 生成一个 Excel 文件。我生成文件并保存,没有编译或 运行-time 错误。但是,当我在 Excel 中打开文件时,它会弹出消息:
We found a problem with some content in 'filename.xlsx'. Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes.
所以我点击Yes
。一两秒后,它会显示以下消息:
Excel was able to open the file by repairing or removing the unreadable content.
Repaired Records: Format from /xl/styles.xml (Styles)
Click to view log file listing repairs: 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>
所以,我想好吧...我刚刚找到了 Microsoft 漂亮的小 OOXML SDK Validator/Compare 工具。所以我在其中打开 "bad" 文件,然后 运行 一个 Validate
。它完全成功地返回,并表明文件中没有错误。所以我不太确定 Excel 在抱怨什么。
此外,允许Excel到"repair",然后完成打开文件,工作表的所有样式和显示都正确,并且所有数据都已填写,并且看起来完全一样期待的样子。
这是我用来生成 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>
也在一些工作之后追踪到这个,并在这里发布答案以供后代使用。
原来 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 应用程序也是如此?)非常 对 XLSX 文件中的 XML 很挑剔,你需要花很多时间调试和追踪像这样愚蠢的小东西,即使它们是你不知道的东西您的文件中实际上不需要。
好的,我正在从 DataTable 生成一个 Excel 文件。我生成文件并保存,没有编译或 运行-time 错误。但是,当我在 Excel 中打开文件时,它会弹出消息:
We found a problem with some content in 'filename.xlsx'. Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes.
所以我点击Yes
。一两秒后,它会显示以下消息:
Excel was able to open the file by repairing or removing the unreadable content.
Repaired Records: Format from /xl/styles.xml (Styles)
Click to view log file listing repairs: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>
所以,我想好吧...我刚刚找到了 Microsoft 漂亮的小 OOXML SDK Validator/Compare 工具。所以我在其中打开 "bad" 文件,然后 运行 一个 Validate
。它完全成功地返回,并表明文件中没有错误。所以我不太确定 Excel 在抱怨什么。
此外,允许Excel到"repair",然后完成打开文件,工作表的所有样式和显示都正确,并且所有数据都已填写,并且看起来完全一样期待的样子。
这是我用来生成 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>
也在一些工作之后追踪到这个,并在这里发布答案以供后代使用。
原来 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 应用程序也是如此?)非常 对 XLSX 文件中的 XML 很挑剔,你需要花很多时间调试和追踪像这样愚蠢的小东西,即使它们是你不知道的东西您的文件中实际上不需要。