【问题标题】:Fastest way to get an Excel Range of Rows获取 Excel 行范围的最快方法
【发布时间】:2012-09-11 05:17:26
【问题描述】:

在 VSTO C# 项目中,我想从一组行索引中获取一系列行。

行索引可以是例如“7,8,9,12,14”。

然后我想要范围“7:9,12,14”行。

我现在这样做:

Range rng1 = sheet.get_Range("A7:A9,A12,A14", Type.Missing);
rng1  = rng1.EntireRow;

但由于范围规范中的字符串处理,效率有点低。

sheet.Rows["7:9"]

有效,但我不能给这个

sheet.Rows["7:9,12,14"] // Fails

【问题讨论】:

  • 您可以合并各个范围,但这可能不会比使用连接地址的单个调用更有效。

标签: c# excel vsto office-interop


【解决方案1】:

试试这个:

Sheet.Range("7:9,12:12,14:14")

编辑:抱歉,如果在 C# 中使用 VSTO,它应该是:

sheet.get_Range("7:9,12:12,14:14", Type.Missing)

【讨论】:

  • 我试图展示的重要部分是您可以在范围方法中使用行号,而无需使用 .entirerow。 OP 已经有了 .get_range 所以我想希望他知道我的意思。键盘在大脑前齿轮。 ;)
  • 是的,这看起来像是我的答案,但我现在就试一试。
  • 抱歉,这似乎可行。但是对于某些 Range.Properties,您似乎仍然需要 EntireRow-Range。例如“OutlineLevel”、“Hidden”等
  • 请注意,.get_Range() 的参数有 255 个字符的限制。请参阅我对这个问题的回答,了解一些复制/粘贴代码来解决这个问题。
【解决方案2】:

这是您要查找的代码:

int startRow, endRow, startCol, endCol, row,col;
var singleData = new object[col];
var data = new object[row,col];
//For populating only a single row with 'n' no. of columns.
var startCell = (Range)worksheet.Cells[startRow, startCol];
startCell.Value2 = singleData;
//For 2d data, with 'n' no. of rows and columns.
var endCell = (Range)worksheet.Cells[endRow, endCol];
var writeRange = worksheet.Range[startCell, endCell];
writeRange.Value2 = data;

您可以拥有整个范围,无论是一维还是二维单元格数组。

此方法在遍历整个 Excel 工作表并在需要的地方和时间填充数据时特别有用。

【讨论】:

    【解决方案3】:

    我不是 C# 方面的专家,但 AFAIK 你必须像上面所做的那样使用 EntireRow。您正在寻找的字符串可以从.Address 属性中获得。例如

        private void button1_Click(object sender, EventArgs e)
        {
            Microsoft.Office.Interop.Excel.Application xlexcel;
            Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
            Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
            Microsoft.Office.Interop.Excel.Range xlRange;
    
            object misValue = System.Reflection.Missing.Value;
            xlexcel = new Excel.Application();
    
            xlWorkBook = xlexcel.Workbooks.Add();
    
            // Set Sheet 1 as the sheet you want to work with
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
    
            xlRange = xlWorkSheet.get_Range("A7:A9,A12,A14", misValue);
    
            MessageBox.Show(xlRange.EntireRow.Address);
    
            xlRange = xlWorkSheet.get_Range(xlRange.EntireRow.Address, misValue);
    
            MessageBox.Show(xlRange.Address);
        }
    

    所以你可以把上面写成

        private void button1_Click(object sender, EventArgs e)
        {
            Microsoft.Office.Interop.Excel.Application xlexcel;
            Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
            Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
            Microsoft.Office.Interop.Excel.Range xlRange;
    
            object misValue = System.Reflection.Missing.Value;
            xlexcel = new Excel.Application();
    
            xlWorkBook = xlexcel.Workbooks.Add();
    
            // Set Sheet 1 as the sheet you want to work with
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
    
            xlRange = xlWorkSheet.get_Range("$7:$9,$12:$12,$14:$14", misValue);
    
            MessageBox.Show(xlRange.Address);
        }
    

    查看部分

        xlRange = xlWorkSheet.get_Range("$7:$9,$12:$12,$14:$14", misValue);
    

    【讨论】:

      【解决方案4】:

      Reafidy's edited answer is a great start,但我想对其进行扩展,而不是发表评论。 sheet.get_Range(rangeselect) 比逐行快得多,但我还没有看到提到的一件事是 get_Range 参数有 255 个字符的限制。

      要绕过该限制,请照常构造一组范围,例如“8:8,10:13,14:55”,然后使用以下代码的变体:

      string rangeSelectPart;
      while (rangeSelect.Length >= 255)
      {
          rangeSelectPart = rangeSelect.Substring(0, rangeSelect.Substring(0,255).LastIndexOf(','));
          Range multiRangePart = sheet.get_Range(rangeSelectPart, Type.Missing);
      
          //do something with the range here using multiRangePart 
      
          rangeSelect= rangeSelect.Substring(rangeSelectPart.Length + 1);
      }
      Range multiRange = sheet.get_Range(rangeSelect, Type.Missing);
      // do the same something with the last part of the range using multiRange 
      // now that the remaining rows are described in less than 255 characters
      

      这将比对单个行执行操作要快得多,但在呈现大型非连续行集时也不会失败。


      请注意SutharMonil's answer is way faster IFF 在连续矩形范围内设置值。从 C# 到 excel 的瓶颈通常是通过 COM 对象的重复调用,这些对象在创建和更新时阻塞,他的回答很好地整合了调用。

      不幸的是,到目前为止,在我的测试中,尝试使用它来处理不是字符串类型的非字符串属性会导致类型错误。例如:

      object[,] colors;
      //use C# to set appropriate colors to each location in array...
      for(int i = 0; i < colors.get_Length(0); i++){
          for(int j = 0; j < colors.get_Length(1); j++){
              colors[i,j] = XlThemeColor.xlThemeColorAccent6;
          }
      }
      
      //below causes a type error
      formatRange.Interior.ThemeColor = color;
      

      如果我让它工作,我会尽量记住更新。


      最后对于重复操作设置Globals.ThisAddIn.Application.ScreenUpdating = false;,然后在完成后将其设置为true。如果没有这个,Excel 会在每组范围属性更新后停止更新屏幕,这会增加操作的大量时间。

      【讨论】:

        【解决方案5】:

        此代码根据条件为范围单元格分配颜色:

        using Microsoft.Office.Interop.Excel;
        
        (...)
        
        var excel = new Application { Visible = true };
        Workbook workbook = excel.Workbooks.Add(XlSheetType.xlWorksheet);
        Worksheet sheet = workbook.Sheets[1];
        
        
        var i = 2;
        foreach (Data d in this.Datos)
        {
            sheet.Cells[i, 1].Value = d.Fecha;
            sheet.Cells[i, 2].Value = d.Ubicacion;
            sheet.Cells[i, 3].Value = d.Lote;
            sheet.Cells[i, 4].Value = d.ArticuloId;
            sheet.Cells[i, 5].Value = d.Articulo;
            sheet.Cells[i, 6].Value = d.ColorId;
            sheet.Cells[i, 7].Value = d.Color;
            sheet.Cells[i, 8].Value = d.StockOriginal;
            sheet.Cells[i, 9].Value = d.Diferencia;
            sheet.Cells[i, 10].Value = d.StockFinal;
            if (d.BackGroundColor == "#FFA061")
                sheet.Range[sheet.Cells[i, 1], sheet.Cells[i, 10]].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.FromArgb(255, 160, 97));
            i++;
        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-01
          • 2022-08-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多