I am creating below conditional formatting rule in Apache POI.
Issue
Expected:
The formula should highlight only invalid values in column 'J'.
Actual:
But all values of the entire column 'J' get highlighted, even for valid values.
Formula
String kkf="IF(AND(NOT(ISBLANK(J4)),ISERROR(SUM(MATCH(FILTERXML(\"<t><s>\"&SUBSTITUTE(J4,\",\",\"</s><s>\")&\"</s></t>\",\"//s\"),FILTERXML(\"<t><s>\"&SUBSTITUTE(PossibleValues!$D$2,\",\",\"</s><s>\")&\"</s></t>\",\"//s\"),0))),\"\"),TRUE())";
Full Code
import java.util.ArrayList;
import org.apache.commons.io.FileUtils;
import org.json.CDL;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFHyperlink;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.ComparisonOperator;
import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.common.usermodel.Hyperlink;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
public class Red {
public static void main(String[] args) throws Exception{
String str="{\"rulesetgroupname\":\"Coastal122\",\"downloadtype\":\"Template\",\"rulesetid\":\"638a0ac02944f902b1eebab3\",\"rulesetversion\":\"0.1\",\"rulegroupid\":\"638a09f28bd88c16a76fa599\",\"product\":\"CAT\",\"ruletype\":\"ERWR\",\"dataobjects\":\"Location 24,Class Codes 24,BPP Covg 24,Building Covg 24,Building 24,Policy 24\",\"ruletemplateversion\":\"1\",\"ruleTemplaeResponseId\":\"638a09f28bd88c16a76fa599\",\"dataobject\":\"Location 24\",\"rulegroup\":\"CAT Testing122\",\"metadataheaders\":[\"Rule Name\",\"Rule Label\",\"Modified By\",\"Modified At\",\"Rule ID\",\"Rule Status (Add/Change/Expire/Verify)\",\"Effective Date [MM/DD/YYYY]\",\"Expiration Date [MM/DD/YYYY]\",\"Has Rule Changed?\"],\"conditionheaders\":[{\"label\":\"State\",\"type\":\"Collection\",\"name\":\"State\",\"dataobject\":\"Location 24\",\"values\":\"NC,SC,TX,VA,MA,GA,AL,IL,DE,NY,MS,NH,RI,ME,FL,MN,CT,NJ,MD\"},{\"label\":\"Counties\",\"type\":\"Collection\",\"name\":\"Counties\",\"dataobject\":\"Location 24\",\"values\":\"\"},{\"label\":\"Zip Codes\",\"type\":\"Collection\",\"name\":\"ZipCodes\",\"dataobject\":\"Location 24\",\"values\":\"\"}],\"outcomeheaders\":[{\"label\":\"Output\",\"type\":\"String\",\"name\":\"RuleCode\",\"dataobject\":\"Location 24\"}]}";
JSONObject output;
try {
output = new JSONObject(str);
String filename = "D:\\project\\excel\\color.xlsx" ;
XSSFWorkbook workbook = new XSSFWorkbook();
String rulegroup = output.getString("rulegroup");
String downloadtype = output.getString("downloadtype");
XSSFSheet sheet = workbook.createSheet("Ruleset");
sheet.setDefaultColumnWidth(10);
ArrayList<String> headers = new ArrayList<String>();
ArrayList<String> nameheaders = new ArrayList<String>();
// Top Element Font
Font font31 = workbook.createFont();
font31.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
font31.setBold(true);
XSSFCellStyle style12 = workbook.createCellStyle();
style12.setFillForegroundColor(HSSFColor.HSSFColorPredefined.PALE_BLUE.getIndex());
style12.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style12.setAlignment(HorizontalAlignment.CENTER);
style12.setVerticalAlignment(VerticalAlignment.CENTER);
style12.setBorderTop(BorderStyle.MEDIUM);
style12.setBorderBottom(BorderStyle.MEDIUM);
style12.setBorderLeft(BorderStyle.MEDIUM);
style12.setBorderRight(BorderStyle.MEDIUM);
style12.setWrapText(true);
style12.setFont(font31);
XSSFCellStyle style13 = workbook.createCellStyle();
style13.setFillForegroundColor(HSSFColor.HSSFColorPredefined.GREY_40_PERCENT.getIndex());
style13.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style13.setAlignment(HorizontalAlignment.CENTER);
style13.setVerticalAlignment(VerticalAlignment.CENTER);
style13.setBorderTop(BorderStyle.MEDIUM);
style13.setBorderBottom(BorderStyle.MEDIUM);
style13.setBorderLeft(BorderStyle.MEDIUM);
style13.setBorderRight(BorderStyle.MEDIUM);
style13.setWrapText(true);
style13.setFont(font31);
XSSFCellStyle style14 = workbook.createCellStyle();
Font font32 = workbook.createFont();
font32.setBold(true);
font32.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
style14.setBorderTop(BorderStyle.MEDIUM);
style14.setBorderBottom(BorderStyle.MEDIUM);
style14.setBorderLeft(BorderStyle.MEDIUM);
style14.setBorderRight(BorderStyle.MEDIUM);
style14.setAlignment(HorizontalAlignment.CENTER);
style14.setVerticalAlignment(VerticalAlignment.CENTER);
style14.setWrapText(true);
style14.setFont(font32);
// Get Top elements
String product = output.getString("product");
String ruletype = output.getString("ruletype");
String dataobject = output.getString("dataobjects");
String rulesetid = output.getString("rulesetid");
String rulesetversion = output.getString("rulesetversion");
String rulegroupid = output.getString("rulegroupid");
String ruletemplateversion = output.getString("ruletemplateversion");
String rulesetgroupname = output.getString("rulesetgroupname");
XSSFRow rowhead = sheet.createRow((short) 0);
rowhead.createCell(0).setCellValue("Product/Process");
rowhead.getCell(0).setCellStyle(style14);
rowhead.createCell(1).setCellValue(product);
rowhead.getCell(1).setCellStyle(style13);
rowhead.createCell(2).setCellValue("RuleType");
rowhead.getCell(2).setCellStyle(style14);
rowhead.createCell(3).setCellValue(ruletype);
rowhead.getCell(3).setCellStyle(style13);
rowhead.createCell(4).setCellValue("DataObject");
rowhead.getCell(4).setCellStyle(style14);
rowhead.createCell(5).setCellValue(dataobject);
rowhead.getCell(5).setCellStyle(style13);
rowhead.createCell(6).setCellValue("RuleTemplate");
rowhead.getCell(6).setCellStyle(style14);
rowhead.createCell(7).setCellValue(rulegroup);
rowhead.getCell(7).setCellStyle(style13);
rowhead.createCell(8).setCellValue("RulesetID");
rowhead.getCell(8).setCellStyle(style14);
rowhead.createCell(9).setCellValue(rulesetid);
rowhead.getCell(9).setCellStyle(style13);
rowhead.createCell(10).setCellValue("RuleSetVersion");
rowhead.getCell(10).setCellStyle(style14);
rowhead.createCell(11).setCellValue(rulesetversion);
rowhead.getCell(11).setCellStyle(style13);
rowhead.createCell(12).setCellValue("RuleTemplateID");
rowhead.getCell(12).setCellStyle(style14);
rowhead.createCell(13).setCellValue(rulegroupid);
rowhead.getCell(13).setCellStyle(style13);
rowhead.createCell(14).setCellValue("RuleTemplateVersion");
rowhead.getCell(14).setCellStyle(style14);
rowhead.createCell(15).setCellValue(ruletemplateversion);
rowhead.getCell(15).setCellStyle(style13);
rowhead.createCell(16).setCellValue("RuleSetGroupName");
rowhead.getCell(16).setCellStyle(style14);
rowhead.createCell(17).setCellValue(rulesetgroupname);
rowhead.getCell(17).setCellStyle(style12);
rowhead.setHeightInPoints((2 * sheet.getDefaultRowHeightInPoints()));
JSONArray metadataheader = output.getJSONArray("metadataheaders");
JSONArray conditionheader = output.getJSONArray("conditionheaders");
JSONArray outcomeheader = output.getJSONArray("outcomeheaders");
Integer metheadcount = metadataheader.length();
Integer conheadcount = conditionheader.length();
Integer outheadcount = outcomeheader.length();
metadataheader.getString(0);
for (int i = 0; i < metadataheader.length(); i++) {
headers.add(metadataheader.getString(i));
nameheaders.add(metadataheader.getString(i));
}
for (int i = 0; i < conditionheader.length(); i++) {
JSONObject json = conditionheader.getJSONObject(i);
String conname = json.getString("label");
String contype = json.getString("type");
String dataobject1 = json.getString("dataobject");
contype = "[" + contype + "]";
String fnl = dataobject1 + "." + conname + " " + contype;
headers.add(fnl);
nameheaders.add(conname);
}
for (int i = 0; i < outcomeheader.length(); i++) {
JSONObject json = outcomeheader.getJSONObject(i);
// if(json.isEmpty()) {
// throw new Exception("Outcome Attributes filed should not be empty");
// }
String conname = json.getString("label");
String contype = json.getString("type");
String dataobject1 = json.getString("dataobject");
contype = "[" + contype + "]";
String fnl = dataobject1 + "." + conname + " " + contype;
headers.add(fnl);
nameheaders.add(conname);
}
// Merging Region
// HSSFRow merge = sheet.createRow((short)1);
Row row = sheet.createRow(1);
Cell cell = row.createCell(0);
cell.setCellValue("MetaData");
// Merging cells by providing cell index
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, metheadcount - 1));
Font font3 = workbook.createFont();
font3.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
font3.setBold(true);
XSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_GREEN.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setWrapText(true);
/*
* style.setBorderTop(BorderStyle.MEDIUM);
* style.setBorderBottom(BorderStyle.MEDIUM);
* style.setBorderLeft(BorderStyle.MEDIUM);
* style.setBorderRight(BorderStyle.MEDIUM);
*/
style.setFont(font3);
cell.setCellStyle(style);
// style.setFont(headerFont);
// style.setFillForegroundColor(IndexedColors.BLACK.getIndex());
Cell cell1 = row.createCell(metheadcount);
cell1.setCellValue("Conditional Attributes");
if (conheadcount > 1) {
sheet.addMergedRegion(new CellRangeAddress(1, 1, metheadcount, metheadcount + conheadcount - 1));
}
XSSFCellStyle style1 = workbook.createCellStyle();
Font font1 = workbook.createFont();
font1.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
font1.setBold(true);
style1.setFont(font1);
style1.setWrapText(true);
style1.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_ORANGE.getIndex());
style1.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style1.setAlignment(HorizontalAlignment.CENTER);
style1.setVerticalAlignment(VerticalAlignment.CENTER);
/*
* style1.setBorderTop(BorderStyle.MEDIUM);
* style1.setBorderBottom(BorderStyle.MEDIUM);
* style1.setBorderLeft(BorderStyle.MEDIUM);
* style1.setBorderRight(BorderStyle.MEDIUM);
*/
cell1.setCellStyle(style1);
Cell cell2 = row.createCell(metheadcount + conheadcount);
cell2.setCellValue("Outcome Attributes");
if (outheadcount > 1) {
sheet.addMergedRegion(new CellRangeAddress(1, 1, metheadcount + conheadcount,
metheadcount + conheadcount + outheadcount - 1));
}
XSSFCellStyle style2 = workbook.createCellStyle();
Font font2 = workbook.createFont();
font2.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
font2.setBold(true);
style2.setFont(font2);
style2.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_CORNFLOWER_BLUE.getIndex());
style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style2.setAlignment(HorizontalAlignment.CENTER);
style2.setVerticalAlignment(VerticalAlignment.CENTER);
style2.setWrapText(true);
/*
* style2.setBorderTop(BorderStyle.MEDIUM);
* style2.setBorderBottom(BorderStyle.MEDIUM);
* style2.setBorderLeft(BorderStyle.MEDIUM);
* style2.setBorderRight(BorderStyle.MEDIUM);
*/
cell2.setCellStyle(style2);
row.setHeightInPoints((2 * sheet.getDefaultRowHeightInPoints()));
/*
* HSSFCellStyle style22 = workbook.createCellStyle(); Font font22 =
* workbook.createFont();
* font22.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
* font22.setBold(true); style22.setFont(font22);
* style22.setAlignment(HorizontalAlignment.CENTER);
*/
XSSFCellStyle style22 = workbook.createCellStyle();
Font font22 = workbook.createFont();
font22.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
font22.setBold(true);
style22.setFont(font22);
style22.setBorderTop(BorderStyle.MEDIUM);
style22.setBorderBottom(BorderStyle.MEDIUM);
style22.setBorderLeft(BorderStyle.MEDIUM);
style22.setBorderRight(BorderStyle.MEDIUM);
style22.setWrapText(true);
// style22.setFillForegroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
// style22.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style22.setAlignment(HorizontalAlignment.CENTER);
XSSFRow rowheader = sheet.createRow((short) 2);
for (int z = 0; z < headers.size(); z++) {
rowheader.createCell(z).setCellValue(headers.get(z));
String metaDataCellValue = rowheader.getCell(z).getStringCellValue();
if(metaDataCellValue.equals("Rule Name") || metaDataCellValue.equals("Modified By") ||
metaDataCellValue.equals("Modified At") || metaDataCellValue.equals("Rule ID")) {
rowheader.getCell(z).setCellStyle(style13);
} else {
rowheader.getCell(z).setCellStyle(style22);
}
}
rowheader.setHeightInPoints((2 * sheet.getDefaultRowHeightInPoints()));
// Get Details
DataFormatter formatter = new DataFormatter();
if (downloadtype.equalsIgnoreCase("rulesets")) {
JSONArray values = output.getJSONArray("values");
if (!values.isEmpty()) {
short valcell = 3;
for (int val = 0; val < values.length(); val++) {
XSSFRow rowheader2 = sheet.createRow((short) valcell + val);
try {
JSONObject firstvals = values.getJSONObject(val);
JSONArray methead1 = firstvals.optJSONArray("metadata");
JSONArray conhead1 = firstvals.optJSONArray("condition");
JSONArray outhead1 = firstvals.optJSONArray("outcome");
for (int i = 0; i < methead1.length(); i++) {
JSONObject json = methead1.getJSONObject(i);
String val23 = json.get("value").toString();
String name = "";
if (!json.isNull("label")) {
name = (json.getString("label"));
} else {
name = (json.getString("name"));
}
int index = nameheaders.indexOf(name);
rowheader2.createCell(index).setCellValue(val23);
}
for (int y = 0; y < conhead1.length(); y++) {
JSONObject json = conhead1.getJSONObject(y);
String val23 = json.get("value").toString();
String name = "";
if (!json.isNull("label")) {
name = (json.getString("label"));
} else {
name = (json.getString("name"));
}
String oper = (json.getString("operator"));
if (oper.equalsIgnoreCase("not in")) {
val23 = "NOT IN(" + val23 + ")";
} else if (oper.equalsIgnoreCase("neq")) {
val23 = "NOT EQUALS(" + val23 + ")";
} else if (oper.equalsIgnoreCase(">") || oper.equalsIgnoreCase("GT") ) {
val23 = ">" + val23;
} else if (oper.equalsIgnoreCase(">=") || oper.equalsIgnoreCase("GTE")) {
val23 = ">=" + val23;
}else if (oper.equalsIgnoreCase("<") || oper.equalsIgnoreCase("LT")) {
val23 = "<" + val23;
}
else if ( oper.equalsIgnoreCase("<=") || oper.equalsIgnoreCase("LTE")) {
val23 = "<=" + val23;
}
int index = nameheaders.indexOf(name);
if (index > 0) {
rowheader2.createCell(index).setCellValue(val23);
}
}
for (int za = 0; za < outhead1.length(); za++) {
JSONObject json = outhead1.getJSONObject(za);
String val23 = json.get("value").toString();
String name = "";
if (!json.isNull("label")) {
name = (json.getString("label"));
} else {
name = (json.getString("name"));
}
int index = nameheaders.indexOf(name);
if (index > 0) {
rowheader2.createCell(index).setCellValue(val23);
}
}
} catch (JSONException e) {
e.printStackTrace();
String error = e.getMessage();
throw new Exception(error);
} catch (Exception e) {
// String error = e.getMessage();
e.printStackTrace();
throw new Exception(e.getMessage());
}
}
} //
}
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
evaluator.evaluateAll();
// Duplicate Highlighter
String lcollett = "";
String csv1 = "";
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
int s1 = sheet.getNumMergedRegions();
for (int i = 0; i < s1; i++) {
CellRangeAddress region = sheet.getMergedRegion(i);
int colIndex = region.getFirstColumn();
int rowNum = region.getFirstRow();
String val1 = formatter.formatCellValue(sheet.getRow(rowNum).getCell(colIndex));
if (val1.contains("MetaData")) {
int fcol = sheet.getMergedRegion(i).getFirstColumn();
int lcol = sheet.getMergedRegion(i).getLastColumn();
lcollett = CellReference.convertNumToColString(lcol);
for (i = fcol; i <= lcol; i++) {
sheet.autoSizeColumn(i);
}
}
}
for (int i = 0; i < s1; i++) {
CellRangeAddress region = sheet.getMergedRegion(i);
int colIndex = region.getFirstColumn();
int rowNum = region.getFirstRow();
String val1 = formatter.formatCellValue(sheet.getRow(rowNum).getCell(colIndex));
ArrayList<String> xsdf = new ArrayList<String>();
if (val1.contains("Conditional")) {
int fcol = sheet.getMergedRegion(i).getFirstColumn();
int lcol = sheet.getMergedRegion(i).getLastColumn();
String fcollett = "";
lcollett = CellReference.convertNumToColString(lcol);
for (i = fcol; i <= lcol; i++) {
fcollett = CellReference.convertNumToColString(i);
if (i == lcol) {
xsdf.add("$" + fcollett + "$4:$" + fcollett + "$10000,\"*\"&$" + fcollett + "4&\"*\"");
} else {
xsdf.add("$" + fcollett + "$4:$" + fcollett + "$10000,$" + fcollett + "4");
}
sheet.autoSizeColumn(i);
}
csv1 = String.join(",", xsdf);
csv1 = "COUNTIFS(" + csv1 + ")>1";
}
}
for (int i = 0; i < s1; i++) {
CellRangeAddress region = sheet.getMergedRegion(i);
int colIndex = region.getFirstColumn();
int rowNum = region.getFirstRow();
String val1 = formatter.formatCellValue(sheet.getRow(rowNum).getCell(colIndex));
if (val1.contains("Outcome")) {
int fcol = sheet.getMergedRegion(i).getFirstColumn();
int lcol = sheet.getMergedRegion(i).getLastColumn();
lcollett = CellReference.convertNumToColString(lcol);
for (i = fcol; i <= lcol; i++) {
sheet.autoSizeColumn(i);
}
}
}
ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(csv1);
org.apache.poi.ss.usermodel.FontFormatting font = rule1.createFontFormatting();
font.setFontStyle(false, true);
font.setFontColorIndex(IndexedColors.BLUE.index);
String cellrangeadd = "A4:" + lcollett + "10000";
CellRangeAddress[] regions = new CellRangeAddress[] { CellRangeAddress.valueOf(cellrangeadd) };
sheetCF.addConditionalFormatting(regions, rule1);
// Sheet 3
SheetConditionalFormatting sheetCFa = sheet.getSheetConditionalFormatting();
XSSFSheet sheet21 = workbook.createSheet("PossibleValues");
sheet21.setColumnWidth(0, 20 * 256);
sheet21.setColumnWidth(1, 50 * 256);
XSSFRow rowhead33 = sheet21.createRow((short) 0);
rowhead33.createCell(0).setCellValue("DataObject");
rowhead33.getCell(0).setCellStyle(style14);
rowhead33.createCell(1).setCellValue("AttributeName");
rowhead33.getCell(1).setCellStyle(style14);
rowhead33.createCell(2).setCellValue("DataType");
rowhead33.getCell(2).setCellStyle(style14);
rowhead33.createCell(3).setCellValue("PossibleValues");
rowhead33.getCell(3).setCellStyle(style14);
int attcell=1;
ArrayList<String> xkdf = new ArrayList<String>();
for (int i = 0; i < conditionheader.length(); i++) {
JSONObject json = conditionheader.getJSONObject(i);
String conname = json.getString("label");
String contype = json.getString("type");
String dataobject1 = json.getString("dataobject");
String pv = json.getString("values");
String contypea = "[" + contype + "]";
String fnl = dataobject1 + "." + conname + " " + contypea;
xkdf.add(fnl);
XSSFRow rowhead334 = sheet21.createRow((short) attcell + i);
rowhead334.createCell(0).setCellValue(dataobject1);
rowhead334.createCell(1).setCellValue(conname);
rowhead334.createCell(2).setCellValue(contype);
rowhead334.createCell(3).setCellValue(pv);
}
String kkf = "IF(AND(NOT(ISBLANK(J4)),ISERROR(SUM(MATCH(FILTERXML(\"<t><s>\"&SUBSTITUTE(J4,\",\",\"</s><s>\")&\"</s></t>\",\"//s\"),FILTERXML(\"<t><s>\"&SUBSTITUTE(PossibleValues!$D$2,\",\",\"</s><s>\")&\"</s></t>\",\"//s\"),0))),\"\"),TRUE())";
ConditionalFormattingRule rule13 = sheetCF.createConditionalFormattingRule(kkf);
org.apache.poi.ss.usermodel.FontFormatting font535 = rule13.createFontFormatting();
font535.setFontStyle(false, true);
font535.setFontColorIndex(IndexedColors.RED.index);
String cellrangeadd2 = "J4:J10000";
CellRangeAddress[] regionssd = new CellRangeAddress[] { CellRangeAddress.valueOf(cellrangeadd2) };
sheetCF.addConditionalFormatting(regionssd, rule13);
FileOutputStream fileOut = new FileOutputStream(filename);
workbook.write(fileOut);
fileOut.close();
workbook.close();
System.out.println("Your excel file has been generated!");
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Required manual post-production in Excel
Now I did the below steps
Add three values in column 'J' named "State". All cells are getting highlighted, see image below:
Click Conditional Formatting > Manage Rules > Select Rule (Format Red) > Edit Rules > OK > Apply > OK
After this action the column values are getting highlighted correctly.
Question
Is there anything I missed in my Java code?
How do I avoid this manual activity in Excel?
Short answer
The problem is with the FILTERXML function used in your conditional formatting. This should be prefixed _xlfn in XML sheet storage. To make it work your formula should be changed to following:
String kkf = "IF(AND(NOT(ISBLANK(J4)),ISERROR(SUM(MATCH(_xlfn.FILTERXML(\"<t><s>\"&SUBSTITUTE(J4,\",\",\"</s><s>\")&\"</s></t>\",\"//s\"),_xlfn.FILTERXML(\"<t><s>\"&SUBSTITUTE(PossibleValues!$D$2,\",\",\"</s><s>\")&\"</s></t>\",\"//s\"),0))),\"\"),TRUE())";
Reason
FILTERXML function was introduced in Excel 2013. So it was introduced after Microsoft had published the Office Open XML file format for Microsoft Office files in 2006 for Office 2007. To mark such later introduced functions, Microsoft decided to prefix them with _xlfn in XML storage. After reading the XML, the Excel GUI knows whether the function is known in that Excel version or not. If yes, the prefix gets removed and the function name gets localized (e.g. in German Excel: to XMLFILTER). If not, the prefix remains and the user also knows that this function is unknown in that Excel version. See Issue: An _xlfn. prefix is displayed in front of a formula.
Why we need the storage formula version?
In Apache POI Cell.setCellFormula as well as SheetConditionalFormatting.createConditionalFormattingRule sets the formula string into the XML directly. So that string must be exactly as it shall be stored in XML.
Learn more about this by inspecting the file-formats
Office Open XML files, and so also *.xlsx files, are ZIP archives containing XML files and other files into a specific directory structure. So one simply can unzip a *.xlsx file to have a look into.
So after creating your color.xlsx using your code, unzip it and have a look into xl/worksheets/sheet1.xml.
You will find something like:
<conditionalFormatting sqref="J4:J10000">
<cfRule type="expression" dxfId="1" priority="2">
<formula>
<![CDATA[ IF(AND(NOT(ISBLANK(J4)),ISERROR(SUM(MATCH(FILTERXML("<t><s>"&SUBSTITUTE(J4,",","</s><s>")&"</s></t>","//s"),FILTERXML("<t><s>"&SUBSTITUTE(PossibleValues!$D$2,",","</s><s>")&"</s></t>","//s"),0))),""),TRUE()) ]]>
</formula>
</cfRule>
</conditionalFormatting>
And this does not work in Excel.
Now open the color.xlsx in Excel and make it work. Then save the the color.xlsx, unzip it again and have a look into xl/worksheets/sheet1.xml.
You will find something like:
<x14:conditionalFormattings>
<x14:conditionalFormatting xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
<x14:cfRule type="expression" priority="2" id="{00000000-000E-0000-0000-000002000000}">
<xm:f>IF(AND(NOT(ISBLANK(J4)),ISERROR(SUM(MATCH(_xlfn.FILTERXML("<t><s>"&SUBSTITUTE(J4,",","</s><s>")&"</s></t>","//s"),_xlfn.FILTERXML("<t><s>"&SUBSTITUTE(PossibleValues!$D$2,",","</s><s>")&"</s></t>","//s"),0))),""),TRUE())</xm:f>
...
</x14:cfRule>
...
</x14:conditionalFormatting>
</x14:conditionalFormattings>
This shows the _xlfn prefix before FILTERXML in formula string.
It also shows that a totally different version of conditional formatting is used. But that's a secondary problem. The prefixed version of the formula string also works using as formula string within the old version of conditionalFormatting. But, of course that is not guaranteed in all cases. So to be on save side for all cases, one of two possibilities must be given:
either one avoids using all Excel functions introduced after publishing Office Open XML in 2006 (Office 2007)
or Apache POI has to fully support all changes Microsoft made after publishing Office Open XML in 2006 (Office 2007).
To fulfill the latter Apache POI is far away. It not even supports all features of Office 2007 up to now.
If using VBA is an acceptable solution for you, then a possible solution would be to create an .xlsm file containing the functions needed for conditional formatting.
Create manually the color.xlsm file
Add the 2 empty sheets "Ruleset" and "PossibleValues"
Open VBA editor
In sheet "Ruleset" add following Sub:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("$j$4:$j$1000")) Is Nothing Then
Highlight Target
End If
End Sub
Create a VBA Module and add following Sub...
Sub Highlight(ByVal Cell As Range)
Dim Entry() As String
Entry = Split(Cell.Value, ",")
Dim StatesString As String
StatesString = UCase(Worksheets("PossibleValues").Range("D2").Value)
Dim States() As String
States = Split(StatesString, ",")
Dim Matches As Integer
Matches = 0
For EntryIdx = 0 To UBound(Entry)
If (IsInArray(Entry(EntryIdx), States)) Then
Matches = Matches + 1
End If
Next EntryIdx
If (UBound(Entry) + 1 = Matches) Then
Cell.Font.Color = vbBlack
Else
Cell.Font.Color = vbRed
End If End Sub
...and the following function:
Private Function IsInArray(valToBeFound As Variant, arr As Variant) As Boolean
'DEVELOPER: Ryan Wells (wellsr.com)
'DESCRIPTION: Function to check if a value is in an array of values
'INPUT: Pass the function a value to search for and an array of values of any data type.
'OUTPUT: True if is in array, false otherwise
Dim element As Variant
On Error GoTo IsInArrayError: 'array is empty
For Each element In arr
If element = valToBeFound Then
IsInArray = True
Exit Function
End If
Next element
Exit Function
IsInArrayError:
On Error GoTo 0
IsInArray = False
End Function
Finally, you will need to adapt your code to open this manually created .xlsm file rather than creating it programmatically.
Hope it helps
I'm trying to write data in excel while running my tests and in Excel Test Class I have written a code to check if specific row under column is empty then write data else increment the row by 1 and then check same and write data.
From another class I'm calling ExcelTest:
ExcelTest sfName = new ExcelTest("C:\\Users\\abc\\eclipse-workspace\\dgc\\src\\com\\dg\\base\\utility\\TestData.xlsx");
sfName.setCellData("Sheet1","SingleFactor Campaign",SFCampName);
ExcelTest Class
public class ExcelTest
{
public FileInputStream fis = null;
public FileOutputStream fos = null;
public XSSFWorkbook workbook = null;
public XSSFSheet sheet = null;
public XSSFRow row = null;
public XSSFCell cell = null;
String xlFilePath;
boolean isEmptyStringCell;
public ExcelTest(String xlFilePath) throws Exception
{
this.xlFilePath = xlFilePath;
fis = new FileInputStream(xlFilePath);
workbook = new XSSFWorkbook(fis);
fis.close();
}
public void setCellData(String sheetName, String colName, int rowNum, String value)
{
try
{
int col_Num = -1;
sheet = workbook.getSheet(sheetName);
row = sheet.getRow(0);
for (int i = 0; i < row.getLastCellNum(); i++)
{
if(row.getCell(i).getStringCellValue().trim().equals(colName))
{
col_Num = i;
}
}
sheet.autoSizeColumn(col_Num);
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
isEmptyStringCell=cell.getStringCellValue().trim().isEmpty();
if (this.isEmptyStringCell)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
else
{
j=j+1;
}
}
/*row = sheet.getRow(rowNum - 1);
if(row==null)
row = sheet.createRow(rowNum - 1);
cell = row.getCell(col_Num);
if(cell == null)
cell = row.createCell(col_Num);
cell.setCellValue(value);*/
System.out.println("The cell value is "+cell.getStringCellValue());
fos = new FileOutputStream(xlFilePath);
workbook.write(fos);
fos.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
If we remove the block comment(mentioned above in code and add then comment to this code listed below then it will just write data in cell whichever is provided while calling the function.
In below code I'm starting a loop till max 7 rows and then checking if the cell contains data then increment or write data and once it writes then exit the loop.
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
isEmptyStringCell=cell.getStringCellValue().trim().isEmpty();
if (this.isEmptyStringCell)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
else
{
j=j+1;
}
}
Expected: It should write data in a row which has no cell data.
Actual: It doesn't write anything.
I've found solution for the above question and only need to change few code and now it is working as expected:
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
//it will check if cell contains no value then create cell and set value
if(cell == null)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
}
I am new to Apache POI.
I have written a small code for removing duplicate records from a excel file. I am successfully able to identify the duplicate records across sheets but when writing to a new file after removing records, no output is being generated.
Please help where I am goin wrong?
Am I writing properly ?? Or am missing something?
public static void main(String args[]) {
DataFormatter formatter = new DataFormatter();
HSSFWorkbook input_workbook;
HSSFWorkbook workbook_Output_Final;
HSSFSheet input_workbook_sheet;
HSSFRow row_Output;
HSSFRow row_1_index;
HSSFRow row_2_index;
String value1 = "";
String value2 = "";
int count;
//main try catch block starts
try {
FileInputStream input_file = new FileInputStream("E:\\TEST\\Output.xls"); //reading from input file
input_workbook = new HSSFWorkbook(new POIFSFileSystem(input_file));
for (int sheetnum = 0; sheetnum < input_workbook.getNumberOfSheets(); sheetnum++) { //traversing sheets
input_workbook_sheet = input_workbook.getSheetAt(sheetnum);
int input_workbook_sheet_total_row = input_workbook_sheet.getLastRowNum(); //fetching last row nmber
for (int input_workbook_sheet_row_1 = 0; input_workbook_sheet_row_1 <= input_workbook_sheet_total_row; input_workbook_sheet_row_1++) { //traversing row 1
for (int input_workbook_sheet_row_2 = 0; input_workbook_sheet_row_2 <= input_workbook_sheet_total_row; input_workbook_sheet_row_2++) {
row_1_index = input_workbook_sheet.getRow(input_workbook_sheet_row_1); //fetching one iteration row index
row_2_index = input_workbook_sheet.getRow(input_workbook_sheet_row_2); //fetching sec iteration row index
if (row_1_index != row_2_index) {
count = 0;
value1 = "";
value2 = "";
for (int row_1_index_cell = 0; row_1_index_cell < row_1_index.getLastCellNum(); row_1_index_cell++) { //traversing cell for each row
try {
value1 = value1 + formatter.formatCellValue(row_1_index.getCell(row_1_index_cell)); //fetching row cells value
value2 = value2 + formatter.formatCellValue(row_2_index.getCell(row_1_index_cell)); //fetching row cells value
} catch (NullPointerException e) {
}
count++;
if (count == row_1_index.getLastCellNum()) {
if (value1.hashCode() == value2.hashCode()) { //remove the duplicate logic
System.out.println("deleted : " + row_2_index);
System.out.println("------------------");
input_workbook_sheet.removeRow(row_2_index);
}
}
}
}
}
}
}
FileOutputStream fileOut = new FileOutputStream("E:\\TEST\\workbook.xls");
input_workbook.write(fileOut);
fileOut.close();
input_file.close();
} catch (Exception e) {
//e.printStackTrace();
}
//main try catch block ends
}
A couple of things to note:
you swallow any kind of Exception; Igotsome nullpointers with my test data, and that would prevent the workbook from being written
when removing rows, it is an old trick to move backwards through the row numbers because then you don't have to adjust for the row number you have just removed
the code empties the row, but it doesn't move all rows upwards (=there is a gap after the delete). If you want to remove that gap, you can work with shiftRows
you compare things by hashcode, which is possible (in some use cases), but I feel like .equals() is what you want to do. See also Relationship between hashCode and equals method in Java
Here's some code that worked for my test data, feel free to comment if something doesn't work with your data:
public static void main(String args[]) throws IOException {
DataFormatter formatter = new DataFormatter();
HSSFWorkbook input_workbook;
HSSFWorkbook workbook_Output_Final;
HSSFSheet input_workbook_sheet;
HSSFRow row_Output;
HSSFRow row_1_index;
HSSFRow row_2_index;
String value1 = "";
String value2 = "";
int count;
FileInputStream input_file = new FileInputStream("c:\\temp\\test.xls");
input_workbook = new HSSFWorkbook(new POIFSFileSystem(input_file));
for (int sheetnum = 0; sheetnum < input_workbook.getNumberOfSheets(); sheetnum++) {
input_workbook_sheet = input_workbook.getSheetAt(sheetnum);
int input_workbook_sheet_total_row = input_workbook_sheet.getLastRowNum();
for (int input_workbook_sheet_row_1 = input_workbook_sheet_total_row; input_workbook_sheet_row_1 >=0; input_workbook_sheet_row_1--) { // traversing
for (int input_workbook_sheet_row_2 = input_workbook_sheet_total_row; input_workbook_sheet_row_2 >= 0 ; input_workbook_sheet_row_2--) {
row_1_index = input_workbook_sheet.getRow(input_workbook_sheet_row_1);
row_2_index = input_workbook_sheet.getRow(input_workbook_sheet_row_2);
if (row_1_index != null && row_2_index != null && row_1_index != row_2_index) {
count = 0;
value1 = "";
value2 = "";
int row_1_max = row_1_index.getLastCellNum() - 1;
for (int row_1_index_cell = 0; row_1_index_cell < row_1_max; row_1_index_cell++) {
try {
value1 = value1 + formatter.formatCellValue(row_1_index.getCell(row_1_index_cell));
value2 = value2 + formatter.formatCellValue(row_2_index.getCell(row_1_index_cell));
} catch (NullPointerException e) {
e.printStackTrace();
}
count++;
if (value1.equals(value2)) {
System.out.println("deleted : " + row_2_index.getRowNum());
System.out.println("------------------");
input_workbook_sheet.removeRow(row_2_index);
input_workbook_sheet.shiftRows(
row_2_index.getRowNum() + 1,
input_workbook_sheet_total_row,
-1,
true,
true);
}
}
}
}
}
}
FileOutputStream fileOut = new FileOutputStream("c:\\temp\\workbook.xls");
input_workbook.write(fileOut);
fileOut.close();
input_file.close();
input_workbook.close();
}
I am using APACHE POI 3.0 to add sheets to existing excel sheet. It works fine.
But as APACHE POI has limitations about making charts, I used a template excel file to create charts, which also worked fine, but this always result in new excel file.
If I have an existing excel sheet and I want to add a sheet, having charts, I am not able to do it. As, when I create charts, I use template file and it always makes a new excel file.
so I was wondering if there is any solution of it of adding sheets to excel, where the sheets have charts
public class TagBrowserSelection
{
private static String[] excelBarPlot_Template = { "","barPlot_1Panel_template.xlsx"};
private static String[] excelPieChart_Template = { "","pieChart_1Panel_template.xlsx"};
private static String[] excelPieAndBarPlot_Template = { "","pieAndBarChart_1Panel_template.xlsx"};
private static String REGEX = "";
static public boolean makeTagBrowserSelection(String strOutputFileName, ArrayList<TagBrowserChildPanel> childList, String sheetName, boolean addSheet, ArrayList<Boolean> chartAttributes)
{
// chart attributes
boolean addBarChart = chartAttributes.get(0);
boolean addPieChart = chartAttributes.get(1);
boolean addNoTag = chartAttributes.get(2);
boolean addZeros = chartAttributes.get(3);
REGEX = "^" + sheetName;
Pattern p = Pattern.compile(REGEX);
String[] templateArray = null;
if (addBarChart && addPieChart)
templateArray = excelPieAndBarPlot_Template;
else if (addBarChart)
templateArray = excelBarPlot_Template;
else if (addPieChart)
templateArray = excelPieChart_Template;
try
{
int number = childList.size();
XSSFWorkbook workbook = null;
XSSFWorkbook wb = null;
XSSFSheet sheet = null;
int col_num = 0;
int row_num = 0;
XSSFRow row = null;
XSSFCell cell = null;
// if adding sheet to existing excel file
if (addSheet)
{
FileInputStream fis = new FileInputStream(new File(strOutputFileName));
workbook = new XSSFWorkbook(fis);
fis.close();
// number of existing sheets in excel file
int numberOfSheets = workbook.getNumberOfSheets();
// check is sheetName exists already
if (isSheetExist(sheetName, workbook))
{
int counter = 1;
for (int ii = 0; ii < numberOfSheets; ii++)
{
Matcher m = p.matcher(workbook.getSheetName(ii));
if (m.find())
counter++;
}
sheetName = sheetName + " (" + counter + ")";
}
}
else
{
workbook = new XSSFWorkbook();
}
======================================================================
// if template file needs to be used(if bar chart/pie chart option is selected)
if (templateArray != null)
{
InputStream is = TagBrowserSelection.class.getClassLoader().getResourceAsStream(templateArray[number]);
wb = new XSSFWorkbook(OPCPackage.open(is));
sheet = wb.getSheetAt(0);
// wb.close();
}
else
{
sheet = workbook.createSheet(sheetName);
}
// Freeze top two row
// sheet.createFreezePane(0, 1, 0, 1);
// Filling up the workbook and performing the row/column formatting
for (TagBrowserChildPanel child : childList)
{
// Check if row is already created before(previous tag category)
row = sheet.getRow(0);
if (row == null)
row = sheet.createRow(0);
// Adding tag category name as header
String tagCategory = child.getSelectedCategory().getName();
cell = row.createCell(col_num);
cell.setCellValue(tagCategory);
row = sheet.getRow(1);
if (row == null)
row = sheet.createRow(1);
// Adding column headers
cell = row.createCell(col_num);
cell.setCellValue("tag");
cell = row.createCell(col_num + 1);
cell.setCellValue("counts");
row_num = 2;
// Adding tag category document summary(name and counts)
ArrayList<TagSummaryItem> tagSummary = child.getTagChartCounts();
for (int i = 0; i < tagSummary.size(); i++)
{
// Check if row is already created before(previous tag category)
row = sheet.getRow(row_num);
if (row == null)
row = sheet.createRow(row_num);
cell = row.createCell(col_num);
if (!addNoTag)
{
if (tagSummary.get(i).m_strTag == "[No Tag]")
continue;
}
if (!addZeros)
{
if (tagSummary.get(i).m_nCount == 0)
continue;
}
cell.setCellValue(tagSummary.get(i).m_strTag);
cell = row.createCell(col_num + 1);
cell.setCellValue(tagSummary.get(i).m_nCount);
row_num++;
}
// auto-size of tag column
sheet.autoSizeColumn(col_num);
col_num = col_num + 3;
}
FileOutputStream out = new FileOutputStream(strOutputFileName);
if (templateArray != null)
{
wb.setSheetName(0, sheetName);
wb.write(out);
wb.close();
}
else
{
workbook.write(out);
workbook.close();
}
out.close();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
Above is my code, its one code. I split into two sections. Section is the one which uses template to make chart excel sheet.
there's the method cloneSheet() in the HSSFWorkbook class. Try it.
I have an Excel worksheet with some Text cells that contains a superscript and an hyperlink. The hyperlink is simple to extract but i could't extract the superscript :/, the program detects it like plain text. "8^2 --> 82".
The code
excel = WorkbookFactory.create(new File("filename.xlsx"));
Sheet hoja = excel.getSheetAt(4);
List<String> datos = new ArrayList<String>();
List<String> links = new ArrayList<String>();
//recorrido
Iterator<Row> filas = hoja.rowIterator();
while (filas.hasNext()) {
Row fila = filas.next();
Iterator<Cell> celdas = fila.cellIterator();
while (celdas.hasNext()) {
Cell celda = celdas.next();
System.out.print(celda.toString() + " || ");
datos.add(String.valueOf(celda));
Hyperlink linkAddress = celda.getHyperlink();
if (linkAddress != null) {
links.add(linkAddress.getAddress());
}
}
System.out.println();
}
The code shows how i'm whatching the cell contain, just the code probe.
I'm using Apache POI 3.14.
I solved this problem using some RichTextString properties. I created two methods to extract the value and the superscript of the Cell's RichTextString.
To obtain the value we may need to iterate and to concatenate all the String content, except the last one. The last one is always the full superscript.
private static String getValue(XSSFRichTextString cellContent){
String value = "";
for (int i = 0; i < cellContent.numFormattingRuns() - 1; i++) {
int lenVal = cellContent.getLengthOfFormattingRun(i);
int iVal = cellContent.getIndexOfFormattingRun(i);
value += cellContent.toString().substring(iVal, lenVal + iVal);
}
return value;
}
private static String getSuperScript(XSSFRichTextString cellContent) {
int lenSuper = cellContent.getLengthOfFormattingRun(cellContent.numFormattingRuns() - 1);
int iSuper = cellContent.getIndexOfFormattingRun(cellContent.numFormattingRuns() - 1);
return cellContent.toString().substring(iSuper, lenSuper + iSuper);
}
It obtains from 8^1 --> value=8, superScript=1 for example.
Or from "superscript example ^ A,B" --> value="superscript example", superScript="A,B".