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);
}
Related
I wrote simple method which generate excel file using data from Order class. I use createCell() method to put the data into this cells. createCell() method use identifier on which position of sheet I want to insert data. Is there a way to generate cells for each getter of Order class using java streams?
private static void createCell(Order order, Product product, Row row) {
Cell idCell = row.createCell(0);
Cell dateCell = row.createCell(1);
Cell destinationCell = row.createCell(2);
Cell productCell = row.createCell(3);
Cell productQuantityCell = row.createCell(4);
idCell.setCellValue(order.getOrderID());
dateCell.setCellValue(String.valueOf(order.getDate()));
destinationCell.setCellValue(order.getDestination());
productCell.setCellValue(product.getProductCode());
productQuantityCell.setCellValue(product.getProductQuantity());
}
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);
}
}
I've seen that the best way of handling large tables in itext 7 is explained in http://developers.itextpdf.com/examples/tables/clone-large-tables
I have a table inside another one. What if the large table is the inner one?
Table outTable = new Table(new float[]{1f},true);
Cell cellHeader1 = new Cell();
cellHeader1.add(new Paragraph("Header 1").addStyle(style));
outTable.addHeaderCell(cellHeader1);
document.add(outTable);
for (int i=0; i<smallArray.size();i++) {
Table innerTable = new Table(new float[]{0.5f,0.5f},true);
Cell cellHeader2 = new Cell(1,2);
cellHeader2.add(new Paragraph("Header 2").addStyle(style));
innerTable.addHeaderCell(cellHeader2);
Cell cellInnerTable = new Cell();
cellInnerTable.add(innerTable);
outTable.addCell(cellInnerTable);
for(int j=0;j<bigArray.size();j++){
//add cells to innerTable;
if (j%20==0){
innerTable.flush(); (1)
outTable.flush(); (2)
}
}
innerTable.complete(); (1)
}
outTable.complete();
(2) This flush doesn't solve the memory problem.
(1) These lines return a NullPointerException in the Table object, line 539 because document is null. The outTable's parent is the document so the 'flush' method flushes the data into the document, but the innerTable's parent is the outTable, not the document. Is there a way of having the innerTable flushed into the outTable and the outTable into the document?
If I set the document to the innerTable so I don't get the NullPointerException:
innerTable.setDocument(document);
it doesn't behave as it should, because now the innerTable is being flushed into the document, not into the outTable and it does weird things.
Thank you very much!
Unfortunately, large tables are only supported if you add them directly to the Document. Inner large tables are not supported and there are no plans to add support for inner large tables in the nearest future.
Try:
for(int j=0;j<bigArray.size();j++){
//add cells to innerTable;
if (j%20==0){
Cell cellContent = new Cell(1,2).add(innerTable);
outTable.addCell(cellContent);
innerTable.flushContent(); // API says is internal but is public and works OK
outTable.flush();
}
}
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()
I'm using POI library to deal with the Excel file, I want to change the ForGroundColor of the particular cells. As I'm not satisfied with the list of IndexedColors I want to create my own by substituting one already existing (in my case HSSFColor.BLUE), the problem is - it saves only the color from the last iteration (all cells have the same color).
The code (convData - two dim double array, normalized to 255):
HSSFPalette hssfPalette = excelFile.getCustomPalette();
CellStyle cellStyle = excelFile.createCellStyle();
hssfPalette = excelFile.getCustomPalette();
cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
for (int i=0; i<convData.length; i++) {
Row row = excelSheet.createRow(i);
for (int j=0; j<convData[i].length; j++) {
Cell cell = row.createCell(j);
hssfPalette.setColorAtIndex(HSSFColor.BLUE.index, convData[i][j].byteValue(), convData[i][j].byteValue(), convData[i][j].byteValue());
cellStyle.setFillForegroundColor(hssfPalette.getColor(HSSFColor.BLUE.index).getIndex());
cell.setCellStyle(cellStyle);
}
}
Your problem is that you're creating one single cell style, assigning it to a bunch of cells, then changing it to be blue part way through. As the cell style is global, that blue then applies to everything
Instead, you either need move the "redefine what blue is" outside of the loop, or create a new cell style + apply colour to it for each differently coloured cell. However, there's a limit to the number of colours and cell styles you can have, so make sure you re-use them if you have multiple cells wanting the same colour