How to cache the formula cell by using Apache POI - java

I created code as below to create excel file and calculate and get cell value after because I need to use function in excel.(this function is not supported by apache poi, so I think I have to read cached./formatted value)
package main;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
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.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class WorkbookEvaluator
{
public static void pop_mean()
{
System.out.println ("Test population mean in two different populations are same or not");
System.out.println ("This program works only for two-tailed ");
Scanner in = new Scanner(System.in);
System.out.println ("What is population mean?:");
double m = in.nextDouble();
System.out.println ("How many samples are taken from population?:");
double n = in.nextDouble();
System.out.println ("What is Sample mean?:");
double X = in.nextDouble();
System.out.println ("What is unbiased variance for population:");
double U = in.nextDouble();
System.out.println ("What is Level of Significance (Type with %-value)");
double L = in.nextDouble();
double l = L/100;
double a = n-1;
double b = X-m;
double c = Math.sqrt(n);
double d = Math.sqrt(U);
double f = d/c;
double T = b/f;
System.out.println ("Degree of freedom is " + a);
System.out.println ("Test statistic is " + T);
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet();
Row row1 = sheet.createRow(1);
Row row2 = sheet.createRow(2);
Cell cell1_1 = row1.createCell(1);
Cell cell1_2 = row1.createCell(2);
Cell cell1_3 = row1.createCell(3);
Cell cell2_3 = row2.createCell(3);
Cell cell2_4 = row2.createCell(4);
cell1_1.setCellValue(l);
cell1_2.setCellValue(a);
cell2_3.setCellFormula("_xlfn.T.INV.2T(" + l +"," + a + ")");
cell2_4.setCellFormula("SUM(" + l +"," + a + ")");
FileOutputStream out = null;
try {
out = new FileOutputStream("T-inverse.xlsx");
wb.write(out);
} catch(IOException e) {
System.out.println(e.toString());
} finally {
try {
out.close();
} catch(IOException e) {
System.out.println(e.toString());
}
}
}
public static void read_excel() throws IOException
{
for (int q=3;q<5;q++)
{
XSSFWorkbook book = new XSSFWorkbook("C:\\Users\\shump\\Java\\Population mean Test\\T-inverse.xlsx");
book.setForceFormulaRecalculation(true);
XSSFSheet sheet = book.getSheetAt(0);
sheet.setForceFormulaRecalculation(true);
XSSFRow row = sheet.getRow(2);
final DataFormatter dataFormatter = new DataFormatter();
final double formtatedValue = row.getCell((short) q).getNumericCellValue();
System.out.println(formtatedValue);
}
}
public static void main(String[] args) throws IOException
{
pop_mean();
read_excel();
}
}
As can be see from the attempted picture below, it works successfully in excel. However, consoled output will display 0.0. I thought this is because of function is not supported so I tried same thing by using sum function which is one of the basic function and this function is supported. However, it didn't work. In picture D3 is where I used T.INV.2T function.
Test population mean in two different populations are same or not
This program works only for two-tailed
What is population mean?:
171.4
How many samples are taken from population?:
9
What is Sample mean?:
172.8
What is unbiased variance for population:
4
What is Level of Significance (Type with %-value)
5
Degree of freedom is 8.0
Test statistic is 2.1000000000000085
0.0
0.0
After few research, I found article which states when the formula value is not cached, output will be 0. So, please tell me how I can cache the value or is there any other way that I can take to get value of non-supported function.

You seems misunderstand what apache poi is made for. In terms of Excel it is made for creating Excel files. That meams it creates files which Excelis able to open then. When it opens workbook files, it opens them as apache poi Workbook only to be able to append content. Apache poi is not thought to be the same as Excel and it does not interact with any Excel application.
So the setForceFormulaRecalculation is not a apache poi setting but a setting for Excel when Excel opens the workbook. If setForceFormulaRecalculation is set true, then Excel recalculates all formulas when Excel opens the workbook file. It does not mean that apache poi recalculates all formulas.
To force apache poi calculating the formulas, FormulaEvaluator needs to be used.
For example if you extend your code as follows:
...
import org.apache.poi.ss.usermodel.FormulaEvaluator;
...
Workbook wb = new XSSFWorkbook();
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
...
cell2_4.setCellFormula("SUM(" + l +"," + a + ")");
try {
evaluator.evaluateFormulaCell(cell2_4);
} catch (org.apache.poi.ss.formula.eval.NotImplementedException notImplEx) {
notImplEx.printStackTrace();
}
...
then the SUM formula gets evaluated and cell2_4 contains the evaluated numeric value additional to the formula.
But of course
...
cell2_3.setCellFormula("TINV(" + l +"," + a + ")");
try {
evaluator.evaluateFormulaCell(cell2_3);
} catch (org.apache.poi.ss.formula.eval.NotImplementedException notImplEx) {
notImplEx.printStackTrace();
}
...
will lead to NotImplementedException since TINV is not yet implemented in apache poi.
So we need to do what is shown in Developing Formula Evaluation. In terms of the TINV function this would be:
...
import org.apache.poi.ss.formula.WorkbookEvaluator;
import org.apache.poi.ss.formula.eval.*;
import org.apache.poi.ss.formula.functions.*;
import org.apache.commons.math3.distribution.TDistribution;
...
static Function TINV = new Fixed2ArgFunction() {
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg1, ValueEval arg2) {
try {
ValueEval ve1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex);
double dArg1 = OperandResolver.coerceValueToDouble(ve1);
ValueEval ve2 = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex);
double dArg2 = OperandResolver.coerceValueToDouble(ve2);
TDistribution t = new TDistribution(dArg2);
double result = t.inverseCumulativeProbability(1d - dArg1/2d);
if (Double.isNaN(result) || Double.isInfinite(result)) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
return new NumberEval(result);
} catch (EvaluationException e) {
return e.getErrorEval();
}
}
};
...
and then
...
WorkbookEvaluator.registerFunction("TINV", TINV);
...
Note, I have implemented TINV instead of _xlfn.T.INV.2T since the latter is not able to be implemented that way because of it's strange name. All Excel versions I know also support TINV instead of _xlfn.T.INV.2T.
Complete example extending your code:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
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.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.formula.WorkbookEvaluator;
import org.apache.poi.ss.formula.eval.*;
import org.apache.poi.ss.formula.functions.*;
import org.apache.commons.math3.distribution.TDistribution;
public class WorkbookEvaluatorTest {
static Function TINV = new Fixed2ArgFunction() {
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg1, ValueEval arg2) {
try {
ValueEval ve1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex);
double dArg1 = OperandResolver.coerceValueToDouble(ve1);
ValueEval ve2 = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex);
double dArg2 = OperandResolver.coerceValueToDouble(ve2);
TDistribution t = new TDistribution(dArg2);
double result = t.inverseCumulativeProbability(1d - dArg1/2d);
if (Double.isNaN(result) || Double.isInfinite(result)) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
return new NumberEval(result);
} catch (EvaluationException e) {
return e.getErrorEval();
}
}
};
public static void pop_mean() {
WorkbookEvaluator.registerFunction("TINV", TINV);
System.out.println ("Test population mean in two different populations are same or not");
System.out.println ("This program works only for two-tailed ");
Scanner in = new Scanner(System.in);
System.out.println ("What is population mean?:");
double m = in.nextDouble();
System.out.println ("How many samples are taken from population?:");
double n = in.nextDouble();
System.out.println ("What is Sample mean?:");
double X = in.nextDouble();
System.out.println ("What is unbiased variance for population:");
double U = in.nextDouble();
System.out.println ("What is Level of Significance (Type with %-value)");
double L = in.nextDouble();
double l = L/100;
double a = n-1;
double b = X-m;
double c = Math.sqrt(n);
double d = Math.sqrt(U);
double f = d/c;
double T = b/f;
System.out.println ("Degree of freedom is " + a);
System.out.println ("Test statistic is " + T);
Workbook wb = new XSSFWorkbook();
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
Sheet sheet = wb.createSheet();
Row row1 = sheet.createRow(1);
Row row2 = sheet.createRow(2);
Cell cell1_1 = row1.createCell(1);
Cell cell1_2 = row1.createCell(2);
Cell cell1_3 = row1.createCell(3);
Cell cell2_3 = row2.createCell(3);
Cell cell2_4 = row2.createCell(4);
cell1_1.setCellValue(l);
cell1_2.setCellValue(a);
cell2_3.setCellFormula("TINV(" + l +"," + a + ")");
try {
evaluator.evaluateFormulaCell(cell2_3);
} catch (org.apache.poi.ss.formula.eval.NotImplementedException notImplEx) {
notImplEx.printStackTrace();
}
cell2_4.setCellFormula("SUM(" + l +"," + a + ")");
try {
evaluator.evaluateFormulaCell(cell2_4);
} catch (org.apache.poi.ss.formula.eval.NotImplementedException notImplEx) {
notImplEx.printStackTrace();
}
FileOutputStream out = null;
try {
out = new FileOutputStream("T-inverse.xlsx");
wb.write(out);
} catch(IOException e) {
System.out.println("Write: " + e.toString());
} finally {
try {
out.close();
wb.close();
} catch(IOException e) {
System.out.println("Close: " + e.toString());
}
}
}
public static void read_excel() throws IOException {
for (int q=3;q<5;q++) {
XSSFWorkbook book = new XSSFWorkbook("T-inverse.xlsx");
//book.setForceFormulaRecalculation(true);
XSSFSheet sheet = book.getSheetAt(0);
//sheet.setForceFormulaRecalculation(true);
XSSFRow row = sheet.getRow(2);
final DataFormatter dataFormatter = new DataFormatter();
final double formtatedValue = row.getCell((short) q).getNumericCellValue();
System.out.println(formtatedValue);
}
}
public static void main(String[] args) throws IOException {
pop_mean();
read_excel();
}
}

Related

How to change cell color of source excel sheet after comparison with another excel using Apache POI

I have been trying to change the cell color of exact match string from source excel file when compared with another excel file and unable to do it with all the various examples suggested.
I am treating each cell entry as string and comparing that string with row of another excel sheet and if a match is found then want to highlight the source string cell color as GREEN.
Here is the code which I have written so far for comparing two excel sheets(Book1 and Book2) and need help if someone can guide in changing the cell color of exact match condition in Book1.
Or if there is a need to create a new excel file with redirected contents from Book1 exact match conditions?
import org.apache.poi.xssf.usermodel.XSSFCell;
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.CellType;
import java.io.FileInputStream;
import java.io.IOException;
public class ExcelCompare {
public static void main(String[] srgs) throws IOException {
FileInputStream fileInputStream1 = new
FileInputStream("C:\\Stuff\\JavaProject\\Book1.xlsx");
XSSFWorkbook workbook1 = new XSSFWorkbook(fileInputStream1);
XSSFSheet worksheet1 = workbook1.getSheet("Sheet1");
int rowCount1= worksheet1.getPhysicalNumberOfRows();
FileInputStream fileInputStream2 = new
FileInputStream("C:\\Stuff\\JavaProject\\Book2.xlsx");
XSSFWorkbook workbook2 = new XSSFWorkbook(fileInputStream2);
XSSFSheet worksheet2 = workbook2.getSheet("Sheet1");
int rowCount2= worksheet2.getPhysicalNumberOfRows();
System.out.println("Row count 1=" + rowCount1 + " Row count 2 = " + rowCount2);
for (int i = 1; i < rowCount1; i++) {
XSSFRow row1 = worksheet1.getRow(i);
//------------------------------ comapring Name --------------------------
String namestr1 = "";
XSSFCell name1 = row1.getCell(0);
if (name1 != null)
{
name1.setCellType(CellType.STRING);
namestr1 = name1.getStringCellValue();
}
int j=1;
int notNullRows=0;
int rowCount2WithNulls = rowCount2;
while(j<rowCount2WithNulls && notNullRows <= rowCount2 )
{
XSSFRow row2 = worksheet2.getRow(j);
String namestr2 = "";
j++;
if (row2 != null)
{
notNullRows++;
XSSFCell name2 = row2.getCell(0);
if (name2 != null) {
name2.setCellType(CellType.STRING);
namestr2 = name2.getStringCellValue();
}
}
else
{
rowCount2WithNulls++;
}
if(namestr1.equals(namestr2))
{
System.out.println("[Processing] :"+"NAME " + namestr1 + "=> Book 1 name = " + namestr1+ " Book 2 name = " + namestr2);
}
}
}
}
}
You must set a cellstyle and then apply a desired color to it.
if (namestr1.equals(namestr2)) {
System.out.println("[Processing] :" + "NAME " + namestr1 + "=> Book 1 name = " + namestr1 + " Book 2 name = " +
// add color
XSSFCellStyle style = workbook1.createCellStyle();
style.setFillForegroundColor(IndexedColors.GREEN.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
assert name1 != null;
name1.setCellStyle(style);
FileOutputStream fos = new FileOutputStream(BOOK1);
workbook1.write(fos);
fos.close();
}

I want to copy data in a 2-D array into an excel sheet with Java

The below is my code and I am facing (The type java.lang.CharSequence cannot be resolved. It is indirectly referenced from required .class files) error which will occur for myCell.setCellValue(value); statement.
import java.io.FileOutputStream;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class test3 {
private static String dest = "D:\\testexcel.xls";
private static HSSFWorkbook myWorkBook = new HSSFWorkbook();
private static HSSFSheet mySheet = myWorkBook.createSheet();
private static void excelLog(int row, int col, String value) {
HSSFRow myRow = mySheet.getRow(row);
if (myRow == null)
myRow = mySheet.createRow(row);
HSSFCell myCell = myRow.createCell(col);
myCell.setCellValue(value);
}
public static void main(String[] args) {
int numCol = 10; // assume 10 cols
for (int i = 0; i < 10; i++) {
for (int j = 0; j < numCol; j++) {
excelLog(i, j, "Row : " + i + ", Cell : " + j);
}
}
try {
FileOutputStream out = new FileOutputStream(dest);
myWorkBook.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Most probably it is just an IDE build process related issue, code works perfect for org.apache.poi version 3.17.
Please try to clean the project and build it once again.
If it will not work delete the project from your IDE and import it once again - this should help.
As a quick check for this (in case of using build tool) - you can run build process from cmd and it should work.

How to access excel cell using cell name with java [duplicate]

I am writing a Java program to read data from excel sheet (having XLSX extension) using Apache POI library. I am able to iterate through all the cells and get all the values. But I am unable to get a specific cell value, say E10.
Is there any way to do this?
Please see the code below that I used for iterating through the cells.
package application;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import org.apache.poi.hssf.usermodel.HSSFCell;
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.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadFromXLSX {
public static void readXLSXFile() throws IOException
{
InputStream ExcelFileToRead = new FileInputStream("C:\\Test.xlsx");
XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
XSSFWorkbook test = new XSSFWorkbook();
XSSFSheet sheet = wb.getSheetAt(0);
XSSFRow row;
XSSFCell cell;
Iterator rows = sheet.rowIterator();
while (rows.hasNext())
{
row=(XSSFRow) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext())
{
cell=(XSSFCell) cells.next();
if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING)
{
System.out.print(cell.getStringCellValue()+" ");
}
else if(cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC)
{
System.out.print(cell.getNumericCellValue()+" ");
}
else
{
}
}
System.out.println();
}
}
}
For example, to get E10 of the first worksheet:
wb.getSheetAt(0).getRow(9).getCell(4);
Note: subtract one because the indices are null-based.
You can also use this convenience method to map E to 4.
wb.getSheetAt(0).getRow(9).getCell(CellReference.convertColStringToIndex("E"));
To get a value from a specific cell in excel you can use the below code line.
wb.getSheetAt(0).getRow(1).getCell(1);
XSSFSheet has the method getRow(int rownum)
It returns the logical row ( 0-based). If you ask for a row that is not defined you get a null. This is to say row 4 represents the fifth row on a sheet.
Once you get the row, you can call getCell(int cellnum) method of XSSFRow object. It returns the cell at the given (0 based) index.
Just version-up the getCell method
public XSSFCell getCell(String cellName){
Pattern r = Pattern.compile("^([A-Z]+)([0-9]+)$");
Matcher m = r.matcher(cellName);
XSSFWorkbook wb = new XSSFWorkbook();
if(m.matches()) {
String columnName = m.group(1);
int rowNumber = Integer.parseInt(m.group(2));
if(rowNumber > 0) {
return wb.getSheetAt(0).getRow(rowNumber-1).getCell(CellReference.convertColStringToIndex(columnName));
}
}
return null;
}
Now you can get the cell easily by this line
getCell("E10")
public class XmlFileRead {
public static void main(String[] args) throws IOException {
FileInputStream fi = new FileInputStream("abc.xls");
ArrayList<EmployeeVo> al = new ArrayList<>();
EmployeeVo evo = null;
Scanner scanner = null;
Workbook wb = new XSSFWorkbook(fi);
Sheet sh = wb.getSheet("Sheet0");
int starRow = sh.getFirstRowNum();
int endRow = sh.getLastRowNum();
for (int i = starRow + 1; i < endRow; i++) {
scanner = new Scanner(System.in);
evo = new EmployeeVo();
Cell c = wb.getSheetAt(0).getRow(i).getCell(1);
evo.setEmployeeId((int) c.getNumericCellValue());
Cell c2 = wb.getSheetAt(0).getRow(i).getCell(2);
evo.setEmployeeName(c2.toString());
// add to collection
al.add(evo);
} // for
al.forEach(i -> {
System.out.println(i.getEmployeeId() + " " + i.getEmployeeName());
});
}
}

How to get row data without using formula cells in apache poi

I am working on a program where the row data from excel sheet should be displayed as output. An id is been taken as input which will map to the particular row for displaying output. I am using apache poi on java to write the code. I want to display the output without using cells which I currently used in my prog. Is there any function that directly prints row data for row object?
package exceldata;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
public class exceldata {
private static final String FILE_NAME = "C:\\Users\\agandiko\\Desktop\\data.xlsx";
public static void main(String[] args) {
try {System.out.println("Enter the id:");
Scanner s=new Scanner(System.in);
String field=s.next();
int on=0;
int n=0;
int cc=1;
FileInputStream excelFile = new FileInputStream(new File(FILE_NAME));
Workbook wb = new XSSFWorkbook(excelFile);
DataFormatter formatter = new DataFormatter();
for (int i = 0; i < wb.getNumberOfSheets(); i++) {
System.out.println();
System.out.println();
System.out.println("Data for Sheet"+" "+(i+1));
System.out.println("-----------------------------------");
System.out.println();
System.out.println();
Sheet datatypeSheet = wb.getSheetAt(i);
Iterator<Row> iterator = datatypeSheet.iterator();
int noOfColumns = datatypeSheet.getRow(0).getPhysicalNumberOfCells();
while (iterator.hasNext()) {
Row currentRow = iterator.next();
Iterator<Cell> cellIterator = currentRow.iterator();
while (cellIterator.hasNext()) {
Cell currentCell = cellIterator.next();
Cell k=currentCell;
//getCellTypeEnum shown as deprecated for version 3.15
//getCellTypeEnum ill be renamed to getCellType starting from version 4.0
String val=formatter.formatCellValue(currentCell).toString();
if((val.equals(field)))
{
while(cellIterator.hasNext()){
if(cc==1){System.out.print(formatter.formatCellValue(k).toString()+" ");}
else{currentCell = cellIterator.next();System.out.print(formatter.formatCellValue(currentCell).toString()+" ");}
cc++;
}
// System.out.print(currentRow.toString()+" ");
// currentRow = iterator.next();
// cellIterator = currentRow.iterator();
// on=1;n++;}
//System.out.println(cc);
}
// if(n==noOfColumns){System.out.println();n=0;}
//on=0;
}
cc=1; }
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here's how I understand the use case: look for some id (the code assumes it to be in the first column of each sheet) and print the whole row if it matches the id that was entered; here's how this could be solved (depending on the data in your sheet, some null checks might need to be added, but in general it works "as is"):
public static void main(String[] args) throws IOException {
System.out.println("Enter the id:");
Scanner s = new Scanner(System.in);
String id = s.next();
FileInputStream excelFile = new FileInputStream(new File(FILE_NAME));
Workbook wb = new XSSFWorkbook(excelFile);
DataFormatter formatter = new DataFormatter();
for (int i = 0; i < wb.getNumberOfSheets(); i++) {
System.out.println();
System.out.println();
System.out.println("Data for Sheet" + " " + (i + 1));
System.out.println("-----------------------------------");
System.out.println();
System.out.println();
Sheet datatypeSheet = wb.getSheetAt(i);
Iterator<Row> iterator = datatypeSheet.iterator();
while (iterator.hasNext()) {
Row currentRow = iterator.next();
if(id.equals(formatter.formatCellValue(currentRow.getCell(0)))) {
currentRow.cellIterator().forEachRemaining(c -> System.out.print(formatter.formatCellValue(c) + " "));
}
}
}
wb.close();
s.close();
}

How to move position of chart in excel by Java POI

I want to add row in excel by java POI and I try with both shiftRows() function and createRow() function
both function can add row in excel but below chart position is remain and not move
I also like to move (shift down) the position of chart
I use poi version 3.9
Can anyone give me the advice or idea to move the position of that chart image
As the fact, the data range of chart also not changed. I need not only to move the position of charts but also need to increase the data range of chart
thanks!!
The shifting of the drawing anchors which determine the chart positions is possible. The method void insertRowsShiftShapes(Sheet sheet, int startRow, int n) does this for all drawing anchors which are affected of row inserting process into the sheet.
The correcting of the chart data ranges which are affected of the row inserting into the sheet is complicated as said already. It is not well tested and not ready yet. But I will provide it as a working draft. I hope it is a useful start point for further programming.
For running the code the ooxml-schemas-1.3.jar is needed as mentioned in apache poi FAQ
A good resource for documentation of the ooxml-schema objects for me is grepcode
Examples: CTTwoCellAnchor, CTPieChart, CTPieSer
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import java.io.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer;
import java.util.List;
class InsertRowsAboveChart {
//a method for shift rows and shift all anchors in drawing below the shifted rows
private static void insertRowsShiftShapes(Sheet sheet, int startRow, int n) {
java.util.List<CTTwoCellAnchor> drawingAnchors = ((XSSFDrawing)sheet.getDrawingPatriarch()).getCTDrawing().getTwoCellAnchorList();
for (CTTwoCellAnchor drawingAnchor : drawingAnchors) {
int fromRow = drawingAnchor.getFrom().getRow();
int toRow = drawingAnchor.getTo().getRow();
if (fromRow >= startRow) {
drawingAnchor.getFrom().setRow(fromRow + n);
drawingAnchor.getTo().setRow(toRow + n);
}
}
sheet.shiftRows(startRow, sheet.getLastRowNum(), n);
correctDataRangesOfCharts(sheet, startRow, n);
}
//a method for correcting data ranges for charts which are affected of the shifted rows
//!!working draft, not ready yet!!
private static void correctDataRangesOfCharts(Sheet sheet, int startRow, int n) {
java.util.List<XSSFChart> charts = ((XSSFDrawing)sheet.getDrawingPatriarch()).getCharts();
for (XSSFChart chart : charts) {
//pie charts
java.util.List<CTPieChart> piecharts = chart.getCTChart().getPlotArea().getPieChartList();
for (CTPieChart piechart : piecharts) {
java.util.List<CTPieSer> pieseries = piechart.getSerList();
for (CTPieSer pieserie : pieseries) {
boolean strRefchanged = false;
if (pieserie.getCat().isSetMultiLvlStrRef()) {
String strRef = pieserie.getCat().getMultiLvlStrRef().getF();
//todo: this only corrects the end row of the ranges, should also correct start row if affected
int strRefEndRow = Integer.parseInt(strRef.substring(strRef.lastIndexOf('$') + 1));
if (strRefEndRow >= startRow) {
strRef = strRef.substring(0, strRef.lastIndexOf('$') +1) + (strRefEndRow + n);
pieserie.getCat().getMultiLvlStrRef().setF(strRef);
strRefchanged = true;
}
} else if (pieserie.getCat().isSetStrRef()) {
String strRef = pieserie.getCat().getStrRef().getF();
int strRefEndRow = Integer.parseInt(strRef.substring(strRef.lastIndexOf('$') + 1));
if (strRefEndRow >= startRow) {
strRef = strRef.substring(0, strRef.lastIndexOf('$') +1) + (strRefEndRow + n);
pieserie.getCat().getStrRef().setF(strRef);
strRefchanged = true;
}
}
if (strRefchanged) {
String numRef = pieserie.getVal().getNumRef().getF();
int numRefEndRow = Integer.parseInt(numRef.substring(numRef.lastIndexOf('$') + 1));
if (numRefEndRow >= startRow) {
numRef = numRef.substring(0, numRef.lastIndexOf('$') +1) + (numRefEndRow + n);
pieserie.getVal().getNumRef().setF(numRef);
}
}
}
}
//pie charts end
}
}
public static void main(String[] args) {
try {
InputStream inp = new FileInputStream("Workbook.xlsx");
Workbook wb = WorkbookFactory.create(inp);
Sheet sheet = wb.getSheetAt(0);
//sheet.shiftRows(3, 5, 4);
insertRowsShiftShapes(sheet, 2, 4);
FileOutputStream fileOut = new FileOutputStream("Workbook.xlsx");
wb.write(fileOut);
wb.close();
} catch (InvalidFormatException ifex) {
} catch (FileNotFoundException fnfex) {
} catch (IOException ioex) {
}
}
}

Categories

Resources