【问题标题】:how to speed up excel interop process in c#如何在 C# 中加速 excel 互操作过程
【发布时间】:2023-03-16 18:21:01
【问题描述】:

这是我的代码。请朋友们帮帮我。此代码可以将任何文本文档转换为 excel。但是在大型文档中,它需要很多时间。我该如何解决这个问题?

Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
    Excel.Workbook xlWorkBook;
    Excel.Worksheet xlWorkSheet;
    xlApp.ScreenUpdating=false;
    object misValue = System.Reflection.Missing.Value;
    xlWorkBook = xlApp.Workbooks.Add(misValue);
    xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
        FileInfo theSourceFile = new FileInfo(@"" + file); 
        StreamReader reader = theSourceFile.OpenText();
        int raw = 1; int column = 1; 
        String text = "";
          do
             {
               text = reader.ReadLine();
               if (text != null)
                  {
                    string[] ss = text.Split('|');
                    int index = 0; double result;
                    //WRITING DATA LINES
                    for (int i = 1; i < ss.Length; i++)
                      {
                       if (!ss[index].Contains('.')) //recognising strings by filtering currency values using "." sign (decimal point)
                          {
                           xlWorkSheet.Cells[raw, column] = ss[index];
                           index++; column++; 
                           }

                        else if (double.TryParse(ss[index], out result))//writing and formating currency values
                           {   xlWorkSheet.Cells[raw, column] = String.Format("{0:n}", result);
                                index++; column++; 
                            }
                         else
                            {
                              xlWorkSheet.Cells[raw, column] = ss[index];//writing "." containing non currcy values
                              index++; column++;
                            }
                      }
                  }
                    raw++; column = 1;
          } while (text != null);
            xlWorkSheet.Columns.AutoFit();
           xlWorkBook.SaveAs(@"" + textBox6.Text + @"\" + line_dup + ".xls", Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
     try
        {
          Marshal.ReleaseComObject(xlWorkSheet);
          Marshal.ReleaseComObject(xlWorkBook);
          Marshal.ReleaseComObject(xlApp);
          xlWorkBook.Close(true, misValue, misValue);
          xlApp.Quit();
        }
    catch (Exception) { }
          foreach (Process clsProcess in Process.GetProcesses())
         if (clsProcess.ProcessName.Equals("EXCEL"))  //KILLING EXCELL Process
             clsProcess.Kill();

          richTextBox1.Text += "\n" + line + "\t" + "excell file created";

        MessageBox.Show("Excel files created , you can find the files in @" + textBox6.Text + line_dup + ".xls");
     foreach (Process clsProcess in Process.GetProcesses())
       if (clsProcess.ProcessName.Equals("EXCEL"))  //KILLING EXCELL Process
         clsProcess.Kill();

【问题讨论】:

  • 这个属于Code Review
  • @bansi,请阅读Guide to Code Review for Stack Overflow users。特别是如果代码被破坏,它不适合代码审查。由于大括号似乎不匹配或存在一些非常奇怪的缩进问题,因此这段代码看起来很糟糕
  • @holroy 根据 OP,代码正在运行并需要优化。代码审查的完美候选人。
  • 快速粘贴到 VS 中发现没有丢失大括号。只要代码起作用(OP 声称它确实如此),它就应该成为代码审查的主题
  • 查看代码时,我看到 8 个左大括号和 12 个右大括号。要么我是盲人,要么这个代码被破坏了。

标签: c# excel


【解决方案1】:

在每个单元格中放入数据真的很慢。您应该尝试对行、列甚至整个区域使用批量插入方法。 插入大约 500% 增加了大约 500%。 20k 行和 10 列。 唯一的缺陷是您必须在内存中创建对象,而不是流式传输。

【讨论】:

  • 是的。我正在逐个单元格写入数据,因为我必须检查每个值是字符串还是十进制。
  • 是否有任何选项可以为程序分配内存?
  • 你仍然可以检查每个单元格,只需使用 get_Range 写入一个数组。见WriteArraySpeedUpDumping
【解决方案2】:

使用对象数组,这是一些工作控制台应用程序。

打印 100,000 行可能需要大约 2 秒。

        //here's some class I used
        public class Movie
        {
            public int MovieID { get; set; }
            public string MovieName { get; set; }

            public System.Data.DataTable MovieListDataTable()
            {
                System.Data.DataTable dataTable = new System.Data.DataTable();
                dataTable.Columns.Add("MovieID", typeof(int));
                dataTable.Columns.Add("MovieName", typeof(string));

                for (int x = 0; x <= 100000; x++)
                {
                    dataTable.Rows.Add(new object[] { x, "Star Wars " + x.ToString() });
                }

                return dataTable;
            }

            public String GetExcelColumnName(int columnIndex)
            {
                if (columnIndex < 0)
                {
                    throw new ArgumentOutOfRangeException("columnIndex: " + columnIndex);
                }
                Stack<char> stack = new Stack<char>();
                while (columnIndex >= 0)
                {
                    stack.Push((char)('A' + (columnIndex % 26)));
                    columnIndex = (columnIndex / 26) - 1;
                }
                return new String(stack.ToArray());
            }
        }

        // then inside the MAIN
        static void Main(string[] args)
        {
            Application myExcelApp = new Application();
            _Worksheet myExcelWorkSheet; //= new _Worksheet();

            Movie movie = new Movie();

            //ensure that you have a Book1.xlsx the same path as this program.
            string ExcelFilePath = AppDomain.CurrentDomain.BaseDirectory + "Book1.xlsx";
            string letterStart = "";
            string letterEnd = "";

            int row = 0, col = 0;

            var toPrint = movie.MovieListDataTable();
            row = toPrint.Rows.Count;
            col = toPrint.Columns.Count;

            letterStart = movie.GetExcelColumnName(0);
            letterEnd = movie.GetExcelColumnName(col - 1);

            Workbook myExcelWorkBook = myExcelApp.Workbooks.Open(ExcelFilePath);
            myExcelWorkSheet = myExcelWorkBook.Worksheets[1];

            var dataBulk = new object[row, movie.GetType().GetProperties().Count()];

            for (int printx = 0; printx < row; printx++)
            {
                for (int printy = 0; printy < col; printy++)
                {
                    dataBulk[printx, printy] = toPrint.Rows[printx][printy].ToString();
                }
            }

            //print start cell range
            Range startCellRange = myExcelWorkSheet.Range[letterStart + 1.ToString(), letterStart + 1.ToString()];
            //print end cell range
            Range endCellRange = myExcelWorkSheet.Range[letterEnd + row.ToString(), letterEnd + row.ToString().ToString()];
            //full write cell range
            Range writeRange = myExcelWorkSheet.Range[startCellRange, endCellRange];

            //data to print within range
            writeRange.Value2 = dataBulk;

            myExcelWorkBook.Save();
            myExcelWorkBook.Close();

            Marshal.ReleaseComObject(myExcelWorkBook);
            Marshal.ReleaseComObject(myExcelWorkSheet);
            Marshal.ReleaseComObject(myExcelApp);
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-22
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多