简体   繁体   English

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

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

I am trying to get the last row of an excel sheet programatically using the Microsoft.interop.Excel Library and C#. I want to do that, because I am charged with looping through all the records of an excel spreadsheet and performing some kind of operation on them.我正在尝试使用 Microsoft.interop.Excel 库和 C# 以编程方式获取 excel 工作表的最后一行。我想这样做,因为我负责循环遍历 excel 电子表格的所有记录并执行某种操作在他们。 Specifically, I need the actual number of the last row, as I will throw this number into a function. Anybody have any idea how to do that?具体来说,我需要最后一行的实际数字,因为我会将这个数字放入 function 中。有人知道该怎么做吗?

Couple ways,几种方式,

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

OR或者

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;

This is a common issue in Excel.这是 Excel 中的常见问题。

Here is some C# code:下面是一些 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;

found here这里找到

or using SpecialCells或使用SpecialCells

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

[EDIT] Similar threads: [编辑] 类似主题:

Pryank's answer is what worked closest for me. Pyank 的答案是最适合我的答案 I added a little bit towards the end ( .Row ) so I am not just returning a range , but an integer .我在最后添加了一点( .Row ),所以我不只是返回一个range ,而是一个integer

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

The only way I could get it to work in ALL scenarios (except Protected sheets):我可以让它在所有场景中工作的唯一方法(受保护的工作表除外):

It supports:它支持:

  • Scanning Hidden Row / Columns扫描隐藏的行/列

  • Ignores formatted cells with no data / formula忽略没有数据/公式的格式化单元格

Code:代码:

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

For questions involving the Excel object model, it's often easier to try it out in VBA first, then translating to C# is fairly trivial.对于涉及 Excel 对象模型的问题,通常先在 VBA 中尝试更容易,然后转换为 C# 则相当简单。

In this case one way to do it in VBA is:在这种情况下,在 VBA 中执行此操作的一种方法是:

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

The ActiveSheet.UsedRange.Value returns a 2 dimensional object array of [row, column] . ActiveSheet.UsedRange.Value返回[row, column]二维对象数组。 Checking the length of both dimensions will provide the LastRow index and the LastColumn index.检查两个维度的长度将提供LastRow索引和LastColumn索引。 The example below is using C#.下面的示例使用 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; }
}

This issue is even worse when there are possibly empty cells.当可能有空单元格时,这个问题会更糟。 But you have to read a row even if only one value is filled.但是即使只填充了一个值,您也必须读取一行。 It can take a while when there are a lot of unfilled cells but if the input is close to correct it is rather fast.当有很多未填充的单元格时可能需要一段时间,但如果输入接近正确,则速度相当快。

My solution ignores completely empty rows and returns the longest column's row count:我的解决方案忽略完全空行并返回最长列的行数:

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

For those who use SpecialCells method, (I'm not sure about others), Please Note in case your last cell is merged , you won't be able to get last row and column number using Range.Row and Range.Column to get the last row and column as numbers.对于那些使用 SpecialCells 方法的人,(我不确定其他人),请注意,如果您的最后一个单元格被合并,您将无法使用 Range.Row 和 Range.Column 获取最后一行和列号来获取最后一行和最后一列作为数字。 you need to first Unmerge your range and then Again get the last cell.您需要先取消合并范围,然后再次获取最后一个单元格。 It cost me a lot.我花了很多钱。

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

As previously discussed, the techniques above (xlCellTypeLastCell etc.) do not always provide expected results.如前所述,上述技术(xlCellTypeLastCell 等)并不总能提供预期的结果。 Although it's not difficult to iterate down through a column checking for values, sometimes you may find that there are empty cells or rows with data that you want to consider in subsequent rows.尽管遍历列检查值并不困难,但有时您可能会发现有空单元格或包含要在后续行中考虑的数据的行。 When using Excel directly, a good way of finding the last row is to press CTRL + Down Arrow a couple of times (you'll end up at row 1048576 for an XLSX worksheet) and then press CTRL + Up Arrow which will select the last populated cell.直接使用 Excel 时,查找最后一行的一个好方法是按 CTRL + 向下箭头几次(对于 XLSX 工作表,您将在第 1048576 行结束),然后按 CTRL + 向上箭头,这将选择最后一行填充单元格。 If you do this within Excel while recording a Macro you'll get the code to replicate this, and then it's just a case of tweaking it for C# using the Microsoft.Office.Interop.Excel libraries.如果您在录制宏时在 Excel 中执行此操作,您将获得复制此代码的代码,然后只需使用 Microsoft.Office.Interop.Excel 库为 C# 调整它。 For example:例如:

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

It may not be the most elegant solution (I guess instead you could navigate to the final row within the spreadsheet first directly before using XlUp) but it seems to be more reliable.它可能不是最优雅的解决方案(我想您可以在使用 XlUp 之前直接导航到电子表格中的最后一行),但它似乎更可靠。

As CtrlDot and Leo Guardian says, it is not very acuarate the method, there some files where formats affect the "SpecialCells".正如 CtrlDot 和 Leo Guardian 所说,该方法不是很精确,有些文件的格式会影响“SpecialCells”。

So I used a combination of that plus a While.所以我使用了它加上一个 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;
}
                
                

In case of using OfficeOpenXml nowadays:如果现在使用 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;

I don't know if using Microsoft.Office.Interop.Excel is still state of the art or more a legacy library.我不知道使用 Microsoft.Office.Interop.Excel 是否仍然是艺术的 state 或更多的遗留库。 In my opinion I'm doing well replacing with OfficeOpenXml.在我看来,用 OfficeOpenXml 替换我做得很好。 So this answer might be usefull for future search results.所以这个答案可能对未来的搜索结果有用。

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

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