Reading superscript excel text with Apache POI in Java - java

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".

Related

Apache POI - Conditional formatting rule using java [duplicate]

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

Reading from excel files using JAVA poi and ignoring empty cells

I was trying to read data from an excel sheet that contains empty cells consider the following code:
File src = new File(path to your file);
FileInputStream fis = new FileInputStream(src);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet1 = wb.getSheet("Sheet1");
int rowCount = sheet1.getLastRowNum();
System.out.println("total number of rows is: " + rowCount);
for(int i = 1; i < rowCount; i++) {
//getcell returns row num and starts from 1
//Also my sheet column contains data in numeric form
int data = (int) sheet1.getRow(i).getCell(1).getNumericCellValue();
System.out.println(data);
}
However, my code also reads the empty cells and displays the value as 0 (The cells have numeric value). How do I make my script read-only cells that are filled and display them while ignoring the ones that are empty?
Thank you in advance
Just update the for loop with an if condition which will check for the value which is getting retrieved from the Cell. PFB the updated for loop.
For Apache POI version 4.x you can try below-
for(int i = 1; i < rowCount; i++) {
//getcell returns row num and starts from 1
//Also my sheet column contains data in numeric form
Cell cell = sheet1.getRow(i).getCell(1);
int data = (int) sheet1.getRow(i).getCell(1).getNumericCellValue();
if(c.getCellType() == CellType.Blank)
{
continue;
}
else{
System.out.println(data);
}
}
For Apache POI version 3.x you can try below-
for(int i = 1; i < rowCount; i++) {
//getcell returns row num and starts from 1
//Also my sheet column contains data in numeric form
Cell cell = sheet1.getRow(i).getCell(1);
int data = (int) sheet1.getRow(i).getCell(1).getNumericCellValue();
if(cell.getCellType() == Cell.CELL_TYPE_BLANK)
{
continue;
}
else{
System.out.println(data);
}
}

Blank cells in spreadsheet no longer blank when saved to desktop

I have a java application that exports some data to a spreadsheet using POI. The problem is that sometimes (not always) there are a couple of lines that have no information (they are "blank") but when I save the XLS document to my desktop and open it, the cells are filled with the correct information.
Im using POI 3.7.
Down here you have an example of what's happening.
[EDIT] - I add some code:
This is the method that insert the data into the sheet:
public void setTransactionDetailsData(HSSFSheet sheet, String[][] records){
HSSFRow rowContent = null;
HSSFCell cellContent = null;
String cell = "";
Integer recordNumber = records.length;
Integer columnNumber = records[0].length;
Integer nextDataIndex = 0;
String styleText = "";
boolean customStyles = styles.size()>0;
short alignment;
CellStyle cellStyle = null;
for(int i = 0; i<recordNumber;i++){
//New row
rowContent = sheet.createRow(lastRowCreated);
rowContent.setHeightInPoints((customDataCellHeight * sheet.getDefaultRowHeightInPoints()));
for(int j = 0; j<columnNumber;j++){
cellContent = null;
cellContent = rowContent.createCell((nextDataIndex));
cell = records[i][j];
if(customStyles){
try{
styleText = styles.get(nextDataIndex);
alignment = getAlignment(styleText);
}catch(IndexOutOfBoundsException e){
LOG.info("Error while obtaining style for position " +nextDataIndex+ ", max index is " +(styles.size()-1)+ ". Check the list of styles you send");
styleText = "";
alignment = 1;
}
}else{
alignment = 1;
}
cellStyle = getCellStyle(i,Integer.valueOf(alignment),styleText);
//Text
if("".equals(styleText) || "value_left".equals(styleText) || "value".equalsIgnoreCase(styleText)){
cellContent.setCellValue(cell);
}else{
if(isNumeric(cell)){
try{
cellContent.setCellValue(convertoToParseableNumber(cell));
cellContent.setCellType(0);
}catch(NumberFormatException e){
LOG.info("Error ocurred while parsing value " +cell+ " no number");
cellContent.setCellValue(cell);
}
}else{
cellContent.setCellValue(cell);
}
}
cellContent.setCellStyle(cellStyle);
nextDataIndex++;
}
//Back to first column
nextDataIndex = 0;
lastRowCreated++;
}
autosize(sheet);
}
Thank you in advance.

Java - Need help getting row # of a specific value

i'm having a bit of trouble getting the row number of a specific string. Let's say I have a cell content = "HC" at row 9 and using the method findRow(sheet, "HC"). I should get a return value of 9, but right now the return is 0.
The purpose of the excelSheetFinder function is after the row number is returned from findRow(), I can get the cells from a specific column that I input as the parameters(enCol and frCol).
Any help is appreciated!
public static String[] excelSheetFinder(String value, int enCol, int frCol) throws IOException{
String[] shortNames = new String[2];
File excelFile = new File("excel.xlsx");
FileInputStream inputExcelFile = new FileInputStream(excelFile);
XSSFWorkbook wb = new XSSFWorkbook(inputExcelFile);
XSSFSheet sheet = wb.getSheetAt(0);
int shortNameRow = findRow(sheet, value);
System.out.println(shortNameRow);
Row r = sheet.getRow(shortNameRow);
String enCell = r.getCell(enCol).toString();
String frCell = r.getCell(frCol).toString();
shortNames[0] = enCell;
shortNames[1] = frCell;
return shortNames;
}
private static int findRow(XSSFSheet sheet, String value){
//to find row number so we can search through that specific column
int gotRow = 0;
for (Row row: sheet){
for (Cell cell: row){
final DataFormatter df = new DataFormatter();
final XSSFCell cellVal = (XSSFCell) row.getCell(row.getRowNum());
String valueAsString = df.formatCellValue(cellVal);
if (valueAsString.trim() == value){
gotRow = row.getRowNum();
}
}
}
return gotRow;
}
Replace == by .equals for your string comparison:
if (valueAsString.trim() == value)
== tests for reference equality
.equals() tests for value equality

Read data from excel file

I have searched through StackOverflow, but didn't find a clear answer to my question.
I have a simple 2 columns and 24 rows xlsx (excel) file (later on this file will have more columns and rows , and also eventually it will have different sheets).
First row is header row: year=x and population=y, and for each header I want to read the rows below. Later on I want to be able to use this information to create a dynamic plot (x,y),
So I think I need to save the x and y information in variables. Below is my pseudo code.
//Sheet Pop
final String POP = "Pop";
int startRowHeader = 1,
startRowNumeric = 2,
startColNumeric = 1,
nrOfCols = 0,
nrOfRows = 0;
int nrOfSheets = excelFile.getWorkbook().getNumberOfSheets();
org.apache.poi.ss.usermodel.Sheet sheet1 = excelFile.getWorkbook().getSheetAt(0);
String[] sheets = {POP};
boolean sheetExists;
String activeSheet = "";
nrOfCols = sheet1.getRow(0).getLastCellNum();
nrOfRows = excelFile.getLastRowNum(POP);
try {
for (String sheet : sheets) {
sheetExists = false;
for (int sheetIndex = 0; sheetIndex < nrOfSheets; sheetIndex++) {
if (sheet.equalsIgnoreCase( excelFile.getWorkbook().getSheetName(sheetIndex))) {
SheetExists = true;
}
}
if (!sheetExists) {
throw new Exception("Sheet " + sheet + " is missing!");
}
}
//Take off!
// Sheet Pop
activeSheet = sheets[0];
for(int j=0; j < nrOfCols; j++) {
for(int i=0; i<nrofRows; i++) {
column[i] = (int)excelFile.getCellNumericValue(POP, startRowNumeric, startColNumeric);
}
}
} catch (Exception e) {
traceln(" ..... ");
traceln("Error in sheet: " + activeSheet);
traceln("Message: " + e.getMessage()); //Write out in console
}
create a new class:
public class Point {
int x;
int y;
}
in your main function create a
List<Point> allPoints = new List<Point>();
then add the points you read from excel to this List
do this in a loop
Point p = new Point();
p.x = xCoordinateFromExcel;
p.y = yCoordinateFromExcel;
allPoints.add(p);
also consider adding constructor and getter/setters to your Point class.
also you might want to use the Point class available in java.awt directly.
http://docs.oracle.com/javase/7/docs/api/java/awt/Point.html
EDIT: regarding fetching values from excel
this is what i understand from your question
you have 24 rows with 2 columns
first column has x, second column has y value
so you can just do something like this in a loop
for(int i=0;i<24;i++){
Row row = sheet.getRow(i);
Cell cellX = row.getCell(1);
Cell cellY = row.getCell(2);
//assign to point class
...
}
dont forget to parse it to int, or use getNumericCellValue()
http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#getNumericCellValue()
You can use a java.util.ArrayList of java.awt.geom.Point2D.Double
Declare the list:
ArrayList<Point2D.Double> points = new ArrayList<>();
Then for each row:
// Read x
// Read y
Point2D.Double p = new Point2D.Double(x, y);
/// And add to the list:
points.add(p);

Categories

Resources