Apache POI setCellData not actually setting cell data - java

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.

Related

How to copy/write particular row using apache poi

I know i am missing the main function here. I want to copy/ write only particular row from my source excel to destination excel using apache POI.
eg. My source excel has 10 rows. I need only 5th row to be copied to my destination excel.
My class,
public class Test1 {
public static void main(String[] args) throws Exception{
File srcFile=new File("C:\\Test\\Read.xlsx");
FileInputStream fis=new FileInputStream(srcFile);
XSSFWorkbook wb=new XSSFWorkbook(fis);
XSSFSheet sheet1=wb.getSheetAt(0);
File desFile=new File("C:\\Test\\Write.xlsx");
FileOutputStream fout=new FileOutputStream(desFile);
wb.write(fout);
wb.close();
}
}
As per the Apache POI docs, you can use the XSSFSheet.getRow(int) method to get a row at a specific index.
// 5th row
Row row = sheet.getRow(4);
To add this row to a new workbook, you'll have to iterate through each cell in the row object and set the value of cells in the new workbook to these values. An example can be found here.

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);
}
}
}

Get the computed value of a formula in Excel using Apache POI 3.14

Update 2: Well for some reason I completely forgot to mention that the cell I am trying to access is actually summing up cells that contain formulas themselves. These cells contain a SUMIF formula as such:
=SUMIF('Sheet1'!B2:B4,DATE(2016,8,31),'Sheet1'!E2:E4)
So my reasoning was that I had to evaluate these cells before evaluating the actual cell I need, and this is where the FormulaEvaluator isn't working correctly. In other words, the simple SUM function is evaluating as intended, but is mistakenly summing up 0.0 from the cells containing the SUMIF functions. I tried using evaluator.sumInCell() every time I would update a cell containing the SUMIF function, but that is evaluating into 0.0 as well.
Does it have to do with the libraries not supporting the SUMIF function? Or maybe I should change the condition?
=========================================================================
Update: Okay so I only managed to get the correct value by manually opening the excel file and then closing it right after. I would get a prompt to save my changes to the file when in fact I made none. I imagine there's something wrong with how I am generating and manipulating the file.
private void createDataFile(File dataFile) throws IOException {
FileOutputStream fos = new FileOutputStream(dataFile);
XSSFWorkbook workBook = new XSSFWorkbook();
//
// Code to create and populate rows and cells
//
workBook.write(fos);
fos.close();
}
private void updateSheet(File dataFile) throws IOException {
Workbook workBook = WorkbookFactory.create(new FileInputStream(dataFile));
Sheet sheet = workBook.getSheet(0);
//
// Code to update and manipulate cells
//
FileOutputStream fos = new FileOutputStream(dataFile);
workBook.write(fos);
fos.close();
}
Note: I am only able to read the value through cell.getNumericCellValue(), FormulaEvaluator still doesn't work either way.
=========================================================================
Hello I am trying to read a value computed using a formula in an excel sheet.
The formula is a simple sum function as follows: SUM(B2:B6).
Using Apache POI 3.14 libraries, I came up with the following snippet of code:
public Double getCellValue() throws IOException, InvalidFormatException{
Workbook workBook = WorkbookFactory.create(new FileInputStream(new File("data.xlsx")));
Sheet sheet = workBook.getSheetAt(0);
// i only need one specific cell, at the last row in my sheet
Row row = sheet.getRow(sheet.getLastRowNum());
Cell cell = row.getCell(1);
// this is where I am stuck
FormulaEvaluator evaluator = workBook.getCreationHelper().createFormulaEvaluator();
CellValue cellValue = evaluator.evaluate(cell);
return cellValue.getNumberValue();
}
I made sure that I am targeting the correct cell, however this method returns 0.0 instead of the correct computed value.
I initially tried a different approach using cell.getNumericCellValue() instead of FormulaEvaluator, however that was giving me the same incorrect result, 0.0.
After going through the documentation online, I failed to find an explanation to my problem, any insight on the matter would be greatly appreciated.
Cheers.
With
This works for me:
import org.apache.poi.ss.usermodel.*;
import java.io.File;
import java.io.FileInputStream;
public final class Demo {
public static void main(final String[] args) throws Exception {
System.out.println(getCellValue());
}
public static Double getCellValue() throws Exception {
final Workbook workBook = WorkbookFactory.create(new FileInputStream(new File("data.xlsx")));
final Sheet sheet = workBook.getSheetAt(0);
// i only need one specific cell, at the last row in my sheet
final Row row = sheet.getRow(1);
final Cell cell = row.getCell(0); // formula in A2
System.err.println(cell.getCellFormula());
// this is where I am stuck
final FormulaEvaluator evaluator = workBook.getCreationHelper().createFormulaEvaluator();
final CellValue cellValue = evaluator.evaluate(cell);
return cellValue.getNumberValue();
}
}
output:
SUM(B2:B6)
15.0
So I assume there is some issue with your way to get the cell, or the xlsx content. Using a debugger, you should be able to figure out whats wrong

Using Apache POI to get/modify cell values in one or more Excel sheets

I have a small application written in Java which uses Apache POI to read/modify values in an Excel document. I'm referencing cells using sheet name, like for cell A1 in sheet "Sheet1", I use "Sheet1!A1".
The application runs from the command line with three arguments: the document name, the cells with values I want to replace, the cells from where I want to get the output.
Example: ReadExcel test.xls Sheet1!B2=10;Sheet1!B3=20 Sheet1!B7
The above example works fine.
The problem is when I want to modifiy cells or get the output from another sheet.
Example: ReadExcel test.xls Sheet1!B2=10;Sheet1!B3=20 Sheet2!B2
My code is bellow:
package poitest;
import java.util.List;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.*;
public class ReadExcel {
public static void main(String[] args) throws FileNotFoundException, IOException {
// Will contain cell name / value pair for input cells
Map<String, String> inputCellsMap = new HashMap<String, String>();
// Will contain cell name for output cells
List<String> outputCells = new ArrayList<String>();
// Open the Excel file
FileInputStream file = new FileInputStream(new File(args[0]));
// Get the current workbook
HSSFWorkbook workbook = new HSSFWorkbook(file);
// Get the first sheet of the workbook
HSSFSheet sheet = workbook.getSheetAt(0);
// Get the input cells that need to be modified and
// store their name and value in the inputCellsMap
for (String element : args[1].split(";")) {
inputCellsMap.put(element.split("=")[0], element.split("=")[1]);
}
// Get the output cells that will be accessed for resulting values
for (String element : args[2].split(";")) {
outputCells.add(element);
}
// Loop through the cells that need to be modified and
// set the new value in the Excel document
Iterator<Entry<String,String>> inputIterator = inputCellsMap.entrySet().iterator();
while (inputIterator.hasNext()) {
Map.Entry<String,String> inputEntry = (Map.Entry<String,String>) inputIterator.next();
CellReference cellReferenceInput = new CellReference(inputEntry.getKey());
int cellReferenceInputRow = cellReferenceInput.getRow();
int cellReferenceInputColumn = cellReferenceInput.getCol();
Row rowInput = sheet.getRow(cellReferenceInputRow);
if (rowInput == null)
rowInput = sheet.createRow(cellReferenceInputRow);
Cell cellInput = rowInput.getCell(cellReferenceInputColumn, Row.CREATE_NULL_AS_BLANK);
cellInput.setCellValue(Integer.parseInt(inputEntry.getValue()));
}
// Apply all formulas after altering cell values
HSSFFormulaEvaluator.evaluateAllFormulaCells(workbook);
// Get the results from the output cells
for (int i = 0; i < outputCells.size(); i++) {
CellReference cellReferenceOutput = new CellReference(outputCells.get(i));
int cellReferenceOutputRow = cellReferenceOutput.getRow();
int cellReferenceOutputColumn = cellReferenceOutput.getCol();
Row rowOutput = sheet.getRow(cellReferenceOutputRow);
Cell cellOutput = rowOutput.getCell(cellReferenceOutputColumn, Row.CREATE_NULL_AS_BLANK);
// Display results
System.out.println(cellOutput.getNumericCellValue());
}
workbook.close();
}
}
If you look at the longest constructor of CellReference, you'd notice that a reference consists of 5 properties:
String sheetName (can be null)
int row
int col
boolean rowAbsolute
boolean colAbsolute
Your command-line arguments include the sheet name, but you're not using it.
First, remove the following line from your code: HSSFSheet sheet = workbook.getSheetAt(0);
Instead, you'll need to lookup the sheet by name using getSheet(String), right after you create the CellReference:
HSSFSheet sheet = workbook.getSheet(cellReferenceInput.getSheetName());
HSSFSheet sheet = workbook.getSheet(cellReferenceOutput.getSheetName());

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