SonhanDev
SonhanDev

Reputation: 21

NPOI: Excel column formatted to decimal with SXSSFWorkbook?

I am developing a website with ASP.net (VS2015 C #).

I need to export a MySql table with a large amount of data (500000+ rows and 100 columns) to excel (xlsx), with format.

After trying many options, the NPOI (v 3.20) library allows this export using types that use streaming (SXSSFWorkbook & SXSSFSheet).

If I use XSSFWorkbook I get and Out of memory filling the rows.

With SXSSFWorkbook I have been able to format the xlsx with different fonts and colors, but I am having problems with the types of data exported:

The code I use to format the data is:

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++;

}

With this code, in the decimal column (cont ==3), I get a text column.

However, with the same code, if I declare the no streaming types:

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

Only with this changes I get a perfect numeric columnn 3...

For this line:

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

I have tried with different types:

In some cases I get a number, but not with the desired format.

So...streaming types do not allow this formatting?

Upvotes: 2

Views: 7965

Answers (2)

Armando Gutheil
Armando Gutheil

Reputation: 21

Just change the Culture Info to 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");

It works for me!

Upvotes: 1

kumar chandraketu
kumar chandraketu

Reputation: 2370

can you try your formatting based on below code snippet. I am using this approach to format phone number.

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

sometimes its tricky to find exact formatting in NPOI :). Please try below approaches

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

or

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

Upvotes: 0

Related Questions