使用C#封闭XML在Excel中合并列的性能

4 c# excel performance worksheet performance-testing

我有一个包含9个属性的列表,它包含一个子列表。

例如

Public Class BaseClass
{
    public string Item1 { get; set; }
    public string Item2 { get; set; }
    public List<ChildClass> Item3 { get; set; }
    ............
}

Public Class ChildClass
{
    public string Item1 { get; set; }
    public string Item2 { get; set; }
    public string Item3 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我编程为使用列分组将集合转换为Excel文件。在我的“实际原始列表”中,我有3000多个项目,每个项目都有一个子计数为4到6的子列表。要迭代Collection ,1500个Collections需要花费20多分钟的时间

Excel工作表示例快照:

在此处输入图片说明

请参考下面的示例代码,它使用虚拟数据生成Excel

我正在使用ClosedXML-请从NuGet获取引用

using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


class Program
{
    static void Main(string[] args)
    {
        Program obj = new Program();
        obj.GenerateData();
    }

    public void GenerateData()
    {
        XLWorkbook xlWorkBook = new XLWorkbook();
        IXLWorksheet xlWorkSheet = xlWorkBook.Worksheets.Add("SearchResults");

        Stopwatch stopwatch = new Stopwatch();
        List<TimeSpan> timeElapsedList = new List<TimeSpan>();

        Console.WriteLine("Excel Generation Started...");

        stopwatch.Start();
        int counter = 0;
        int length = 1500;
        int rowCount = 1;

        for (int i = 0; i < length; i++)
        {
            Stopwatch loopstopwatch = new Stopwatch();
            loopstopwatch.Start();
            counter++;

            #region Loop Statements Start
            int rowHeight = 5;

            int minHt = rowCount;
            int maxHt = rowCount + rowHeight - 1;

            xlWorkSheet.Cell(rowCount, 1).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(rowCount, 1).Value = "Row " + i + " - Item 1";
            xlWorkSheet.Cell(rowCount, 1).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("A" + minHt.ToString() + ":A" + maxHt).Column(1).Merge();

            xlWorkSheet.Cell(rowCount, 2).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(rowCount, 2).Value = "Row " + i + " - Item 2";
            xlWorkSheet.Cell(rowCount, 2).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("B" + minHt.ToString() + ":B" + maxHt).Column(1).Merge();

            xlWorkSheet.Cell(rowCount, 3).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(rowCount, 3).Value = "Row " + i + " - Item 3";
            xlWorkSheet.Cell(rowCount, 3).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("C" + minHt.ToString() + ":C" + maxHt).Column(1).Merge();

            xlWorkSheet.Cell(rowCount, 4).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(rowCount, 4).Value = "Row " + i + " - Item 4";
            xlWorkSheet.Cell(rowCount, 4).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("D" + minHt.ToString() + ":D" + maxHt).Column(1).Merge();

            xlWorkSheet.Cell(rowCount, 5).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(rowCount, 5).Value = "Row " + i + " - Item 5";
            xlWorkSheet.Cell(rowCount, 5).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("E" + minHt.ToString() + ":E" + maxHt).Column(1).Merge();

            xlWorkSheet.Cell(rowCount, 6).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(rowCount, 6).Value = "Row " + i + " - Item 6";
            xlWorkSheet.Cell(rowCount, 6).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("F" + minHt.ToString() + ":F" + maxHt).Column(1).Merge();

            xlWorkSheet.Cell(rowCount, 7).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(rowCount, 7).Value = "Row " + i + " - Item 7";
            xlWorkSheet.Cell(rowCount, 7).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("G" + minHt.ToString() + ":G" + maxHt).Column(1).Merge();

            xlWorkSheet.Cell(rowCount, 8).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(rowCount, 8).Value = "Row " + i + " - Item 8";
            xlWorkSheet.Cell(rowCount, 8).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("H" + minHt.ToString() + ":H" + maxHt).Column(1).Merge();

            for (int j = 0; j < rowHeight; j++)
            {
                xlWorkSheet.Cell(rowCount, 9).WorksheetColumn().Width = 25;
                xlWorkSheet.Cell(rowCount, 9).Value = "Row " + i + " | SubRow" + j + " - Sub Item 1";
                xlWorkSheet.Cell(rowCount, 10).WorksheetColumn().Width = 25;
                xlWorkSheet.Cell(rowCount, 10).Value = "Row " + i + " | SubRow" + j + " - Sub Item 2";
                xlWorkSheet.Cell(rowCount, 11).WorksheetColumn().Width = 25;
                xlWorkSheet.Cell(rowCount, 11).Value = "Row " + i + " | SubRow" + j + " - Sub Item 3";
                xlWorkSheet.Cell(rowCount, 12).WorksheetColumn().Width = 25;
                xlWorkSheet.Cell(rowCount, 12).Value = "Row " + i + " | SubRow" + j + " - Sub Item 4";
                xlWorkSheet.Cell(rowCount, 13).WorksheetColumn().Width = 25;
                xlWorkSheet.Cell(rowCount, 13).Value = "Row " + i + " | SubRow" + j + " - Sub Item 5";
                xlWorkSheet.Cell(rowCount, 14).WorksheetColumn().Width = 25;
                xlWorkSheet.Cell(rowCount, 14).Value = "Row " + i + " | SubRow" + j + " - Sub Item 6";
                xlWorkSheet.Cell(rowCount, 15).WorksheetColumn().Width = 25;
                xlWorkSheet.Cell(rowCount, 15).Value = "Row " + i + " | SubRow" + j + " - Sub Item 7";

                rowCount++;
            }

            xlWorkSheet.Cell(minHt, 16).WorksheetColumn().Width = 25;
            xlWorkSheet.Cell(minHt, 16).Value = "Row " + i + " - Item 9";
            xlWorkSheet.Cell(minHt, 16).Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
            xlWorkSheet.Range("P" + minHt.ToString() + ":P" + maxHt).Column(1).Merge();

            #endregion

            loopstopwatch.Stop();
            timeElapsedList.Add(loopstopwatch.Elapsed);

            Console.WriteLine("Iteration No: {0} - Time Taken {1}", counter, loopstopwatch.Elapsed);
        }

        stopwatch.Stop();

        Console.WriteLine("Excel Construction Completed !");
        Console.WriteLine("Total Time Taken to Complete {0}", stopwatch.Elapsed);
        Console.WriteLine("Minimum Time : {0}", timeElapsedList.Min());
        Console.WriteLine("Maximum Time : {0}", timeElapsedList.Max());
    }

}
Run Code Online (Sandbox Code Playgroud)

请协助我如何在时间管理方面使用列合并优化代码。

Iva*_*oev 5

如果确定要合并的范围不相交(似乎是这种情况),则可以通过使用以下Merge重载来获得更好的性能:

IXLRange Merge(bool checkIntersect)
Run Code Online (Sandbox Code Playgroud)

并通过falseMerge当前正在使用的无参数重载true)通过checkIntersect。看起来,检查相交的ClosedXML实现具有O(N ^ 2)时间复杂度。

不久,将所有.Merge()调用替换为.Merge(false),执行时间将接近没有合并的调用。