【问题标题】:Using EPPlus how can I generate a spreadsheet where numbers are numbers not text使用 EPPlus 如何生成数字是数字而不是文本的电子表格
【发布时间】:2015-10-10 20:15:11
【问题描述】:

我正在使用 LoadFromArraysList<object[]> 创建电子表格

数组的第一个条目是标题,其他条目可能是数字、文本或日期(但列表中的每个数组都相同)。

生成的 Excel 工作表带有绿色三角形警告,表示数字格式为文本。

我遍历所有单元格并将它们的格式设置为 Number 像这样ws.Cells[i, j].Style.Numberformat.Format = "0";

但是问题仍然存在,我仍然看到绿色警告,即使在我查看 Format Cell... 对话框时数字格式设置为数字。

我在这里有什么选择?我可以更多地了解每列中的类型,但是如何设置列标题?

有比 EPPlus 更好的解决方案吗?或者我可以在下载之前对电子表格进行更多后期处理?

【问题讨论】:

  • 通常这些绿色三角形来自存储在字符串变量或属性中的数字(在代码中)。因此,无论您如何设置 excel,您都必须将字符串转换为代码中的数字。会是这样吗?

标签: c# excel epplus


【解决方案1】:

由于您使用的是对象数组,它们可以包含看起来像数字的数字和字符串,您必须遍历每个对象并确定其类型:

[TestMethod]
public void Object_Type_Write_Test()
{
    //http://stackoverflow.com/questions/31537981/using-epplus-how-can-i-generate-a-spreadsheet-where-numbers-are-numbers-not-text
    var existingFile = new FileInfo(@"c:\temp\temp.xlsx");
    if (existingFile.Exists)
        existingFile.Delete();

    //Some data
    var list = new List<Object[]>
    {
        new object[]
        {
            "111.11",
            111.11,
            DateTime.Now
        }
    };

    using (var package = new ExcelPackage(existingFile))
    {
        var ws = package.Workbook.Worksheets.Add("Sheet1");
        ws.Cells[1, 1, 2, 2].Style.Numberformat.Format = "0";
        ws.Cells[1, 3, 2, 3].Style.Numberformat.Format = "[$-F400]h:mm:ss\\ AM/PM";

        //This will cause numbers in string to be stored as string in excel regardless of cell format
        ws.Cells["A1"].LoadFromArrays(list);

        //Have to go through the objects to deal with numbers as strings
        for (var i = 0; i < list.Count; i++)
        {
            for (var j = 0; j < list[i].Count(); j++)
            {

                if (list[i][j] is string)
                    ws.Cells[i + 2, j + 1].Value = Double.Parse((string) list[i][j]);
                else if (list[i][j] is double)
                    ws.Cells[i + 2, j + 1].Value = (double)list[i][j];
                else
                    ws.Cells[i + 2, j + 1].Value = list[i][j];

            }
        }

        package.Save();
    }
}

通过上面的操作,您可以看到下图作为输出 注意左上角的单元格带有绿色箭头,因为它是由LoadFromArray 编写的字符串,看起来像一个数字:

【讨论】:

  • 一个赞成票和一个小勾是对这个奇妙帮助的小小补偿......我真的很喜欢这个!
  • @Loofer Na,没问题。很高兴它有帮助。
【解决方案2】:

我基于 EPPlus LoadFromArray 创建了一个扩展方法 LoadFormulasFromArray。该方法假定列表中的所有对象都被视为公式(而不是LoadFromArray)。大局是ValueFormula 属性都采用string 而不是特定的类型。我认为这是一个错误,因为无法区分字符串是Text 还是Formula。实现 Formula 类型将启用重载和类型检查,从而可以始终做正确的事情。

// usage: ws.Cells[2,2].LoadFormulasFromArrays(MyListOfObjectArrays)

public static class EppPlusExtensions
{
    public static ExcelRangeBase LoadFormulasFromArrays(this ExcelRange Cells, IEnumerable<object[]> Data)
    {
        //thanx to Abdullin for the code contribution
        ExcelWorksheet _worksheet = Cells.Worksheet;
        int _fromRow = Cells.Start.Row;
        int _fromCol = Cells.Start.Column;
        if (Data == null) throw new ArgumentNullException("data");

        int column = _fromCol, row = _fromRow;

        foreach (var rowData in Data)
        {
            column = _fromCol;
            foreach (var cellData in rowData)
            {
                Cells[row, column].Formula = cellData.ToString();
                column += 1;
            }
            row += 1;
        }
        return Cells[_fromRow, _fromCol, row - 1, column - 1];
    }
}

【讨论】:

    【解决方案3】:

    诀窍是不要将数字作为“原始对象”传递给 EPPlus,而是正确地转换它们。

    以下是我在使用 EPPlus 制作的 DataTable-to-Excel 导出方法中的做法:

    if (dc.DataType == typeof(int)) ws.SetValue(row, col, !r.IsNull(dc) ? (int)r[dc] : (int?)null);
    else if (dc.DataType == typeof(decimal)) ws.SetValue(row, col, !r.IsNull(dc) ? (decimal)r[dc] : (decimal?)null);
    else if (dc.DataType == typeof(double)) ws.SetValue(row, col, !r.IsNull(dc) ? (double)r[dc] : (double?)null);
    else if (dc.DataType == typeof(float)) ws.SetValue(row, col, !r.IsNull(dc) ? (float)r[dc] : (float?)null);
    else if (dc.DataType == typeof(string)) ws.SetValue(row, col, !r.IsNull(dc) ? (string)r[dc] : null);
    else if (dc.DataType == typeof(DateTime))
    {
        if (!r.IsNull(dc))
        {
            ws.SetValue(row, col, (DateTime)r[dc]);
            // Change the following line if you need a different DateTime format
            var dtFormat = "dd/MM/yyyy";
            ws.Cells[row, col].Style.Numberformat.Format = dtFormat;
        }
        else ws.SetValue(row, col, null);
    }
    

    重要提示:值得注意的是,DateTime 值需要更多的工作才能正确处理,因为我们希望以某种方式对其进行格式化,并且可以说支持 NULL 值column: 上述方法同时满足这两个要求。

    我在this post on my blog 中发布了完整的代码示例(使用 EPPlus 将数据表转换为 Excel 文件)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      相关资源
      最近更新 更多