我试图在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认为即使我刚刚删除了所有单元格,但在将具有较少行的新数据复制到工作表中之前,某些单元格仍然已填充。
有没有办法“调整”工作表中数据的视图,这样我就可以获得正确数量的已用过的单元格,或者找到最后一次使用行数的另一种方式?
感谢。
答案 0 :(得分:12)
由于Joe提供了正确的代码来获取最后一次使用的行。
Worksheet.UsedRange.Row + Worksheet.UsedRange.Rows.Count - 1
使用以下命令清除内容和格式
Selection.Delete
Selection.ClearFormats
这应该有用;)
答案 1 :(得分:5)
要获取工作表中最后使用的行,您可以使用:
Worksheet.UsedRange.Row + Worksheet.UsedRange.Rows.Count - 1
请注意:
UsedRange不一定从第一行开始 - 第一行可能为空。
UsedRange包含包含格式的单元格,即使其内容为空。我怀疑这就是为什么你看到的价值超出你的预期。您需要删除格式以及空单元格中的数据。
我不确定如何以编程方式删除单元格上的格式
您可以使用Range.ClearFormats
清除格式,或Range.Clear
清除所有内容。通常,如果您不确定如何在Excel中以编程方式执行某些操作,请尝试录制宏,手动执行,然后检查生成的宏。
答案 2 :(得分: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
计为非空单元格。