Apache POI apply foating point format only if Number is decimal - java

Currently I'm using the format "#,##0.00" for all the Number type values retrieved from oracle DB to be saved in an excel file, but I don't want to save all values with a floating point if they don't have it on DB
For example
12 should be 12
12.1 should be 12.10
12.123 should be 12.12

If no special number format is set for the cell, then number format "General" is used. That will show 12 or 12.1 or 12.123. So to get what you want two different number formats ("0" (or "#,##0" if thousands separator shall be used) for integers and "#,##0.00" for decimals) are needed.
So main question is how to determine whether a number is integer or decimal. Following code does this task using the methods of Number. If number's integer value is equal to number's decimal value, then number is integer.
It creates a sheet showing 12 in A1, 12.10 in A2 and 12.12 in A3.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.util.List;
import java.util.ArrayList;
public class CreateExcelDifferentNumberformats {
public static void main(String[] args) throws Exception {
//Workbook workbook = new HSSFWorkbook();
Workbook workbook = new XSSFWorkbook();
// Create CellStyles
DataFormat format = workbook.createDataFormat();
CellStyle integerCellStyle = workbook.createCellStyle();
//integerCellStyle.setDataFormat(format.getFormat("0"));
integerCellStyle.setDataFormat(format.getFormat("#,##0"));
CellStyle decimalCellStyle = workbook.createCellStyle();
decimalCellStyle.setDataFormat(format.getFormat("#,##0.00"));
Sheet sheet = workbook.createSheet();
List<Number> numbers = new ArrayList<Number>();
numbers.add(12); numbers.add(12.1); numbers.add(12.123);
int r = 0;
for (Number number : numbers) {
Row row = sheet.createRow(r++);
Cell cell = row.createCell(0);
cell.setCellValue(number.doubleValue());
if (number.intValue() == number.doubleValue()) {
cell.setCellStyle(integerCellStyle);
} else {
cell.setCellStyle(decimalCellStyle);
}
}
FileOutputStream out = null;
if (workbook instanceof HSSFWorkbook) {
out = new FileOutputStream("./CreateExcelDifferentNumberformats.xls");
} else if (workbook instanceof XSSFWorkbook) {
out = new FileOutputStream("./CreateExcelDifferentNumberformats.xlsx");
}
workbook.write(out);
out.close();
workbook.close();
}
}

Related

How To Convert From Scientific To Number Value While Writing Excel In Apache Poi Java

I need to create an XL sheet using Apache POI with some values which are long numeric for ex:1234567891011.
When i use below sample code to generate the excel sheet, the data is stored in form of Scientific format (1.23457E+12). But i want to store this data as a number ex. 1234567891011.00 is fine.
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("format sheet");
String str = "1234567891011";
Row row;
Cell cell;
short rowNum = 0;
short colNum = 0;
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(str);
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
I tried to set the cell format to Numeric as below code but doesnt work.
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(str);
dateCell1.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
double converted = new Double(str);
dateCell1.setCellValue(converted);
Please tell if any way possible to do it.
Excel is using number format General per default. This switches to scientific format if needed. That means if cell width is too small or numeric value is too big.
So do using a cell style having a special number format 0.00 or 0.
Example:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
class CreateExcelBigDecimal {
public static void main(String[] args) throws Exception {
//Workbook workbook = new XSSFWorkbook(); String filePath = "./Excel.xlsx";
Workbook workbook = new HSSFWorkbook(); String filePath = "./Excel.xls";
DataFormat format = workbook.createDataFormat();
CellStyle numberCellStyle = workbook.createCellStyle();
numberCellStyle.setDataFormat((short)8);
numberCellStyle.setDataFormat(format.getFormat("0.00"));
Sheet sheet = workbook.createSheet();
Cell cell = sheet.createRow(0).createCell(0);
double value = 1234567891011d;
cell.setCellValue(value);
cell.setCellStyle(numberCellStyle);
sheet.setColumnWidth(0, 20*256);
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close();
workbook.close();
}
}
That leads to showing 1234567891011.00 in cell A1.
Leave the cell as String type and format your number java side.
long yourLongNumber = 1234567891011;
String strLong = String.format("%d", yourLongNumber);
//out: "1234567891011"

Apache POI shiftRows corrupts file and deletes content

I want to fill table a template excel file. I want to insert rows and fill them. I used java Apache POI library to access excel files. At first, I created a new file and filled column A from row 1 to 10 with 1..10 numbers and saved the file. Then I read the file and tried to insert a single empty row with a sheet.shiftRows() method. I tried below code but output file has a problem in the opening (reading) and rows 5,6,7 are empty and move has not occurred.
InputStream inputStream = new FileInputStream("TestIn-1.xlsx");
Workbook workbookIn = new XSSFWorkbook(inputStream);
Sheet sheetIn = workbookIn.getSheet("Sheet1");
sheetIn.shiftRows(4,5,1);
OutputStream outputStream = new FileOutputStream("TestOut.xlsx");
workbookIn.write(outputStream);
outputStream.close();
Your shiftRows tries shifting rows between row 5 (index 4) and row 6 (index 5) one row down. But what about row 7, 8, 9 and 10? You needs shifting rows between row 5 and last row one row down if the need is getting a new empty row 5.
Using apache poi version 3.17 this is as simple as:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ExcelReadShiftRowsAndWrite {
public static void main(String[] args) throws Exception {
//String fileIn= "TestIn.xls";
//String fileOut= "TestOut.xls";
String fileIn= "TestIn.xlsx";
String fileOut= "TestOut.xlsx";
try (Workbook workbook = WorkbookFactory.create(new FileInputStream(fileIn));
FileOutputStream out = new FileOutputStream(fileOut)) {
Sheet sheet = workbook.getSheet("Sheet1");
sheet.shiftRows(4, sheet.getLastRowNum(), 1); //shifts rows between row 5 (index 4) and last row one row down
workbook.write(out);
}
}
}
But apache poi versions greater than 3.17, also 4.1.0, have a bug in shiftRows using XSSF. There, after shifting, the references in the cells remain old instead being adjusted to the new rows. For example the references A5, A6, ... remain after shifting down instead of getting adjusted to A6, A7, ...
So this bug must be corrected:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ExcelReadShiftRowsAndWrite {
public static void main(String[] args) throws Exception {
//String fileIn= "TestIn.xls";
//String fileOut= "TestOut.xls";
String fileIn= "TestIn.xlsx";
String fileOut= "TestOut.xlsx";
try (Workbook workbook = WorkbookFactory.create(new FileInputStream(fileIn));
FileOutputStream out = new FileOutputStream(fileOut)) {
Sheet sheet = workbook.getSheet("Sheet1");
sheet.shiftRows(4, sheet.getLastRowNum(), 1); //shifts rows between row 5 (index 4) and last row one row down
if (sheet instanceof XSSFSheet) {
XSSFSheet xSSFSheet = (XSSFSheet)sheet;
// correcting bug that shiftRows does not adjusting references of the cells
// if row 3 is shifted down, then reference in the cells remain r="A3", r="B3", ...
// they must be adjusted to the new row thoug: r="A4", r="B4", ...
// apache poi 3.17 has done this properly but had have other bugs in shiftRows.
for (int r = xSSFSheet.getFirstRowNum(); r < sheet.getLastRowNum() + 1; r++) {
XSSFRow row = xSSFSheet.getRow(r);
if (row != null) {
long rRef = row.getCTRow().getR();
for (Cell cell : row) {
String cRef = ((XSSFCell)cell).getCTCell().getR();
((XSSFCell)cell).getCTCell().setR(cRef.replaceAll("[0-9]", "") + rRef);
}
}
}
// end correcting bug
}
workbook.write(out);
}
}
}

Apache POI sets Values in Cells of an xlsx file, but doesnt confirm them in the processing strip

I'm trying to write values into a xlsx file using java and POI.
It's nearly working as I want, but i have the following Problem:
The Values that my programm writes into the xlsx file are displayed there, but excel doesn't use my VLOOKUP and displays #N/A untill I go into the
processing strip and press Enter, then it works..
Here is my code:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.*;
public class XLSXEditor {
public XLSXEditor(){
}
public void xlsxWriter(String path, String uName, Date date/*, String timeF, String timeT*/) throws FileNotFoundException, IOException{
File excel = new File(path);
FileInputStream fis = new FileInputStream(excel);
XSSFWorkbook book = new XSSFWorkbook(fis);
XSSFSheet sheet = book.getSheetAt(1);
int r = getNonBlankRowCount(path);
XSSFRow row = sheet.getRow(r);
//Datum Style
CellStyle csDate = book.createCellStyle();
CreationHelper createHelper = book.getCreationHelper();
csDate.setDataFormat(createHelper.createDataFormat().getFormat("dd.mm.yyyy"));
csDate.setBorderBottom(XSSFCellStyle.BORDER_THIN);
csDate.setBorderTop(XSSFCellStyle.BORDER_THIN);
csDate.setBorderLeft(XSSFCellStyle.BORDER_THIN);
csDate.setBorderRight(XSSFCellStyle.BORDER_THIN);
csDate.setFillForegroundColor(IndexedColors.LIGHT_TURQUOISE.getIndex());
csDate.setFillPattern(CellStyle.SOLID_FOREGROUND);
//uname style
CellStyle csUname = book.createCellStyle();
csUname.setBorderBottom(XSSFCellStyle.BORDER_THIN);
csUname.setBorderTop(XSSFCellStyle.BORDER_THIN);
csUname.setBorderLeft(XSSFCellStyle.BORDER_THIN);
csUname.setBorderRight(XSSFCellStyle.BORDER_THIN);
csUname.setFillForegroundColor(IndexedColors.LIGHT_TURQUOISE.getIndex());
csUname.setFillPattern(CellStyle.SOLID_FOREGROUND);
//fill username column in xlsx file
XSSFCell celluName = row.getCell(0, Row.RETURN_BLANK_AS_NULL);
while(celluName != null){
r++;
row = sheet.createRow(r);
celluName = row.createCell(0);
}
if(celluName == null){
celluName = sheet.getRow(r).createCell(0);
celluName.setCellStyle(csUname);
}
celluName.setCellValue(uName);
//fill date column in xlsx file
XSSFCell cellDate = row.getCell(5, Row.RETURN_BLANK_AS_NULL);
while(cellDate != null){
r++;
row = sheet.createRow(r);
cellDate = row.getCell(5);
}
if(cellDate == null){
cellDate = sheet.getRow(r).createCell(5);
cellDate.setCellValue(date);
cellDate.setCellStyle(csDate);
}
//fill PNr column in xlsx file
int r1 = r+1;
XSSFCell cellPNr = row.getCell(1, Row.RETURN_BLANK_AS_NULL);
cellPNr = sheet.getRow(r).createCell(1);
cellPNr.setCellValue("=SVERWEIS(A"+r1+";'MA Stamm'!$A$2:$E$98;2;FALSCH)");
FileOutputStream fos = new FileOutputStream(path);
book.write(fos);
fos.flush();
fos.close();
}
public int getNonBlankRowCount(String path) throws IOException{
File excel = new File(path);
FileInputStream fis = new FileInputStream(excel);
XSSFWorkbook book = new XSSFWorkbook(fis);
XSSFSheet sheet = book.getSheetAt(1);
int rowCount = 0;
int index = book.getSheetIndex(sheet);
if(index==-1){
rowCount=-1;
return rowCount;
}
else{
sheet=book.getSheetAt(index);
Iterator<Row> rowIterator = sheet.rowIterator();
rowCount=0;
while(rowIterator.hasNext()){
Row row = (Row) rowIterator.next();
XSSFCell cell =(XSSFCell) row.getCell(0, Row.RETURN_BLANK_AS_NULL);
if(cell == null){
break;
}
rowCount++;
}
return rowCount;
}
}
}
Formula cell content is fundamentally different from text cell content in Excel. Your code line:
cellPNr.setCellValue("=SVERWEIS(A"+r1+";'MA Stamm'!$A$2:$E$98;2;FALSCH)");
sets a string cell value instead of a formula. Do using Cell.setCellFormula instead to set formula cell content.
And since Excel stores only formulas in English_US notation in its files you need using English_US notation of the formula:
cellPNr.setCellFormula("VLOOKUP(A"+r1+",'MA Stamm'!$A$2:$E$98,2,FALSE)");
English_US notation means English function names (for ex. VLOOKUP instead of SVERWEIS), English constant names (for ex. FALSE instead of FALSCH), comma as parameter delimiter (for ex. VLOOKUP(A1,F1:G100,2,FALSE) instead of VLOOKUP(A1;F1:G100;2;FALSE)) and dot as decimal delimiter in floating point literals (for ex. SUM(1.23, 3.45, 4) instead of SUMME(1,23; 3,45; 4).
The localization is made in the localized Excel GUI versions after opening the file.
And then you need some kind of Formula Recalculation. Simplest way is by delegating re-calculation to Excel by setting:
book.setForceFormulaRecalculation(true);
before writing out the book.

Apache POI setCellData not actually setting cell data

Using Apache POI 3.16
Eclipse IDE neon 3
Selenium 3.4 (not that it matters in this case)
I'm having an issue with writing values to an excel spreadsheet then reading back the value.
Here's what I want to do at a high level:
Open up an excel file
write to row 1 column 1 (we are using index starting at 0)
Read back what was written in that cell.
The cell contains the value "B2". In a setCellData() function, I write to the cell a "Hello World" and have the function return the contents of the cell. I also have a separate function that reads in the contents of a specified cell.
When I run the following code:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class Udemy_Excel_Driven {
public static XSSFWorkbook wb;
public static XSSFSheet sheet;
public static XSSFRow row;
public static XSSFCell cell;
public static FileInputStream fis;
public static void main(String[] args) throws IOException, Exception
{
System.out.println("Before cell edit value is:");
System.out.println(getCellData(1,1));
String value = setCellData(1,1,"Hello World");
System.out.println("What's the value after setting it with setCellData()?");
System.out.println(value);
System.out.println("What's the value using getCellData()?");
System.out.println(getCellData(1,1));
}
public static String getCellData(int rowNum, int colNum) throws IOException
{
/*
* Hierarchy of excel data:
*
* Workbook - take control of this
* Sheet - pick up the sheet of the workbook
* Row - pick the row
* Column - after picking the row, select the column
* Value - grab the value from the cell
*
*/
//0. = identify the path to the excel file in the system.
fis = new FileInputStream("C:\\data.xlsx");
//1. Create a new XSSFWorkbook object. You need to pass in a FileInputStream object into it, which you created earlier.
wb = new XSSFWorkbook(fis);
//2. Get the sheet in the workbook. Create a new XSSFsheet object and set it to the sheet in the workbook
// Access the workbook method "getSheet" and pass in the name of the sheet
sheet = wb.getSheet("script");
//3. Get the row and column. We are going to access the data from row 2 column 2. And remember the indices start at 0.
row = sheet.getRow(rowNum);
cell = row.getCell(colNum);
//get the value specified in the row and cell
return cell.getStringCellValue();
}
public static String setCellData(int rowNum, int colNum, String data) throws IOException
{
fis = new FileInputStream("C:\\data.xlsx");
wb = new XSSFWorkbook(fis);
sheet = wb.getSheet("script");
row = sheet.getRow(rowNum);
cell = row.getCell(colNum);
cell.setCellValue(data);
String cellData = cell.getStringCellValue();
return cellData;
}
I get the following output:
Before cell edit value is:
B2
What's the value after setting it with setCellData()?
Hello World
What's the value using getCellData()?
B2
I don't think the write actually occurred since I opened up the excel file and the "Hello World" string wasn't in the specified cell. Any answers to this issue?
I don't see any part of your code that actually writes to your file.
It should more or less look something like this:
FileOutputStream fileOut = new FileOutputStream("C:\\data.xlsx");
wb.write(fileOut);
fileOut.close();
You can also consult this guide for this issue as well as other functionality that you might be interested in implementing.

POI Java - Numeric Cell with Decimals

I'm having a lot of problems with numeric formats in a Cell with POI.
I need to print in the cell 11 decimals for a number and also that the cell has a numeric format to make the sum when you select the data
And I have this code:
private void writeDecimal(HSSFRow row, Double data, int position) {
String pattern = "#.0000000000";
HSSFCell celda = row.createCell(position);
CellStyle styleDecimal = styles.get(ITEM_DECIMAL); // Font and alignment
styleDecimal.setDataFormat(libro.getCreationHelper().createDataFormat().getFormat(pattern));
celda.setCellStyle(styleDecimal);
celda.setCellType(Cell.CELL_TYPE_NUMERIC);
celda.setCellValue(data);
}
But the result always print less decimal because Excel rounds the number:
If I convert the Double to String, prints the 11 decimals but it doesn't make the sum if I select all the numbers.
Any idea how to resolve this?
Thanks
Open the xlsx file select the column , right click on cell -> Format cells...->custom->type = 0.00000000000 click ok.
now whatever you will write on that cell, it will print on that format and if you select also it will show the sum.
by code
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
public class ChangeXlxsDataFormat {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Workbook wb = new HSSFWorkbook();
Sheet sheet = (Sheet) wb.createSheet("format sheet");
CellStyle style;
DataFormat format = wb.createDataFormat();
Row row;
Cell cell;
short rowNum = 0;
short colNum = 0;
row = sheet.createRow(rowNum);
cell = row.createCell(colNum);
style = wb.createCellStyle();
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
style = wb.createCellStyle();
style.setDataFormat(format.getFormat("0.00000000000"));
cell.setCellStyle(style);
cell.setCellValue(5.12345678908);
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(2.12345678908);
FileOutputStream fileOut = new FileOutputStream("test.xls");
wb.write(fileOut);
fileOut.close();
}
}
This code snippet doesn't contain celda.setCellStyle( styleDecimal ). Is it missing in the real code too? Add it.
Edit:
Here is a simple example using your function. It works well.
private static HSSFWorkbook workbook;
public static void main( String args[] ) throws IOException {
workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet( "sheet" );
HSSFRow row = sheet.createRow( 0 );
writeDecimal( row, 0.0781013, 0 );
FileOutputStream fos = new FileOutputStream( "workbook.xls", false );
workbook.write( fos );
fos.close();
}
private static void writeDecimal( HSSFRow row, Double data, int position ) {
String pattern = "#.0000000000";
HSSFCell celda = row.createCell(position);
CellStyle styleDecimal = workbook.createCellStyle(); // Font and alignment
styleDecimal.setDataFormat(workbook.createDataFormat().getFormat(pattern));
celda.setCellStyle(styleDecimal);
celda.setCellType(Cell.CELL_TYPE_NUMERIC);
celda.setCellValue(data);
}
What was the problem in your code? I don't know. Your style definitely wasn't applied to the page: zeros shouldn't be rendered with "#".

Categories