EPPlus 没有正确地排列调用不同工作表的公式

EPPlus doesn't properly range a formula calling on a different worksheet

我一直在使用 EPPlus 导出一个 excel 作品sheet,记录各种测试的结果,然后对它们做一个基本的总结。我有这些运行良好的代码行

groupsheet.Cells[3, 5, 3, (25 + (tPts.Count() - 1) * 9) ].Formula = "AVERAGE(E6:E"+(5+ mCount).ToString()+")";
groupsheet.Cells[4, 5, 4, (25 + (tPts.Count() - 1) * 9) ].Formula = "STDEV(E6:E"+(5+ mCount).ToString()+")";
groupsheet.Cells[5, 5, 5, (25 + (tPts.Count() - 1) * 9) ].Formula = "MAX(E6:E"+(5+ mCount).ToString()+")";

正如我对 EPPlus 的期望,该代码范围。所以 E3 得到“=Average(E6:E8)”(如果 mCount 为 3),F3 得到“=Average(F6:F8)”等等,一直到最后(由 tPts 的长度定义)。类似地,第 4 行中的所有内容均获得所需范围的标准差,第 5 行中的所有内容均获得所需范围的最大值。

我还有一个总体摘要 sheet,它记录了所有个人组 sheet 的数据。我目前正在通过使用以下代码复制确切的值来做到这一点。

summarysheet.Cells[3 + groupCount * 4, 5, 5 + groupCount * 4, (25 + (tPts.Count() - 1) * 9)].Value = groupsheet.Cells[3 , 5, 5 , (25 + (tPts.Count() - 1) * 9)].Value;

这按预期工作,将个人组 sheet 的值放入摘要 sheet 的正确位置。但我希望每个单元格都包含对单个组工作 sheet(标题为 Group1、Group2、Group3...)中适当单元格的引用,以便摘要 sheet 会随着所做的更改而动态更改个人组sheets.

我的直觉告诉我正确的方法是通过以下代码。

summarysheet.Cells[3 + groupCount * 4, 5, 5 + groupCount * 4, (25 + (tPts.Count() - 1) * 9)].Formula = "Group"+ groupNumKey.ToString() +"!E3";

然而,这只是将单元格 E3 的公式粘贴到每个单元格中。我无法弄清楚如何使公式调用范围类似于它们全部包含在一个作品中时的方式sheet。

非常感谢!

这是我尝试的暴力破解方法

// Iterate over each column to put the references in place
int currColNum = 5; //Start at 5 (E)
string currColName = "E";
int maxColNum = (25 + (tPts.Count() - 1) * 9); // End at the last column
while (currColNum <= maxColNum)
{
    currColName = Base26Encode(currColNum); // Finds the excel column name from the row #
    summarysheet.Cells[3 + groupCount * 4, currColNum].Formula = "Group" + groupNumKey.ToString() + "!" + currColName + "3"; // Grab Average
    summarysheet.Cells[4 + groupCount * 4, currColNum].Formula = "Group" + groupNumKey.ToString() + "!" + currColName + "4"; // Grab STD
    summarysheet.Cells[5 + groupCount * 4, currColNum].Formula = "Group" + groupNumKey.ToString() + "!" + currColName + "5"; // Grab Max

    currColNum++;
}

其中 "Base26Encode" 是一段代码,它在给定 1 时输出 A,在给定 26 时输出 Z,在给定 27 时输出 AA,依此类推(将列索引转换为 excel 列名)

如果您想引用另一个 sheet 中的单元格,您的公式似乎是正确的,但您已将 !E3 硬编码到其中,因此公式等于 `GroupX! E3”。看来你需要做的就是改变这个:

summarysheet.Cells[3 + groupCount * 4, 5, 5 + groupCount * 4, (25 + (tPts.Count() - 1) * 9)].Formula 
    = "Group" + groupNumKey.ToString() +"!E3";

对此:

//Use a variable to save space and avoid repeating the same calculation over and over
var row = (25 + (tPts.Count() - 1) * 9);
summarysheet.Cells[3 + groupCount * 4, 5, 5 + groupCount * 4, row].Formula 
    = "Group" + groupNumKey.ToString() +"!E" + row; 

如果我有误会请告诉我。


回复评论: @Iassac 我仍然无法理解您要做什么。也许 post 更多代码,因为没有更多代码有点难以掌握。如果有帮助,这是一个单元测试,其中包含我提出的内容,它允许我在另一个具有公式的 sheet 中引用一个单元格:

[TestMethod]
public void SheetReferenceTest()
{
    //
    var file = new FileInfo(@"c:\temp\SheetReferenceTest.xlsx");
    if (file.Exists)
        file.Delete();

    using (var pck = new ExcelPackage(file))
    {
        var group = 1;
        var workbook = pck.Workbook;    
        var group1 = workbook.Worksheets.Add($"group{group}");
        var summarysheet = workbook.Worksheets.Add("summarysheet");

        group1.Cells["A1"].Value = 2;
        group1.Cells["A2"].Value = 3;
        group1.Cells["A3"].Value = 6;
        group1.Cells["A4"].Value = 27;
        group1.Cells["A5"].Formula = "Average(A1:A4)";

        //This shows "=group1!A5" in Excel when the cell is selected
        summarysheet.Cells["A1"].Formula = $"group{group}!A5";

        pck.Save();
    }
}

对编辑的回应

好的,现在我明白你的意思了。看来你是对的,我无法得到 excel 来处理共享字符串公式。我不确定这是 Epplus 问题,因为我什至不知道 excel 是否可以做到这一点?这是我想出的显示问题的单元测试:

[TestMethod]
public void SheetReferenceTest()
{
    //
    var file = new FileInfo(@"c:\temp\SheetReferenceTest.xlsx");
    if (file.Exists)
        file.Delete();

    using (var pck = new ExcelPackage(file))
    {
        var group = 1;
        var workbook = pck.Workbook;    
        var group1 = workbook.Worksheets.Add($"group{group}");
        var summarysheet = workbook.Worksheets.Add("summarysheet");
        var random = new Random();

        const int rows = 10;
        const int cols = 15;
        for (var r = 0; r < rows; r++)
            for (var c = 0; c < cols; c++)
                group1.Cells[r + 1, c + 1].Value = random.Next(100);

        //This works fine and auto increments the formala to B1:B10, C1:C10, etc.
        group1.Cells[rows + 1, 1, rows + 1, cols].Formula = $"AVERAGE(A1:A{rows})";

        //This does not, it just does group1!A1:A10 for all cells.
        summarysheet.Cells[rows + 1, 1, rows + 1, cols].Formula = $"AVERAGE(group1!A1:A{rows})";

        pck.Save();
    }
}

下面是 xml 工作 sheet 的样子:

<row r="11">
    <c r="A11" s="0">
        <f ref="A11:O11" t="shared" si="1">AVERAGE(A1:A10)</f>
    </c><c r="B11" s="0">
        <f t="shared" si="1"/>
    </c><c r="C11" s="0">
        <f t="shared" si="1"/>
    </c><c r="D11" s="0">
        <f t="shared" si="1"/>
    </c><c r="E11" s="0">
        <f t="shared" si="1"/>
    </c><c r="F11" s="0">
        <f t="shared" si="1"/>
    </c><c r="G11" s="0">
        <f t="shared" si="1"/>
    </c><c r="H11" s="0">
        <f t="shared" si="1"/>
    </c><c r="I11" s="0">
        <f t="shared" si="1"/>
    </c><c r="J11" s="0">
        <f t="shared" si="1"/>
    </c><c r="K11" s="0">
        <f t="shared" si="1"/>
    </c><c r="L11" s="0">
        <f t="shared" si="1"/>
    </c><c r="M11" s="0">
        <f t="shared" si="1"/>
    </c><c r="N11" s="0">
        <f t="shared" si="1"/>
    </c><c r="O11" s="0">
        <f t="shared" si="1"/>
    </c>
</row>

但对于非工作摘要sheet:

<row r="11">
    <c r="A11" s="0">
        <f ref="A11:O11" t="shared" si="1">AVERAGE(group1!A1:A10)</f>
    </c><c r="B11" s="0">
        <f t="shared" si="1"/>
    </c><c r="C11" s="0">
        <f t="shared" si="1"/>
    </c><c r="D11" s="0">
        <f t="shared" si="1"/>
    </c><c r="E11" s="0">
        <f t="shared" si="1"/>
    </c><c r="F11" s="0">
        <f t="shared" si="1"/>
    </c><c r="G11" s="0">
        <f t="shared" si="1"/>
    </c><c r="H11" s="0">
        <f t="shared" si="1"/>
    </c><c r="I11" s="0">
        <f t="shared" si="1"/>
    </c><c r="J11" s="0">
        <f t="shared" si="1"/>
    </c><c r="K11" s="0">
        <f t="shared" si="1"/>
    </c><c r="L11" s="0">
        <f t="shared" si="1"/>
    </c><c r="M11" s="0">
        <f t="shared" si="1"/>
    </c><c r="N11" s="0">
        <f t="shared" si="1"/>
    </c><c r="O11" s="0">
        <f t="shared" si="1"/>
    </c>
</row>