如何获取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文本方式导出?