如何提高我编写的 Excel 到 PDF 转换器的性能?

How do I improve the performance of this Excel to PDF converter I wrote?


选定的视图行数据 -> Excel -> PDF

工具: Excel com interop

这是我的程序的要点,

  1. 它从 90,000 行或大约该估计值的 MASSIVE 数据库中读取数据。 (只有那些从数据网格视图中选择的行,虽然目标是批量转换)

  2. 将它们分配给变量,变量被写入预先格式化的excel文件的单元格中(因为它的单元格排列,字体大小,颜色等,不可避免)。

  3. 最后我将 excel 文件转换成 PDF,我的主要 objective.

不幸的是,我的程序只需要大约一个小时来处理 700 个项目,但我不确定它是否是我的机器,一个 i3、2GB ram 笔记本电脑单元。 下面的代码仅转换来自 datagridview 的选定记录,我将其用作测试大型数据集的临时权宜之计。

我的问题是,如何提高它的性能?我写的代码已经相对简单并且可以运行,我不知道去哪里看看是什么在减慢它的速度以及如何提高写入速度。 这些是性能命中的嫌疑人:

  1. 数据是从 datagridview 读取的,尽管该视图由 Access 数据库支持,但单独读取 datagridview 应该不会影响性能。
  2. 写入Excel可能需要一些时间,我截断了一段代码以缩短我在 Whosebug 的代码输入。单元写入可能会占用一些资源。
  3. Excel 到 pdf 基本上是 1 行代码,所以我不确定是否有成功,或者这里是否有任何改进。
  4. 可能在下面的代码块中循环遍历 datagridview 到 for 循环的当前索引时命中。
  5. 我的资源监视器似乎检测到 EXCEL.exe 的多个签名正在处理和终止,根据代码这应该是正常的,但是因为 none 其中的逗留时间比他们应该的要长。

非常感谢在此问题上提供的帮助!


if (DGVmain.RowCount > 0)
{
    if (DGVmain.SelectedCells.Count <= 0)
    {
        return;
    }
    //Source
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.Filter = "Excel Files|*.xls;*.xlsx";
    openFileDialog.ShowDialog();
    lblSuccess.Text = openFileDialog.FileName;
    lblPathings = Path.ChangeExtension(openFileDialog.FileName, null);
    int count = DGVmain.SelectedRows.Count;
    int ballast = 0;
    foreach (DataGridViewRow selectedRow in DGVmain.SelectedRows)
    {
        //Drag
        if (lblSuccess.Text == null)
            return;
        //Drag
        if (lblSuccess.Text == null)
            return;
        string drags = Convert.ToString(selectedRow.Cells[0].Value);
        string dragsy = Convert.ToString(selectedRow.Cells[1].Value);
        string drag = Convert.ToString(selectedRow.Cells[2].Value);
        string drag2 = Convert.ToString(selectedRow.Cells[3].Value);
        string drag3 = Convert.ToString(selectedRow.Cells[4].Value);
        string drag4 = Convert.ToString(selectedRow.Cells[5].Value);
        string drag5 = Convert.ToString(selectedRow.Cells[6].Value);
        string drag6 = Convert.ToString(selectedRow.Cells[7].Value);
        string drag7 = Convert.ToString(selectedRow.Cells[8].Value);
        \trimmed this part down for Whosebug
        Persona = drag;
        generateID();
        //Initialize the Excel File
        try
        {
            ballast++;
            lblItem.Text = "Item #" + ballast;
            Xls = new Excel.Application();
            WBs = Xls.Workbooks;
            WB = WBs.Open(lblSuccess.Text, 0, false, 5, "", "", true,
                XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
            if (WB == null)
            {
                Xls.Quit();
                Xls = null;
                WB = null;
                return;
            }
            SS = WB.Worksheets;
            WS = SS.get_Item(1);
            //Tin Algorithm
            string input = drag23;
            string digit1 = "0";
            string digit2 = "0";
            string digit3 = "0";
            string digit4 = "0";
            StringBuilder sb = new StringBuilder();
            StringBuilder partBuilder = new StringBuilder();
            int partsSplitted = 0;
            for (int i = 1; i <= input.Length; i++)
            {
                partBuilder.Append(input[i - 1]);
                if (i % 3 == 0 && partsSplitted <= 3)
                {
                    sb.Append(' ');
                    sb.Append(partBuilder.ToString());
                    partBuilder = new StringBuilder();
                    partsSplitted++;
                }
            }
            sb.Append(partBuilder.ToString());
            string formatted = sb.ToString().TrimStart();
            string[] formatCollection = formatted.Split(' ');
            digit1 = formatCollection[0];
            digit2 = formatCollection[1];
            digit3 = formatCollection[2];
            digit4 = formatCollection[3];
            //Names
            WS.Cells[14, 2] = dragsy + ",  " + drag + drag2;
            // Write to cells here
            WS.Cells[8, 8] = "2016";
            WS.Cells[8, 29] = drag24;
            WS.Cells[8, 34] = drag25;
            WS.Cells[11, 9] = digit1;
            WS.Cells[11, 12] = digit2;

            //Trimmed for Whosebug!

            WB.Save();
            try
            {
                WB.ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, finalformat);

            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Error occurred: " + ex, "General error exception");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Write Excel: " + ex.Message);
        }
        finally
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            WB.Close();
            Xls.Quit();
            releaseObject(SS);
            releaseObject(WS);
            releaseObject(WBs);
            releaseObject(WB);
            releaseObject(Xls);
        }
    }
}

这是拍号,我不知道这些加载的模块是什么或它们做了什么。不记得之前包括 them/noticing 它们。

新话题link:

我看到从第一次保存到最终创建 PDF 大约需要 60 秒。如果您要保存和导出 4 次,这似乎是一个合理的时间跨度。如果您的性能问题是从 foreach 循环开始到第一次保存的 ~80 秒,我猜您的问题出在这些行上:

WS.Cells[14, 2] = dragsy + ",  " + drag + drag2;
// Write to cells here
WS.Cells[8, 8] = "2016";
WS.Cells[8, 29] = drag24;
WS.Cells[8, 34] = drag25;
WS.Cells[11, 9] = digit1;
WS.Cells[11, 12] = digit2;

//Trimmed for Whosebug!

TaW所述:

Moving data to Excel is most likely the culprit. Not sure if there is a way to bulk insert the data.

好吧,有一种方法可以批量插入,但是您的代码赢得了 "Most Unmanageable Code of the Year" 奖。所以,我不确定您将如何实现它,但您会希望使用 RangeValue 而不是 Cell。在您的情况下,它可能看起来像...

string[,] values = new string[15, 35];  //or objects
values[7, 7] = "2016";
values[7, 28] = drag24;
values[7, 33] = drag25;
values[10, 8] = digit1;
values[10, 11] = digit2;
// etc.

Range range = WS.Range[WS.Cells[1, 1], WS.Cells[15, 35]];
range.Value = values;

如果您想使用数字,也可以使用 object 而不是 string。如果您真的只使用字符串,也可以将 Value 替换为 Text