7

可能重复:
如何获取excel工作表中占用单元格的范围

我试图在 Excel 工作表中找到最后使用的行。为此,我正在使用以下代码:

int lastUsedRow = currentWS.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell,Type.Missing).Row;

大多数情况下它工作正常,但有时 Excel 认为工作表中的行数比假设的要多。

Fx:如果我将包含 12 行的 sheet1 中的数据复制到空 sheet2,然后通过右键单击并按“删除...”删除 sheet2 中的所有数据,然后将包含 5 行的 sheet3 中的数据复制到 sheet2,然后lastUsedRow 会给我 12 的值,应该是 5。

在此处输入图像描述 上面的图像示例假设我的值为 22 作为行数,但我会得到 634。请注意右侧的滚动条。

即使我刚刚删除了所有单元格,Excel 似乎也认为某些单元格已被填充,然后将行数较少的新数据复制到工作表中。

有什么方法可以“调整”工作表中数据视图的大小,以便我获得正确数量的已使用单元格,或者以另一种方式查找最后使用的行数?

谢谢。

4

3 回答 3

12

编辑:新解决方案

由于乔提供了正确的代码来获取最后使用的行。

Worksheet.UsedRange.Row + Worksheet.UsedRange.Rows.Count - 1 

并使用以下命令清除内容和格式

Selection.Delete
Selection.ClearFormats

这应该工作;)

于 2012-09-05T08:36:24.770 回答
5

要获取工作表中最后使用的行,您可以使用:

Worksheet.UsedRange.Row + Worksheet.UsedRange.Rows.Count - 1

注意:

  • UsedRange 不一定从第一行开始 - 第一行可能为空。

  • UsedRange 包括包含格式的单元格,即使它们的内容为空。我怀疑这就是为什么您看到的值比您预期的要大。您需要从空单元格中删除格式和数据。

我不确定如何以编程方式删除单元格上的格式

您可以使用Range.ClearFormats清除格式,或Range.Clear清除所有内容。一般来说,如果您不确定如何在 Excel 中以编程方式执行某些操作,请尝试录制宏,手动执行,然后检查生成的宏。

于 2012-09-05T09:09:07.533 回答
4

这是我使用的代码:

public static string GetMinimalUsedRangeAddress(Excel.Worksheet sheet)
{
    string address = String.Empty;
    try
    {
        int rowMax = 0;
        int colMax = 0;

        Excel.Range usedRange = sheet.UsedRange;
        Excel.Range lastCell = usedRange.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
        int lastRow = lastCell.Row;
        int lastCol = lastCell.Column;
        int rowMin = lastRow + 1;
        int colMin = lastCol + 1;

        int rr = usedRange.Rows.Count;
        int cc = usedRange.Columns.Count;
        for (int r = 1; r <= rr; r++)
        {
            for (int c = 1; c <= cc; c++)
            {
                Excel.Range cell = usedRange.Cells[r, c] as Excel.Range;
                if (cell != null && cell.Value != null && !String.IsNullOrEmpty(cell.Value.ToString()))
                {
                    if (cell.Row > rowMax)
                        rowMax = cell.Row;
                    if (cell.Column > colMax)
                        colMax = cell.Column;
                    if (cell.Row < rowMin)
                        rowMin = cell.Row;
                    if (cell.Column < colMin)
                        colMin = cell.Column;
                }
                MRCO(cell);
            }
        }

        if (!(rowMax == 0 || colMax == 0 || rowMin == lastRow + 1 || colMin == lastCol + 1))
            address = Cells2Address(rowMin, colMin, rowMax, colMax);

        MRCO(lastCell);
        MRCO(usedRange);
    }
    catch (Exception ex)
    {
        // log as needed
    }
    return address; // caller should test return for String.Empty
}


public static string Cells2Address(int row1, int col1, int row2, int col2)
{
    return ColNum2Letter(col1) + row1.ToString() + ":" + ColNum2Letter(col2) + row2.ToString();
}


public static string ColNum2Letter(int colNum)
{
    if (colNum <= 26) 
        return ((char)(colNum + 64)).ToString();

    colNum--; //decrement to put value on zero based index
    return ColNum2Letter(colNum / 26) + ColNum2Letter((colNum % 26) + 1);
}


public static void MRCO(object obj)
{
    if (obj == null) { return; }
    try
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
    }
    catch
    {
        // ignore, cf: http://support.microsoft.com/default.aspx/kb/317109
    }
    finally
    {
        obj = null;
    }
}

注意:您可能想要替换所有单个单元格值检查,CountA但在某些情况下会失败。例如,如果一个单元格包含公式=IF(A1=55,"Y",""),则生成的空字符串将使用 计算为非空白单元格CountA

于 2012-09-05T10:41:53.587 回答