如何获取excel表格中占用单元格的范围

Posted

技术标签:

【中文标题】如何获取excel表格中占用单元格的范围【英文标题】:How to get the range of occupied cells in excel sheet 【发布时间】:2009-08-16 14:10:26 【问题描述】:

我使用 C# 来自动化一个 excel 文件。我能够得到工作簿及其包含的工作表。 例如,如果我在 sheet1 中有两列和 5 行。我想获得被占用单元格的范围为 A1:B5。我尝试了以下代码,但没有给出正确的结果。 列 # 和行 # 大得多,单元格也是空的。

     Excel.Range xlRange = excelWorksheet.UsedRange;
     int col = xlRange.Columns.Count;
     int row = xlRange.Rows.Count;

我可以使用其他方法来获得该范围吗?

【问题讨论】:

您在目标范围内拥有什么样的数据。只要工作簿和工作表是活动的,我之前使用 UsedRange 属性没有问题。 【参考方案1】:

我遇到了和你非常相似的问题。实际起作用的是:

iTotalColumns = xlWorkSheet.UsedRange.Columns.Count;
iTotalRows = xlWorkSheet.UsedRange.Rows.Count;

//These two lines do the magic.
xlWorkSheet.Columns.ClearFormats();
xlWorkSheet.Rows.ClearFormats();

iTotalColumns = xlWorkSheet.UsedRange.Columns.Count;
iTotalRows = xlWorkSheet.UsedRange.Rows.Count;

恕我直言,当您从 Excel 中删除数据时,它会一直认为这些单元格中有数据,尽管它们是空白的。当我清除格式时,它会删除空白单元格并因此返回实际计数。

【讨论】:

这是我看到的唯一没有问题的答案。这解决了以下问题:检测空的格式化单元格。检测隐藏行/列中的值。 xlWorkSheet.Columns.ClearFormats(); xlWorkSheet.Rows.ClearFormats();很好的答案 这是一个非常有用的答案,但请注意,这需要对电子表格进行写访问。 哎呀。是的,这确实有效(以前,Excel 报告我有 16,349 列,而不仅仅是 13 列!)但是 - 显而易见 - 它删除了所有单元格格式。无论如何,如果不这样做就可以获得“真实”的列数..? 很好的解决方案。但是这个解决方案的缺点是,如果你需要读取 Excel 中显示的值,那么通过清除所有格式,你将无法做到这一点。我在解决这个问题时发现了这个:***.com/questions/39931543/…【参考方案2】:
Excel.Range last = sheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range range = sheet.get_Range("A1", last);

“范围”现在将是占用的单元格范围

【讨论】:

它总是返回空白单元格,我认为问题作者想要“不得到”那个空白单元格。【参考方案3】:

参见 Range.SpecialCells 方法。例如,要获取具有恒定值或公式的单元格,请使用:

_xlWorksheet.UsedRange.SpecialCells(
        Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeConstants |
        Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeFormulas)

【讨论】:

(六年,之后两次痛苦的 Excel 迭代......)这似乎正是我所需要的,但在 Excel 2013 中,它会引发“Range 类的 SpecialCells 方法失败”异常...... . 使用“Cells.SpecialCells(XlCellType.xlCellTypeLastCell)”工作正常...但有时会返回一个无可救药的错误答案(例如,包含 9 列数据的工作表中的第 16,349 列...)【参考方案4】:

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

它支持:

扫描隐藏的行/列

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

代码:

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

【讨论】:

哇。精彩的代码。没错,这是我发现的唯一正确获取工作表中列/行数的代码。 VSTO 自己的“SpecialCells(XlCellType.xlCellTypeLastCell)”有时告诉我我的 9 列工作表包含 16349 列数据。使用您的代码,我得到了我正在寻找的 9。太棒了。 只是补充一点,经过大量测试,我们发现此代码似乎无法检测到包含值的 Excel 单元格,在已“分组”和折叠的列/行上。我们的用户还抱怨它缺少仅包含公式的列/行,因此我们需要进行两次查找 - 一次用于“XlFindLookIn.xlValues”,另一次用于“XlFindLookIn.xlFormulas”。 使用 ClearFormats 的问题是,如果需要,您将无法完全按照屏幕上显示的方式阅读单元格文本。我的一个项目中有这样的要求;那么有什么方法可以在不使用 ClearFormats 的情况下找到 Used Range? 很好的答案,我可以指出你在列代码中写了三遍'System.Reflection.Missing.Value'。我已经在我的代码中更正了它【参考方案5】:
dim lastRow as long   'in VBA it's a long 
lastrow = wks.range("A65000").end(xlup).row

【讨论】:

此解决方案仅适用于 VBA。这不是 C# 解决方案【参考方案6】:

现在有点老问题了,但是如果有人正在寻找解决方案,这对我有用。

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

【讨论】:

这假设您确切地知道您需要什么范围。提供的其他解决方案更通用且运行良好。 @Dan:实际上它们都不适合我——当它应该超过 2000 行时总是得到 15242 行 这个方法肯定只会给你 10 行。你的数据是什么样的?也许创建一个新问题并链接到这个问题,说明您尝试过哪些方法以及结果。【参考方案7】:

这两行本身对我不起作用:

xlWorkSheet.Columns.ClearFormats();
xlWorkSheet.Rows.ClearFormats();

您可以通过在工作表中按 ctrl+end 并查看选择了哪个单元格来进行测试。

我发现在前两行之后添加这一行解决了我遇到的所有情况下的问题:

Excel.Range xlActiveRange = WorkSheet.UsedRange;

【讨论】:

有没有办法以编程方式找出 Excel 在使用 Ctrl + End 时将显示的单元格?【参考方案8】:

如果您知道从哪里找到范围,您应该尝试 currentRegion 属性。这将为您提供使用范围的边界。

【讨论】:

【参考方案9】:

这是为查找公式量身定制的,但您应该能够通过更改测试起始单元格的方式将其扩展为一般内容。您必须处理超出此范围的单个单元格范围。

    public static Range GetUsedPartOfRange(this Range range)
    
        Excel.Range beginCell = range.Cells[1, 1];
        Excel.Range endCell = range.Cells[range.Rows.Count, range.Columns.Count];

        if (!beginCell.HasFormula)
        
            var beginCellRow = range.Find(
                "*",
                beginCell,
                XlFindLookIn.xlFormulas,
                XlLookAt.xlPart,
                XlSearchOrder.xlByRows,
                XlSearchDirection.xlNext,
                false);

            var beginCellCol = range.Find(
                "*",
                beginCell,
                XlFindLookIn.xlFormulas,
                XlLookAt.xlPart,
                XlSearchOrder.xlByColumns,
                XlSearchDirection.xlNext,
                false);

            if (null == beginCellRow || null == beginCellCol)
                return null;

            beginCell = range.Worksheet.Cells[beginCellRow.Row, beginCellCol.Column];
        

        if (!endCell.HasFormula)
        
            var endCellRow = range.Find(
            "*",
            endCell,
            XlFindLookIn.xlFormulas,
            XlLookAt.xlPart,
            XlSearchOrder.xlByRows,         
            XlSearchDirection.xlPrevious,
            false);

            var endCellCol = range.Find(
                "*",
                endCell,
                XlFindLookIn.xlFormulas,
                XlLookAt.xlPart,
                XlSearchOrder.xlByColumns,
                XlSearchDirection.xlPrevious,
                false);

            if (null == endCellRow || null == endCellCol)
                return null;

            endCell = range.Worksheet.Cells[endCellRow.Row, endCellCol.Column];
        

        if (null == endCell || null == beginCell)
            return null;

        Excel.Range finalRng = range.Worksheet.Range[beginCell, endCell];

        return finalRng;
    

【讨论】:

【参考方案10】:

您不应该通过按“删除”来删除框中的数据,我认为这就是问题所在,因为 excel 仍会将框检测为“”

【讨论】:

以上是关于如何获取excel表格中占用单元格的范围的主要内容,如果未能解决你的问题,请参考以下文章

Office表中如何把一定范围单元格的内容多列数据去除空值以TXT文本方式导出?

从 vba 中的单元格地址获取 excel 合并单元格的值

在代码页中如何获取FastReport中一个单元格的值

当单元格的高度不同时,如何在表格视图中获取所有单元格的高度?

如何在 Google 表格中获取单元格的字体颜色?

vb.net中如何获得DataGridView单元格内容