繁体   English   中英

使用 C# 以编程方式获取最后填充的 excel 行

[英]Programmatically getting the last filled excel row using C#

我正在尝试使用 Microsoft.interop.Excel 库和 C# 以编程方式获取 excel 工作表的最后一行。我想这样做,因为我负责循环遍历 excel 电子表格的所有记录并执行某种操作在他们。 具体来说,我需要最后一行的实际数字,因为我会将这个数字放入 function 中。有人知道该怎么做吗?

几种方式,

using Excel = Microsoft.Office.Interop.Excel;

Excel.ApplicationClass excel = new Excel.ApplicationClass();
Excel.Application app = excel.Application;
Excel.Range all = app.get_Range("A1:H10", Type.Missing);

或者

Excel.Range last = sheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range range = sheet.get_Range("A1", last);

int lastUsedRow = last.Row;
int lastUsedColumn = last.Column;

这是 Excel 中的常见问题。

下面是一些 C# 代码:

// Find the last real row
nInLastRow = oSheet.Cells.Find("*",System.Reflection.Missing.Value, 
System.Reflection.Missing.Value, System.Reflection.Missing.Value,    Excel.XlSearchOrder.xlByRows,Excel.XlSearchDirection.xlPrevious, false,System.Reflection.Missing.Value,System.Reflection.Missing.Value).Row;

// Find the last real column
nInLastCol = oSheet.Cells.Find("*", System.Reflection.Missing.Value,     System.Reflection.Missing.Value,System.Reflection.Missing.Value, Excel.XlSearchOrder.xlByColumns,Excel.XlSearchDirection.xlPrevious,    false,System.Reflection.Missing.Value,System.Reflection.Missing.Value).Column;

这里找到

或使用SpecialCells

Excel.Range last = sheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range range = sheet.get_Range("A1", last);

[编辑] 类似主题:

Pyank 的答案是最适合我的答案 我在最后添加了一点( .Row ),所以我不只是返回一个range ,而是一个integer

int lastRow = wkSheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing).Row;

我可以让它在所有场景中工作的唯一方法(受保护的工作表除外):

它支持:

  • 扫描隐藏的行/列

  • 忽略没有数据/公式的格式化单元格

代码:

// Unhide All Cells and clear formats
sheet.Columns.ClearFormats();
sheet.Rows.ClearFormats();

// Detect Last used Row - Ignore cells that contains formulas that result in blank values
int lastRowIgnoreFormulas = sheet.Cells.Find(
                "*",
                System.Reflection.Missing.Value,
                InteropExcel.XlFindLookIn.xlValues,
                InteropExcel.XlLookAt.xlWhole,
                InteropExcel.XlSearchOrder.xlByRows,
                InteropExcel.XlSearchDirection.xlPrevious,
                false,
                System.Reflection.Missing.Value,
                System.Reflection.Missing.Value).Row;
// Detect Last Used Column  - Ignore cells that contains formulas that result in blank values
int lastColIgnoreFormulas = sheet.Cells.Find(
                "*",
                System.Reflection.Missing.Value,
                System.Reflection.Missing.Value,
                System.Reflection.Missing.Value,
                InteropExcel.XlSearchOrder.xlByColumns,
                InteropExcel.XlSearchDirection.xlPrevious,
                false,
                System.Reflection.Missing.Value,
                System.Reflection.Missing.Value).Column;

// Detect Last used Row / Column - Including cells that contains formulas that result in blank values
int lastColIncludeFormulas = sheet.UsedRange.Columns.Count;
int lastColIncludeFormulas = sheet.UsedRange.Rows.Count;

对于涉及 Excel 对象模型的问题,通常先在 VBA 中尝试更容易,然后转换为 C# 则相当简单。

在这种情况下,在 VBA 中执行此操作的一种方法是:

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

ActiveSheet.UsedRange.Value返回[row, column]二维对象数组。 检查两个维度的长度将提供LastRow索引和LastColumn索引。 下面的示例使用 C#。

Excel.Worksheet activeSheet;
Excel.Range activeRange;

public virtual object[,] RangeArray 
{
    get { return ActiveRange.Value; }
}

public virtual int ColumnCount 
{
    get { return RangeArray.GetLength(1); }
}

public virtual int RowCount
{
    get { return RangeArray.GetLength(0); }
}

public virtual int LastRow 
{
    get { return RowCount; }
}

当可能有空单元格时,这个问题会更糟。 但是即使只填充了一个值,您也必须读取一行。 当有很多未填充的单元格时可能需要一段时间,但如果输入接近正确,则速度相当快。

我的解决方案忽略完全空行并返回最长列的行数:

private static int GetLastRow(Worksheet worksheet)
    {
        int lastUsedRow = 1;
        Range range = worksheet.UsedRange;
        for (int i = 1; i < range.Columns.Count; i++)
        {
            int lastRow = range.Rows.Count;
            for (int j = range.Rows.Count; j > 0; j--)
            {
                if (lastUsedRow < lastRow)
                {
                    lastRow = j;
                    if (!String.IsNullOrWhiteSpace(Convert.ToString((worksheet.Cells[j, i] as Range).Value)))
                    {
                        if (lastUsedRow < lastRow)
                            lastUsedRow = lastRow;
                        if (lastUsedRow == range.Rows.Count)
                            return lastUsedRow - 1;
                        break;
                    }
                }
                else
                    break;
            }
        }
        return lastUsedRow;
    }

对于那些使用 SpecialCells 方法的人,(我不确定其他人),请注意,如果您的最后一个单元格被合并,您将无法使用 Range.Row 和 Range.Column 获取最后一行和列号来获取最后一行和最后一列作为数字。 您需要先取消合并范围,然后再次获取最后一个单元格。 我花了很多钱。

private int[] GetLastRowCol(Ex.Worksheet ws)
    {
        Ex.Range last = ws.Cells.SpecialCells(Ex.XlCellType.xlCellTypeLastCell, Type.Missing);
        bool isMerged = (bool)last.MergeCells;
        if (isMerged)
        {
            last.UnMerge();
            last = ws.Cells.SpecialCells(Ex.XlCellType.xlCellTypeLastCell, Type.Missing);
        }
        return new int[2] { last.Row, last.Column };
    }

如前所述,上述技术(xlCellTypeLastCell 等)并不总能提供预期的结果。 尽管遍历列检查值并不困难,但有时您可能会发现有空单元格或包含要在后续行中考虑的数据的行。 直接使用 Excel 时,查找最后一行的一个好方法是按 CTRL + 向下箭头几次(对于 XLSX 工作表,您将在第 1048576 行结束),然后按 CTRL + 向上箭头,这将选择最后一行填充单元格。 如果您在录制宏时在 Excel 中执行此操作,您将获得复制此代码的代码,然后只需使用 Microsoft.Office.Interop.Excel 库为 C# 调整它。 例如:

    private int GetLastRow()
    {
        Excel.Application ExcelApp;
        ExcelApp = new Excel.Application();

        ExcelApp.Selection.End(Excel.XlDirection.xlDown).Select();
        ExcelApp.Selection.End(Excel.XlDirection.xlDown).Select();
        ExcelApp.Selection.End(Excel.XlDirection.xlDown).Select();

        ExcelApp.Selection.End(Excel.XlDirection.xlUp).Select();

        return ExcelApp.ActiveCell.Row;
    }

它可能不是最优雅的解决方案(我想您可以在使用 XlUp 之前直接导航到电子表格中的最后一行),但它似乎更可靠。

正如 CtrlDot 和 Leo Guardian 所说,该方法不是很精确,有些文件的格式会影响“SpecialCells”。

所以我使用了它加上一个 While 的组合。

Range last = sheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);
Range range = sheet.get_Range("A1", last);
int lastrow = last.Row;
// Complement to confirm that the last row is the last
string textCell= "Existe";
while (textCell != null)
{
 lastrow++;
 textCell = sheet.Cells[lastrow + 1, 1].Value;
}
                
                

如果现在使用 OfficeOpenXml:

using OfficeOpenXml;
using System.IO;

FileInfo excelFile = new FileInfo(filename);
ExcelPackage package = new ExcelPackage(excelFile);
ExcelWorksheet sheet = package.Workbook.Worksheets[1];
int lastRow = sheet.Dimension.End.Row;
int lastColumn = sheet.Dimension.End.Column;

我不知道使用 Microsoft.Office.Interop.Excel 是否仍然是艺术的 state 或更多的遗留库。 在我看来,用 OfficeOpenXml 替换我做得很好。 所以这个答案可能对未来的搜索结果有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM