Apache POI - Excel Get value by given ranges - java

User will insert ranges value for example A1:A3 to retrieve the data. How i can get the value based on the given ranges using Apache POI?
or is there any library that i can use?

Below is the solution that i got. Using AreaReference function.
AreaReference aref = new AreaReference(sheet.getSheetName() + "!A3:A9", SpreadsheetVersion.EXCEL2007);
CellReference[] crefs = aref.getAllReferencedCells();
for (int i=0; i<crefs.length; i++) {
XSSFSheet s = workbook.getSheet(crefs[i].getSheetName());
Row r = s.getRow(crefs[i].getRow());
Cell c = r.getCell(crefs[i].getCol());
}

import org.apache.poi.ss.util.SheetUtil
final Cell cell= SheetUtil.getCellWithMerges(sheet, 5, 2);
visit http://poi.apache.org/apidocs/4.1/org/apache/poi/ss/util/SheetUtil.html

Related

Select specific range/scope of a pivot table to apply format on (Aspose.Cells for Java)

Is there an equivalent of this VBA function PivotTable.PivotSelect in Aspose.Cells product ?
I am looking for a way to create a border on a whole selection of cells containing specific data field values, or on a specific scope as you prefer.
The VBA macro to perform this action is the following, by giving only the data field name parameter :
v_wbx.Sheets(v_SheetName).**PivotTables(v_CurrentPivotName).PivotSelect **DataFieldName**, xlDataAndLabel, True**
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Color = v_Color
.TintAndShade = 0
.Weight = v_Weight
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Color = v_Color
.TintAndShade = 0
.Weight = v_Weight
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Color = v_Color
.TintAndShade = 0
.Weight = v_Weight
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Color = v_Color
.TintAndShade = 0
.Weight = v_Weight
End With
Is this covered by Aspose.Cells ? I looked into documentation but haven't found any solution.
I'm aware that the "scope" selection is available with the Aspose conditional formatting, but here I want to create the border around the WHOLE selection of cells by specifying the data field name, and NOT use any Conditional Format rule.
This is done via VBA using this enum : https://learn.microsoft.com/en-us/office/vba/api/excel.xlptselectionmode and the function mentioned before.
I precise I'm using the trial version of the product to evaluate the range of features.
Please share your positive or negative feedback on this topic, thank you
You can format specific data area values in the Pivot Table via Aspose.Cells for Java. See the following example for your reference. You can apply formatting via both ways (i.e., use directly apply formatting and via pivot format condition).
e.g.
Sample code:
//Instantiating a Workbook object
Workbook workbook = new Workbook();
//Obtaining the reference of the newly added worksheet
int sheetIndex = workbook.getWorksheets().add();
Worksheet sheet = workbook.getWorksheets().get(sheetIndex);
Cells cells = sheet.getCells();
//Setting the value to the cells
Cell cell = cells.get("A1");
cell.setValue("Sport");
cell = cells.get("B1");
cell.setValue("Quarter");
cell = cells.get("C1");
cell.setValue("Sales");
cell = cells.get("A2");
cell.setValue("Golf");
cell = cells.get("A3");
cell.setValue("Golf");
cell = cells.get("A4");
cell.setValue("Tennis");
cell = cells.get("A5");
cell.setValue("Tennis");
cell = cells.get("A6");
cell.setValue("Tennis");
cell = cells.get("A7");
cell.setValue("Tennis");
cell = cells.get("A8");
cell.setValue("Golf");
cell = cells.get("B2");
cell.setValue("Qtr3");
cell = cells.get("B3");
cell.setValue("Qtr4");
cell = cells.get("B4");
cell.setValue("Qtr3");
cell = cells.get("B5");
cell.setValue("Qtr4");
cell = cells.get("B6");
cell.setValue("Qtr3");
cell = cells.get("B7");
cell.setValue("Qtr4");
cell = cells.get("B8");
cell.setValue("Qtr3");
cell = cells.get("C2");
cell.setValue(1500);
cell = cells.get("C3");
cell.setValue(2000);
cell = cells.get("C4");
cell.setValue(600);
cell = cells.get("C5");
cell.setValue(1500);
cell = cells.get("C6");
cell.setValue(4070);
cell = cells.get("C7");
cell.setValue(5000);
cell = cells.get("C8");
cell.setValue(6430);
PivotTableCollection pivotTables = sheet.getPivotTables();
//Adding a PivotTable to the worksheet
int index = pivotTables.add("=A1:C8", "E3", "PivotTable2");
//Accessing the instance of the newly added PivotTable
PivotTable pivotTable = pivotTables.get(index);
//Unshowing grand totals for rows.
pivotTable.setRowGrand(false);
//Dragging the first field to the row area.
pivotTable.addFieldToArea(PivotFieldType.ROW, 0);
//Dragging the second field to the column area.
pivotTable.addFieldToArea(PivotFieldType.COLUMN, 1);
//Dragging the third field to the data area.
pivotTable.addFieldToArea(PivotFieldType.DATA, 2);
pivotTable.refreshData();
pivotTable.calculateData();
/*
//Apply formatting to specific data area values via Pivot format condition.
PivotFormatConditionCollection pfcc = pivotTable.getPivotFormatConditions();
int pIndex = pfcc.add();
PivotFormatCondition pfc = pfcc.get(pIndex);
FormatConditionCollection fcc = pfc.getFormatConditions();
CellArea dataBodyRange = pivotTable.getDataBodyRange();
fcc.addArea(dataBodyRange);
int idx = fcc.addCondition(FormatConditionType.CELL_VALUE);
FormatCondition fc = fcc.get(idx);
fc.setFormula1("6000");
fc.setOperator(OperatorType.GREATER_OR_EQUAL);
//fc.getStyle().setBackgroundColor(com.aspose.cells.Color.getRed());
fc.getStyle().setBorder(BorderType.LEFT_BORDER, CellBorderType.THICK, com.aspose.cells.Color.getRed());
fc.getStyle().setBorder(BorderType.TOP_BORDER, CellBorderType.THICK, com.aspose.cells.Color.getRed());
fc.getStyle().setBorder(BorderType.RIGHT_BORDER, CellBorderType.THICK, com.aspose.cells.Color.getRed());
fc.getStyle().setBorder(BorderType.BOTTOM_BORDER, CellBorderType.THICK, com.aspose.cells.Color.getRed());
*/
///*
//Apply formatting directly to specific data fields.
CellArea dataArea = pivotTable.getDataBodyRange();
for(int dataRowNum = dataArea.StartRow; dataRowNum <= dataArea.EndRow;dataRowNum++){
for(int dataColNum = dataArea.StartColumn;dataColNum <= dataArea.EndColumn;dataColNum++){
cell = cells.get(dataRowNum,dataColNum);
int value = cell.getIntValue();
System.out.println(value);
if (value > 6000) {
Style style = cell.getStyle();
com.aspose.cells.Font font = style.getFont();
font.setColor(com.aspose.cells.Color.getBlue());
style.setBorder(BorderType.LEFT_BORDER, CellBorderType.THICK, com.aspose.cells.Color.getRed());
style.setBorder(BorderType.TOP_BORDER, CellBorderType.THICK, com.aspose.cells.Color.getRed());
style.setBorder(BorderType.RIGHT_BORDER, CellBorderType.THICK, com.aspose.cells.Color.getRed());
style.setBorder(BorderType.BOTTOM_BORDER, CellBorderType.THICK, com.aspose.cells.Color.getRed());
pivotTable.format(dataRowNum, dataColNum, style);
}
}
}
workbook.save("f:\\files\\out1.xlsx");
You may also post your queries in the dedicated forum.
PS. I am working as Support developer/ Evangelist at Aspose.

How to handle an empty numeric cell in POI

Is there any particular reason POI creates a numeric cell when in fact, it's actually empty? What happens is that by the time I get to that cell I obviously get an runtime error as I can't get the string value (it's a numeric cell, after all) and I can't get the numeric value either (can't get a number from an empty string) so my 2 questions would be:
How does POI got there?
Is there any way I can handle this scenario without having to explicitly go to my excel file?
UPDATE I:
After reading / parsing my excel file, POI generates the following XML for this particular cell:
<x:c r="AA2" t="n">
<x:v/>
</x:c>
My method is something like this:
final FileInputStream inputStream = new FileInputStream(new File("PATH/TO/FILE.xml"));
final XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
final XSSFSheet sheet = workbook.getSheet("SHEET_NAME");
final int columnCount = sheet.getRow(0).getLastCellNum();
for (int rowNumber = 0; rowNumber <= sheet.getLastRowNum(); rowNumber++)
{
final XSSFRow row = sheet.getRow(rowNumber);
for (int column = 0; column < columnCount; column++)
{
// By now my cell would throw an exception if I attempt cell.getStringCellValue() or cell.getNumericCellValue() as cell.getCellType() returns "0" / NUMERIC
final XSSFCell cell = row.getCell(column);
...
}
}
I was thinking about adding an additional validation to determine whether the cell is empty by using the getRawValue() method, but not sure if there's a better way to handle this as it was obviously wrongly parsed.
UPDATE II
I've been able to reproduce this scenario by doing adding this as part of a unit test (I still don't understand why POI would fall into this scenario though):
final XLSXSheetConverterImpl xlsxSheetConverter = new XLSXSheetConverterImpl();
xlsxSheetConverter.setSheetName(SHEET_NAME);
xlsxSheetConverter.setFilePrefix(FILE_PREFIX);
XSSFWorkbook workbook = new XSSFWorkbook();
final XSSFSheet sheet = workbook.createSheet(SHEET_NAME);
final XSSFRow row = sheet.createRow(0);
XSSFCell cell = row.createCell(0);
final CTCellImpl ctCell = (CTCellImpl) cell.getCTCell();
ctCell.setT(STCellType.N);
ctCell.setV("");
Thanks in advance!
This is a known bug in older POI versions, see: https://bz.apache.org/bugzilla/show_bug.cgi?id=56702
It's been fixed since 3.11 version
Thank you all for your help!!

Apache POI : Update cells in a named range

I am using Apache POI library to read/write to xlsx. In my original xlsx, I have a namedrange "XYZ".
I want to update the values of cells within this name range. How can I do that?
I did this:
XSSFName name = workbook.getName("XYZ");
String formula = name.getRefersToFormula();
System.out.println("Formula = " + formula);
Now, I dont know how to get a handle to individual cell in this named range.
Can anyone please point me to the correct API that I can use?
Rgds
Sapan
There is an example from the Busy Developers' Guide for retrieving the cells in the range. Then you can use Cell.setCellValue() to update.
// setup code
String cname = "TestName";
Workbook wb = getMyWorkbook(); // retrieve workbook
// retrieve the named range
int namedCellIdx = wb.getNameIndex(cname);
Name aNamedCell = wb.getNameAt(namedCellIdx);
// retrieve the cell at the named range and test its contents
AreaReference aref = new AreaReference(aNamedCell.getRefersToFormula());
CellReference[] crefs = aref.getAllReferencedCells();
for (int i=0; i<crefs.length; i++) {
Sheet s = wb.getSheet(crefs[i].getSheetName());
Row r = s.getRow(crefs[i].getRow());
Cell c = r.getCell(crefs[i].getCol());
// extract the cell contents based on cell type etc.
}

Excel formula not updating on row delete from java application using Apache POI

I'm using Apache POI in my application to write data to an excel file. I've an excel file template and a few formulas are also there in it. In my application, i use the excel template, write into it ,then delete unused rows and calculate formulas in the end. I'm using SUM formula in the file. The problem is when rows are deleted, the SUM formula is not updating,due to which error values are coming up in excel.
Example : the formula being used is : for cell B215 : SUM(B15:B214). in the application,after writing to the file i delete unused rows. now I've data till 70th row in the file.All other rows have been deleted. So my formula should get updated to : SUM(B15:B69) for cell B70. But in the file it's still showing the formula as SUM(B15:B214). Hence the value of that cell is "VALUE#
Code snippet :
File file = new File(path)
InputStream is = new FileInputStream(file)
POIFSFileSystem fs = new POIFSFileSystem(is)
HSSFWorkbook wb = new HSSFWorkbook(fs)
HSSFSheet excelSheet
int[] indexArray = populateSheet(excelSheet)
//indexArray is array with 3 values as startrow, lastrow, and first empty row.
removeBlankRows(excelSheet,indexArray)
//evaluate formula
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator()
for(HSSFRow r : excelSheet) {
for(HSSFCell c : r) {
if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
String formula = c.getCellFormula();
evaluator.evaluateFormulaCell(c)
}
}
}
private void removeBlankRows(HSSFSheet sheet, int[] shiftInfo){
for(int i = shiftInfo[2]; i <= shiftInfo[1]; ++i) {
sheet.removeRow(sheet.getRow(i))
}
//Shift up the rows
def startRow = shiftInfo[1]+1
def endRow = sheet.getLastRowNum()
def rowCount = -1* (shiftInfo[1] - shiftInfo[2] + 1)
sheet.shiftRows(startRow, endRow, rowCount)
}
This is an Excel bug. I've dealt with this in the past by doing the following:
Label the sum cell BSUM
We need a stable range that won't be affected by inserts/deletes.
Add a formula to a safe (one that won't get deleted) cell, for this example D15: ="B15:B"&ROW(BSUM)-1
This will produce a stable range.
Use INDIRECT in the BSUM cell like so:
=SUM(INDIRECT(D15))

Apache POI blank values

I am using Apache POI to import data from excel file to database.(newbie to APACHE POI)
In which I am allowing user to select columns from excel sheet and Map those columns to the Database columns. After mapping the columns, when I try to insert the records from Excel to Database then:
If Columns with NO blank values in them are Mapped then Proper data is inserted into the database
If columns are Mapped with BLANK values in them, then if a Excel Cell has blank value then previous value of that column is assigned.
Source Code:
FileInputStream file = new FileInputStream(new File("C:/Temp.xls"));
HSSFWorkbook workbook = new HSSFWorkbook(file); //Get the workbook instance for XLS file
HSSFSheet sheet = workbook.getSheetAt(0); //Get first sheet from the workbook
Iterator<Row> rowIterator = sheet.iterator(); //Iterate through each rows from first sheet
while (rowIterator.hasNext())
{
HSSFRow hssfRow = (HSSFRow) rowIterator.next();
Iterator<Cell> iterator = hssfRow.cellIterator();
int current = 0, next = 1;
while (iterator.hasNext())
{
HSSFCell hssfCell = (HSSFCell) iterator.next();
current = hssfCell.getColumnIndex();
for(int i=0;i<arrIndex.length;i++) //arrayIndex is array of Excel cell Indexes selected by the user
{
if(arrIndex[i] == hssfCell.getColumnIndex())
{
if(current<next)
{
//System.out.println("Condition Satisfied");
}
else
{
System.out.println( "pstmt.setString("+next+",null);");
pstmt.setString(next,null);
next = next + 1;
}
System.out.println( "pstmt.setString("+next+","+((Object)hssfCell).toString()+");");
pstmt.setString(next,((Object)hssfCell).toString());
next = next + 1;
}
}
}
pstmt.addBatch();
}
I have look for similar questions on SO, but still not able to solve the issue.. So any help will be appreciated.
Thanks in advance..
You've made a very common mistake, which has been covered in rather a lot of past StackOverflow questions
As the Apache POI documentation on cell iterating says
In some cases, when iterating, you need full control over how missing or blank cells are treated, and you need to ensure you visit every cell and not just those defined in the file. (The CellIterator will only return the cells defined in the file, which is largely those with values or stylings, but it depends on Excel).
It sounds like you are in that situation, where you need to care about hitting every row/cell, and not just grabbing all the available cells without worrying about the gaps
You'll want to change you code to look somewhat like the example in the POI docs:
// Decide which rows to process
int rowStart = Math.min(15, sheet.getFirstRowNum());
int rowEnd = Math.max(1400, sheet.getLastRowNum());
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
Row r = sheet.getRow(rowNum);
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
for (int cn = 0; cn < lastColumn; cn++) {
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// The spreadsheet is empty in this cell
// Mark it as blank in the database if needed
} else {
// Do something useful with the cell's contents
}
}
}

Categories