首页 > 解决方案 > EPPLUS 使用 loadfromcollection 与合并的单元格

问题描述

我必须填写这样的excel

在此处输入图像描述

我在每一行上合并了单元格。我正在尝试使用 loadfromcollection,但它忽略了合并的单元格并填充了每一行。

请问您知道有什么快速的方法吗?


编辑:我认为一种方法是实现自定义 loadfromcollection 步骤如下:

  1. 迭代集合
  2. 对于每个对象,使用反射读取属性/字段
  3. 迭代每一行的单元格
  4. 检查范围地址是否在 worksheet.mergecells
  5. 用属性/字段值填充它

但是在复杂的工作表(带有一些 loadfromcollection)的情况下,我认为这种方法可能很繁重且成本很高。


编辑2:添加一个例子:这样的代码

public class MyObj
{
  public string first {get; set;}
  public string second {get; set;}
}
...
List<MyObj> myList = new List<MyObj>() {
   new MyObj() {first = "first1", second = "second1"},
   new MyObj() {first = "first2", second = "second2"} };
...
ws.Cells["A1"].LoadFromCollection(myList);

在普通工作表中,loadfromcollection 具有以下输出: 在此处输入图像描述

如果我在填充后合并 A 列和 B 列,我会得到:

在此处输入图像描述

如果我的工作表模板是

在此处输入图像描述

然后我尝试使用 loadfromcollection 填充它我得到了这个结果

在此处输入图像描述

loadfromcollection 忽略合并的单元格,并填充 A 和 B 列,但我的期望是

在此处输入图像描述

标签: c#epplusepplus-4

解决方案


问题是这是 excel 中的“有意”行为。当您在 A 列和 B 列中有值并将它们合并时,将仅保留 A 列中的值。LoadFromCollection 没有这种场景的重载。

我可以想到几种可行的“解决方法”,具体取决于您希望代码的通用程度。

  1. 您使用反射遍历对象属性的解决方案将起作用。如果“合并”总是两列,我建议使用列计数器并在每次属性迭代时添加 2。

所以像这样(当然你已经定义了 excel 包和工作表等以及起始行和列):

var type = testObject.GetType();
var properties = type.GetProperties();
            
foreach (var property in properties)
{
       cell = worksheet.Cells[row, column];
       cell.Value = property.GetValue(testObject);

       column += 2;
}
  1. 或者,您可以决定从模板中删除合并并将其移动到您的代码中。这也可以提供更多的一致性和灵活性。

上面的代码看起来更像:

var type = testObject.GetType();
var properties = type.GetProperties();
            
foreach (var property in properties)
{
       cellRange = worksheet.Cells[row, column, row, column + 1];

       cellRange.Merge = true;
       cellRange.Value = property.GetValue(testObject);
       
       column += 2;
}

您甚至可以有点“疯狂”并根据属性使范围变量。您使用所有已知属性创建一个 switch 语句,这些属性应该是 2 个合并单元格,那些应该是 3 个合并单元格等。然后设置默认的 1 个单元格/列。通过这种方式,您可以获得对输出的完全控制,并且将来更容易调整。

编辑

我的情况有点复杂,不是我所有的合并单元格都由 2 个单元格组成

一些代码用一些代码来说明我的上述陈述,以帮助解决这个问题。使用旧的 switch 表示法,因为你说它是一个“旧项目”,我假设你还没有使用 C# 8 或更高版本。

var type = testObject.GetType();
var properties = type.GetProperties();
int columnMergeSize;
            
foreach (var property in properties)
{
       columnMergeSize = GetPropertyColumnMergeSize(property.Name);

       cellRange = worksheet.Cells[row, column, row, column + columnMergeSize];

       cellRange.Merge = true;
       cellRange.Value = property.GetValue(testObject);
       
       column += 2;
}

private int GetPropertyColumnMergeSize(string propertyName)
{
    switch (propertyName)
    {
        case "Property1":
        case "Property2":
        case "Property3":
        case "Property4":
            return 2;
        case "Property5":
        case "Property6":
            return 3;
        default:
            return 1;
    }
}

这将比每次都读取单元格的属性以查看它是否“合并”要少。我还发现,如果您从 excel 模板中删除几乎所有格式,它的加载速度会更快,从而加快您的程序。

您可以决定将其放入服务中,然后将方法注入 DI 需要的任何地方,或者您可以将其设为静态方法并使用它。


推荐阅读