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.
}
Related
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.
I have an excel file. I want to set a unique name to a particular cell.
But there is no method called "cell.setName".
Regarding official documentation:
Named Range is a way to refer to a group of cells by a name. Named Cell is a degenerate case of Named Range in that the 'group of cells' contains exactly one cell. You can create as well as refer to cells in a workbook by their named range. When working with Named Ranges, the classes org.apache.poi.ss.util.CellReference and org.apache.poi.ss.util.AreaReference are used.
Note: Using relative values like 'A1:B1' can lead to unexpected moving of the cell that the name points to when working with the workbook in Microsoft Excel, usually using absolute references like '$A$1:$B$1' avoids this, see also this discussion.
Creating Named Range / Named Cell
// setup code
String sname = "TestSheet", cname = "TestName", cvalue = "TestVal";
Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet(sname);
sheet.createRow(0).createCell(0).setCellValue(cvalue);
// 1. create named range for a single cell using areareference
Name namedCell = wb.createName();
namedCell.setNameName(cname + "1");
String reference = sname+"!$A$1:$A$1"; // area reference
namedCell.setRefersToFormula(reference);
// 2. create named range for a single cell using cellreference
Name namedCel2 = wb.createName();
namedCel2.setNameName(cname + "2");
reference = sname+"!$A$1"; // cell reference
namedCel2.setRefersToFormula(reference);
// 3. create named range for an area using AreaReference
Name namedCel3 = wb.createName();
namedCel3.setNameName(cname + "3");
reference = sname+"!$A$1:$C$5"; // area reference
namedCel3.setRefersToFormula(reference);
// 4. create named formula
Name namedCel4 = wb.createName();
namedCel4.setNameName("my_sum");
namedCel4.setRefersToFormula("SUM(" + sname + "!$I$2:$I$6)");
Link: https://poi.apache.org/components/spreadsheet/quick-guide.html#NamedRanges
// setup code
String sname = "TestSheet", cname = "TestName", cvalue = "TestVal";
Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet(sname);
sheet.createRow(0).createCell((short) 0).setCellValue(cvalue);
// 1. create named range for a single cell using areareference
Name namedCell = wb.createName();
namedCell.setNameName(cname);
String reference = sname+"!A1:A1"; // area reference
namedCell.setRefersToFormula(reference);
From : http://poi.apache.org/components/spreadsheet/quick-guide.html#NamedRanges
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
I want to get the cell data of a particular sheet with column name rather than column index,
Currently i can get the cell data using
fis = new FileInputStream(ExcelPath);
wb = new XSSFWorkbook(fis);
sh = wb.getSheet(SheetName);
cell = sh.getRow(rownum).getCell(colnum);
but I am looking for a way where I can get the cell data by,
cell = sh.getRow(rownum).getCell(ColName); //not working
Excel columns don't have names. They only have letters, eg A, D, BB
To work out how to map an Excel-style column letter into a POI-style 0-based index, you need to use the method convertColStringToIndex(java.lang.String ref) which does it for you
If you mean you want to lookup a column based on the value held in the first row, you should do something like:
DataFormatter fmt = new DataFormatter();
Map<String,Integer> headings = new HashMap<String,Integer>();
Row headings = sheet.getRow(0);
if (headings == null) throw new IllegalArgumentException("Empty headings row");
for (Cell c : headings) {
headings.put(fmt.formatCellValue(c), c.getColumnIndex());
}
If you have more complex use cases, such as a heading running over multiple rows, you'll need to write more complex code... It's all driven by your use-case
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))