I am currently using Apache POI to create empty excel files (that I will later read and edit). The problem is that whenever I try to get the cell, I always get a null value. I have tried initializing the first few columns and rows (the cells are no longer null) but with this approach, I cannot insert new rows and columns. How can I be able to initialize all cells of a sheet without having to set the number of rows and columns? Thanks
EDIT: Hi this is my code in creating excel files. I could not use the iterator to initialize all my cells since there are no rows and columns for the spreadsheet.
FileOutputStream fileOut = new FileOutputStream(loc + formID +".xls");
HSSFWorkbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet("Sheet1");
for (Row row : sheet) {
for (Cell cell : row) {
CellStyle style = workbook.createCellStyle();
style.setFillBackgroundColor(IndexedColors.BLACK.getIndex());
cell.setCellValue("");
cell.setCellStyle(style);
}
}
workbook.write(fileOut);
fileOut.flush();
fileOut.close();
You might find that MissingCellPolicy can help with your needs. When calling getCell on a row, you can specify a MissingCellPolicy to have something happen if no cell was there, eg
Row r = sheet.getRow(2);
Cell c = r.getCell(5, MissingCellPolicy.CREATE_NULL_AS_BLANK);
c.setCellValue("This will always work, c will never be null");
org.apache.poi.ss.util.CellUtil can also help too:
// Get the row, creating it if needed
Row r = CellUtil.getRow(4, sheet);
// Get the cell, creating it if needed
Cell c = CellUtil.getCell(2, r);
Related
I use Apache POI to write data to a predefined XLSM file. I use this code to open existing file:
Cell cell;
File file = new File(XLSMPath);
FileInputStream inputStream = new FileInputStream(file);
XSSFWorkbook workbook = XSSFWorkbookFactory.createWorkbook(inputStream);
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.getRow(recordcount+4);
Data is written in first iteration in the 5th row and so on. Code to set value of a given cell:
cell = row.getCell(CellReference.convertColStringToIndex("A"));
cell.setCellValue(myvalue);
It worked fine for the first 400 iterations, but after that I get following error message:
Cannot invoke "org.apache.poi.ss.usermodel.Cell.setCellValue(String)"
because "cell" is null
You need to create the worksheet cells yourself. Just check if your Cell is null and create new Cell using createCell(int):
cell = row.getCell(CellReference.convertColStringToIndex("A"));
if (cell == null) {
// maybe in your case index should be taken in other way
cell = row.createCell(CellReference.convertColStringToIndex("A"));
}
cell.setCellValue(myvalue);
I am reading an xlsx file using java (Apache POI).
I have created a Document class (having all excel column heading as variables)
i have to read each row in the excel and map to the Document class by creating a collection of Document class.
The problem I am facing is that I have to start reading from row 2 and from column 7 to column 35 and map the corresponding values to the document class.
Unable to to figure out exactly how the code should be ?
I have written the following lines of code.
List sheetData = new ArrayList();
InputStream excelFile = new BufferedInputStream(new FileInputStream("D:\\Excel file\\data.xlsx"));
Workbook workBook = new XSSFWorkbook(excelFile); // Creates Workbook
XSSFSheet sheet = (XSSFSheet) workBook.getSheet("Daily");
DataFormatter formatter = new DataFormatter();
for (int i = 7; i <= 35; i++) {
XSSFRow row = sheet.getRow(i);
Cell cell = row.getCell(i);
String val = formatter.formatCellValue(cell);
sheetData.add(val);
}
Assuming I've understood your question correctly, I believe you want to process every row which exists from row 2 onwards to the end of the file, and for each of those rows consider the cells in columns 7 through 35. I believe you also might need to process those values, but you haven't said how, so for this example I'll just stuff them in a list of strings and hope for the best...
This is based on the Apache POI documentation for iterating over rows and cells
File excelFile = new File("D:\\Excel file\\data.xlsx");
Workbook workBook = WorkbookFactory.create(excelFile);
Sheet sheet = workBook.getSheet("Daily");
DataFormatter formatter = new DataFormatter();
// Start from the 2nd row, processing all to the end
// Note - Rows and Columns in Apache POI are 0-based not 1-based
for (int rn=1; rn<=sheet.getLastRowNum(); rn++) {
Row row = sheet.getRow(rn);
if (row == null) {
// Whole row is empty. Handle as required here
continue;
}
List<String> values = new ArrayList<String>();
for (int cn=6; cn<35; cn++) {
Cell cell = row.getCell(cn);
String val = null;
if (cell != null) { val = formatter.formatCellValue(cell); }
if (val == null || val.isEmpty()) {
// Cell is empty. Handle as required here
}
// Save the value to list. Save to an object instead if required
values.append(val);
}
}
workBook.close();
Depending on your business requirements, put in logic for handling blank rows and cells. Then, do whatever you need to do with the values you find, again as per your business requirements!
You could iterate with an Iterator in the document, but there is also an function "getRow() and getCell()"
Workbook workbook = new XSSFWorkbook(excelFile);
// defines the standard pointer in document in the first Sheet
XSSFSheet data = this.workbook.getSheetAt(0);
// you could iterate the document with an iterator
Iterator<Cell> iterator = this.data.iterator();
// x/y pointer at the document
Row row = data.getRow(y);
Cell pointingCell = row.getCell(x);
String pointingString = pointingCell.getStringCellValue();
I am writing numeric cells to a new excel file 'Test.xlsx' using POI.
I first insert 2 rows with 2 columns each with values:
Row 1 --> 10 (Cell A1), 20
Row 2 --> 15, 20 (Cell B2)
For row 3, column 1, I set the formula SUM(A1:B2).
XSSFWorkbook wb = null;
String absPath = "C:\excel\Test.xlsx";
File f2 = createFileIfDirExist(absPath); //method will return handle if file created successfully
if (f2 != null) {
wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("MySheet");
if (sheet != null) {
XSSFRow row0 = sheet.createRow(0);
XSSFCell cell0 = row0.createCell(0);
cell0.setCellValue(10);
XSSFCell cell1 = row0.createCell(1);
cell1.setCellValue(20);
XSSFRow row1 = sheet.createRow(0);
XSSFCell cell2 = row1.createCell(0);
cell2.setCellValue(15);
XSSFCell cell3 = row1.createCell(1);
cell3.setCellValue(20);
XSSFRow row2 = sheet.createRow(0);
XSSFCell cell4 = row2.createCell(0);
cell4.setCellType(Cell.CELL_TYPE_FORMULA);
cell4.setCellFormula("SUM(A1:B2)");
FileOutputStream outFile = new FileOutputStream(new File(f2));
wb.write(outFile);
outFile.close();
f2.close();
// call method to evaluate formulaEval.evaluateFormulaCell(cell) on every cell in sheet.
}
}
In my actual implementation, i create these sheets, rows and cells dynamically using user input and using loops which I have not used here. It's a basic version of what my code does.
Now, after I run this program, I see that the file is created. I open the file and see that the cell corresponding to cell A3 (formula cell) has the value 65. However, when I close the file, I get the prompt 'want to save your changes to create.xlsx'?
I unzipped create.xlsx before and after clicking on the save for the above prompt and see that the formula cell has the same values for tags F and V in MySheet.xml.
I also noticed that the xml file calcChain.xml is missing before I manually save the excel file and it appears once I save it manually.
Am I missing something to get rid of the prompt when I close the excel? Any pointers will be greatly appreciated.
I am using Apache POI to create, access and modify *.xlsx and *.xls files. I got stuck on changing cell formats(don't confuse with styles).
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet();
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue(100); // setting cell value with double makes it numeric -> 100 aligned to the right
cell.setCellType(1); // changing cell format to text -> 100.0 aligned to the left
cell.setCellType(0); // changing cell format back to numeric -> 0 aligned to the right
FileOutputStream fos = new FileOutputStream("test.xlsx");
wb.write(fos);
One may think that changing between text and numeric format causes the data to be replaced with 0. However trying the same thing for more cells gives some more unexpected results:
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet();
for(int i=0;i<10;i++){
Row row = sheet.createRow(i);
for(int j=0;j<10;j++){
Cell cell = row.createCell(j);
cell.setCellValue(i*j);
cell.setCellType(1);
cell.setCellType(0);
}
}
FileOutputStream fos = new FileOutputStream("test.xlsx");
wb.write(fos);
The expected output is Multiplication table. Well... it's not. Actually changing the range of i and j affects the results for the same cell addresses.
Is this a bug in Apache POI?
Maybe it's due to OOXML specification and it's actually Microsofts mistake?
Or is something wrong with my computer and your output files look like they should?
I have generated an excel (.xls) document using Apache POI. I use HSSF classes.
Could someone advise me on the following question:
How can we keep the column headers in the diaplay part constant and have scroll only on the data part?
That is, I want the header columns to be always visible when the excel file is scrolled down.
Thanks,
David
One option may be the repeating rows suggestion from timboo. Not sure on your exact needs, but it's possible you might want a Freeze Pane instead.
To have the first row always on screen, never scrolling off, you'd do:
Workbook wb = new HSSFWorkbook();
Sheet sheet1 = wb.createSheet("No Scroll");
sheet1.createFreezepane(0,1);
You can freeze rows, columns or both, see this javadoc or this for details
Check out the Apache POI Busy Developers Guide:
It's possible to set up repeating rows and columns in your printouts
by using the setRepeatingRowsAndColumns() function in the HSSFWorkbook
class.
This function Contains 5 parameters. The first parameter is the index
to the sheet (0 = first sheet). The second and third parameters
specify the range for the columns to repreat. To stop the columns from
repeating pass in -1 as the start and end column. The fourth and fifth
parameters specify the range for the rows to repeat. To stop the
columns from repeating pass in -1 as the start and end rows.
Workbook wb = new HSSFWorkbook();
Sheet sheet1 = wb.createSheet("new sheet");
Sheet sheet2 = wb.createSheet("second sheet");
// Set the columns to repeat from column 0 to 2 on the first sheet
wb.setRepeatingRowsAndColumns(0,0,2,-1,-1);
// Set the the repeating rows and columns on the second sheet.
wb.setRepeatingRowsAndColumns(1,4,5,1,2);
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
This should help you. I've searched for days and found this. This solved my problem.
`Workbook wb = new XSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper();
Sheet sheet1 = wb.createSheet("new sheet");
Row row = sheet1.createRow((short) 0);
// Create a cell and put a value in it.
row.createCell(0).setCellValue(
createHelper.createRichTextString("Freeze"));
for (int i = 1; i < 20; i++) {
row = sheet1.createRow((short) i);
row
.createCell(0)
.setCellValue(
createHelper
.createRichTextString("This is the Moving Row"));
}
// Freeze just one row
sheet1.createFreezePane(0, 1, 0, 1);`