如何提高从 OpenXml Excel 电子表格工具中的 SharedStringTable 检索值的性能?
How can I improve the performance of retrieving values from SharedStringTable in OpenXml Excel spreadsheet tools?
我正在使用 DocumentFormat.OpenXml
阅读 Excel 电子表格。我有一个性能瓶颈,用于从 SharedStringTable
对象查找单元格值的代码(它似乎是某种查找 table 单元格值):
var returnValue = sharedStringTablePart.SharedStringTable.ChildElements.GetItem(parsedValue).InnerText;
我创建了一个字典以确保我只检索一次值:
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 秒。还有其他方法可以优化这个操作吗?
我会一次性将整个共享字符串 table 读入您的字典,而不是根据需要查找每个值。这将允许您按顺序移动文件并存储准备好进行哈希查找的值,这将比扫描 SST 以获取您需要的每个值更有效。
运行 在您的流程开始时,如下所示的内容将允许您使用 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
工作正常。
我正在使用 DocumentFormat.OpenXml
阅读 Excel 电子表格。我有一个性能瓶颈,用于从 SharedStringTable
对象查找单元格值的代码(它似乎是某种查找 table 单元格值):
var returnValue = sharedStringTablePart.SharedStringTable.ChildElements.GetItem(parsedValue).InnerText;
我创建了一个字典以确保我只检索一次值:
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 秒。还有其他方法可以优化这个操作吗?
我会一次性将整个共享字符串 table 读入您的字典,而不是根据需要查找每个值。这将允许您按顺序移动文件并存储准备好进行哈希查找的值,这将比扫描 SST 以获取您需要的每个值更有效。
运行 在您的流程开始时,如下所示的内容将允许您使用 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
工作正常。