c# - 用 C# 在 excel 中格式化多行的最快方法
问题描述
我有一个庞大的数据集,我想将其写入 Excel,并且需要根据业务逻辑对行进行条件格式化。因此,对于数据插入部分,我使用数据数组来填充 Excel,它的工作速度非常快。但是,在格式化行时,我发现性能严重下降。仅进行格式化几乎需要两倍以上的时间。
到目前为止,我正在将格式应用于各个行并循环遍历一系列行。但是,我想知道是否可以一次选择多行并将批量格式化选项应用于这些行:这是我现在所拥有的:
foreach (int row in rowsToBeFormatted)
{
Excel.Range range = (Excel.Range)xlsWorksheet.Range[xlsWorksheet.Cells[row + introFormat, 1], xlsWorksheet.Cells[row + introFormat, 27]];
range.Font.Size = 11;
range.Interior.ColorIndex = 15;
range.Font.Bold = true;
}
这是我如何尝试在范围内选择多行并应用格式的演示:
string excelrange = "A3:AA3,A83:AA83,A88:AA88,A94:AA94,A102:AA102,A106:AA106,A110:AA110,...." (string with more than 3000 characters)
xlsWorksheet.get_Range(excelrange).Interior.Color = Color.SteelBlue;
但是,执行代码时出现以下错误:
HRESULT 异常:0x800A03EC
内部异常没有什么。任何想法如何才能达到预期的结果?
解决方案
根据问题下的评论,范围字符串的硬编码限制为 255 个字符,但是我找不到任何有关它的文档。另一位评论者建议使用分号作为分隔符,但文档明确指出逗号应用作范围字符串中的联合运算符:
应用程序语言中采用A1 样式表示法的范围名称。它可以包括范围运算符(冒号)、交集运算符(空格)或联合运算符(逗号)。它也可以包括美元符号,但它们被忽略。您可以在范围的任何部分使用本地定义的名称。如果您使用名称,则假定该名称使用应用程序的语言。
那么,我们该何去何从?单独格式化每个范围确实效率低下。Application
interface 提供了 method Union
,但是在循环中调用它和单独格式化一样低效。所以自然的选择是使用最大范围字符串限制,从而最大限度地减少对 COM 接口的调用次数。
您可以将整个范围拆分为块;每个不超过 255 个字符的限制。我会使用枚举器来实现它:
static IEnumerable<string> GetChunks(IEnumerable<string> ranges)
{
const int MaxChunkLength = 255;
var sb = new StringBuilder(MaxChunkLength);
foreach (var range in ranges)
{
if (sb.Length > 0)
{
if (sb.Length + range.Length + 1 > MaxChunkLength)
{
yield return sb.ToString();
sb.Clear();
}
else
{
sb.Append(",");
}
}
sb.Append(range);
}
if (sb.Length > 0)
{
yield return sb.ToString();
}
}
var rowsToFormat = new[] { 3, 83, 88, 94, 102, 106, 110/*, ...*/ }
var rowRanges = rowsToFormat.Select(row => "A" + row + ":" + "AA" + row);
foreach (var chunk in GetChunks(rowRanges))
{
var range = xlsWorksheet.Range[chunk];
// do formatting stuff here
}
以上比单独格式化快 10-15 倍:
foreach (var rangeStr in rowRanges)
{
var range = xlsWorksheet.Range[rangeStr];
// do formatting stuff here
}
我还可以看到进一步的优化空间,例如对连续行进行分组,但如果您使用小计格式化离散行,它将无济于事。
推荐阅读
- c# - 从数据库表中检索数据并在标签中获取其值时出错
- ruby - 我可以从它的受让人那里得到变量名吗?
- c - 用于小数据文件 (~10KB) 的快速且强大的校验和算法
- bash - 从 bash 中的原始数据中提取列表,或者只是格式化输出 list_name 后跟列表内容
- reactjs - React 和 TypeScript - 组件
- objective-c - 为什么我不能访问这个指针的值。目标c
- c# - Selenium C# - Web 元素属性存在但找不到?
- c# - 如何添加不使用属性的服务器端验证规则?
- facebook - 使用带有永久页面访问令牌的 Instagram Graph Api 仅适用于某些帐户
- java - 结合 2 个区间