如何快速阅读c#中的Excel电子表格

如何快速阅读c#中的Excel电子表格,c#,excel,interop,C#,Excel,Interop,我正在使用Microsoft.Office.Interop.Excel读取在内存中打开的电子表格 gXlWs = (Microsoft.Office.Interop.Excel.Worksheet)gXlApp.ActiveWorkbook.ActiveSheet; int NumCols = 7; string[] Fields = new string[NumCols]; string input = null; int NumRow = 2; while (Convert.ToString

我正在使用Microsoft.Office.Interop.Excel读取在内存中打开的电子表格

gXlWs = (Microsoft.Office.Interop.Excel.Worksheet)gXlApp.ActiveWorkbook.ActiveSheet;
int NumCols = 7;
string[] Fields = new string[NumCols];
string input = null;
int NumRow = 2;
while (Convert.ToString(((Microsoft.Office.Interop.Excel.Range)gXlWs.Cells[NumRow, 1]).Value2) != null)
{
    for (int c = 1; c <= NumCols; c++)
    {
        Fields[c-1] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)gXlWs.Cells[NumRow, c]).Value2);
    }
    NumRow++;

    //Do my other processing
}
gXlWs=(Microsoft.Office.Interop.Excel.Worksheet)gXlApp.ActiveWorkbook.ActiveSheet;
int NumCols=7;
字符串[]字段=新字符串[NumCols];
字符串输入=null;
int NumRow=2;
while(Convert.ToString(((Microsoft.Office.Interop.Excel.Range)gXlWs.Cells[NumRow,1]).Value2)!=null)
{

对于(int c=1;c有几个选项-都涉及一些附加库:

  • (MS提供的免费库)可用于读取/修改.xlsx的内容,以便您可以随心所欲地使用它

  • 一些(商业)第三方库带有网格控件,允许您在应用程序中对excel文件进行更多操作(如Winforms/WPF/ASP.NET等)


    • 我想这不是“减速”的根源

      实际上,检索单元格值非常慢

      我认为这种转换是没有必要的:

      (Microsoft.Office.Interop.Excel.Range)gXlWs
      
      没有这一点,它应该会起作用

      你可以直接问:

      gXlWs.Cells[NumRow, 1].Value != null
      
      尝试将整个范围或至少整行移动到对象矩阵,并使用它而不是范围本身

      我不确定“转换”是否有效。我能做些什么吗 这么快

      你怎么会相信这一点?我向你保证,Convert.ToString()是你发布的代码中最有效的方法。你的问题是你在excel文档中循环处理180000条记录

      您可以将工作拆分,因为您知道这是一项繁琐的工作


      为什么要将Value2完全转换为字符串?

      嗨,我找到了一种更快的方法

      最好使用“get_range”一次性读取整个数据。这会将数据加载到内存中,我可以像普通数组一样循环读取

      Microsoft.Office.Interop.Excel.Range range = gXlWs.get_Range("A1", "F188000");
      object[,] values = (object[,])range.Value2;
      int NumRow=1;
      while (NumRow < values.GetLength(0))
      {
          for (int c = 1; c <= NumCols; c++)
          {
              Fields[c - 1] = Convert.ToString(values[NumRow, c]);
          }
          NumRow++;
      }
      
      Microsoft.Office.Interop.Excel.Range Range=gXlWs.get_Range(“A1”、“F188000”);
      对象[,]值=(对象[,])范围。值2;
      int NumRow=1;
      while(NumRow对于(int c=1;c使用
      OleDB
      方法

      string con =
        @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\temp\test.xls;" + 
        @"Extended Properties='Excel 8.0;HDR=Yes;'";    
      using(OleDbConnection connection = new OleDbConnection(con))
      {
          connection.Open();
          OleDbCommand command = new OleDbCommand("select * from [Sheet1$]", connection); 
          using(OleDbDataReader dr = command.ExecuteReader())
          {
               while(dr.Read())
               {
                   var row1Col0 = dr[0];
                   Console.WriteLine(row1Col0);
               }
          }
      }
      

      但是它可能会更快吗?是的,这就是我提出它的原因,它访问文件时不使用Excel,也不需要COM/Interopb的开销,但我想访问一个在内存中打开的电子表格。这样我就可以以交互方式更改它,然后再次运行代码。我想你建议的是从磁盘读取保存的文件,还是我错?@ManInMoon-那么你必须接受读取内存中打开的文件会有性能问题。你没有指出读取180000条记录需要多长时间。虽然你说得很好,但这些都不会提高他的代码速度。转换不会减慢他的代码。你会读取整个范围吗在(一个180000,7的矩阵)中更快?我已经看到了一个带有.get_range的引用,但我不确定您将如何使用它-任何线索都会很好。@manimoon-它不会更快,它会更有意义,您仍然会受到文件读取方式的限制。它可能更快。如果每次“读取”都有开销的话从打开的工作簿中。我只是不知道如何使用它。好吧,你上面展示的解决方案似乎就是我建议的。你同意吗?@ManInMoon-解释你所说的话的意思。你确实理解你的字符串[]只能读取7个字符串,对吗?因此,如果您读取180000条记录,那么您的代码就没有多大意义。我在其中放置了“//执行其他处理”我处理每一行另外,您知道自己是IO绑定还是CPU绑定吗?您可能可以在多核/CPU计算机上并行化此代码。您也可以使用ADO.NET在Excel电子表格上执行SQL请求。这样可以避免执行While循环。请参见NumRow++的含义。NumRow++与NumRow=NumRow+1相同;您使用了“F188000”。在我的情况下,我不知道会有多少行。我该怎么办?可以使用
      Array.Copy()加快转换速度
      。请参见。这当然取决于单元格内容。它们是数字还是字符串?@user728630获取数据范围的另一种方法是:
      Excel.Excel.range DataRange=ExcelWorksheet.UsedRange;object[,]ExcelRangeValues=(object[,])DataRange.Value2;var RowCount=DataRange.Rows.Count+1;var ColumnCount=DataRange.Columns.Count+1;