获取非连续范围的值数组
Get Array of Values for Non-Contiguous Range
我希望能够仅获取工作表上可见单元格的值数组。但是,Range.Value2
属性 似乎只适用于连续的单元格。
将可见单元格值放入多维数组的有效方法是什么?也许我们可以对 Range.Areas
?
进行某种循环
如果您查看下面的示例代码,您将看到 .Value2
属性 仅 returns Range
中第一个 Area
的值=].
示例输出是(您会看到可见值缺少最后两行):
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;
}
既然你不想使用我上面给你的链接中提到的任何方法,你也不想将数据复制到新作品中sheet那么这是唯一的方法我能想到。
逻辑
- 以只读方式打开工作簿。如果您正在使用隐藏了 rows/columns 的活动 sheet,那么 create a copy(excel 文件的那些 rows/columns 被隐藏,然后使用该副本。
- 找到作品的最后一个 row/columnsheet
- 遍历作品的rows/Columnssheet并删除不可见的rows/columns
- 您现在只剩下一个连续的范围。将其复制到数组
- 关闭 Excel 文件而不保存。
注意:我已经向您展示了一个遍历行的示例。您可以对列做类似的事情
代码
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 可以将可见单元格复制到新作品sheet,然后按照评论中的建议使用.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"));
我希望能够仅获取工作表上可见单元格的值数组。但是,Range.Value2
属性 似乎只适用于连续的单元格。
将可见单元格值放入多维数组的有效方法是什么?也许我们可以对 Range.Areas
?
如果您查看下面的示例代码,您将看到 .Value2
属性 仅 returns Range
中第一个 Area
的值=].
示例输出是(您会看到可见值缺少最后两行):
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;
}
既然你不想使用我上面给你的链接中提到的任何方法,你也不想将数据复制到新作品中sheet那么这是唯一的方法我能想到。
逻辑
- 以只读方式打开工作簿。如果您正在使用隐藏了 rows/columns 的活动 sheet,那么 create a copy(excel 文件的那些 rows/columns 被隐藏,然后使用该副本。
- 找到作品的最后一个 row/columnsheet
- 遍历作品的rows/Columnssheet并删除不可见的rows/columns
- 您现在只剩下一个连续的范围。将其复制到数组
- 关闭 Excel 文件而不保存。
注意:我已经向您展示了一个遍历行的示例。您可以对列做类似的事情
代码
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 可以将可见单元格复制到新作品sheet,然后按照评论中的建议使用.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"));