Apache POI - Excel Write - Lock Single Cell - java

I am using Apache POI to generate Exccel Templete which my clients could download, add values and upload back.
I would like to set the cell values non editable so that the template headers could not be edited.
I tried this code but it does not work,
cell.getCellStyle().setLocked(true)
I also read that locking the excel sheet and then allowing the columns to setlocked(false) would work but I am not sure how many columns will be filled by client, so I want is all other columns t be edited except the one which I filled dynamically with Apache POI.
I hope my query is clear to understand.

Try the following code, it may solve your problem:
HSSFWorkbook workbook = new XSSFWorkbook();
// Cell styles. Note the setLocked(true) method call.
HSSFCellStyle lockedNumericStyle = workbook.createCellStyle();
lockedNumericStyle.setAlignment(XSSFCellStyle.ALIGN_RIGHT);
lockedNumericStyle.setLocked(true);
HSSFSheet sheet = workbook.createSheet("Protection Test");
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell(0);
cell.setCellValue(100);
cell.setCellStyle(lockedNumericStyle);
// This line should cause all locked cells to be protected,
// the user should not be able to change the cells
// contents.
sheet.protectSheet("password");
The password makes it possible to remove the protection from the sheet and makes it possible then for the locked cells to be modified.

I don't recall how well this works -- for example, I think that the client can unprotect the sheet using the menu -- but you do need to protect the sheet via something like Sheet.protectSheet("") (no password, but nevertheless a protected sheet.)

Related

cloneStyleFrom shows ArrayIndexOutOfBound error while coping cellStyle using java poi, how to fix this issue

I am trying to copy an excel workbook to another excel workbook(some cell values needs some calculations as per)
I need to copy the CellStyles as well, as there are Data and Amount fields with styling.
Im using the below lines of code :
CellStyle cellStyle = wb_out.createCellStyle();
cellStyle.cloneStyleFrom(cell_in.getCellStyle());
Cell cell_out = row_out.createCell(cellIndex);
cell_out.setCellValue(value);
cell_out.setCellStyle(cellStyle);
For large files,
The cloneStyleFrom throws ArrayIndexOutofBound error,
How do we fix this.
Thanks in advance.
Basically there's a limit to number of Styles that one can create,
and if the excel sheet is a large file, the limit crosses and the error 'ArrayIndexOutofBound' is thrown.This is called Style explosion.
To escape this scenario, you have to create separate cell styles and use it wherever is required
This is what I tried and it worked.
I created a cell style for the Date format and Currency format, and applied those wherever required.
CellStyle cellStyleDate = wb_out.createCellStyle();
short dateFormat = wb_out.createDataFormat().getFormat("d-mmm");
cellStyleDate.setDataFormat(dateFormat);
CellStyle cellStyleCurrency = wb_out.createCellStyle();
short currencyFormat = wb_out.createDataFormat().getFormat("#,##0.0");
cellStyleCurrency.setDataFormat(currencyFormat);
Likewise one can create a cell style and add different specific format or properties to it and use it in the workbook,
like this :
cell_out.setCellStyle(cellStyleDate);

Apache POI - Applying styles per row

I am working on generating a excel in my app for reporting purposes. I can apply styles to all rows but when I try and target specific rows (as shown below), the style does not work.
public void postProcessXLS(Object document) {
HSSFWorkbook wb = (HSSFWorkbook) document;
HSSFSheet sheet = wb.getSheetAt(0);
CellStyle cs = wb.createCellStyle();
cs.setFillBackgroundColor(IndexedColors.RED1.index);
cs.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cs.setFillForegroundColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());
sheet.getRow(0).setRowStyle(cs);
}
Trying to format the data in my table so the users have an easier time reading / handling it. I want to display different styles for alternate rows. If there is an easier way to do this in HSSF without having to manually write the styles, I am open to suggestions.
If you want to apply styles based on some condition or pattern , then go for conditional formatting , i faced the same challenges during my tussle with Apache POI and this post helped http://www.javavillage.in/fills-and-colors-using-conditional-formate-using-apache-poi.php , hope this helps you too

Apache POI generated xlsx file size is larger than manually created via Microsoft Excel

I am using Apache POI to generate xlsx sheet for reports. One of the POI generated report I saved as another using Microsoft excel . When comparing the original file and the saved file there was 12Mb difference. The original file was 15Mb while the saved file is just 2.5Mb. The Workbook used is XSSFWorkbook.
Is it possible to reduce the file size created by Apache POI
Here is the code snippet I have used:
XSSFWorkbook workbookTitle = new XSSFWorkbook(fileInputStream);
workbook = new SXSSFWorkbook(workbookTitle, maxRows);
font = workbook.createFont();
font.setFontHeightInPoints((short) 9);
font.setFontName(FONT_NAME);
cellTwoDecimal = workbook.createCellStyle();
DataFormat format = workbook.createDataFormat();
cellTwoDecimal.setDataFormat(format.getFormat("0.00"));
cellTwoDecimal.setFont(font);
cellCommon = workbook.createCellStyle();
cellCommon.setFont(font);
cellText = workbook.createCellStyle();
cellText.setDataFormat((short) BuiltinFormats.getBuiltinFormat("text"));
cellText.setFont(font);
cellWrpText = workbook.createCellStyle();
cellWrpText.setWrapText(true);
cellWrpText.setFont(font);
Row row;
Cell cell;
for (int i = 0; i < size; i++) {
row = excelSheet.createRow(rowIndex++);
cell = row.createCell(i);
cell.setCellValue(rowHeader);
cell.setCellStyle(cellCommon);
}
I have removed some internal logics from code. Please share your ideas.
[Edit 1]
I am inserting a lot of blank cells where there is no value, ie. some part of the report will not have any value. So I put a blank cell there. I am also setting style for the blank cell. Can this be the reason?
Thanks in advance.
According to your "edit 1"... if i understand you correctly you create cells with no value.
you do not have to do so. if you dont want to write something then do not create the empty cell.
on my poi-experience you only have to create rows and cells if you want to write something.
from this point of view it is clear, that your xlsx is very large (many many cell-objects). i think MS Excel removes the empty cells on manual save.
added: Need to mention that there is also an issue with styling your cells. please try to use as few as possible instances of CellStyle. if you have cells with same style do not create a new instance of CellStyle with same attributes. please apply the same instance of CellStyle. Also do not assign style to simple text cells. in this case excel uses a default style (background='white', textcolor='black', font='any default', size='any default', format='default').
I had a similar problem, and later figured out that I was opening the FileOutputStream in append mode(append=true). The file size grew exponentially(say from 7KB to 54KB) every-time I update a single cell on the sheet.
When removed the append, it worked just fine.

JXLS - how to create hyperlink to Excel worksheets in workbook

I am trying to create an Excel workbook with with JXLS. I want a text hyperlink for navigating through worksheets in a workbook. I couldn't find any helpful information online. Please give any idea or hyperlink for that can help to to solve the problem. Thanks
jXLS is a small and easy-to-use Java library for writing Excel files using XLS templates and reading data from Excel into Java objects using XML configuration. If you are trying to create hyerlink, jXLS doen't have low lever excel manupulation capability. But you can to use Apache POI a free library. This code create hyperlink to a Cell for that task as shown below.
//creating the cell
Row row = my_sheet.createRow(0);
Cell cell = row.createCell(0);
//creating helper class
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFCreationHelper helper= workbook.getCreationHelper();
//creating the hyperlink
link = helper.createHyperlink(HSSFHyperlink.LINK_DOCUMENT);
link.setAddress("'target_worksheet_name'!A1");
//optional hyperlink style
XSSFCellStyle hlinkstyle = workbook.createCellStyle();
XSSFFont hlinkfont = workbook.createFont();
hlinkfont.setUnderline(XSSFFont.U_SINGLE);
hlinkfont.setColor(HSSFColor.BLUE.index);
hlinkstyle.setFont(hlinkfont);
//applying the hyperlink to the cell
cell.setHyperlink(link);
jxls supports Parameterized formulas, you can probably
use cell with a formula like below
=HYPERLINK("http://test.com/", "Click ME")
Parameterize it in cell with
=HYPERLINK(${paramLink}, ${paramDisplay})
pass parameters to jxls context and they will be rendered as proper link
http://jxls.sourceforge.net/samples/param_formulas.html
Old question, but another possible solution is to use JXLS 2+ and the PoiTransformer. It has a utility class called PoiUtil which can be injected to the context.
final var transformer = PoiTransformer.createTransformer(inputStream, outputStream);
// it is important to create the context like this
// or you can manually insert the PoiUtil instance if you wish
final var context = PoiTransformer.createInitialContext();
// setup your context...
JxlsHelper.getInstance().processTemplate(context, transformer);
And in the template you can use it like this: ${util.hyperlink(linkVar, titleVar)} where the linkVar and titleVar are the corresponding variables in the context.

Is it possible to unlock specific cells in a protected sheet (Using Aspose)

I'm using Aspose-Cells and java to export excel templates in my system.
In this particular situation I'm generating a spreadsheet where I have two sheets that I want to protect.
In one of them, I need to let the user edit only 4 cells. All the rest should be protected.
The simplest implementation should be:
protect the sheet
unlock each cell I want to let the user edit.
The problem is that I was searching to check if it's possible to do this (protect the entire sheet and unlock only a few cells) and it seems to not to be possible. Please.. tell me I'm wrong and there's a way to do this, otherwise I'll have to lock all the existing cells in the sheet and unlock only 4 of them.. For my experience using another library (PHPExcel), it seems to be very costly in terms of performance (I had to apply it for 1000 rows and more then 40 columns, so it was really costly).
It can be done easily with Aspose.Cells for Java. You can
First lock all the columns (all cells) in a worksheet
Unlock specific cells or range of cells
See the sample below.
String dataDir = "D:\\data\\";
// Create or load workbook
Workbook book = new Workbook();
// Get the first worksheet
Worksheet sheet = book.getWorksheets().get(0);
Style style;
StyleFlag flag = new StyleFlag();
// First lock all columns
for (int iCol=0 ; iCol<255 ; iCol++)
{
// Get style of the column
style = sheet.getCells().getColumns().get(iCol).getStyle();
// Apply locking to the style
style.setLocked(true);
flag.setLocked(true);
sheet.getCells().getColumns().get(iCol).applyStyle(style, flag);
}
// Get the range of cells, which we want to unlock
Range rangeUnlocked = sheet.getCells().createRange("A1:D4");
// Add a new style
int styleIndex = book.getStyles().add();
Style styleUnlocked = book.getStyles().get(styleIndex);
// Unlock cells
styleUnlocked.setLocked(false);
rangeUnlocked.setStyle(styleUnlocked);
// Protect the sheet
sheet.protect(ProtectionType.ALL);
//Save the Excel file
book.save(dataDir + "protectedrange.xlsx");
I work at Aspose as a Developer Evangelist.

Categories