Merge and edit Excel files with java - java

I'm currently trying to merge two Excel files with each other. But there is a catch, I need to add between files the name of the file each file and an empty row. When I tried that, it added the name of the file and empty row but overwrote the first two rows of each file. How can I do it without losing first two rows of the file ?
public static void main(String[] args) {
try {
File firstFile = new File("/Users/TLQ/Desktop/report-12689-M2398-1.xlsx");
File secondFile = new File("/Users/TLQ/Desktop/report-12695-M2390-1.xlsx");
FileInputStream excellFile1 = new FileInputStream(firstFile);
FileInputStream excellFile2 = new FileInputStream(secondFile);
org.apache.poi.ss.usermodel.Workbook workbook1 = WorkbookFactory.create(excellFile1);
org.apache.poi.ss.usermodel.Workbook workbook2 = WorkbookFactory.create(excellFile2);
org.apache.poi.ss.usermodel.Sheet sheet1a = workbook1.getSheetAt(0);
org.apache.poi.ss.usermodel.Sheet sheet2a = workbook2.getSheetAt(0);
addSheet(sheet1a, sheet2a,secondFile.getAbsolutePath().substring(secondFile.getAbsolutePath().lastIndexOf("/")+1, secondFile.getAbsolutePath().indexOf(".")));
excellFile1.close();
// save merged file
File mergedFile = new File(
"/Users/TLQ/Desktop/Albert_1.xlsx");
if (!mergedFile.exists()) {
mergedFile.createNewFile();
}
FileOutputStream out = new FileOutputStream(mergedFile);
workbook1.write(out);
out.close();
System.out.println(firstFile.getAbsolutePath().substring(firstFile.getAbsolutePath().lastIndexOf("/")+1, firstFile.getAbsolutePath().indexOf(".")));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addSheet(org.apache.poi.ss.usermodel.Sheet mergedSheet, org.apache.poi.ss.usermodel.Sheet sheet,String name) {
// map for cell styles
Map<Integer, org.apache.poi.ss.usermodel.CellStyle> styleMap = new HashMap<Integer, org.apache.poi.ss.usermodel.CellStyle>();
org.apache.poi.ss.usermodel.Row row2 = mergedSheet.createRow((short) 0);
org.apache.poi.ss.usermodel.Cell mcell2 = row2.createCell((short) 0);
mcell2.setCellValue("report-12689-M2398-1.xlsx");
// This parameter is for appending sheet rows to mergedSheet in the end
org.apache.poi.ss.usermodel.Row row1 = sheet.createRow((short) 0);
org.apache.poi.ss.usermodel.Cell mcell = row1.createCell((short) 0);
mcell.setCellValue(name);
org.apache.poi.ss.usermodel.Row row1Empty = sheet.createRow((short) 0);
org.apache.poi.ss.usermodel.Cell mcellEmpty = row1.createCell((short) 0);
int len = mergedSheet.getLastRowNum();
for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {
org.apache.poi.ss.usermodel.Row row = sheet.getRow(j);
org.apache.poi.ss.usermodel.Row mrow = mergedSheet.createRow(len + j + 1);
try {
for (int k = row.getFirstCellNum(); k < row.getLastCellNum(); k++) {
org.apache.poi.ss.usermodel.Cell cell=null;
if(row.getCell(k)!=null){
cell = row.getCell(k);
}else{
cell= row.createCell(k);
}
mcell = mrow.createCell(k);
if (cell.getSheet().getWorkbook() == mcell.getSheet()
.getWorkbook()) {
mcell.setCellStyle(cell.getCellStyle());
} else {
int stHashCode = cell.getCellStyle().hashCode();
org.apache.poi.ss.usermodel.CellStyle newCellStyle = styleMap.get(stHashCode);
if (newCellStyle == null) {
newCellStyle = mcell.getSheet().getWorkbook()
.createCellStyle();
newCellStyle.cloneStyleFrom(cell.getCellStyle());
styleMap.put(stHashCode, newCellStyle);
}
mcell.setCellStyle(newCellStyle);
}
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_FORMULA:
mcell.setCellFormula(cell.getCellFormula());
break;
case HSSFCell.CELL_TYPE_NUMERIC:
mcell.setCellValue(cell.getNumericCellValue());
break;
case HSSFCell.CELL_TYPE_STRING:
mcell.setCellValue(cell.getStringCellValue());
break;
case HSSFCell.CELL_TYPE_BLANK:
mcell.setCellType(HSSFCell.CELL_TYPE_BLANK);
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
mcell.setCellValue(cell.getBooleanCellValue());
break;
case HSSFCell.CELL_TYPE_ERROR:
mcell.setCellErrorValue(cell.getErrorCellValue());
break;
default:
mcell.setCellValue(cell.getStringCellValue());
break;
}
}
} catch (Exception e) {
}
}
}

no sure which one the good but try
workbook1.write(out,true);
or workbook1.write(out,false);
it should set the fact to delete what was before or not.(true should be not erase what you got)
hope it help ;)

Related

How to copy a sheet from an Excel File Cell pop-up docuentation to another using POI Apache?

I am trying to copy a sheet from two different XSSF Workbooks. I have written a code that works really well (see below) but it doesn't take into account the pop-up documentation for cells and doesn't copy it (which is logical because I haven't written that functionnality).
I have searched the Apache POI documentation and it looks like there is no way to do this. Any idea on how I could do to copy-paste that information?
public class CopySheets {
public static void copySheet(String sheetName, XSSFWorkbook wbSrc,XSSFWorkbook wbDest) throws IOException {
XSSFSheet srcSheet = null;
XSSFRow srcRow = null;
XSSFCell srcCell = null;
XSSFSheet destSheet = null;
XSSFRow destRow = null;
XSSFCell destCell = null;
int fCell = 0;
int lCell = 0;
int fRow = 0;
int lRow = 0;
System.out.println(sheetName);
srcSheet = wbSrc.getSheet(sheetName);
System.out.println(srcSheet);
if (srcSheet != null) {
destSheet = wbDest.createSheet(sheetName);
fRow = srcSheet.getFirstRowNum();
lRow = srcSheet.getLastRowNum();
for (int iRow = fRow; iRow <= lRow; iRow++) {
srcRow = srcSheet.getRow(iRow);
destRow = destSheet.createRow(iRow);
if (srcRow != null) {
fCell = srcRow.getFirstCellNum();
lCell = srcRow.getLastCellNum();
for (int iCell = fCell; iCell < lCell; iCell++) {
srcCell = srcRow.getCell(iCell);
destCell = destRow.createCell(iCell);
if (srcCell != null) {
switch (srcCell.getCellTypeEnum()) {
case BLANK:
destCell.setCellValue("");
break;
case BOOLEAN:
destCell.setCellValue(srcCell.getBooleanCellValue());
break;
case ERROR:
destCell.setCellErrorValue(srcCell.getErrorCellValue());
break;
case FORMULA:
destCell.setCellFormula(srcCell.getCellFormula());
break;
case NUMERIC:
destCell.setCellValue(srcCell.getNumericCellValue());
break;
case STRING:
destCell.setCellValue(srcCell.getStringCellValue());
break;
default:
destCell.setCellFormula(srcCell.getCellFormula());
}
CellStyle origStyle = srcCell.getCellStyle(); // Or from a cell
CellStyle newStyle = wbDest.createCellStyle();
newStyle.cloneStyleFrom(origStyle);
destCell.setCellStyle(newStyle);
Comment origComment=srcCell.getCellComment();
destCell.setCellComment(origComment);
}
}
}
}
}
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("workbook.xls", true));
wbDest.write(bos);
bos.close();
}
}
Thanks a lot!
Okay, I found the answer, it turns out POI has something that enables us to get that info on the sheet as a whole so I added this bit to my code and it works like a charm!
List<XSSFDataValidation> validations=srcSheet.getDataValidations();
for (XSSFDataValidation validation:validations){
destSheet.addValidationData(validation);
}
Looking at the documentation-
http://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/Comment.html
Seems like the getAddress() method of the src Comment object will return the reference to the cell it was previously attached to (which is the src cell).
You should try creating a new Comment instead of doing
Comment origComment=srcCell.getCellComment();
destCell.setCellComment(origComment);
You should use RangeCopier.
XSSFWorkbook workbookFrom = new XSSFWorkbook(new File("/path/to/workbookFrom.xlsx"));
XSSFSheet sheetFrom = workbookFrom.getSheetAt(0);
XSSFWorkbook workbookTo = new XSSFWorkbook(new File("/path/to/workbookTo.xlsx"));
XSSFSheet sheetTo = workbookTo.createSheet("sheet1");
workbookTo.setSheetOrder("sheet1", 0);
XSSFRangeCopier xssfRangeCopier = new XSSFRangeCopier(sheetFrom, sheetTo);
//copy the row height and column width, and find the max column num
int lastRow = sheetFrom.getLastRowNum();
int lastCol = 0;
for (int i = 0; i < lastRow; i++) {
Row row = sheetFrom.getRow(i);
if (row != null) {
if (row.getLastCellNum() > lastCol) {
lastCol = row.getLastCellNum();
}
sheetTo.setDefaultRowHeight(sheetFrom.getDefaultRowHeight());
}
}
for (int j = 0; j < lastCol; j++) {
sheetTo.setColumnWidth(j, sheetFrom.getColumnWidth(j));
}
//copy contents from source sheet to destination sheet
CellRangeAddress cellAddresses = new CellRangeAddress(0, lastRow, 0, lastCol);
xssfRangeCopier.copyRange(cellAddresses, cellAddresses, true, true);
workbookTo.write(new FileOutputStream(new File("/path/to/worksheetTo.xlsx")));

Read Excel file and write in other excel at specific sheet using POI

I am reading an Excel file and writing the content into an already existing file based on sheet name. The Excel file has 3 header columns.
XSSFSheet conSheet = workbook.getSheet("EMPLOYYEE");
XSSFRow headerRow = conSheet.getRow(0);
XSSFRow dataRow = conSheet.createRow(conSheet.getLastRowNum() + 1);
int physicalNumberOfCells = headerRow.getPhysicalNumberOfCells();
for (int i = 0; i < physicalNumberOfCells; i++) {
XSSFCell headerCell = headerRow.getCell(i);
if (headerCell != null) {
String stringCellValue = headerCell.getStringCellValue();
ConvertsColumn charcol = ConvertsColumn.getEnum(stringCellValue);
XSSFCell dataCell = dataRow.createCell(i);
if (charcol != null) {
try {
FileInputStream file = new FileInputStream("file..anme");
Workbook wb1 = new XSSFWorkbook(file);
Sheet sheet1 = wb1.getSheetAt(0);
Iterator < Row > iterator = sheet1.iterator();
while (iterator.hasNext()) {
Row nextRow = iterator.next();
Iterator < Cell > cellIterator = nextRow.cellIterator();
while (cellIterator.hasNext()) {
Cell nextCell = cellIterator.next();
int columnIndex = nextCell.getColumnIndex();
System.out.println(columnIndex + "" + nextCell);
switch (columnIndex) {
case 0:
dataCell.setCellValue(nextCell.getStringCellValue());
break;
case 1:
dataCell.setCellValue(nextCell.getStringCellValue());
break;
case 2:
dataCell.setCellValue(nextCell.getStringCellValue());
break;
default:
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
We are Using POI. When data is writing to the Excel file it is over-writen with the first column and only one column data is adding with one value...

Apache POI - Excel Import, insert data from a new sheet into a column

I'm here to ask for help in my java project in Netbeans.
I'm using Apache POI to import/export excel data. To make you understand what is the problem in my application, I'm showing you a print of the debug.
In the print, you can see 2 sheets. The first header "aiai" and the data from that sheet.
My problem is: How do i insert the data from "aiai2" which is the second sheet from my excel file, in its proper place, below the header "aiai2"
On other words, I want to separate the sheets vertically.
Below, I will show my code:
Workbook wb;
public String Importar(File archivo, JTable tablaD) {
String answer = "Unable to import";
DefaultTableModel modeloT = new DefaultTableModel();
tablaD.setModel(modeloT);
tablaD.getModel();
tablaD.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
try {
wb = WorkbookFactory.create(new FileInputStream(archivo));
int nsheets = wb.getNumberOfSheets();
for (int i = 0; i < nsheets; i++) {
Sheet sheet = wb.getSheetAt(i);
Iterator filaIterator = sheet.rowIterator();
int rownum = -1;
while (filaIterator.hasNext()) {
rownum++;
Row fila = (Row) filaIterator.next();
/*if (i > 0) {//se o nr da ficha atual for maior que 0, começa a escrever as linhas apartir da row 0 da tabela
modeloT.moveRow(modeloT.getRowCount() -1, modeloT.getRowCount() - 1, 0);
}*/
Iterator columnaIterator = fila.cellIterator();
Object[] listaColumna = new Object[1000];
int columnnum = -1;
while (columnaIterator.hasNext()) {
columnnum++;
Cell celda = (Cell) columnaIterator.next();
if (rownum == 0) {
modeloT.addColumn(celda.getStringCellValue());
} else {
if (celda != null) {
switch (celda.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
listaColumna[columnnum] = (int) Math.round(celda.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
listaColumna[columnnum] = celda.getStringCellValue();
break;
case Cell.CELL_TYPE_BOOLEAN:
listaColumna[columnnum] = celda.getBooleanCellValue();
break;
default:
listaColumna[columnnum] = celda.getDateCellValue();
break;
}//end switch case
System.out.println("Column:" + columnnum + " Row:" + rownum + " value:" + celda + ".");
}
}
}//end while column Iterator
if (rownum != 0) {
modeloT.addRow(listaColumna);
}
}//end while row iterator
}//end for
answer = "Imported with success";
} catch (IOException | InvalidFormatException | EncryptedDocumentException e) {
System.err.println(e.getMessage());
}
return answer;
}
public String Exportar(File archivo, JTable tablaD) {
String answer = "Unable to export";
int numFila = tablaD.getRowCount(), numColumna = tablaD.getColumnCount();
if (archivo.getName().endsWith("xls")) {
wb = new HSSFWorkbook();
} else {
wb = new XSSFWorkbook();
}
Sheet hoja = wb.createSheet("Default");
try {
for (int i = -1; i < numFila; i++) {
Row fila = hoja.createRow(i + 1);
for (int j = 0; j < numColumna; j++) {
Cell celda = fila.createCell(j);
if (i == -1) {
celda.setCellValue(String.valueOf(tablaD.getColumnName(j)));
} else {
celda.setCellValue(String.valueOf(tablaD.getValueAt(i, j)));
}
wb.write(new FileOutputStream(archivo));
}
}
answer = "Exported with success";
} catch (Exception e) {
System.err.println(e.getMessage());
}
return answer;
}
As I understand your question, I assume you want to create a separate table for each sheet, one below other. In that case you need to create a new table everytime you read a new sheet. If you use only one table, you will get only one header.
Try this :
Create a new method Importar that takes a new table and a Sheet parameter
public String Importar(JTable tablaD, Sheet sheet) {
String answer = "Unable to import";
DefaultTableModel modeloT = new DefaultTableModel();
tablaD.setModel(modeloT);
tablaD.getModel();
tablaD.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
try {
Iterator filaIterator = sheet.rowIterator();
int rownum = -1;
....
....
So the calling method would be :
try {
Workbook wb = WorkbookFactory.create(new FileInputStream(archivo));
int nsheets = wb.getNumberOfSheets();
for (int i = 0; i < nsheets; i++) {
//You have to make sure your JTable gets rendered.
JTable tablaD = new JTable();
Importar( tablaD, wb.getSheetAt(i) );
}
} catch ( Exception e ) {
e.printStackTrace();
}
Important point is that your new table needs to get rendered or added to frame each time before you call Importar

Reading Excel file using poi and shift it to two-dimensional array

I am using POI to read excel file and convert it to a two-dimensional array. Following is code section:
import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.CellValue;
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 XlsxRead_2 {
public XlsxRead_2(){
getvalue_1();
}
public static void getvalue_1(){
XSSFRow row;
XSSFCell cell;
String [][] value =null;
double[][] nums =null;
try {
FileInputStream inputStream = new FileInputStream("TEST.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
//get sheet number
int sheetCn = workbook.getNumberOfSheets();
for(int cn = 0; cn < sheetCn; cn++){
//get 0th sheet data
XSSFSheet sheet = workbook.getSheetAt(cn);
//get number of rows from sheet
int rows = sheet.getPhysicalNumberOfRows();
//get number of cell from row
int cells = sheet.getRow(cn).getPhysicalNumberOfCells();
for (int r = 0; r < rows; r++) {
row = sheet.getRow(r); // bring row
if (row != null) {
for (int c = 0; c < cells; c++) {
cell = row.getCell(c);
value = new String[rows][cells];
nums= new double [rows][cells];
if (cell != null) {
switch (cell.getCellType()) {
case XSSFCell.CELL_TYPE_FORMULA:
value [r][c]= cell.getCellFormula();
break;
case XSSFCell.CELL_TYPE_NUMERIC:
value [r][c]= "" + cell.getNumericCellValue();
break;
case XSSFCell.CELL_TYPE_STRING:
value [r][c]= "" + cell.getStringCellValue();
break;
case XSSFCell.CELL_TYPE_BLANK:
value [r][c]= "[BLANK]";
break;
case XSSFCell.CELL_TYPE_ERROR:
value [r][c]= "" + cell.getErrorCellValue();
break;
default:
}
System.out.print(value);
} else {
System.out.print("[null]\t");
}
} // for(c)
System.out.print("\n");
}
} // for(r)
}
} catch (Exception e) {
e.printStackTrace();
}
}
public class Starter {
public static void main(String[] args) {
XlsxRead_2 gv=new XlsxRead_2();
}
}
However, it didn't work properly. Attached is wrong result in JAVA. When i worked it without using array, it work properly. Any suggestions is appreciated.
Result in java:
[[Ljava.lang.String;#167fdd33[[Ljava.lang.String;#1e965684
[[Ljava.lang.String;#4d95d2a2[[Ljava.lang.String;#53f65459
[[Ljava.lang.String;#3b088d51[[Ljava.lang.String;#1786dec2
[[Ljava.lang.String;#74650e52[[Ljava.lang.String;#15d0c81b
[[Ljava.lang.String;#6acdbdf5[[Ljava.lang.String;#4b1c1ea0
[[Ljava.lang.String;#3712b94[[Ljava.lang.String;#2833cc44
[[Ljava.lang.String;#33f88ab[[Ljava.lang.String;#27a8c74e
You should create array after first for loop. And also you should create values array for each sheet. And one more point you should print value[r][c] not value
I hope that helps you.
public class XlsxRead_2 {
public static void main(String[] args) {
XlsxRead_2 xread2 = new XlsxRead_2();
}
public XlsxRead_2() {
getvalue_1();
}
public static void getvalue_1() {
XSSFRow row;
XSSFCell cell;
String[][] value = null;
double[][] nums = null;
try {
FileInputStream inputStream = new FileInputStream("TEST.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
// get sheet number
int sheetCn = workbook.getNumberOfSheets();
for (int cn = 0; cn < sheetCn; cn++) {
// get 0th sheet data
XSSFSheet sheet = workbook.getSheetAt(cn);
// get number of rows from sheet
int rows = sheet.getPhysicalNumberOfRows();
// get number of cell from row
int cells = sheet.getRow(cn).getPhysicalNumberOfCells();
value = new String[rows][cells];
for (int r = 0; r < rows; r++) {
row = sheet.getRow(r); // bring row
if (row != null) {
for (int c = 0; c < cells; c++) {
cell = row.getCell(c);
nums = new double[rows][cells];
if (cell != null) {
switch (cell.getCellType()) {
case XSSFCell.CELL_TYPE_FORMULA:
value[r][c] = cell.getCellFormula();
break;
case XSSFCell.CELL_TYPE_NUMERIC:
value[r][c] = ""
+ cell.getNumericCellValue();
break;
case XSSFCell.CELL_TYPE_STRING:
value[r][c] = ""
+ cell.getStringCellValue();
break;
case XSSFCell.CELL_TYPE_BLANK:
value[r][c] = "[BLANK]";
break;
case XSSFCell.CELL_TYPE_ERROR:
value[r][c] = ""+cell.getErrorCellValue();
break;
default:
}
System.out.print(value[r][c]);
} else {
System.out.print("[null]\t");
}
} // for(c)
System.out.print("\n");
}
} // for(r)
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Reading blank xls cells through POI

I'm trying to read the empty cells of an xls file and port them to my object xls as null entries. But I'm not identifying these cells as blank. Can someone can tell me what I'm doing wrong?
private boolean lerArquivo(String dir) throws IOException {
HSSFWorkbook wb = null;
HSSFRow row = null;
HSSFCell cell = null;
String path = dir;
boolean flag = false;
InputStream inp = new FileInputStream(path);
wb = new HSSFWorkbook(inp);
HSSFSheet sheet = wb.getSheetAt(0);
for (Iterator rit = (Iterator) sheet.rowIterator(); rit.hasNext();) {
row = (HSSFRow) rit.next();
for (Iterator cit = (Iterator) row.cellIterator(); cit.hasNext();) {
cell = (HSSFCell) cit.next();
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
xls.add(cell.getRichStringCellValue().getString());
break;
case HSSFCell.CELL_TYPE_BLANK:
xls.add(null);
break;
case HSSFCell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
xls.add(cell.getDateCellValue().toString());
} else {
xls.add(String.valueOf(cell.getNumericCellValue()));
}
break;
default:
}
}
}
EDIT 01 -
Hello Gagravarr, thanks for your help.
I Tried your suggest, and read the documentation.
following what i understood, i changed my code, reaching this:
even this way, the code isn't reading the blank cell. any guess ?
for (int rowNum = 0; rowNum < 4; rowNum++) {
row = sheet.getRow(rowNum);
for (int celNum = 0; celNum < row.getLastCellNum(); celNum++) {
cell = row.getCell(celNum, org.apache.poi.ss.usermodel.Row.RETURN_BLANK_AS_NULL);
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
xls.add(cell.getRichStringCellValue().getString());
break;
case HSSFCell.CELL_TYPE_BLANK: {
xls.add("");
break;
}
case HSSFCell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
xls.add(cell.getDateCellValue().toString());
} else {
xls.add(String.valueOf(cell.getNumericCellValue()));
}
break;
default:
}
}
}
Apache POI has pretty detailed and explicit documentation on iterating over rows and cells, you'd be very well advised to read it!
Copying and pasting the example from there, you can see how to handle / detect missing rows and cells, along with blank cells:
// 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
} else {
// Do something useful with the cell's contents
}
}
}

Categories