【问题标题】:Fastest way to format multiple rows in an excel in C#用 C# 在 excel 中格式化多行的最快方法
【发布时间】:2019-07-16 13:54:03
【问题描述】:

我有一个庞大的数据集,我想将其写入 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

并且内部异常中没有任何内容。有什么想法可以达到预期的效果吗?

【问题讨论】:

  • 尝试输入一个数字而不是枚举,看看是否有效。即.Interior.Color = 11829830; 代替.Interior.Color = Color.SteelBlue;
  • 那不起作用..得到了同样的例外。 @shahkalpesh
  • 请用分号代替逗号。有时(取决于区域设置)它的工作方式有点奇怪。所以"A3:AA3;A83:AA83;A88:AA88;A94:AA94;A102:AA102;A106:AA106;A110:AA110"
  • 那也没有帮助.. @smartobelix
  • 是的,这是有道理的。将此限制为 3000 个字符的限制作为答案。它也会帮助其他人。此外,您的代码没有长字符串范围,这无助于人们模拟您看到的错误。

标签: c# .net excel office-interop


【解决方案1】:

根据问题下的 cmets,范围字符串的硬编码限制为 255 个字符,但是我找不到任何有关它的文档。另一位评论者建议使用分号作为分隔符,但the documentation 明确指出逗号应用作范围字符串中的联合运算符:

应用程序语言中 A1 样式 表示法的范围名称。它可以包括范围运算符(冒号)、交集运算符(空格)或联合运算符(逗号)。它也可以包括美元符号,但它们被忽略。您可以在范围的任何部分使用本地定义的名称。如果您使用名称,则假定名称采用应用程序的语言。

那么我们从这里去哪里呢?单独格式化每个范围确实效率低下。 Application 接口提供了方法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
}

我还可以看到进一步的优化空间,例如对连续行进行分组,但如果您使用小计格式化离散行,这将无济于事。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-31
    • 2010-10-16
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    相关资源
    最近更新 更多