Apache POI shiftRows corrupts file and deletes content - java

I want to fill table a template excel file. I want to insert rows and fill them. I used java Apache POI library to access excel files. At first, I created a new file and filled column A from row 1 to 10 with 1..10 numbers and saved the file. Then I read the file and tried to insert a single empty row with a sheet.shiftRows() method. I tried below code but output file has a problem in the opening (reading) and rows 5,6,7 are empty and move has not occurred.
InputStream inputStream = new FileInputStream("TestIn-1.xlsx");
Workbook workbookIn = new XSSFWorkbook(inputStream);
Sheet sheetIn = workbookIn.getSheet("Sheet1");
sheetIn.shiftRows(4,5,1);
OutputStream outputStream = new FileOutputStream("TestOut.xlsx");
workbookIn.write(outputStream);
outputStream.close();

Your shiftRows tries shifting rows between row 5 (index 4) and row 6 (index 5) one row down. But what about row 7, 8, 9 and 10? You needs shifting rows between row 5 and last row one row down if the need is getting a new empty row 5.
Using apache poi version 3.17 this is as simple as:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ExcelReadShiftRowsAndWrite {
public static void main(String[] args) throws Exception {
//String fileIn= "TestIn.xls";
//String fileOut= "TestOut.xls";
String fileIn= "TestIn.xlsx";
String fileOut= "TestOut.xlsx";
try (Workbook workbook = WorkbookFactory.create(new FileInputStream(fileIn));
FileOutputStream out = new FileOutputStream(fileOut)) {
Sheet sheet = workbook.getSheet("Sheet1");
sheet.shiftRows(4, sheet.getLastRowNum(), 1); //shifts rows between row 5 (index 4) and last row one row down
workbook.write(out);
}
}
}
But apache poi versions greater than 3.17, also 4.1.0, have a bug in shiftRows using XSSF. There, after shifting, the references in the cells remain old instead being adjusted to the new rows. For example the references A5, A6, ... remain after shifting down instead of getting adjusted to A6, A7, ...
So this bug must be corrected:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ExcelReadShiftRowsAndWrite {
public static void main(String[] args) throws Exception {
//String fileIn= "TestIn.xls";
//String fileOut= "TestOut.xls";
String fileIn= "TestIn.xlsx";
String fileOut= "TestOut.xlsx";
try (Workbook workbook = WorkbookFactory.create(new FileInputStream(fileIn));
FileOutputStream out = new FileOutputStream(fileOut)) {
Sheet sheet = workbook.getSheet("Sheet1");
sheet.shiftRows(4, sheet.getLastRowNum(), 1); //shifts rows between row 5 (index 4) and last row one row down
if (sheet instanceof XSSFSheet) {
XSSFSheet xSSFSheet = (XSSFSheet)sheet;
// correcting bug that shiftRows does not adjusting references of the cells
// if row 3 is shifted down, then reference in the cells remain r="A3", r="B3", ...
// they must be adjusted to the new row thoug: r="A4", r="B4", ...
// apache poi 3.17 has done this properly but had have other bugs in shiftRows.
for (int r = xSSFSheet.getFirstRowNum(); r < sheet.getLastRowNum() + 1; r++) {
XSSFRow row = xSSFSheet.getRow(r);
if (row != null) {
long rRef = row.getCTRow().getR();
for (Cell cell : row) {
String cRef = ((XSSFCell)cell).getCTCell().getR();
((XSSFCell)cell).getCTCell().setR(cRef.replaceAll("[0-9]", "") + rRef);
}
}
}
// end correcting bug
}
workbook.write(out);
}
}
}

Related

Apache POI apply foating point format only if Number is decimal

Currently I'm using the format "#,##0.00" for all the Number type values retrieved from oracle DB to be saved in an excel file, but I don't want to save all values with a floating point if they don't have it on DB
For example
12 should be 12
12.1 should be 12.10
12.123 should be 12.12
If no special number format is set for the cell, then number format "General" is used. That will show 12 or 12.1 or 12.123. So to get what you want two different number formats ("0" (or "#,##0" if thousands separator shall be used) for integers and "#,##0.00" for decimals) are needed.
So main question is how to determine whether a number is integer or decimal. Following code does this task using the methods of Number. If number's integer value is equal to number's decimal value, then number is integer.
It creates a sheet showing 12 in A1, 12.10 in A2 and 12.12 in A3.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.util.List;
import java.util.ArrayList;
public class CreateExcelDifferentNumberformats {
public static void main(String[] args) throws Exception {
//Workbook workbook = new HSSFWorkbook();
Workbook workbook = new XSSFWorkbook();
// Create CellStyles
DataFormat format = workbook.createDataFormat();
CellStyle integerCellStyle = workbook.createCellStyle();
//integerCellStyle.setDataFormat(format.getFormat("0"));
integerCellStyle.setDataFormat(format.getFormat("#,##0"));
CellStyle decimalCellStyle = workbook.createCellStyle();
decimalCellStyle.setDataFormat(format.getFormat("#,##0.00"));
Sheet sheet = workbook.createSheet();
List<Number> numbers = new ArrayList<Number>();
numbers.add(12); numbers.add(12.1); numbers.add(12.123);
int r = 0;
for (Number number : numbers) {
Row row = sheet.createRow(r++);
Cell cell = row.createCell(0);
cell.setCellValue(number.doubleValue());
if (number.intValue() == number.doubleValue()) {
cell.setCellStyle(integerCellStyle);
} else {
cell.setCellStyle(decimalCellStyle);
}
}
FileOutputStream out = null;
if (workbook instanceof HSSFWorkbook) {
out = new FileOutputStream("./CreateExcelDifferentNumberformats.xls");
} else if (workbook instanceof XSSFWorkbook) {
out = new FileOutputStream("./CreateExcelDifferentNumberformats.xlsx");
}
workbook.write(out);
out.close();
workbook.close();
}
}

Apache POI page break in excel

Hi guys I just want to ask about how to remove the page break in column N in excel using the Apache poi in Java. I've already set up in my code that my print area is until column P. But when I try to print the generated excel it always set that the page break is in column N.
How can I adjust the page break in column using Apache poi on java?
If the goal is that at print all columns (A:P) fit to one page width, then one could solve this using Scale a worksheet.
The following code uses Sheet.setAutobreaks and Sheet.setFitToPage combinated with PrintSetup.setFitWidth and PrintSetup.setFitHeight to set the print setup to scale to fit. The width is set to fit all columns to 1 page width and the height is set automatic, so multiple pages are used when enough rows are present.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class CreateExcelAllColumnsFitToOnePageWidth {
public static void main(String[] args) throws Exception {
//Workbook workbook = new HSSFWorkbook();
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
for (int r = 0; r < 200; r++) {
Row row = sheet.createRow(r);
for (int c = 0; c < 16; c++) {
Cell cell = row.createCell(c);
cell.setCellValue("Lorem ipsum");
if (r==0) sheet.autoSizeColumn(c);
}
}
sheet.setAutobreaks(true);
sheet.setFitToPage(true);
PrintSetup printSetup = sheet.getPrintSetup();
printSetup.setFitHeight((short)0);
printSetup.setFitWidth((short)1);
String fileout = (workbook instanceof HSSFWorkbook)?"Excel.xls":"Excel.xlsx";
FileOutputStream out = new FileOutputStream(fileout);
workbook.write(out);
out.close();
}
}

Excel Apache POI is printing only last element while performing setCellValue()

I am reading some data from excel and writing it to another sheet in the same file in the form of column and I want the column to be printed in the row. When I am performing iteration createRow().setCellValue() is printing only last element.
package com.editDistance;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadColumnsEditDistance {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
File src = new File("C:\\Users\\xyz\\Desktop\\folder\\file.xlsx");
FileInputStream file = new FileInputStream(src);
Workbook workbook = new XSSFWorkbook(file);
Sheet sheet1 = workbook.getSheetAt(0);
int rows = sheet1.getPhysicalNumberOfRows();
workbook.createSheet();
Sheet sheet2 = workbook.getSheetAt(1);
for (int Readingrowindex = 1; Readingrowindex < rows; Readingrowindex++) {
String ah = sheet1.getRow(Readingrowindex).getCell(1).getStringCellValue();
sheet2.createRow(Readingrowindex).createCell(0).setCellValue(ah);
sheet2.createRow(0).createCell(Readingrowindex).setCellValue(ah);
}
FileOutputStream fout = new FileOutputStream(src);
workbook.write(fout);
}
}
Do you want to create sheet with the same cells in first column and first row, like a named table? If yes, you need modify your code, because you always rewrite first row, that's why you get only last item. Do this:
File src = new File("C:\\Users\\xyz\\Desktop\\folder\\file.xlsx");
FileInputStream file = new FileInputStream(src);
Workbook workbook = new XSSFWorkbook(file);
Sheet sheet1 = workbook.getSheetAt(0);
int rows = sheet1.getPhysicalNumberOfRows();
workbook.createSheet();
Sheet sheet2 = workbook.getSheetAt(1);
Row sheet2FirstRow = sheet2.createRow(0);
for (int Readingrowindex = 1; Readingrowindex < rows; Readingrowindex++) {
String ah = sheet1.getRow(Readingrowindex).getCell(1).getStringCellValue();
sheet2.createRow(Readingrowindex).createCell(0).setCellValue(ah);
Cell cell = sheet2FirstRow.createCell(Readingrowindex);
cell.setCellValue((String) ah);
}
FileOutputStream fout = new FileOutputStream(src);
workbook.write(fout);
I think it's because you keep creating row 0 over and over again so it's overwriting what you already created.
You probably want to do something like this:
if(sheet2.getRow() == null){
sheet2.createRow(0).createCell(Readingrowindex).setCellValue(ah);
}else{
sheet2.getRow(0).createCell(Readingrowindex).setCellValue(ah);
}
I faced the similar problem while writing to the code (it was printing the last row only).
Here is the solution for my code:
Failed solution (printing only last cell) i.e. "Hello3"
sheet.createRow(8).createCell(0).setCellValue("Hello1");
sheet.createRow(8).createCell(1).setCellValue("Hello2");
sheet.createRow(8).createCell(2).setCellValue("Hello3");
Working solution (Printing all the data) :
XSSFRow row;
row = sheet.createRow(8);
row.createCell(0).setCellValue("India 123");
row.createCell(1).setCellValue("India 234");
row.createCell(2).setCellValue("India 3453");
row = sheet.createRow(9);
row.createCell(0).setCellValue("Test 123");
row.createCell(1).setCellValue("Test 234");
row.createCell(2).setCellValue("Test 3453");

Apache POI setCellData not actually setting cell data

Using Apache POI 3.16
Eclipse IDE neon 3
Selenium 3.4 (not that it matters in this case)
I'm having an issue with writing values to an excel spreadsheet then reading back the value.
Here's what I want to do at a high level:
Open up an excel file
write to row 1 column 1 (we are using index starting at 0)
Read back what was written in that cell.
The cell contains the value "B2". In a setCellData() function, I write to the cell a "Hello World" and have the function return the contents of the cell. I also have a separate function that reads in the contents of a specified cell.
When I run the following code:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
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 Udemy_Excel_Driven {
public static XSSFWorkbook wb;
public static XSSFSheet sheet;
public static XSSFRow row;
public static XSSFCell cell;
public static FileInputStream fis;
public static void main(String[] args) throws IOException, Exception
{
System.out.println("Before cell edit value is:");
System.out.println(getCellData(1,1));
String value = setCellData(1,1,"Hello World");
System.out.println("What's the value after setting it with setCellData()?");
System.out.println(value);
System.out.println("What's the value using getCellData()?");
System.out.println(getCellData(1,1));
}
public static String getCellData(int rowNum, int colNum) throws IOException
{
/*
* Hierarchy of excel data:
*
* Workbook - take control of this
* Sheet - pick up the sheet of the workbook
* Row - pick the row
* Column - after picking the row, select the column
* Value - grab the value from the cell
*
*/
//0. = identify the path to the excel file in the system.
fis = new FileInputStream("C:\\data.xlsx");
//1. Create a new XSSFWorkbook object. You need to pass in a FileInputStream object into it, which you created earlier.
wb = new XSSFWorkbook(fis);
//2. Get the sheet in the workbook. Create a new XSSFsheet object and set it to the sheet in the workbook
// Access the workbook method "getSheet" and pass in the name of the sheet
sheet = wb.getSheet("script");
//3. Get the row and column. We are going to access the data from row 2 column 2. And remember the indices start at 0.
row = sheet.getRow(rowNum);
cell = row.getCell(colNum);
//get the value specified in the row and cell
return cell.getStringCellValue();
}
public static String setCellData(int rowNum, int colNum, String data) throws IOException
{
fis = new FileInputStream("C:\\data.xlsx");
wb = new XSSFWorkbook(fis);
sheet = wb.getSheet("script");
row = sheet.getRow(rowNum);
cell = row.getCell(colNum);
cell.setCellValue(data);
String cellData = cell.getStringCellValue();
return cellData;
}
I get the following output:
Before cell edit value is:
B2
What's the value after setting it with setCellData()?
Hello World
What's the value using getCellData()?
B2
I don't think the write actually occurred since I opened up the excel file and the "Hello World" string wasn't in the specified cell. Any answers to this issue?
I don't see any part of your code that actually writes to your file.
It should more or less look something like this:
FileOutputStream fileOut = new FileOutputStream("C:\\data.xlsx");
wb.write(fileOut);
fileOut.close();
You can also consult this guide for this issue as well as other functionality that you might be interested in implementing.

Printing entire Excel Workbook in java without opening the excel document

How do I print an excel Workbook without having it open in the background, using Java?
Please note that I need to print all the sheets, not just the active one.
I have tried things like Desktop.print(FileName); but that doesn't seem to work for all the sheets.
I am using the Apache POI API to create Excel files through Java.
Many thanks!
UPDATE
To explain my problem a little more, I am using Apace POI to print the Excel file as -
HSSFSheet sheet = workbook.getSheet("Sheet5");
HSSFRow row21 = sheet.getRow((short)5);
row21.getCell((short)2).setCellValue(notcorrect);
desktop.print(new File(filename));
HSSFSheet sheet7 = workbook.getSheet("Sheet7");
HSSFRow row20 = sheet7.getRow((short)3);
row20.getCell((short)2).setCellValue(logreference);
row20.getCell((short)4).setCellValue(ISSUENUMBER);
desktop.print(new File(filename));
HSSFSheet sheet8 = workbook.getSheet("Sheet8");
HSSFRow row22 = sheet8.getRow((short)3);
row22.getCell((short)2).setCellValue(logreference);
row22.getCell((short)4).setCellValue(ISSUENUMBER);
desktop.print(new File(filename));
But this seems to work only for the active workbook. If I have a workbook in my Excel file as the following -
The code above will only print the active sheet i.e. sheet # 5. How do I use Jexcel to print Sheet 5, 6 AND 7?
Many thanks!
Before writing code we have to download apache-poi jars
https://poi.apache.org/download.html
Download - poi-bin-5.0.0-20210120.tar.gz (current version)
package test1;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class P1 {
public static void main(String[] args) throws IOException {
//Path to excel from system = /Users/user/Downloads/test1.xlsx"
File f = new File("/Users/user/Downloads/test1.xlsx");
FileInputStream fis = new FileInputStream(f);
XSSFWorkbook wb = new XSSFWorkbook(fis);
//June2021 is my sheet name of excel
XSSFSheet sheet = wb.getSheet("June2021");
int RowCount = sheet.getLastRowNum() - sheet.getFirstRowNum();
for(int i=0; i<= RowCount; i++) {
System.out.print("Row "+ i + " data is : ");
int cellCount = sheet.getRow(i).getLastCellNum();
for(int j=0; j<cellCount; j++) {
XSSFCell c1 = sheet.getRow(i).getCell(j);
System.out.print(c1 + " ");
}
System.out.println();
}
}
}

Categories