获取非连续范围的值数组

我想能够获得工作表上可见单元格的数组值。 但是, Range.Value2属性似乎只适用于连续的单元格。

什么将是一个有效的方法获取可见的单元格值multidimensional array? 也许我们可以在Range.Areas做一些循环?

如果您查看下面的代码示例,您将看到.Value2属性仅返回Range第一个Area的值。

示例输出是(您将看到可见值缺less最后两行):

 All Values: String1 String2 String3 String4 String5 String6 String7 String8 String9 String10 String11 String12 String13 String14 String15 String16 String17 String18 String19 String20 String21 String22 String23 String24 String25 Visible Values: String1 String2 String3 String4 String6 String7 String8 String9 

_

  public static void RunTest() { SetData(); HideRowsAndColumns(); Excel.Application excelApp = Globals.ThisAddIn.Application; Excel.Worksheet sht = excelApp.ActiveSheet; var usedRange = sht.UsedRange; var visibleUsedRange = usedRange.SpecialCells(XlCellType.xlCellTypeVisible); var usedRangeVals = (object[,])usedRange.Value2; var visibleUsedRangeVals = (object[,]) visibleUsedRange.Value2; //this doesn't get the full set of values because Value2 does not work with non-contiguous ranges string s = "All Values:\n\n" + ArrayToString(usedRangeVals) + "\n\nVisible Values:\n\n" + ArrayToString(visibleUsedRangeVals); MessageBox.Show(s); } private static string ArrayToString(object[,] vals) { int dim1Start = vals.GetLowerBound(0); //Excel Interop will return index-1 based arrays instead of index-0 based int dim1End = vals.GetUpperBound(0); int dim2Start = vals.GetLowerBound(1); int dim2End = vals.GetUpperBound(1); var sb = new StringBuilder(); for (int i = dim1Start; i <= dim1End; i++) { for (int j = dim2Start; j <= dim2End; j++) { sb.Append(vals[i, j]); if (j != dim2End) sb.Append("\t"); } sb.Append("\n"); } return sb.ToString(); } private static void SetData() { const int rows = 5; const int cols = 5; var a = new string[rows, cols]; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) a[i, j] = "String" + (i * cols + j + 1); Excel.Application excelApp = Globals.ThisAddIn.Application; Excel.Worksheet sht = excelApp.ActiveSheet; Excel.Range rng = sht.Range[sht.Cells[1, 1], sht.Cells[rows, cols]]; rng.Value2 = a; } private static void HideRowsAndColumns() { Excel.Application excelApp = Globals.ThisAddIn.Application; Excel.Worksheet sht = excelApp.ActiveSheet; var row = (Excel.Range) sht.Rows[3]; row.Hidden = true; var col = (Excel.Range) sht.Columns[5]; col.Hidden = true; } 

既然你不想使用上面给出的链接中提到的任何方法,也不想将数据复制到新的工作表中,那么这是我能想到的唯一方法。

逻辑

  1. 打开工作簿为只读。 如果您正在使用具有隐藏行/列的活动工作表,请创build一个副本 (隐藏那些行/列的Excel文件的副本 ,然后使用该副本。
  2. 查找工作表上的最后一行/列
  3. 循环遍历工作表的行/列,并删除不可见的行/列
  4. 你现在剩下一个连续的范围。 将其复制到数组中
  5. closuresExcel文件而不保存。

注意 :我已经向您展示了循环遍历行的一个示例。 你可以为列做类似的事情

 int _lastRow = xlWorkSheet.Cells[xlWorkSheet.Rows.Count, 1].End[Microsoft.Office.Interop.Excel.XlDirection.xlUp].Row; for (int i = 1; i <= _lastRow; i++) { if (xlWorkSheet.Cells[i, 1].Entirerow.Hidden == true) xlWorkSheet.Cells[i, 1].EntireRow.Delete(Microsoft.Office.Interop.Excel.XlDirection.xlUp); ; } 

编辑

我将此作为一个单独的部分添加,而不是删除上面的代码,因为它可能有助于未来的访问者。

显然,OP是好的想法,将可见单元格复制到新的工作表,然后使用.Value2将数据存储到数组中,如注释中所示。

 object misValue = System.Reflection.Missing.Value; xlNewWorkSheet = xlexcel.Worksheets.Add(misValue, misValue, misValue, misValue); Excel.Range MyRange = xlWorkSheet.UsedRange.SpecialCells(Excel.XlCellType.xlCellTypeVisible,misValue); MyRange.Copy(xlNewWorkSheet.get_Range("A1", "A1"));