添加自动筛选和sorting导致Excel崩溃
我正在开发一个应用程序,您可以使用OpenXML将一些数据导出到Excel文件。 除了自动filter之外,一切正常。 这个想法是将一个自动filter添加到数据的主体,以便用户自动控制过滤和sorting数据。 所以在代码中,我做了这样的事情:
var filter = new AutoFilter() { Reference = string.Format("{0}:{1}", topLeftCellReference, bottomRightCellReference ) }; worksheet.AppendChild(filter);
在导出的XLSX中,它看起来像这样:
<x:autoFilter ref="A4:L33" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" />
并将其添加到sheetData
和mergeCells
之间的工作表中。
我可以在Excel中打开这个filter,它工作正常。 预计如果您尝试对列进行sorting,该列将进行sorting,然后Excel崩溃。 保存并重新加载文件(强制Excel清理所有内容)不能解决问题。 但是,如果你先应用一个filter(比如过滤一个列到> 10
,然后删除那个filter,你现在可以sorting而不会崩溃。我应用一个filter并删除它之后保存了一个文件,现在这个文件很好,但是看着“修复”文件的XML,我没有看到任何明显的差异。
有没有人知道什么可能会导致这个问题? 除了将其添加到工作表之外,在应用自动filter时还有其他事情要做吗?
注意:我们正在使用Excel 2010(版本14.0.7153.5000)
下面是一个示例文件 (点击下载,它将以.zip
下载,重命名为.xlsx
以在Excel中打开。启用编辑,select其中一列并尝试sorting)。
编辑 :玩这个更多。 如果您在Excel中重新保存文件,它仍然是坏的。 但是,如果您首先应用filter(然后清除它),然后在Excel中重新保存,则会得到一个工作文件。 仔细观察两个文件(仍然损坏的resaved文件和现在工作的文件),我注意到在应用(和清除)filter之后,这个额外的位被添加到工作簿中:
<x:definedNames> <x:definedName name="_xlnm._FilterDatabase" localSheetId="0" hidden="1">'Sheet 1'!$A$1:$E$11</x:definedName> </x:definedNames>
不知道这可能是不是…
好吧,看来这里的魔术公式是添加DefinedNames
部分,正如我在我的编辑build议:
<x:definedName name="_xlnm._FilterDatabase" localSheetId="0" hidden="1">'Sheet 1'!$A$1:$E$11</x:definedName>
显然, _xlmn._FilterDatabase
是自动_xlmn._FilterDatabase
器工作(至less为了sorting)所需要的。 我想如果filter不在那里,它会被创build,但是如果它不在那里,那么就会炸毁Excel。
所以你需要sheetname和单元格引用来填充它。
通过Open XML标准,在defineName的第18.2.5节中,我看到这个:
filter和高级filter
_xlnm .Criteria:此定义的名称是指包含要将高级筛选器应用于数据范围时使用的条件值的范围。
_xlnm ._FilterDatabase:可以是下列之一
一个。 此定义的名称是指已应用高级filter的范围。 这代表未经过滤的源数据范围。
湾 此定义的名称是指已应用AutoFilter的范围。
因此,您需要为每个具有filter的工作表添加一个_xlnm._FilterDatabase
(似乎无法在一个工作表上有多个filter)。 名称是相同的_xlmn_FilterDatabase
无论你有多less张filter,因为我猜想只有name和localSheetId
的组合需要是唯一的。
所以最后,我有这样的事情:
var filter = new AutoFilter() { Reference = string.Format("{0}:{1}", topLeftCellReference, bottomRightCellReference ) }; worksheet.AppendChild(filter); workbookPart.Wookbook.DefinedNames.AppendChild(new DefinedName(string.Format("'{0}'!$A${1}:${2}${3}", sheet.Name, leftColumnLetter, topRowIndex, rightColumnLetter, bottomRowIndex)) { Name = "_xlnm._FilterDatabase", LocalSheetId = sheet.SheetId - 1, Hidden = true });
这似乎是在解决Excel中的一个bug。 Excel应该检查名称是否在sorting之前被定义,如果需要的话自动创build它(如果你过滤而不是sorting的话,它会出现这种情况)。