Below is my code which I am trying to read the excel data using Apache POI and want to store the first column and last column values in Hashmap by taking First column values as keys and last column as values. I am facing an issue while putting the values in the hashmap. My expected output should be like
Key value
UserDefined Xpath_original
seldriver xpath;//div[#id='mBody']
Selenium xpath;//table[#id='choice']/tbody/tr/td[1]/ul/li[1]
but I am getting the output as
*
null null
null
null xpath;//div[#id='mBody']
*
Below is my piece of code
package com.selenium.common;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class ReadMacroExcel {
public static void main(String[] args) {
try {
File f=new File("C:\\Users\\Rajaram.8.Kannuri\\Downloads\\Fire-IEBrowser1.4.xlsm");
HashMap <String,String> innerMap =null;
Workbook workbook = WorkbookFactory.create(f);
System.out.println(workbook);
int numberOfSheets = workbook.getNumberOfSheets();
org.apache.poi.ss.usermodel.Sheet sheet=null;
String key = "";
String value = "";
//Get the sheet in the xlsx file
for (int i = 0; i < numberOfSheets; i++) {
sheet = workbook.getSheetAt(i);
System.out.println(sheet.getSheetName());
int firstColumn = sheet.getRow(0).getFirstCellNum();
int lastColumn = sheet.getRow(0).getLastCellNum();
Iterator<Row> rowIterator = sheet.iterator();
innerMap = new HashMap<String,String>();
while(rowIterator.hasNext())
{
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext())
{
Cell cell = cellIterator.next();
if(cell.getColumnIndex()==firstColumn||cell.getColumnIndex()==lastColumn-1)
{
switch (cell.getCellType())
{
case Cell.CELL_TYPE_STRING:
key = cell.getStringCellValue();
/*System.out.print(key + "\t");*/
/* Thread.sleep(5000);*/
break;
case Cell.CELL_TYPE_FORMULA:
value = cell.getRichStringCellValue().toString();
/*System.out.print(value + "\t");*/
/*Thread.sleep(5000);*/
break;
}
System.out.print(innerMap.put(key,value));
}
}
System.out.println("");
}
/* System.out.println(innerMap.get("UserDefined"));*/
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Can any one help me in solving this issue??
It seems that you are trying to print the inserted value with
System.out.print(innerMap.put(key,value));
However, put returns the previous value associated with the given key, or null if there was no mapping for that key.
See also https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html#put-K-V-
You should use something like
innerMap.put(key,value); // add the new mapping to the hashmap
System.out.print(innerMap); // dumps the complete map with all entries
System.out.print(innerMap.get(key)); // dumps the value for the recently inserted key
Related
for example there is formula as "VLOOKUP($B2,'03 meest recente
gegevens'!$A:$V,5,0)"
I want to drag this formula upto a certain row in order to do so i need
the current row position and add one to it $B2 to $B3 and so on
whenever i am calling the method copyFormula it is copying but the formula
is getting changed for ex. VLOOKUP($B2,'03 meest recente
gegevens'!$A:$V,5,0) change to VLOOKUP($B3,'03 meest recente
gegevens'!A:V,5,0)
you can see "$" symbol is changeing.
So i have created another method dragFormula() in which i am using regex to
get the row number and increasing it by 1 for every row
Is there any other way around to solve this because what i have done is ...
seems pretty static because lets say if you want to drag below formula
=DATE(LEFT(G2,4),MID(G2,5,2),RIGHT(G2,2))
the G2 needs to get adusted acording to the row and my dragFormula(args..) method can do that ..... However this can be achived by the copyFormula(args..) method .. I am confused sometimes copyFormula method is needed and sometimes dragFormula method works
how to solve this Help ... And THANKS in advance
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.formula.FormulaParser;
import org.apache.poi.ss.formula.FormulaRenderer;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.formula.ptg.Area3DPtg;
import org.apache.poi.ss.formula.ptg.AreaPtg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.RefPtgBase;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class DragFormula {
public static void main(String[] args) {
DragFormula from = new DragFormula();
File file = new File("C:\\Users\\mayank.kumar01\\Desktop\\Project\\Mailmerge\\format_mailmerge_20140527(template).xlsx");
try{
OPCPackage pkg = OPCPackage.open(file);
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(file));
XSSFSheet sheet2 = workbook.getSheetAt(1);
CellReference cellReference = new CellReference("F2");
Row oldRow = sheet2.getRow(cellReference.getRow());
Row newRow = sheet2.createRow(2);
Cell oldCell = oldRow.getCell(cellReference.getCol());
Cell newCell = newRow.createCell(cellReference.getCol());
newCell.setCellFormula(oldCell.getCellFormula());
String oldFormula = oldCell.getCellFormula();
System.out.println("oldFolmula : "+oldFormula);
from.copyFormula(sheet2, oldCell, newCell, 1);
from.dragFormula(oldCell, sheet2, 25);
workbook.write(new FileOutputStream(file));;
}
catch(Exception e){
e.printStackTrace();
}
finally{
System.exit(0);
}
}
private void copyFormula(Sheet sheet, Cell org, Cell dest,int inc) {
if (org == null || dest == null || sheet == null
|| org.getCellType() != Cell.CELL_TYPE_FORMULA)
return;
if (org.isPartOfArrayFormulaGroup())
return;
String formula = org.getCellFormula();
XSSFEvaluationWorkbook workbookWrapper =
XSSFEvaluationWorkbook.create((XSSFWorkbook) sheet.getWorkbook());
Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL
, sheet.getWorkbook().getSheetIndex(sheet));
for (int i=0;i<ptgs.length;i++) {
if (ptgs[i] instanceof RefPtgBase) // base class for cell references
{
RefPtgBase ref = (RefPtgBase) ptgs[i];
if (ref.isColRelative())
ref.setColumn(ref.getColumn());
if (ref.isRowRelative())
ref.setRow(ref.getRow()+inc);
}
else if (ptgs[i] instanceof Area3DPtg) // base class for range references
{
Area3DPtg ref = (Area3DPtg) ptgs[i];
}
}
formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
System.out.println("Modified Formula : "+formula);
dest.setCellFormula(formula);
}
public void dragFormula(Cell oldCell,XSSFSheet sheet,int uptoRow){
String formula = "VLOOKUP($B2,'03 meest recente gegevens'!$A:$V,5,0)";
String regex = "(\\$)?([A-Za-z]+)(\\d+)"; // creating the regex
Pattern p = Pattern.compile(regex);
int rowIndex = oldCell.getRowIndex()+1;
int inc = 1;
for(int i=0;i<=uptoRow;i++){
Row row = sheet.createRow(rowIndex++);
Matcher match = p.matcher(formula);
if(match.find()){ // matching the pattern
formula = formula.replaceFirst(match.group(3),((Integer)(Integer.parseInt(match.group(3))+inc)).toString());
}
Cell newCell = row.createCell(oldCell.getColumnIndex());
newCell.setCellFormula(formula);
System.out.println("Modified Formula"+formula);
}
}
}
I'm using Apache POI to alter some values in an Excel document and then read the result from different cells. Everything went ok until I got a test document from the client. After testing it I found out that I have two issues:
1) When I try to get the value from a cell that has a formula but returns the result formatted as currency with the € sign as a prefix I get an error.
2) When I try to get the value from a cell that references another cell that is a formula (eg.: cell B20 from Sheet 3 has the value of "=Sheet 2!A20" where A20 in Sheet 2 is a SUM() formula.), I get an error.
The error is: Exception in thread "main" java.lang.IllegalStateException: Cannot get a numeric value from a error formula cell.
The document name, input columns (where the values are altered) and output columns (from where the values are read) are taken from the command line.
You can find my code bellow:
package poitest;
import java.util.List;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.usermodel.*;
public class ReadExcel {
public static void main(String[] args) throws FileNotFoundException, IOException {
// Will contain cell name / value pair for input cells
Map<String, String> inputCellsMap = new HashMap<String, String>();
// Will contain cell name for output cells
List<String> outputCells = new ArrayList<String>();
// Open the Excel file
FileInputStream file = new FileInputStream(new File(args[0]));
// Get the current workbook
HSSFWorkbook workbook = new HSSFWorkbook(file);
// Get the input cells that need to be modified and
// store their name and value in the inputCellsMap
for (String element : args[1].split(";")) {
inputCellsMap.put(element.split("=")[0], element.split("=")[1]);
}
// Get the output cells that will be accessed for resulting values
for (String element : args[2].split(";")) {
outputCells.add(element);
}
// Loop through the cells that need to be modified and
// set the new value in the Excel document
Iterator<Entry<String,String>> inputIterator = inputCellsMap.entrySet().iterator();
while (inputIterator.hasNext()) {
Map.Entry<String,String> inputEntry = (Map.Entry<String,String>) inputIterator.next();
CellReference cellReferenceInput = new CellReference(inputEntry.getKey());
int cellReferenceInputRow = cellReferenceInput.getRow();
int cellReferenceInputColumn = cellReferenceInput.getCol();
// Get sheet name for each input cell
HSSFSheet inputSheet = workbook.getSheet(inputEntry.getKey().split("!")[0]);
Row rowInput = inputSheet.getRow(cellReferenceInputRow);
if (rowInput == null)
rowInput = inputSheet.createRow(cellReferenceInputRow);
Cell cellInput = rowInput.getCell(cellReferenceInputColumn, Row.CREATE_NULL_AS_BLANK);
cellInput.setCellValue(Integer.parseInt(inputEntry.getValue()));
}
// Apply all formulas after altering cell values
workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();
// Get the results from the output cells
for (int i = 0; i < outputCells.size(); i++) {
CellReference cellReferenceOutput = new CellReference(outputCells.get(i));
int cellReferenceOutputRow = cellReferenceOutput.getRow();
int cellReferenceOutputColumn = cellReferenceOutput.getCol();
// Get sheet name for each output cell
HSSFSheet outputSheet = workbook.getSheet(outputCells.get(i).split("!")[0]);
Row rowOutput = outputSheet.getRow(cellReferenceOutputRow);
Cell cellOutput = rowOutput.getCell(cellReferenceOutputColumn, Row.CREATE_NULL_AS_BLANK);
// Display results
switch (cellOutput.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
System.out.println(cellOutput.getBooleanCellValue());
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.println(cellOutput.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
System.out.println(cellOutput.getStringCellValue());
break;
case Cell.CELL_TYPE_BLANK:
break;
case Cell.CELL_TYPE_FORMULA:
switch (cellOutput.getCachedFormulaResultType()) {
case Cell.CELL_TYPE_STRING:
System.out.println(cellOutput.getRichStringCellValue());
break;
case Cell.CELL_TYPE_NUMERIC:
HSSFCellStyle style = (HSSFCellStyle) cellOutput.getCellStyle();
if (style == null) {
System.out.println(cellOutput.getNumericCellValue());
} else {
DataFormatter formatter = new DataFormatter();
System.out.println(formatter.
formatRawCellContents(
cellOutput.getNumericCellValue(),
style.getDataFormat(),
style.getDataFormatString())
);
}
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
System.out.println(cellOutput.getBooleanCellValue());
break;
case HSSFCell.CELL_TYPE_ERROR:
System.out.println(ErrorEval.getText(cellOutput.getErrorCellValue()));
break;
}
break;
}
}
workbook.close();
}
}
case Cell.CELL_TYPE_FORMULA:
System.out.println(cellOutput.getNumericCellValue());
break;
should actually be:
case Cell.CELL_TYPE_FORMULA:
System.out.println(cellOutput.getCellFormula());
break;
After that you can do:
case Cell.CELL_TYPE_FORMULA:
System.out.println(cellOutput.getCellFormula());
switch(cellOutput.getCachedFormulaResultType()) {
case Cell.CELL_TYPE_NUMERIC:
System.out.println(cellOutput.getNumericCellValue());
break;
See the docs for more
Your exception is pretty clear:
Exception in thread "main" java.lang.IllegalStateException: Cannot get a numeric value from a error formula cell.
You have a formula cell which evaluated to an error. Therefore, you can't fetch the numeric value of it, as there isn't one, just the error value
Since what you seem to be doing is printing out the cell's value, the easy option is just to use DataFormatter to get the Cell formatted into a String. That takes care of all the fiddly bits around cell types, styles etc. Just use DataFormatter.formatCellValue(Cell) and it'll take care of it for you
If not, you need to check both the cell's type, and the evaluated type, eg
if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
switch(cell.getCachedFormulaResultType()) {
case Cell.CELL_TYPE_ERROR:
System.out.println(cell.getErrorCellValue());
break;
case Cell.CELL_TYPE_NUMERIC:
// Prints unstyled, use DataFormatter to style it
System.out.println(cell.getNumericCellValue());
break;
// TODO Remaining cell types
I would advice to do
evaluator.clearAllCachedResultValues()
before any operation with evaluator if not created just now.
Javadoc:
/**
* Should be called whenever there are changes to input cells in the evaluated workbook.
* Failure to call this method after changing cell values will cause incorrect behaviour
* of the evaluate~ methods of this class
*/
All,
Good Morning!
I have an excel file with data listed as the following, I'm trying to parse down using POI
A
B
C
D1
D2
F
G1
G2
G3
M
S1
R
T
U
L
X
Y
Z
is it possible to generate an output like the following
A
A-->B
A-->B-->C
A-->B-->C-->D1
A-->B-->C-->D2
A-->B-->F
A-->B-->F-->G1
A-->B-->F-->G2
A-->B-->F-->G3
A-->B-->M
A-->B-->M-->S1
A-->R
A-->R-->T
A-->U
L
L-->X
L-->X-->Y
L-->X-->Y-->Z
I have been trying from quite some time but havent figured out the logic
Thanks
Solution in Java, using Apache POI:
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ParseTreeDemo
{
private static final int NUM_COLUMNS = 4;
public static void main(String[] args)
{
try
{
FileInputStream file = new FileInputStream(new File("Test.xlsx"));
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
// Use a column marker to save the 'farthest' column so far
int currColMarker = -1;
List<String> list = new ArrayList<>();
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
for(int currCol = 0; currCol < NUM_COLUMNS; currCol++)
{
Cell cell = row.getCell(currCol);
if(cell == null)
continue;
if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
if(currCol > currColMarker) {
// A farther column, simply append and
// update column marker
currColMarker = currCol;
list.add(cell.getStringCellValue());
}
else if (currCol == currColMarker) {
// At same level as column marker
// Remove old value at same level, before appending
list.remove(list.size() - 1);
list.add(cell.getStringCellValue());
}
else {
// At a 'nearer' column, remove those values beyond
// this level before appending
currColMarker = currCol;
list = list.subList(0, currCol);
list.add(cell.getStringCellValue());
}
}
}
// For displaying the current contents
StringBuilder sb = new StringBuilder();
for(String s : list) {
if(sb.length() != 0) {
sb.append("-->");
}
sb.append(s);
}
System.out.println(sb.toString());
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Output:
A
A-->B
A-->B-->C
A-->B-->C-->D1
A-->B-->C-->D2
A-->B-->F
A-->B-->F-->G1
A-->B-->F-->G2
A-->B-->F-->G3
A-->B-->M
A-->B-->M-->S1
A-->R
A-->R-->T
A-->U
L
L-->X
L-->X-->Y
L-->X-->Y-->Z
The idea:
Use a 'column marker' to keep track of the active column
If the new value is at a column, with a larger column value, append
If it has the same column value, remove the last value, and append
If it has a smaller column value, remove all current values beyond the new column value, before appending
Note: Test.xlsx contains the values as stated in the question.
If the listed data is in a variable called data, the following will work in Tcl:
proc merge {a b} {
set res {}
foreach ac [split $a {}] bc [split $b {}] {
if {![string is space $ac] && [string is space -strict $bc]} {
append res $ac
} else {
append res $bc
}
}
set res
}
set current {}
foreach line [split [string trim $data] \n] {
set current [merge $current [string trimright $line]]
puts [join $current -->]
}
I originally went with a pseudo-stack approach, but it seemed simpler to "merge" each new line with the accumulated line (current) such that non-blank text in the new line would overwrite text in the accumulated line, and that the accumulated line would be truncated if the new line was shorter (after trimming off trailing whitespace from it).
Once I had the merged line, I could take advantage of the fact that (most) strings in Tcl are also lists, and print it as a string formed by joining the words using "-->" tokens.
Documentation: append, foreach, if, proc, puts, set, split, string
Using Apache POI 3.9, I want to map some values to an Excel template that looks similar to this:
Looks pretty easy, at least for the Seller table in which I can map the values from my bean without problems.
However, the issue I am facing is related to the Products table because I need to set the data from my bean for each column which makes the logic a little bit complex since during the loop process I'll need to look for the next column letter:
e.g. My first product data will be set under B7 then at C7, D7, E7, etc until the loop ends.
(Just to know, for this example template I am just showing the "Name" attribute of the product but each one has around 35 attributes in real life, that's why I am not showing the data in rows since the table won't look so friendly to the user in horizontal view).
So, my question is:
What happen If my products count is more than the total letters of the
alphabet, how can I get the right column and cell during the loop process
to set my product bean data following Excel column distribution?
With "Excel column distribution" I mean the following:
e.g. In Excel, when going to the column which contains the last letter of the alphabet "Z" then the columns continue showing AA, AB, AC, etc.
Is it possible?
This is what I've tried (using dummy data) and this will work until getting into the letter "Z" column:
Empty Excel template used in this code snippet can be downloaded at: https://www.dropbox.com/s/eo0s54o9vkqhlbl/template.xls
package com.app.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
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.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellReference;
/**
* Test class for generating Excel sheet
*/
public class ExportTest
{
public static void main(String[] args) throws IOException
{
CellReference ref;
// Load template
InputStream fis = ExportTest.class.getResourceAsStream("/template.xls");
Workbook workbook = new HSSFWorkbook(fis);
fis.close();
// Constants
final String TBL_FIRSTCOLUMN = "B"; // Starting product table column at sheet (in which the first product data will be set)
final int MAX_PRODUCTS = 25; // Max. products added to the dummy products list (this will set the last product to the "Z" column)
final int TBL_STARTROW = 7; // Starting product table row number at sheet (in which the first product data will be set)
final int TBL_ATTR_ROWS = 1; // Number of attribute rows at products table (in this case just "Name")
// Generate dummy data with seller information
LinkedHashMap<String, String> cellMap = new LinkedHashMap<String, String>();
cellMap.put("B2", "1");
cellMap.put("B3", "Company");
cellMap.put("B4", "US");
// Generate dummy data with product information
List<String> products = new ArrayList<String>();
for(int i = 0; i < MAX_PRODUCTS; ++i) {
products.add("Chocolate");
}
// Declare style for cells
CellStyle style = workbook.createCellStyle();
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderRight(CellStyle.BORDER_THIN);
style.setRightBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderTop(CellStyle.BORDER_THIN);
style.setTopBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
// Get template sheet
Sheet sheet = workbook.getSheetAt(0);
// Set values to "Seller" table
for(Map.Entry<String, String> entry : cellMap.entrySet()) {
ref = new CellReference(entry.getKey());
sheet.getRow(ref.getRow()).getCell(ref.getCol()).setCellValue(entry.getValue());
}
// Set values to "Products" table
for(int i = 0; i < products.size(); ++i) {
// Get product name
String name = products.get(i);
String num = String.valueOf(i + 1);
// Get char representation of the letter, this will allow me to get
// C, D, E...Z columns but then I will get a IllegalArgumentException
// if my products count exceed the alphabet letters. At this point I'll
// need to follow Excel column distribution behavior.
String nextLetter = String.valueOf((char)(TBL_FIRSTCOLUMN.charAt(0) + i));
for(int j = 0; j < TBL_ATTR_ROWS; ++j) {
// Get cell reference of B7 then C7, etc
ref = new CellReference(nextLetter + (TBL_STARTROW + j));
// Check if row/cell exists, otherwise it will throw NullPointerException when trying to get each one
Row row = sheet.getRow(ref.getRow());
if(row == null) {
row = sheet.createRow(ref.getRow());
}
Cell cell = row.getCell(ref.getCol());
if(cell == null) {
cell = row.createCell(ref.getCol());
}
// Set value and style to cell
cell.setCellValue(name + num);
cell.setCellStyle(style);
}
}
// Write workbook to file
String path = String.format("%s%s%s", System.getProperty("user.home"), System.getProperty("file.separator"), "exported.xls");
OutputStream out = new FileOutputStream(new File(path));
workbook.write(out);
out.close();
}
}
Then, If the products count exceeds the alphabet letters I will get the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid
column index (-11). Allowable column range for BIFF8 is (0..255) or
('A'..'IV') at
org.apache.poi.hssf.usermodel.HSSFCell.checkBounds(HSSFCell.java:939)
at org.apache.poi.hssf.usermodel.HSSFCell.(HSSFCell.java:153)
at org.apache.poi.hssf.usermodel.HSSFRow.createCell(HSSFRow.java:148)
at org.apache.poi.hssf.usermodel.HSSFRow.createCell(HSSFRow.java:126)
at org.apache.poi.hssf.usermodel.HSSFRow.createCell(HSSFRow.java:39)
at
com.app.test.ExportTest.main(ExportTest.java:99)
(To replicate this try using MAX_PRODUCTS = 26, NOT 27 - alphabet count - since we are starting at B column on Excel sheet).
Any help will be appreciated, thanks!
You call a utility method in Apache POI -- CellReference.convertNumToColString to map your column number into an Excel column designation.
Takes in a 0-based base-10 column and returns a ALPHA-26 representation. eg column #3 -> D
Since you're starting with column "B" (1), add 1 to i first.
String nextLetter = String.valueOf(CellReference.convertNumToColString(i + 1));
As title, I have a little trouble here.
I can get font from cell
HSSFFont font =
cell.getRow().getSheet().getWorkbook().
getFontAt(cell.getCellStyle().getFontIndex());
But now I need to get range name of it. Actually I need something to anchor and determine key cell and its own value cell.
Is there some method to get range name such as workBook.getName() or .getNameAt() but how to get name index from HSSFCell?
Apart from rich text strings, a cell has only one font assigned,
but it may be referenced by more than one named range.
So you'll need to iterate through the named ranges of the workbook and check if the cell is referenced. For the sake of simplicity, I have iterated over all area.getAllReferencedCells() - in case of big ranges you'll need to check if the area isContiguous() and if your cell/row-index is inside the cell/row-index of getFirstCell() and getLastCell() bounding box.
For more info check the Busy Developers' Guide to HSSF and XSSF Features.
Or search on stackoverflow ...
(in my testcase, a cell(row 4, col 3) was referenced by three different shaped named ranges)
import java.io.File;
import java.util.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
public class XlsRangeNames {
public static void main(String[] args) throws Exception {
Workbook wb = WorkbookFactory.create(new File("src/test/resources/name-range.xls"));
Cell cell = wb.getSheetAt(0).getRow(3).getCell(2);
for (Name n : getNamedRangesForCell(wb, cell)) {
System.out.println(n.getNameName());
}
}
static List<Name> getNamedRangesForCell(Workbook wb, Cell cell) {
int col = cell.getColumnIndex();
int row = cell.getRowIndex();
String sheetName = cell.getSheet().getSheetName();
List<Name> result = new ArrayList<Name>();
for (int i=0; i<wb.getNumberOfNames(); i++) {
Name name = wb.getNameAt(i);
if (!sheetName.equals(name.getSheetName())) continue;
AreaReference area = new AreaReference(name.getRefersToFormula());
CellReference crList[] = area.getAllReferencedCells();
for (CellReference cr : crList) {
if (cr.getCol() == col
&& cr.getRow() == row) {
result.add(name);
continue;
}
}
}
return result;
}
}