【问题标题】:NPOI: Excel column formatted to decimal with SXSSFWorkbook?NPOI:使用 SXSSFWorkbook 格式化为十进制的 Excel 列?
【发布时间】:2017-11-01 20:30:32
【问题描述】:

我正在用 ASP.net (VS2015 C#) 开发一个网站。

我需要将包含大量数据(500000+ 行和 100 列)的 MySql 表导出到 excel (xlsx),格式。

在尝试了许多选项后,NPOI (v 3.20) 库允许使用使用流式传输的类型 (SXSSFWorkbook & SXSSFSheet) 进行此导出。

如果我使用 XSSFWorkbook 我会得到内存不足填充行。

使用SXSSFWorkbook,我已经能够用不同的字体和颜色格式化xlsx,但是我在导出的数据类型方面遇到了问题:

  • 日期类型正常
  • Int 类型正常
  • 文字没问题
  • 像 100.35 这样的小数输入 --> 问题,我得到一个文本列。我需要一个像数字 100,35 这样的输出。

我用来格式化数据的代码是:

SXSSFWorkbook wb = new SXSSFWorkbook();
SXSSFSheet sh = (SXSSFSheet)wb.CreateSheet("Sheet 1");
sh.SetRandomAccessWindowSize(100);

ICellStyle testStyleHeader = wb.CreateCellStyle();
ICellStyle testStyleRow = wb.CreateCellStyle();

// Header Style
testStyleHeader.FillForegroundColor = NPOI.SS.UserModel.IndexedColors.RoyalBlue.Index;
testStyleHeader.FillPattern = FillPattern.SolidForeground;

// Double style (with 2 decimals like 453.65)
ICellStyle cellStyleDouble = wb.CreateCellStyle();
cellStyleDouble.DataFormat = wb.CreateDataFormat().GetFormat("0.00");

// Font 
XSSFFont hFontBlack = (XSSFFont)wb.CreateFont();
hFontBlack.FontHeightInPoints = 11;
hFontBlack.FontName = "Calibri";
hFontBlack.Color = NPOI.SS.UserModel.IndexedColors.Black.Index;
testStyleHeader.SetFont(hFontBlack);

IRow row = sh.CreateRow(0);
int j = 0;
ICell cell = row.CreateCell(j);

// Fill Header row
cell.SetCellValue("XXXX"); cell.CellStyle = testeStyleHeader; j++; cell = row.CreateCell(j);
cell.SetCellValue("YYYY"); cell.CellStyle = testeStyleHeader; j++; cell = row.CreateCell(j);
cell.SetCellValue("ZZZZ"); cell.CellStyle = testeStyleHeader; j++; cell = row.CreateCell(j);
cell.SetCellValue("WWWW"); cell.CellStyle = testeStyleHeader; j++; cell = row.CreateCell(j);

// Fill Rows
int i = 1; // row Number
IRow row2; // No Header Row
ICell cell2; // No Header cell

while (dr.Read())  // dr is the DataReader
{
   row2 = sh.CreateRow(i);
                                                            
  for (int cont = 0; cont < NumColumns; cont++) 
  {
     if (cont == 0) // This column is a date
     {
       …. // code for date format
     }
     else if (cont == 3) // Double column with 2 decimals¡! (values samples 100.45   5654.80 etc.)
     {
        ICell cell3 = row2.CreateCell(j, NPOI.SS.UserModel.CellType.Numeric);
        cell3.CellStyle = cellStyleDouble;
        cell3.SetCellValue(Convert.ToDouble(dr[cont]));
      }
     else
     {…. // code for tex format, int format etc.
     }
   }
   i++;

}

使用此代码,在小数列 (cont ==3) 中,我得到一个文本列。

但是,使用相同的代码,如果我声明无流类型:

XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sh = (SSFSheet)wb.CreateSheet("Sheet 1");

只有通过这些更改,我才能得到一个完美的数字列 3...

对于这一行:

cellStyleDouble.DataFormat = wb.CreateDataFormat().GetFormat("0.00");

我尝试过不同的类型:

  • “#.#”
  • "#,##0.000"
  • “##.#”
  • 等等……

在某些情况下,我得到一个数字,但不是所需的格式。

所以...流式传输类型不允许这种格式?

【问题讨论】:

  • 我也遇到了同样的问题。此外,创建的文件已损坏。 Excel 成功恢复文件的数据,但十进制数字是文本(而整数是正确的数字)

标签: asp.net excel npoi


【解决方案1】:

只需将文化信息更改为 en-US

        Thread.CurrentThread.CurrentCulture = new CultureInfo("en-Us");

        ISheet worksheet = Workbook.CreateSheet(dt.TableName);

        IRow HeaderRow = worksheet.CreateRow(0);

        for (int i = 0; i < dt.Columns.Count; i++)
        {
            ICell HeaderCell = HeaderRow.CreateCell(i);

            HeaderCell.SetCellValue(dt.Columns[i].ColumnName);
        }

        for (int j = 0; j < dt.Rows.Count; j++)
        {
            IRow Row = worksheet.CreateRow(j + 1);

            for (int i = 0; i < dt.Columns.Count; i++)
            {
                ICell Cell = Row.CreateCell(i);

                if (dt.Columns[i].DataType.IsOfType(typeof(decimal)) && dt.Rows[j][i] != DBNull.Value)
                {
                    Cell.SetCellType(CellType.Numeric);

                    Cell.SetCellValue((double)dt.Rows[j][i]);
                }
                else
                    Cell.SetCellValue(dt.Rows[j][i].ToString());
            }
        }

        Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-Br");

它对我有用!

【讨论】:

  • 它也适用于我,但我不知道为什么。有人可以解释一下吗?
【解决方案2】:

你能根据下面的代码 sn-p 试试你的格式吗?我正在使用这种方法来格式化电话号码。

XSSFCellStyle currencyCellStyle = (XSSFCellStyle)workbook.CreateCellStyle();
XSSFDataFormat currencyDataFormat = (XSSFDataFormat)workbook.CreateDataFormat();
currrencyCellStyle.SetDataFormat(currencyDataFormat.GetFormat("00000.00"));  //Formats: #####.##, 00000##.##

有时很难在 NPOI 中找到准确的格式:)。请尝试以下方法

 ICellStyle CellStyle = workbook.CreateCellStyle();
 CellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("number"); // or Number

CellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat("#.#")); // or #####.## or number

【讨论】:

  • 这种方式我试过了,但我得到的列是文本类型.... :-(
  • 我已经提到了另外两种方法。你能不能有时尝试一下它在 NPOI 中的命中和试验以获得实际输出。
  • 我一直在测试这两种形式的所有可能组合,但我仍然在输出中得到文本。我认为问题在于 SXSSFWorkbook 和 SXSSFSheet 类型,因为使用非流式版本我得到了正确的数字输出。可能是该库没有为使用流类型的双打实现正确的格式吗?
  • 它可能有问题。您可以尝试将其提交到他们的论坛。根据他们的文档,poi.apache.org/apidocs/org/apache/poi/ss/usermodel/… 建议的语法看起来是正确的。
  • 我认为 Java POI 可能与此一起使用,但 NPOI 在此问题中尚未完成(带有流数据的数字格式)...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 1970-01-01
相关资源
最近更新 更多