【问题标题】:How can i get actual used range for modified excels using Epplus?如何使用 Epplus 获得修改后的 Excel 的实际使用范围?
【发布时间】:2016-03-09 11:09:21
【问题描述】:

我正在使用 EPPlus 将数据从 excel 读取到 datable。

在读取了 10 行记录的 excel 表后,我通过删除现有数据来修改 excel 表并仅保留一行数据。 但是当我读取修改后的 excel 时,它仍然会读取 10 行(1 行有值,其余为空字段)到数据表。

如何限制这一点? 我正在使用以下代码来阅读 Excel。

using (var pck = new OfficeOpenXml.ExcelPackage())
{
    using (var stream = File.OpenRead(FilePath))
    {
        pck.Load(stream);
    }
    var ws = pck.Workbook.Worksheets.First();                   
    bool hasHeader = true; // adjust it accordingly(this is a simple approach)
    foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
    {
        DSClientTransmittal.Tables[0].Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
    }
    var startRow = hasHeader ? 2 : 1;
    for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
    {
        //var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
        var wsRow = ws.Cells[rowNum, 1, rowNum, DSClientTransmittal.Tables[0].Columns.Count];
        var row = DSClientTransmittal.Tables[0].NewRow();
        foreach (var cell in wsRow)
        {
            try
            {
                object cellValue = cell.Value;
                //row[cell.Start.Column - 1] = cell.Text;
                row[cell.Start.Column - 1] = cellValue.ToString().Trim();
                //cell.Style.Numberformat.Format = "@";
                //row[cell.Start.Column - 1] = cell.Text;
            }
            catch (Exception ex) { }
        }
        DSClientTransmittal.Tables[0].Rows.Add(row);
    }
    pck.Dispose();
}   

当我使用 Interop excel 读取 excel 时,同样的问题被克服了 clearformat()类似方法

ws.Columns.ClearFormats();
xlColCount = ws.UsedRange.Columns.Count;

在 Epplus open xml 中是否有任何等价物? 如何获得修改后的 Excel 的实际使用范围?

【问题讨论】:

  • 你是如何删除数据的?
  • Dimension 在我的所有测试中似乎都返回了正确的范围。即使在删除行并重新导入之后。删除后你的情况是Dimension指示10行吗?
  • @PhilipBijker,@Ernie:我选择了所有需要删除并按下删除键的单元格,而不是整行
  • 尝试删除整行,这应该会导致正确的维度
  • 如果任何列包含数据,或者上面或下面的任何行包含数据,则行包含在维度中。如果这是您的情况,恐怕为这些空行编写自定义逻辑是您唯一的选择。

标签: c# excel openxml epplus excel-import


【解决方案1】:

当只删除某些单元格中的数据时,没有内置方法来指示不应考虑某行。

Dimension 尽可能接近,但如果 any 列包含数据或 any 行上方或下方包含数据,则行将包含在 Dimension 中数据。

但是,您可以尝试确定是否应该在 for 循环中跳过一行。 例如,如果您总是只删除前 4 列中的数据,那么您可以尝试:

if(!ws.Cells[rowNum, 1, rowNum, 4].All(c => c.Value == null))
{
    //Continue adding the row to the table
}

描述并没有指出跳过一行的标准,但你明白了。

【讨论】:

  • 不可能说哪些行将被删除。而不是给出 4 个放置的 ws.Dimension.End.Row 会起作用吗?
  • 您指出以下内容:“我通过删除现有数据修改了 Excel 工作表并仅保留了一行数据”。究竟删除了哪些数据?这些应该是将该行视为已删除并因此在 for 循环中跳过它的标准。
  • 这就像随机测试,没有删除单元格数据的先验标准,我有一个带有批量导入示例数据的 excel 模板。大多数客户将编辑(通过删除一些行和所有行)现有的模板并发送
  • 客户端需要删除整行,或者您需要知道何时将该行视为已删除。否则你将不知道要处理哪些行,对吧?
  • 正确。或者,您可以使用ws.Dimension.End.Column 而不是DSClientTransmittal.Tables[0].Columns.Count。如果行中的所有单元格为空,则其中任何一个都将跳过该行。
【解决方案2】:

首先,我不是 C# 程序员,但我认为我有一个使用 Excel VBA 脚本工作的解决方案。您或许可以使用 C 运行此 Excel VBA 代码,或者深入了解如何使用 C+ 完成同样的事情。

您遇到的问题与 Excel 处理工作表的工作大小的方式有关。如果您在第 1 百万行中输入数据,然后删除该单元格,Excel 仍将工作表显示为有 100 万行。

我测试了这个 Excel VBA 代码,它成功删除了所有完全为空的行,然后重置了工作表大小。

Sub DelEmptyRowsResizeWorksheet()
  Dim i As Long, iLimit As Long
    iLimit = ActiveSheet.UsedRange.Rows.Count
  For i = iLimit To 1 Step -1
    If Application.CountA(Cells(i, 1).EntireRow) = 0 Then
       Cells(i, 1).EntireRow.Delete
    End If
  Next i
   iLimit = ActiveSheet.UsedRange.Rows.Count   ' resize the worksheet based on the last row with data
End Sub

要在没有脚本的情况下手动执行此操作,请首先删除工作表底部(或右侧的列)的所有空行,保存它,然后关闭并重新打开工作簿。我发现这也会重置 Excel 工作簿的大小。

【讨论】:

  • 这对发布的问题完全没有帮助,而且由于该问题在 VBA 中解决起来很简单,因此在此处发布解决方案只会分散注意力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 1970-01-01
相关资源
最近更新 更多