How to execute excel formula using java Apache POI - java

I am trying to execute some formula using java apache poi API, however
as a first step I can able to create a new sheet and fill required data.
Now, as step two I want to execute formula on the populated data, formula is able to put in cell but result is not displaying when I open the excel sheet,
Please find inline image for better understanding, here G4 is displaying as #NAME? but what actual cell value is =G3*SQRT(5).
Expected: Using java, If we create a excel and execute formula then upon opening excel sheet should display the formula calculated result without any manual intervention
Actual: After opening the excel, cell data is showing as #NAME? as if the formula is not recognized by excel, however, if I click respective cell to edit then the expected result is displaying
Code:
appendCellValue(sheet, 3, colIndex+3, true, "G3*SQRT(5)", null);
...
...
...
appendCellValue(XSSFSheet sheet, int rowIndex, int colIndex,boolean isFormula, String value, CellStyle cellStyle) {
Row row = sheet.getRow(rowIndex);
Cell cell = row.createCell(colIndex);
if(isFormula) {
cell.setCellFormula(value);
} else {
cell.setCellValue(value);
}
if(cellStyle != null) {
cell.setCellStyle(cellStyle);
}
}

Related

Apache POI: Cell in Row is null when content was removed in Microsoft Excel

I am reading an Excel spreadsheet (XLSX) file with Apache POI and I noticed when I open the file in Excel directly and remove the entire content of one row by emptying the cells, save the file, and close the file, the cells of the row from which I removed content from are null on code level.
Note: a cell is also null when it was never filled with any content
In the code, I do the following with Apache POI:
Read workbook from file
Read sheet from workbook
Iterate over rows of sheet
Iterate over cells of row
Check if cell == null
My method
if (sheet == null) {
log.error("Sheet is null!");
return false;
}
//TODO: when content is deleted from excel instead of deleting entire rows, the cells in those rows are 'null'
var valid = true;
for (Row row : sheet) {
// rowNum starts at 1 if header row was removed
int rowNum = row.getRowNum();
for (var i = 0; i < numColumns; i++) {
final var cell = row.getCell(i);
if (cell == null) {
log.error("Cell {}{} is null or empty!", Character.toString('A' + i), rowNum + 1);
valid = false;
continue;
}
}
}
Apache POI JavaDoc of method Row.getCell(int cellNum)
/**
* Get the cell representing a given column (logical cell) 0-based. If you
* ask for a cell that is not defined....you get a null.
*
* #param cellnum 0 based column number
* #return Cell representing that column or null if undefined.
* #see #getCell(int, org.apache.poi.ss.usermodel.Row.MissingCellPolicy)
*/
Cell getCell(int cellnum);
In the beginning, I thought that only cells that never had any content before are null ("undefined") but it seems that even cells that had content before are null.
My issue here is, I cannot differentiated between the case that a cell just was not filled correctly (cell never had any content) and the case that content was intentionally removed (cell did have content before) from the Excel.
A cell that is null suggests to a user the latter: some cell was not filled in the Excel; but a cell that is null with a cell address where no content is supposed to be, because the content was removed, is confusing to my opinion.
Workaround: instead of removing the entire content from a row, you can delete the row all together. But getting all users to do that is unrealistic. The natural thing is to remove the content, not delete the row.
Any ideas? Thank you!

how to move the active cell to the top left cell in the range apache poi using XSSFWorkbook?

I am trying to migrate the java excel code from JBook to XSSFWorkbook. Am not getting exact methods that are used in JBook. Some of them are:
JBook.setSelection(int row, int col, int row, int col);
JBook.setSelection(JBook.getDefinedName("some String"));
The first method explains moving the active cell to the top left cell in the range.
Is there any way to get the rowindex and column index from XSSFWorkbook object?
You can't set active cell via workbook object.
Possible options:
if you have cell object you can mark it as active: cell.setAsActiveCell();
if you work with XSSFSheet and want to set multiple cell selection: xssfSheet.setActiveCell(reference) (works with xmlbeans 2.6.0, not 2.3.0)
Reference can be set as a string: "A1:A2" or using CellReference class:
String reference = new CellReference(rowNum, colNum).formatAsString()
Is there any way to get the rowindex and column index from XSSFWorkbook object?
You can get index from the cell:
cell.getColumnIndex()
cell.getRowIndex()
I don't know what is JBook.getDefinedName("some String") but if it works with named ranges, check POI user guide: Named Ranges and Named Cells.
Did you try this way
HSSFWorkbook book1 = new HSSFWorkbook();
HSSFSheet sheet = book1.getSheet("sheetName");
int rowIndex=sheet.getLastRowNum()+1;//
int columnIndex = sheet.getRow(sheet.getLastRowNum()).getPhysicalNumberOfCells()

How to lock only cell content in Excel sheet

I am working on exporting some data to Excel using Java POI library. Some of the cells in this data have to be read-only. I make it by:
CellStyle lockedCell = workbook.createCellStyle();
lockedCell.setLocked(true);
cell.setCellStyle(lockedCell);
and after it:
workbook.getSheetAt(workbook.getActiveSheetIndex()).protectSheet("");
It works quite well, but there is one problem - I cannot modify the width of columns containing locked cells.
Is it possible to lock only the content of the cells, so that I could modify columns width?
I do not think that it is possible to only allow user-width-modifications on locked cells.
What you can do instead is, after populating the data, call autoSizeColumn(colNumber); on the sheet for each column populated.
int colMaxLength = workbook.getActiveSheetIndex().getRow(0).getLastCellNum();
HSSFSheet activeSheet = workbook.getSheetAt(workbook.getActiveSheetIndex());
for(int i = 0 ; i < colMaxLength ; i++){
activeSheet.autoSizeColumn(i);
}

Usage of cell style

I'm working on a import module from a excel file. I have to read and check this file, if something is wrong I have to color the corrisponding cell of a color. Then I implemented the following method
public void fillCell(Workbook wb, Row row, int errorColumn){
Cell cell = row.getCell(j);
CellStyle cs = wb.createCellStyle();
cs.setFillForegroundColor((short) 10);
cs.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cell.setCellStyle(cs);
}
but i noted that this method changes the data format of the cell. For example if I'm coloring a cell with data value 29/03/2014 i get the colored cell but its value now is 39536, the same thing happen with the numeric value 1534000001629, also in this case i get the colored cell but if i try to change the value from 1534000001629 to 1534000001630 i get 1,534+E12.
How can I fix it?
The problem is that cell styles don't only control the colour of a cell, they also control the formatting applied to it. So, what's happening is that you're replacing a cell style that eg formats as #.#%, and instead applying one that's eg red but has no number/date formatting rules applied to it.
Cell styles are workbook scoped, so you shouldn't create one per cell, thus you should make your logic somewhat like:
// Lookup from number format to the coloured version
Map<String,CellStyle> styles = new Hashmap<String,CellStyle>();
// Method to make the cell a different colour
public void fillCell(Workbook wb, Row row, int errorColumn){
Cell cell = row.getCell(j);
// Try to find a coloured one for this data formatting
String formatStr = cell.getCellStyle().getDataFormatString();
CellStyle cs = styles.get(formatStr);
if (cs == null) {
// Need to create a new coloured one
cs = wb.createCellStyle();
cs.setFillForegroundColor((short) 10);
cs.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cs.setDataFormat(
wb.getCreationHelper().createDataFormat().getFormat(formatStr));
// Save this for later
styles.put(formatStr, cs);
}
// Apply the coloured form, with the format string
cell.setCellStyle(cs);
}
You could either convert it to a string if you don't need to do any date processing on it later as so:
cell.setCellType(CELL_TYPE_STRING);
therwise you may be able to do it by getting the date value from the cell into Java.Util.Date object and then saving it bacl=k:
Date date=cell.getDateCellValue();
//colour change
cell.setValue(date);
I don't have time to test this right now but let me know if it works and if not I'll look more into it.
You can get more information here

increasing the width of the column and not to have exponential value

I have a query is that, I have generated an excel sheet containing many columns with Data. Now there is a column named abc_ID and the value coming from back-end is of long type as shown below
//shown below how the value is passed for that column
private Long abc_Id;
abcdeed.abc_Id(13243534540L);
HSSFCellStyle[] cellStyles = new HSSFCellStyle[11];
HSSFCellStyle styleHeader = null;
HSSFCellStyle styleHeaderRBorder = null;
HSSFCellStyle cellStyleReportName = null;
HSSFCellStyle cellStyle00 = null;
HSSFCellStyle style_WhiteBg = null;
and I have set the following cell style of abc_ID column
if(columnHeaders[i].equals("abc_Id") && abcdeed.getabc_Id() != null){
cell.setCellValue(abcdeed.getabc_Id());
cell.setCellStyle(cellStyles[9]);
Now the issue is that finally when the excel sheet is generated and when I open that excel sheet first the value of column abc_Id looks compressed and the value in it initially is exponent type and it is because the column is of compressed type I want the column width should be expanded one and the value should not be of exponent type , I have tried to increase the cellStyles but it does not work. Please suggest the solution.
Use CELL_TYPE_STRING in all the rows for that particular Cell.
rows.getCell(abc_Id_Cell_No).setCellType(Cell.CELL_TYPE_STRING);
and at the end
Sheet.autoSizeColumn(abc_Id_Cell_No);
This will change all the cell values to String and autoSizeColumn will resize that column width.
The reason your cell is showing an exponent is nothing to do with your cell width it is to do with the type of value you are putting in it.
If your number was input as a string then the cell might hide the entire value from view but the full value would still exist in the cell.
Because your value is a number you need to edit the number format parameter for your cell so that it shows the number of digits you wish to display after the decimal point. You can check the valid number format codes as a reference.

Categories

Resources