C# 如何获取excel工作表中占用单元格的范围

C# 如何获取excel工作表中占用单元格的范围,c#,excel,automation,C#,Excel,Automation,我使用C#自动生成excel文件。我能够得到工作簿和它包含的工作表。 例如,如果我在表1中有两列和5行。我想得到被占用单元的范围为A1:B5。我尝试了以下代码,但没有给出正确的结果。 列和行要大得多,单元格也是空的 Excel.Range xlRange = excelWorksheet.UsedRange; int col = xlRange.Columns.Count; int row = xlRange.Rows.Count; 是否有其他方法可用于获取该范围

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

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

是否有其他方法可用于获取该范围?

请参阅range.SpecialCells方法。例如,要获取具有常量值或公式的单元格,请使用:

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

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

现在有点老问题了,但如果有人在寻找解决方案,这对我来说很有效

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

我和你有一个非常相似的问题。实际起作用的是:

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中删除数据时,它会一直认为这些单元格中有数据,尽管它们是空白的。当我清除格式时,它将删除空白单元格,因此返回实际计数。

< P>我可以在所有场景中(除了受保护的片断之外)(在FARAM的回答的基础上)工作:

它支持:

  • 扫描隐藏行/列

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

代码:


这两条线本身并不适合我:

xlWorkSheet.Columns.ClearFormats();
xlWorkSheet.Rows.ClearFormats();
您可以通过在工作表中按ctrl+end并查看选定的单元格来进行测试

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

Excel.Range xlActiveRange = WorkSheet.UsedRange;

如果知道从何处查找范围,则应尝试currentRegion属性。这将为您提供所用范围的边界。

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

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


您不应该通过按“delete”(删除)来删除框中的数据,我认为这就是问题所在,因为excel仍会将框检测为“目标范围内的数据类型”。我以前使用过UsedRange属性(没有问题),只要工作簿和工作表是活动的。这假设您确切知道所需的范围。提供的其他解决方案更一般,效果也更好。@Dan:实际上,它们都不适合我-总是在应该刚好超过2000行时获得15242行。这个方法肯定只会给你10行。您的数据是什么样子的?也许可以创建一个新问题并链接到此问题,解释您尝试了哪些方法以及结果。它始终返回时间空白单元格,我认为问题作者希望“不获取”空白单元格。这是我看到的唯一没有问题的答案。这可以解决以下问题:检测空的格式化单元格。检测隐藏行/Columns.xlWorkSheet.Columns.ClearFormats()中的值;xlWorkSheet.Rows.ClearFormats();很好的回答这是一个非常有用的答案,但是要知道这需要对电子表格进行写访问。啊,见鬼。是的,这确实有效(以前,Excel报告我有16349列,而不是13列!),但是——显而易见的是——它删除了所有单元格格式。是否有任何方法可以在不这样做的情况下获得“真实”列数…?很好的解决方案。但是这个解决方案的缺点是,如果您需要读取Excel中显示的值,那么清除所有格式,您将无法执行此操作。我在解决此问题时发现:此解决方案仅在VBA中有效。这不是一个C#解决方案(六年后,两次痛苦的Excel迭代…)这似乎正是我所需要的,但在Excel 2013中,它抛出了一个“SpecialCells方法的范围类失败”异常。。。使用“Cells.SpecialCells(XlCellType.xlCellTypeLastCell)”工作正常。。。但有时会返回一个完全错误的答案(例如包含9列数据的工作表中的16349列…)哇。精彩的代码。没错,这是我找到的唯一一个正确获取工作表中列/行数的代码。VSTO自己的“SpecialCells(XlCellType.xlCellTypeLastCell)”有时会告诉我,我的9列工作表包含16349列数据。使用你的代码,我得到了我想要的9。太棒了。再补充一句,经过大量测试,我们发现这段代码似乎无法在“分组”和折叠的列/行上检测到包含值的Excel单元格。我们的用户还抱怨它缺少只包含公式的列/行,因此我们需要做两个查找-一个用于“XlFindLookIn.xlValues”,另一个用于“XlFindLookIn.xlFormulas”。使用ClearFormats的问题是,如果需要,您将无法准确地读取屏幕上显示的单元格文本。在我的一个项目中,我有这样的要求;那么,有没有办法不使用ClearFormats就找到已使用的范围呢?回答得很好,我可以指出,您在列代码中写了三次“System.Reflection.Missing.Value”。我已经在我的代码中更正了它。有没有一种方法可以通过编程方式找到Excel在使用Ctrl+End时显示的单元格?
xlWorkSheet.Columns.ClearFormats();
xlWorkSheet.Rows.ClearFormats();
Excel.Range xlActiveRange = WorkSheet.UsedRange;
    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;
    }
}