【问题标题】:How to get actual columns range Spreadsheetgear如何获取实际列范围 Spreadsheetgear
【发布时间】:2021-07-16 08:06:00
【问题描述】:

我有一个 Excel 工作表,其中有 50 行和 38 列“填充”了实际数据,但是当我尝试获取 .UsedRange 时,我得到的已用范围超过 1025 行和 250 列!请让我知道如何仅获取带有填充数据的实际使用范围并使用 Spreadsheetgear lib 检索实际范围数据?我尝试了类似的方法,但是当用户添加了一些列时,它不起作用。

var workbook = Factory.GetWorkbook(filePath);
var worksheet = workbook.Worksheets[0];
var cells = worksheet.UsedRange;

var headerCount = 0;

// get columns size
for (var columnCount = 0; columnCount <= range.ColumnCount; ++columnCount)
{
    if (columnCount > headers.Length && string.IsNullOrEmpty(range[HeaderRow, columnCount].Text))
    {
        headerCount = columnCount - 1;
        break;
    }
}

【问题讨论】:

  • Used 并不意味着Filled。即使单元格包含空字符串,也会使用它。生成此 Excel 工作表的应用程序可能已经用空格填充了额外的字段,或者忽略了“删除”空单元格。 Excel 本身会在保存工作簿时尝试压缩工作簿,方法是尽可能消除空单元格或将字符串转换为可重用资源
  • 尝试使用不同的库,如 ExcelReader 来读取工作表中的数据。如果要读取特定范围,可以将其转换为具有特定名称的 Table 并按名称寻址范围。也可以只命名一个范围。 This SO question 展示了如何使用 sheet.Tables.Add(range,"SomeName") 从范围创建命名表
  • SpreadsheetGear 在处理单元格值、确定 UsedRange 等方面非常接近地模拟 Excel 的行为。所以我不会在这里忽略 SpreadsheetGear 的行为,因为同样的行为也可能发生在 Excel 中(可以不能肯定地说,因为没有提供足够的信息)。另一种可能性是“预期的”UsedRange 之外的一些单元格以某种方式被格式化。例如,只需为单元格设置不同的字体,即使它没有单元格值,它也会包含在 UsedRange 中。 @Jdo,请看我的回答,看看这是否对你有帮助。

标签: c# .net excel spreadsheetgear


【解决方案1】:

SpreadsheetGear(和 Excel 本身)会将单元格包含到 UsedRange 中,这些单元格为空但具有某种格式。例如,如果单元格 ABC123 具有自定义 NumberFormat、字体颜色或类似内容,则 UsedRange 将包含该单元格,从而可能会炸毁您的 UsedRange A1:ABC123,即使工作表的实际“填充值”或“填充”部分是小得多。

如果这是一个问题,并且您只需要包含实际填充有单元格值的工作表部分,则以下是一种可能的例程,您可以使用它来仅包含具有某种单元格值的单元格。它是作为 IWorksheet 的扩展方法编写的,以便更轻松地使用它,并包含一个 bool 标志,您可以传入该标志以返回“正常”UsedRange(包括具有其他类型格式的单元格)或“已更改" 这里讨论的 UsedRange:

public static class SGExtensionMethods
{
    public static IRange GetUsedRange(this IWorksheet worksheet, bool ignoreEmptyCells)
    {
        IRange usedRange = worksheet.UsedRange;
        if (!ignoreEmptyCells)
            return usedRange;

        // Find last row in used range with a cell containing data.
        IRange foundCell = usedRange.Find("*", usedRange[0, 0], FindLookIn.Formulas,
            LookAt.Part, SearchOrder.ByRows, SearchDirection.Previous, false);
        int lastRow = foundCell?.Row ?? 0;

        // Find last column in used range with a cell containing data.
        foundCell = usedRange.Find("*", usedRange[0, 0], FindLookIn.Formulas,
            LookAt.Part, SearchOrder.ByColumns, SearchDirection.Previous, false);
        int lastCol = foundCell?.Column ?? 0;

        // Return a new used range that clips of any empty rows/cols.
        return worksheet.Cells[worksheet.UsedRange.Row, worksheet.UsedRange.Column, lastRow, lastCol];
    }
}

关于这种方法的一些附加说明。它通常会考虑隐藏的行或列——这意味着具有单元格值的隐藏行或列将包含在 UsedRange 中。包含隐藏行或列的一个例外/边缘情况是,如果在工作表上启用了自动筛选。这会将工作表置于一种特殊的“模式”中,从搜索结果中排除隐藏的行。因此,如果启用了 AutoFilters(在这种情况下 IWorksheet.AutoFilterMode 为真),如果 AutoFiltered 范围的最后一行或最后一列可能已被过滤掉,您可能无法依赖此方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 2019-11-11
    相关资源
    最近更新 更多