Keeping Source Format when copy data using apache poi - java

Using Apache POI,
I successfully copied all my data, but ive lost all my formatting, eg font, foreground color etc.
heres what ive tried
destCell.getCellStyle().setAlignment(srcCell.getCellStyle().getAlignment());
destCell.getCellStyle().setFont(srcCell.getCellStyle().getFont());
destCell.getCellStyle().setFillForegroundColor(srcCell.getCellStyle().getFillForegroundColorColor());
tried this for font still not working
XSSFFont font = new XSSFFont();
font.setFontName(srcSheet.getRow(currentRowIndex).getCell(currCellIndex).getCellStyle().getFont().getFontName());
font.setFontHeightInPoints(srcSheet.getRow(currentRowIndex).getCell(currCellIndex).getCellStyle().getFont().getFontHeightInPoints());
font.setColor(srcSheet.getRow(currentRowIndex).getCell(currCellIndex).getCellStyle().getFont().getColor());
font.setFamily(srcSheet.getRow(currentRowIndex).getCell(currCellIndex).getCellStyle().getFont().getFamily());
destSheet.getRow(currentRowIndex).getCell(currCellIndex).getCellStyle().setFont(font);
and this gives me an error
destSheet.getRow(currentRowIndex).getCell(currCellIndex).setCellStyle(srcSheet.getRow(currentRowIndex).getCell(currentRowIndex).getCellStyle());
This Style does not belong to the supplied Workbook Styles Source. Are you trying to assign a style from one workbook to the cell of a different workbook?
This is the source format
This is how it looked after i copied over using apache poi

I would recommend you to first create a CellStyle with your destination-workbook and add to that one the required parameters from your source-cells. Then apply that CellStyle to your destination-cells.
In my experience the CellStyle object can be a little bit tricky, and the safest way is to create a CellStyle at first.

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: Indexed Color from AWT Color input

I am trying to replicate font and color from a given java.awt.Color and java.awt.Font in my Excel file created using apache POI. The latter works, however setting the color does not: while my fonts in Excel are colored green when directly set so by using IndexedColors.GREEN.getIndex(), using the java.awt.Color to create a XSSFColor does not work (see code below). How do i get the (closest) IndexedColor or even better use the original value of java.awt.Color in my POI font?
Current code snippet:
Font font = workbook.createFont();
//font.setColor(IndexedColors.GREEN.getIndex()); //Works
font.setColor(new XSSFColor(java.awt.Color.GREEN).getIndex()); //Does not work
font.setFontName(getFont(i,j).getFamily());
font.setFontHeightInPoints((short)getFont(i,j).getSize());
font.setItalic(getFont(i,j).isItalic());
font.setBold(getFont(i,j).isBold());
(Apache POI 3.17)
XSSFWorkbook#createFont returns XSSFFont (an implementation of Font) and this XSSFFont class has a setColor(XSSFColor) method.

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.

Categories