如何找到隐藏在 Excel 中的一组不连续的非空单元格
How to find an uncontiguous set of non-empty cells that are hidden in Excel
我正在使用 C# 作为 Excel 插件。
我需要在隐藏行中找到所有非空单元格。这些单元格是不连续的,不遵循某种模式。这是一个例子:
我试过使用 Range.SpecialCells :
Range rangeToSearch = Excel.ActiveSheet.Rows[row].Cells;
try
{
Range rangeMatch = rangeToSearch.SpecialCells(XlCellType.xlCellTypeFormulas | XlCellType.xlCellTypeValues)
// Loop over rangeMatch
}
catch (COMException)
{
// no matches
}
和Range.Find:
Range rangeToSearch = Excel.ActiveSheet.Rows[row].Cells;
Range rangeMatch = rangeToSearch.Find("*", Type.Missing, XlFindLookIn.xlValues, XlLookAt.xlPart, XlSearchOrder.xlByColumns);
// Check if null then loop using FindNext
这些方法适用于可见行,但不适用于隐藏行。
我知道 "trick" 问题的唯一方法是使用 Worksheet.UsedRange,但我认为这根本不可靠,而且它也会得到空单元格。
是否有一种简洁高效的方法来实现我想要做的事情?
您可以通过多种方式做到这一点。我将为您提供一种将单元格从一组非连续单元格(在 Excel 模型中称为区域)输出到列表
的方法
static Excel.Range GetCellsWithValues(Excel.Range row)
{
Excel.Range r = null;
// Cut out unneccessary calcs by using only the intersection of the Row with the UsedRange
Excel.Range usedRow = row.Application.Intersect(row, row.Worksheet.UsedRange);
if (usedRow != null)
{
foreach (Excel.Range cell in usedRow)
if (cell.Value2 != null) //if non-empty unite to r
r = (r == null) ? cell : row.Application.Union(r, cell);
}
return r; // a non-contiguous Range will have Areas with blocks of contiguous Ranges
}
static List<Excel.Range> GetCellListFromAreas(Excel.Range r)
{ // this will unwrap the cells from non-contiguous range into a List
// choose other collections for your use
List<Excel.Range> cellList = new List<Excel.Range>();
Excel.Areas areas = r?.Areas;
if (areas != null)
{
// Unwrap the Areas (blocks of contiguous cells)
foreach (Excel.Range area in areas)
foreach (Excel.Range cell in area)
cellList.Add(cell); // add each cell in each contiguous block
}
return cellList;
}
这样调用:
List<Excel.Range> cellList = GetCellListFromAreas(GetCellsWithValues(Excel.ActiveSheet.Rows[row]));
尽管我们更愿意您通过 Sheet 名称而不是 ActiveSheet 明确限定工作表。
另请注意,您可以省去 Excel 范围(单元格)的 Collection/List,并将值放在数组或其他任何内容中....
很明显,您可以第一次直接放入一个列表,然后将 Union 的步骤切割成范围,而不是展开区域。所以喜欢:
static List<Excel.Range> GetCellListWithValues(Excel.Range row)
{
List<Excel.Range> cellList = new List<Excel.Range>();
Excel.Range r = null;
Excel.Range usedRow = row.Application.Intersect(row, row.Worksheet.UsedRange);
if (usedRow != null)
{
foreach (Excel.Range cell in usedRow)
if (cell.Value2 != null)
cellList.Add(cell);
}
return cellList;
}
我正在使用 C# 作为 Excel 插件。
我需要在隐藏行中找到所有非空单元格。这些单元格是不连续的,不遵循某种模式。这是一个例子:
我试过使用 Range.SpecialCells :
Range rangeToSearch = Excel.ActiveSheet.Rows[row].Cells;
try
{
Range rangeMatch = rangeToSearch.SpecialCells(XlCellType.xlCellTypeFormulas | XlCellType.xlCellTypeValues)
// Loop over rangeMatch
}
catch (COMException)
{
// no matches
}
和Range.Find:
Range rangeToSearch = Excel.ActiveSheet.Rows[row].Cells;
Range rangeMatch = rangeToSearch.Find("*", Type.Missing, XlFindLookIn.xlValues, XlLookAt.xlPart, XlSearchOrder.xlByColumns);
// Check if null then loop using FindNext
这些方法适用于可见行,但不适用于隐藏行。 我知道 "trick" 问题的唯一方法是使用 Worksheet.UsedRange,但我认为这根本不可靠,而且它也会得到空单元格。
是否有一种简洁高效的方法来实现我想要做的事情?
您可以通过多种方式做到这一点。我将为您提供一种将单元格从一组非连续单元格(在 Excel 模型中称为区域)输出到列表
的方法 static Excel.Range GetCellsWithValues(Excel.Range row)
{
Excel.Range r = null;
// Cut out unneccessary calcs by using only the intersection of the Row with the UsedRange
Excel.Range usedRow = row.Application.Intersect(row, row.Worksheet.UsedRange);
if (usedRow != null)
{
foreach (Excel.Range cell in usedRow)
if (cell.Value2 != null) //if non-empty unite to r
r = (r == null) ? cell : row.Application.Union(r, cell);
}
return r; // a non-contiguous Range will have Areas with blocks of contiguous Ranges
}
static List<Excel.Range> GetCellListFromAreas(Excel.Range r)
{ // this will unwrap the cells from non-contiguous range into a List
// choose other collections for your use
List<Excel.Range> cellList = new List<Excel.Range>();
Excel.Areas areas = r?.Areas;
if (areas != null)
{
// Unwrap the Areas (blocks of contiguous cells)
foreach (Excel.Range area in areas)
foreach (Excel.Range cell in area)
cellList.Add(cell); // add each cell in each contiguous block
}
return cellList;
}
这样调用:
List<Excel.Range> cellList = GetCellListFromAreas(GetCellsWithValues(Excel.ActiveSheet.Rows[row]));
尽管我们更愿意您通过 Sheet 名称而不是 ActiveSheet 明确限定工作表。
另请注意,您可以省去 Excel 范围(单元格)的 Collection/List,并将值放在数组或其他任何内容中....
很明显,您可以第一次直接放入一个列表,然后将 Union 的步骤切割成范围,而不是展开区域。所以喜欢:
static List<Excel.Range> GetCellListWithValues(Excel.Range row)
{
List<Excel.Range> cellList = new List<Excel.Range>();
Excel.Range r = null;
Excel.Range usedRow = row.Application.Intersect(row, row.Worksheet.UsedRange);
if (usedRow != null)
{
foreach (Excel.Range cell in usedRow)
if (cell.Value2 != null)
cellList.Add(cell);
}
return cellList;
}