如何提高在OpenXml Excel电子表格工具中从SharedStringTable中检索值的性能?
我使用DocumentFormat.OpenXml
来读取Excel电子表格。 我有一个性能瓶颈用于从SharedStringTable
对象查找单元格值的代码(它似乎是某种查找表的单元格值):
var returnValue = sharedStringTablePart.SharedStringTable.ChildElements.GetItem(parsedValue).InnerText;
我已经创build了一个字典,以确保我只检索一次值:
if (dictionary.ContainsKey(parsedValue)) { return dictionary[parsedValue]; } var fetchedValue = sharedStringTablePart.SharedStringTable.ChildElements.GetItem(parsedValue).InnerText; dictionary.Add(parsedValue, fetchedValue); return fetchedValue;
这使演出时间缩短了近50%。 但是,我的指标表明,从SharedStringTable
对象获取值执行123,951次的代码行仍需要208秒。 有没有其他的方法来优化这个操作?
我会一口气把整个共享string表读入字典,而不是根据需要查找每个值。 这将允许您按顺序浏览文件,并将值存储为散列查找,这比为每个需要的值扫描SST效率更高。
在stream程开始时运行如下的代码将允许您使用dictionary[parsedValue]
访问每个值。
private static void LoadDictionary() { int i = 0; foreach (var ss in sharedStringTablePart.SharedStringTable.ChildElements) { dictionary.Add(i++, ss.InnerText); } }
如果你的文件非常大,你可能会看到使用SAX方法读取文件的一些好处,而不是上面的DOM方法:
private static void LoadDictionarySax() { using (OpenXmlReader reader = OpenXmlReader.Create(sharedStringTablePart)) { int i = 0; while (reader.Read()) { if (reader.ElementType == typeof(SharedStringItem)) { SharedStringItem ssi = (SharedStringItem)reader.LoadCurrentElement(); dictionary.Add(i++, ssi.Text != null ? ssi.Text.Text : string.Empty); } } } }
在我的机器上,使用60000行和2列的文件,使用上面的LoadDictionary
方法代替了问题中的GetValue
方法的速度要快300倍左右。 LoadDictionarySax
方法给出了类似的性能,但是在一个更大的文件(100000行,10列)上,SAX方法比LoadDictionary
方法快25%左右。 在一个更大的文件(100000行,26列)上, LoadDictionary
方法抛出了内存LoadDictionarySax
exception,但LoadDictionarySax
没有问题。