0

I'm creating a spreadsheet with EPPlus. I am trying to get a formula to calculate a sum of values with this code:

using (var totalOccurrencesCell = priceComplianceWorksheet.Cells[rowToPopulate, 2])
{
    totalOccurrencesCell.Style.Font.Size = DATA_FONT_SIZE;
    totalOccurrencesCell.Style.Numberformat.Format = NUMBER_FORMAT_THOUSANDS;
    if (rowToPopulate <= SUMMARY_HEADING_ROW + 1)
    {
        totalOccurrencesCell.Value = "0";
    }
    else
    {
        //totalOccurrencesCell.Formula = string.Format("SUM(B5:B{0})", rowToPopulate - 1);
        // TODO: Comment out or remove below after finding out why the above is not working
        totalOccurrencesCell.Formula = "SUM(B5:B19)";
        totalOccurrencesCell.Calculate();
    }
}

What I would think is correct is being applied to that cell, as can be seen here, namely "=SUM(B5:B19)":

enter image description here

So why is "0" the result? The same is true for column C, and D is also catawamptuously chawed up for some reason, too.

This similar code does work elsewhere on the sheet:

using (var totalVarianceCell = priceComplianceWorksheet.Cells[rowToPopulate, DETAIL_TOTALVARIANCE_COL])
{
    totalVarianceCell.Style.Font.Size = DATA_FONT_SIZE;
    totalVarianceCell.Style.Numberformat.Format = NUMBER_FORMAT_CURRENCY;
    totalVarianceCell.Formula = string.Format("SUM(J{0}:J{1})", _firstDetailDataRow, rowToPopulate - 1);
    totalVarianceCell.Calculate();
}

It sums the value in the appropriate range of column J (10), and when clicking in the "sum" cell, it shows "=SUM(J23:J39)" as the value there.

Why would it work in one case, but fail in the others?

NOTE: I am populating the cells like so ("total" is an int):

totalOccurrencesCell.Value = total.ToString("N0", CultureInfo.CurrentCulture);

UPDATE

This is inelegant and a bit disappointing, but as of now, at least, I'm having to "brute force it" this way:

totalOccurrencesCell.Value = SumCellVals(2, 5, rowToPopulate - 1);
. . .
private string SumCellVals(int colNum, int firstRow, int lastRow)
{
    double runningTotal = 0.0;
    double currentVal;
    for (int i = firstRow; i <= lastRow; i++)
    {
        using (var taterTotCell = priceComplianceWorksheet.Cells[i, colNum])
        {
            currentVal = Convert.ToDouble(taterTotCell.Value);
            runningTotal = runningTotal + currentVal;
        }
    }
    return runningTotal.ToString();
}
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    Is it possible the cells in column B are populated with Text instead of Integers? If I try to SUM a data column in Excel, and that column is "formatted" for "text", my SUM(A1:A4) return 0 even though my 4 cells are filled with *numbers* which are actually being read as text. Which could explain why you need to `Convert.ToDouble(taterTotCell.Value)` to make it work? – blaze_125 Aug 23 '16 at 17:52
  • I'll have to check if there's any difference between the way it is populated with data and the other cases where using Formula works; it seems to me, though, that SUM() should convert, if necessary, the values to numeric ones. I am populating the cells like so ("total" is an int): totalOccurrencesCell.Value = total.ToString("N0", CultureInfo.CurrentCulture); – B. Clay Shannon-B. Crow Raven Aug 23 '16 at 18:07
  • 1
    May I suggest you open the file in Excel and see if the data column is marked as text? In my Excel spreadsheet, the cells containing numbers that are going to be read as text are identified with a "green corner", and there is also a "!" icon that appears if I select the cell. – blaze_125 Aug 23 '16 at 18:23
  • No, I see neither - no green corners, and no exclamation when selecting any of those cells. I guess I'll just keep the manual summation code shown in my Update. Thanks, though. – B. Clay Shannon-B. Crow Raven Aug 23 '16 at 18:26
  • You can ignore the error and the green corner and exclamation mark both disappear, yet the sum adds up to 0. Also, you can turn off background error checking which would keep the corner and ! from showing up as well even if it's a number stored as text. – Duston Aug 23 '16 at 19:47
  • What do you mean "ignore the error"? – B. Clay Shannon-B. Crow Raven Aug 23 '16 at 20:01
  • 1
    Seems like calculation is set to manual. You can try =SUMPRODUCT(B5:B19*1) – Slai Aug 23 '16 at 20:08
  • Well, I've got it working now, but I'm still curious why trying to use a Formula doesn't work in this case, whereas it does work elsewhere with virtually the same code. – B. Clay Shannon-B. Crow Raven Aug 23 '16 at 20:10

1 Answers1

1

The clue for the behavior is in this sentence in your question:

NOTE: I am populating the cells like so ("total" is an int):

totalOccurrencesCell.Value = total.ToString("N0", CultureInfo.CurrentCulture);

There is no need to convert numeric values to strings before you assign them to the Value property of a cell.

I can reproduce what you see by running this MCVE:

static void test4()
{
    var fs = new System.IO.FileInfo(@"c:\temp\test4.xlsx");

    if (fs.Exists) fs.Delete();

    using (ExcelPackage package = new ExcelPackage(fs))
    {

        ExcelWorksheet worksheet = package.Workbook.Worksheets["Test"];
        if (worksheet == null) worksheet = package.Workbook.Worksheets.Add("Test");
        var WS = worksheet;
        WS.Workbook.CalcMode = ExcelCalcMode.Manual;

        // strings with .
        WS.Cells[1, 1].Value = "100.0";
        WS.Cells[2, 1].Value = "42.1";
        using (var sum = WS.Cells[3, 1])
        {
            sum.Formula = "SUM(A1:A2)";
            sum.Calculate();
        }

        // strings with ,
        WS.Cells[1, 2].Value = "100,0";
        WS.Cells[2, 2].Value = "42,1";
        using (var sum = WS.Cells[3, 2])
        {
            sum.Formula = "SUM(B1:B2)";
            sum.Calculate();
        }

        // strings with ,
        WS.Cells[1, 3].Value = "1,100";
        WS.Cells[2, 3].Value = "42";
        using (var sum = WS.Cells[3, 3])
        {
            sum.Formula = "SUM(C1:C2)";
            sum.Calculate();
        }

        // let EPPLUS handle it 
        WS.Cells[1, 4].Value = 100; // int
        WS.Cells[2, 4].Value = 42.1d; // double
        using (var sum = WS.Cells[3, 4])
        {
            sum.Formula = "SUM(D1:D2)";
            sum.Calculate();
        }

        package.Save();
    }
}

This is what I get in my Excel sheet as result:

result in excel

You notice that some cell have the error indicators, but some don't. It is easy to be misled by this. This effect is influenced by the settings for the separators:

separators in Excel Options

In my testing however, column D always was calculated, no matter how I changed the thousands and decimal separator, the SUM was always calculated. Specially if you are converting to strings, using the currentculture isn't a guarantee this will work as the settings in Excel might have been oveeruled.

tl;dr; don't convert numbers (int, doubles, float) to strings but assign them to the value of the cell as is. Both EPPLUS and Excel will handle the correct representation.

Community
  • 1
  • 1
rene
  • 41,474
  • 78
  • 114
  • 152