Apache poi ConditionalFormatting not working properly - java

I'm using apache poi to create excels in my java application.
My use case is when the value in A1 is Change it.
Style in cells A10 to A14 will be changed.
For this I'm following feature of ConditionalFormatting provided by poi.
But the style is only getting applied to cell A10 & not till A14.
What am I missing?
Code:
private void addValidations(Sheet sheet) {
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("=A1=\"Change it\"");
FontFormatting fontFmt = rule1.createFontFormatting();
fontFmt.setFontStyle(true, false);
fontFmt.setFontColorIndex(IndexedColors.YELLOW.index);
BorderFormatting bordFmt = rule1.createBorderFormatting();
bordFmt.setBorderBottom(BorderStyle.THIN);
bordFmt.setBorderTop(BorderStyle.THICK);
bordFmt.setBorderLeft(BorderStyle.DASHED);
bordFmt.setBorderRight(BorderStyle.DOTTED);
ConditionalFormattingRule [] cfRules =
{
rule1
};
CellRangeAddress[] regions = {
CellRangeAddress.valueOf("A10:A14")
};
sheetCF.addConditionalFormatting(regions, cfRules);
}

The code sheetCF.createConditionalFormattingRule("=A1=\"Change it\""); cannot work at all. In HSSF it throws org.apache.poi.ss.formula.FormulaParseException: The specified formula '=A1="Change it"' starts with an equals sign which is not allowed.. In XSSF it creates a corrupt *.xlsx file. The leading equals sign is not stored in Excel formula cells. t only is shown in Excel's GUI. So it would must be sheetCF.createConditionalFormattingRule("A1=\"Change it\"");.
And the formula =A1="Change it" is relative in column letter as well as in row number. So applied to cell A10 it means =A1="Change it". But applied to cell A11 it means =A2="Change it". And applied to cell A12 it means =A3="Change it" and so on. So if the need is changing all font colors in A10:A14 if content of A1 changes, then the reference in the formula would must be fixed using $. So it would must be sheetCF.createConditionalFormattingRule("A$1=\"Change it\"");.
Complete Example:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.FileOutputStream;
public class ConditionalFormatting {
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook(); String filePath ="./ConditionalFormatting.xlsx";
//Workbook workbook = new HSSFWorkbook(); String filePath ="./ConditionalFormatting.xls";
Sheet sheet = workbook.createSheet();
for (int r = 9; r < 14; r++) {
sheet.createRow(r).createCell(0).setCellValue("Text in Cell A" + (r+1));
}
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
ConditionalFormattingRule rule = sheetCF.createConditionalFormattingRule("A$1=\"Change it\"");
FontFormatting fontFormatting = rule.createFontFormatting();
fontFormatting.setFontStyle(false, true);
fontFormatting.setFontColorIndex(IndexedColors.YELLOW.index);
ConditionalFormattingRule[] cfRules = new ConditionalFormattingRule[]{rule};
CellRangeAddress[] regions = new CellRangeAddress[]{CellRangeAddress.valueOf("A10:A14")};
sheetCF.addConditionalFormatting(regions, cfRules);
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close();
workbook.close();
}
}
This changes font color in A10:A14 to yellow if cell content in A1 is Change it.

Try this if this works.
CellRangeAddress[] regions = new CellRangeAddress[]{ CellRangeAddress.valueOf("A10:A14") };

Related

In Streaming XSSFWorkbook make part of cell content to bold using apache poi

I am trying following two sets of code to make part of the cell content bold/italic in streaming XSSFWorkbook that is SXSSFWorkbook. But it is not working. Any help in this regard is appreciated.
The cell content should look like following
This is sample content
try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
SXSSFSheet sheet = wb.createSheet("With Rich Text");
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
XSSFFont fontPlain = (XSSFFont) wb.createFont();
XSSFFont fontBoldItalic = (XSSFFont) wb.createFont();
fontBoldItalic.setBold(true);
fontBoldItalic.setItalic(true);
XSSFFont fontItalic = (XSSFFont) wb.createFont();
fontItalic.setItalic(true);
XSSFRichTextString cell1Value= new XSSFRichTextString();
cell1Value.append("This is ");
cell1Value.append("sample ", fontBoldItalic);
cell1Value.append("content", fontItalic);
cell.setCellValue(cell1Value);
wb.write(new FileOutputStream("BoldFile.xlsx"));
} catch (IOException e) {
e.printStackTrace();
}
Also following code does the same. The cell content should look like following
Hello World
try (SXSSFWorkbook wb = new SXSSFWorkbook()) {
SXSSFSheet sheet = wb.createSheet("With Rich Text");
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
Font fontBold = wb.createFont();
fontBold.setBold(true);
String value = "Hello World";
String subValue = "World";
cell.setCellValue(value);
RichTextString rts = cell.getRichStringCellValue();
rts.applyFont(value.indexOf(subValue), value.length(), fontBold);
cell.setCellValue(rts);
wb.write(new FileOutputStream("BoldFile.xlsx"));
} catch (IOException e) {
e.printStackTrace();
}
You should always create the RichTextString using CreationHelper.createRichTextString(java.lang.String text) where CreationHelper comes from Workbook.getCreationHelper(). So you can be sure, that the created RichTextString always is of same type as the workbook. For example HSSFRichTextString from a HSSFCreationHelper, XSSFRichTextString from a XSSFCreationHelper and XSSFRichTextString for streaming SXSSF from a SXSSFCreationHelper. When created using the constructors that is not always guaranteed.
But using SXSSF there is an issue when SXSSFWorkbook uses inline strings instead of a shared strings table. This is the default in SXSSF because inline strings are better usable in the streaming approach. But Apache POI fails to create rich text content in inline strings. It only creates rich text content in the shared strings table, which is the default in Excel.
So using Workbook workbook = new SXSSFWorkbook(); no rich text cell content can be created. One needs using Workbook workbook = new SXSSFWorkbook(new XSSFWorkbook(), 100, false, true); which tells to create a SXSSFWorkbook from a new empty XSSFWorkbook, using the default rowAccessWindowSize of 100, not to use gzip compression for temporary files and to use a shared strings table.
Following code will work for all kinds of Workbook and create rich text cell content.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
class CreateExcelRichTextString {
public static void main(String[] args) throws Exception {
//Workbook workbook = new XSSFWorkbook(); FileOutputStream out = new FileOutputStream("./Excel.xlsx");
//Workbook workbook = new HSSFWorkbook(); FileOutputStream out = new FileOutputStream("./Excel.xls");
//Workbook workbook = new SXSSFWorkbook(); FileOutputStream out = new FileOutputStream("./Excel.xlsx");
Workbook workbook = new SXSSFWorkbook(new XSSFWorkbook(), 100, false, true); FileOutputStream out = new FileOutputStream("./Excel.xlsx");
CreationHelper creationHelper = workbook.getCreationHelper();
Font font = workbook.createFont(); // default font
Font fontBold = workbook.createFont();
fontBold.setBold(true);
Font fontItalic = workbook.createFont();
fontItalic.setItalic(true);
String text = "This is some sample content.";
RichTextString richTextString = creationHelper.createRichTextString(text);
String word = "some";
int startIndex = text.indexOf(word);
int endIndex = startIndex + word.length();
richTextString.applyFont(startIndex, endIndex, fontBold);
word = "sample";
startIndex = text.indexOf(word);
endIndex = startIndex + word.length();
richTextString.applyFont(startIndex, endIndex, fontItalic);
Sheet sheet = workbook.createSheet();
sheet.createRow(0).createCell(0).setCellValue(richTextString);
workbook.write(out);
out.close();
workbook.close();
if (workbook instanceof SXSSFWorkbook) ((SXSSFWorkbook)workbook).dispose();
}
}
Conclusion: Stop thinking SXSSF is the better XSSF because of using streaming approach to save memory usage. It is not. It has disadvantages of it's own. The structure of spreadsheet application files is nothing what is good to stream bulk data in.

How To Convert From Scientific To Number Value While Writing Excel In Apache Poi Java

I need to create an XL sheet using Apache POI with some values which are long numeric for ex:1234567891011.
When i use below sample code to generate the excel sheet, the data is stored in form of Scientific format (1.23457E+12). But i want to store this data as a number ex. 1234567891011.00 is fine.
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("format sheet");
String str = "1234567891011";
Row row;
Cell cell;
short rowNum = 0;
short colNum = 0;
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(str);
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
I tried to set the cell format to Numeric as below code but doesnt work.
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(str);
dateCell1.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
double converted = new Double(str);
dateCell1.setCellValue(converted);
Please tell if any way possible to do it.
Excel is using number format General per default. This switches to scientific format if needed. That means if cell width is too small or numeric value is too big.
So do using a cell style having a special number format 0.00 or 0.
Example:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
class CreateExcelBigDecimal {
public static void main(String[] args) throws Exception {
//Workbook workbook = new XSSFWorkbook(); String filePath = "./Excel.xlsx";
Workbook workbook = new HSSFWorkbook(); String filePath = "./Excel.xls";
DataFormat format = workbook.createDataFormat();
CellStyle numberCellStyle = workbook.createCellStyle();
numberCellStyle.setDataFormat((short)8);
numberCellStyle.setDataFormat(format.getFormat("0.00"));
Sheet sheet = workbook.createSheet();
Cell cell = sheet.createRow(0).createCell(0);
double value = 1234567891011d;
cell.setCellValue(value);
cell.setCellStyle(numberCellStyle);
sheet.setColumnWidth(0, 20*256);
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close();
workbook.close();
}
}
That leads to showing 1234567891011.00 in cell A1.
Leave the cell as String type and format your number java side.
long yourLongNumber = 1234567891011;
String strLong = String.format("%d", yourLongNumber);
//out: "1234567891011"

Change color of specific text while generating Excel header

I am generating an Excel in my spring based application using apache-poi. While populating the Header for excel i want the specific word of the given sentence in different color.
E.g- suppose i want my header with value Address (*"MANDATORY) with below given color.
Address - in Black Color
*"MANDATORY - in Red Color
I came through a method for changing the fontColor provided by apache-poi but that is changing the font color of whole cell value but i want a specific text in different color.
How to resolve above issue ?
To fulfill your requirement the cell would must contain rich text string content. This is possible using Cell.setCellValue(RichTextString value). The RichTextString can be created as it is described in Busy Developers' Guide to HSSF and XSSF Features.
Let's have an example which provides a method createRichTextString(Workbook workbook, String[] textParts, Font[] fonts) which creates a RichTextString for an array of text parts using an array of fonts.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
class CreateExcelRichText {
static RichTextString createRichTextString(Workbook workbook, String[] textParts, Font[] fonts) {
CreationHelper creationHelper = workbook.getCreationHelper();
RichTextString richTextString = creationHelper.createRichTextString(String.join("", textParts));
int start = 0;
int end = 0;
for (int tp = 0; tp < textParts.length; tp ++) {
Font font = null;
if (tp < fonts.length) font = fonts[tp];
end += textParts[tp].length();
if (font != null) richTextString.applyFont(start, end, font);
start += textParts[tp].length();
}
return richTextString;
}
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook();
//Workbook workbook = new HSSFWorkbook();
String fileName = (workbook instanceof XSSFWorkbook)?"Excel.xlsx":"Excel.xls";
Font font = workbook.createFont(); // default font
Font fontRed = workbook.createFont();
fontRed.setColor(Font.COLOR_RED);
String[] textParts = new String[]{"Address (", "*\"MANDATORY", ")"};
Font[] fonts = new Font[]{font, fontRed, font};
RichTextString richTextString = createRichTextString(workbook, textParts, fonts);
Sheet sheet = workbook.createSheet();
sheet.createRow(0).createCell(0).setCellValue(richTextString);
FileOutputStream out = new FileOutputStream(fileName);
workbook.write(out);
out.close();
workbook.close();
}
}

Apache POI page break in excel

Hi guys I just want to ask about how to remove the page break in column N in excel using the Apache poi in Java. I've already set up in my code that my print area is until column P. But when I try to print the generated excel it always set that the page break is in column N.
How can I adjust the page break in column using Apache poi on java?
If the goal is that at print all columns (A:P) fit to one page width, then one could solve this using Scale a worksheet.
The following code uses Sheet.setAutobreaks and Sheet.setFitToPage combinated with PrintSetup.setFitWidth and PrintSetup.setFitHeight to set the print setup to scale to fit. The width is set to fit all columns to 1 page width and the height is set automatic, so multiple pages are used when enough rows are present.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class CreateExcelAllColumnsFitToOnePageWidth {
public static void main(String[] args) throws Exception {
//Workbook workbook = new HSSFWorkbook();
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
for (int r = 0; r < 200; r++) {
Row row = sheet.createRow(r);
for (int c = 0; c < 16; c++) {
Cell cell = row.createCell(c);
cell.setCellValue("Lorem ipsum");
if (r==0) sheet.autoSizeColumn(c);
}
}
sheet.setAutobreaks(true);
sheet.setFitToPage(true);
PrintSetup printSetup = sheet.getPrintSetup();
printSetup.setFitHeight((short)0);
printSetup.setFitWidth((short)1);
String fileout = (workbook instanceof HSSFWorkbook)?"Excel.xls":"Excel.xlsx";
FileOutputStream out = new FileOutputStream(fileout);
workbook.write(out);
out.close();
}
}

POI Java - Numeric Cell with Decimals

I'm having a lot of problems with numeric formats in a Cell with POI.
I need to print in the cell 11 decimals for a number and also that the cell has a numeric format to make the sum when you select the data
And I have this code:
private void writeDecimal(HSSFRow row, Double data, int position) {
String pattern = "#.0000000000";
HSSFCell celda = row.createCell(position);
CellStyle styleDecimal = styles.get(ITEM_DECIMAL); // Font and alignment
styleDecimal.setDataFormat(libro.getCreationHelper().createDataFormat().getFormat(pattern));
celda.setCellStyle(styleDecimal);
celda.setCellType(Cell.CELL_TYPE_NUMERIC);
celda.setCellValue(data);
}
But the result always print less decimal because Excel rounds the number:
If I convert the Double to String, prints the 11 decimals but it doesn't make the sum if I select all the numbers.
Any idea how to resolve this?
Thanks
Open the xlsx file select the column , right click on cell -> Format cells...->custom->type = 0.00000000000 click ok.
now whatever you will write on that cell, it will print on that format and if you select also it will show the sum.
by code
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
public class ChangeXlxsDataFormat {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Workbook wb = new HSSFWorkbook();
Sheet sheet = (Sheet) wb.createSheet("format sheet");
CellStyle style;
DataFormat format = wb.createDataFormat();
Row row;
Cell cell;
short rowNum = 0;
short colNum = 0;
row = sheet.createRow(rowNum);
cell = row.createCell(colNum);
style = wb.createCellStyle();
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
style = wb.createCellStyle();
style.setDataFormat(format.getFormat("0.00000000000"));
cell.setCellStyle(style);
cell.setCellValue(5.12345678908);
row = sheet.createRow(rowNum++);
cell = row.createCell(colNum);
cell.setCellValue(2.12345678908);
FileOutputStream fileOut = new FileOutputStream("test.xls");
wb.write(fileOut);
fileOut.close();
}
}
This code snippet doesn't contain celda.setCellStyle( styleDecimal ). Is it missing in the real code too? Add it.
Edit:
Here is a simple example using your function. It works well.
private static HSSFWorkbook workbook;
public static void main( String args[] ) throws IOException {
workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet( "sheet" );
HSSFRow row = sheet.createRow( 0 );
writeDecimal( row, 0.0781013, 0 );
FileOutputStream fos = new FileOutputStream( "workbook.xls", false );
workbook.write( fos );
fos.close();
}
private static void writeDecimal( HSSFRow row, Double data, int position ) {
String pattern = "#.0000000000";
HSSFCell celda = row.createCell(position);
CellStyle styleDecimal = workbook.createCellStyle(); // Font and alignment
styleDecimal.setDataFormat(workbook.createDataFormat().getFormat(pattern));
celda.setCellStyle(styleDecimal);
celda.setCellType(Cell.CELL_TYPE_NUMERIC);
celda.setCellValue(data);
}
What was the problem in your code? I don't know. Your style definitely wasn't applied to the page: zeros shouldn't be rendered with "#".

Categories