EPPlus使用模板时未能按预期工作

4

我目前正在使用EPPlus项目来处理一些.xlsx文件。基本思路是我需要从给定的模板创建一个新文件。

但是当我从模板创建新文件时,表格中所有计算列都会出现问题。

我使用的代码如下:

static void Main(string[] args)
{
  const string templatePath = "template_worksheet.xlsx"; // the path of the template
  const string resultPath = "result.xlsx"; // the path of our result

  using (var pck = new ExcelPackage(new FileInfo(resultPath), new FileInfo(templatePath))) // creating a package with the given template, and our result as the new stream
  {
    // note that I am not doing any work ...
    pck.Save(); // savin our work
  }
}

例如,对于一个包含3列的表格(最后一列只是其他两列的总和)的.xlsx文件,该程序会创建一个.xlsx文件,在所有行中,最后一列都具有相同的值(这仅对第一行正确)。
下面的图像显示了结果:
现在问题是: 这里发生了什么?我的代码错了吗? 如何在没有这种意外行为的情况下完成此任务?

你使用的 EpPlus 版本是什么?这似乎是 EpPlus 的一个问题,可能值得在项目的 相应部分 中发布。 - Deilan
我正在使用4.0.3版本。 - Eric Javier Hernandez Saura
用Excel 2007+打开模板文件并将其另存为另一个文件名。然后使用新文件进行与您在帖子中描述的相同工作流程。这样做可以复制吗? - Deilan
@Deilan,是的,意外的行为仍然保持不变。 - Eric Javier Hernandez Saura
请您提供模板文件以便进行进一步分析? - Deilan
@Deilan,感谢您的帮助,这是模板链接:https://s3.amazonaws.com/uploads.hipchat.com/42313/1087738/IlmHOYaGasHzVUk/MyReportTemplate.xlsx。 - Eric Javier Hernandez Saura
3个回答

1
那绝对是有问题的。我自己也能够复现它。它与你创建的表格有关。如果你打开文件并使用“表格工具”选项卡中的“转换为范围”选项将其删除,问题就会消失。
我查看了源代码,并提取了zip级别的xml文件,没有看到任何迹象表明它实际上正在干扰它们——似乎是一个直接的复制。
非常奇怪,因为如果我们从EPPlus创建和保存包括表格的xlsx文件,问题就不会存在。这样做完全没有问题:
[TestMethod]
public void Template_Copy_Test()
{
    //https://dev59.com/CIjca4cB1Zd3GeqPtTZI
    const string templatePath = "c:\\temp\\testtemplate.xlsx"; // the path of the template
    const string resultPath = "c:\\temp\\result.xlsx"; // the path of our result

    //Throw in some data
    var dtdata = new DataTable("tblData");
    dtdata.Columns.Add(new DataColumn("Col1", typeof(string)));
    dtdata.Columns.Add(new DataColumn("Col2", typeof(int)));
    dtdata.Columns.Add(new DataColumn("Col3", typeof(int)));

    for (var i = 0; i < 20; i++)
    {
        var row = dtdata.NewRow();
        row["Col1"] = "String Data " + i;
        row["Col2"] = i * 10;
        row["Col3"] = i * 100;
        dtdata.Rows.Add(row);
    }

    var templateFile = new FileInfo(templatePath);
    if (templateFile.Exists)
        templateFile.Delete();

    using (var pck = new ExcelPackage(templateFile))
    {
        var ws = pck.Workbook.Worksheets.Add("Data");
        ws.Cells["A1"].LoadFromDataTable(dtdata, true);

        for (var i = 2; i <= dtdata.Rows.Count + 1; i++)
            ws.Cells[i, 4].Formula = String.Format("{0}*{1}", ExcelCellBase.GetAddress(i, 2), ExcelCellBase.GetAddress(i, 3));

        ws.Tables.Add(ws.Cells[1, 1, dtdata.Rows.Count + 1, 4], "TestTable");

        pck.Save();
    }

    using (var pck = new ExcelPackage(new FileInfo(resultPath), templateFile)) // creating a package with the given template, and our result as the new stream
    {
        // note that I am not doing any work ...
        pck.Save(); // savin our work
    }
}

但是......

如果我们打开testtemplate.xlsx,删除表格,保存/关闭文件,重新打开并插入完全相同的表格,则在运行此操作时会出现问题:

[TestMethod]
public void Template_Copy_Test2()
{
    //https://dev59.com/CIjca4cB1Zd3GeqPtTZI
    const string templatePath = "c:\\temp\\testtemplate.xlsx"; // the path of the template
    const string resultPath = "c:\\temp\\result.xlsx"; // the path of our result

    var templateFile = new FileInfo(templatePath);

    using (var pck = new ExcelPackage(new FileInfo(resultPath), templateFile)) // creating a package with the given template, and our result as the new stream
    {
        // note that I am not doing any work ...
        pck.Save(); // savin our work
    }
}

我想可能是他们的压缩复制方法中有一些问题,但我没有发现明显的错误。

不过至少你可以尝试解决这个问题。

Ernie


0

试试这个

var package = new ExcelPackage(excelFile)
var excelSheet = package.Workbook.Worksheets[1];
for (var i = 1; i < 5; i++){
    excelWorkSheet.InsertRow(i, 1, 1); // Use value of i or whatever is suitable for you
}
package.Workbook.Calculate(); 

如果最后一个参数设置为1,则插入新行会复制上一行的格式和公式


0
尝试使用以下代码。该代码会将格式和其他规则作为XML节点添加到另一个文件中。Ernie在这里描述得非常好 使用EPPlus将带有所有条件格式规则的Excel文件导入 解决方案的最大优势是,您还可以导入格式以及其他规则。这将使你接近你所需的内容。
//File with your rules, can be your template
var existingFile = new FileInfo(@"c:\temp\temp.xlsx");

//Other file where you want the rules
var existingFile2 = new FileInfo(@"c:\temp\temp2.xlsx");

using (var package = new ExcelPackage(existingFile))
using (var package2 = new ExcelPackage(existingFile2))
{
    //Make sure there are document element for the source
    var worksheet = package.Workbook.Worksheets.First();
    var xdoc = worksheet.WorksheetXml;

    if (xdoc.DocumentElement == null)
        return;

    //Make sure there are document element for the destination
    var worksheet2 = package2.Workbook.Worksheets.First();
    var xdoc2 = worksheet2.WorksheetXml;

    if (xdoc2.DocumentElement == null)
        return;

    //get the extension list node 'extLst' from the ws with the formatting 
    var extensionlistnode = xdoc
        .DocumentElement
        .GetElementsByTagName("extLst")[0];

    //Create the import node and append it to the end of the xml document
    var newnode = xdoc2.ImportNode(extensionlistnode, true);
    xdoc2.LastChild.AppendChild(newnode);

    package2.Save();

}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接