如何查找Excel中隐藏的不连续的非空单元格集

时间:2019-03-05 09:21:57

标签: c# excel visual-studio excel-interop

我正在将C#用于Excel插件。
我需要在隐藏行中找到所有非空单元格。这些单元格是不连续的,并且不遵循模式。这是一个示例:

enter image description here

我尝试使用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

这些方法只适用于可见行,但不适用于隐藏行。 我知道“欺骗”问题的唯一方法是使用Worksheet.UsedRange,但是我认为这根本不可靠,而且它也会得到空单元格。

是否有一种干净有效的方法来实现我要完成的任务?

1 个答案:

答案 0 :(得分:1)

您可以通过多种方式执行此操作。我将为您提供一种方法,可将单元格从一组不连续的单元格(在Excel模型中称为Areas)输出到一个列表中

    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]));

尽管我们更希望您通过图纸名称而不是ActiveSheet明确限定图纸。

还请注意,您可以省去Excel范围(单元格)的集合/列表,并将值放入数组或其他任何内容中。...

因此,很明显,您可以第一次直接进入列表,然后将Union的步骤切入范围,而不是展开Areas。就像这样:

    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;
    }