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
}
}
}
Related
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")));
I have an excel format like this:
And I have 2 functions to fill data.
This one is to fill the details
public XSSFWorkbook getDetail(List<ResultDTO> ResultDTOList, XSSFWorkbook workBook,
String sheetName) throws DaoException {
XSSFSheet sheet = workBook.getSheet(sheetName);
// first row at 9
rowIdx = 9;
int count = 0;
for (ResultDTO dto : ResultDTOList) {
colIdx = 0;
count++;
// get row
row = sheet.getRow(rowIdx);
if (row == null) {
row = sheet.createRow(rowIdx);
}
row.setHeightInPoints(16.5F);
// No
callCreateCell(row, colIdx++).setCellValue(count);
// ItemNo
callCreateCell(row, colIdx++).setCellValue(castRichTextString(dto.getItemNo()));
// ArtistName
callCreateCell(row, colIdx++).setCellValue(castRichTextString(dto.getArtistName()));
colIdx++;
// ItemTitle
callCreateCell(row, colIdx++).setCellValue(castRichTextString(dto.getItemTitle()));
colIdx++;
// Size
callCreateCell(row, colIdx++).setCellValue(dto.getSize());
colIdx++;
// Classification
callCreateCell(row, colIdx++).setCellValue(dto.getClassification());
colIdx++;
// Detail
callCreateCell(row, colIdx++).setCellValue(StringUtil.cutNewLineCharacter(dto.getPayDetail()));
// Technique
callCreateCell(row, colIdx++).setCellValue(dto.getTechnique());
// Uriage
callCreateCell(row, colIdx++).setCellValue(dto.getUriageWithoutTaxPrice());
row = null;
rowIdx++;
rowIdx++;
}
return workBook;
}
and this one to fill the sum
public HSSFWorkbook getSum(UriageForm uriageForm, HSSFWorkbook workBook, String sheetName) {
HSSFSheet sheet = workBook.getSheet(sheetName);
CellStyle style1 = workBook.createCellStyle();
style1.setAlignment(CellStyle.ALIGN_RIGHT);
//set font size 14
Font font1 = workBook.createFont();
font1.setFontHeightInPoints((short)14);
style1.setFont(font1);
style1.setBorderLeft(CellStyle.BORDER_THIN);
style1.setBorderBottom(CellStyle.BORDER_MEDIUM);
Row row = sheet.getRow(20);
//SUM1
Cell cell2 = row.getCell(8);
cell2.setCellValue(uriageForm.getPrintNestedSize());
cell2.setCellStyle(style1);
//SUM2
Cell cell3 = row.getCell(9);
cell3.setCellValue(uriageForm.getPrintTxtShouhi());
cell3.setCellStyle(style1);
//SUM3
Cell cell4 = row.getCell(10);
cell4.setCellValue(uriageForm.getPrintTxtSum());
cell4.setCellStyle(style1);
//SUM4
Cell cell5 = row.getCell(12);
cell5.setCellValue(uriageForm.getPrintTxtSumAll());
cell5.setCellStyle(style1);
return workBook;
}
The problem is that if i have got more than 5 records data will be filled override into 20th row and my format is broken. My expected result is that if there's more than 5 records so it will add 2 rows (as format) for each added one and my SUM is always be the last 2 rows of sheet.
I'm thinking of remove the SUM gender into another sheet and copy it into the last until the details are done. But I get some questions:
Which function to help me copy rows from one sheet to another?
I have format just for 5 records so how can I insert 2 rows for each added record from 6th that keeps format like the old? (eg: copy format of row 10&11 to every added record)
I'm sorry if it's a little confusing. This is my very first time with Java and POI so I'm really looking forward to some helps from you! Thank you!
Add the copyRow function
private void copyRow(XSSFWorkbook workbook, XSSFSheet worksheet, int sourceRowNum, int destinationRowNum) {
XSSFRow newRow = worksheet.getRow(destinationRowNum);
XSSFRow sourceRow = worksheet.getRow(sourceRowNum);
if (newRow != null) {
worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
newRow = worksheet.createRow(destinationRowNum);
} else {
newRow = worksheet.createRow(destinationRowNum);
}
// copy process
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
Cell oldCell = sourceRow.getCell(i);
Cell newCell = newRow.createCell(i);
// if source cell is blank -> stop
if (oldCell == null) {
newCell = null;
continue;
}
//copy style
CellStyle newCellStyle = workbook.createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
newCell.setCellStyle(newCellStyle);
//copy cell type
newCell.setCellType(oldCell.getCellType());
//copy cell value
switch (oldCell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
case Cell.CELL_TYPE_NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
}
}
//copy column merge
for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
(newRow.getRowNum() + (cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow())),
cellRangeAddress.getFirstColumn(), cellRangeAddress.getLastColumn());
worksheet.addMergedRegion(newCellRangeAddress);
}
}
}
In the getDetail function, add this below code:
int listSize = resultUriageWorkDTOList.size();
//add 2 rows for each record from 5th record
for (int i = 1; i <= (listSize - 5); i++) {
this.copyRow(workBook, sheet, 10, 12);
this.copyRow(workBook, sheet, 11, 13);
sheet.addMergedRegion(new CellRangeAddress(11,12,4,5));
}
Source: https://www.sukerou.com/2019/03/poi-apache-poi-tips.html
So im trying to first copy the pivot table as values,
the values are already inserted, but then when i want to insert a specific row, above the pivot table values, sheet.createrow(0) replaces the previous row i don't know why. here is my code
for (int iSheet = 0; iSheet < sheets; iSheet++) {
sheet = workbook.getSheetAt(iSheet);
if (sheet != null) {
mySheet = myWorkBook.createSheet(sheet.getSheetName());
mySheet.createRow(0); //creating the first row
fRow = sheet.getFirstRowNum();
lRow = sheet.getLastRowNum();
for (int iRow = fRow; iRow <= lRow; iRow++) {
row = sheet.getRow(iRow);
myRow = mySheet.createRow(iRow);
if (row != null) {
fCell = row.getFirstCellNum();
lCell = row.getLastCellNum();
for (int iCell = fCell; iCell < lCell; iCell++) {
cell = row.getCell(iCell);
myCell = myRow.createCell(iCell);
if (cell != null) {
myCell.setCellType(cell.getCellType());
switch (cell.getCellType()) {
case BLANK:
myCell.setCellValue("");
break;
case BOOLEAN:
myCell.setCellValue(cell.getBooleanCellValue());
break;
case ERROR:
myCell.setCellErrorValue(cell.getErrorCellValue());
break;
case FORMULA:
myCell.setCellFormula(cell.getCellFormula());
break;
case NUMERIC:
myCell.setCellValue(cell.getNumericCellValue());
break;
case STRING:
myCell.setCellValue(cell.getStringCellValue());
break;
default:
myCell.setCellFormula(cell.getCellFormula());
}
}
}
}
}
}
}
I try to sort sheet with use of Apache POI by a given column. As I know there isn't any built-in solution for this purpose. First row of sheet contains merged cells and grouped columns. I try to sort cells by second column.
public static void sortSheet(XSSFWorkbook workbook, Sheet sheet) {
//copy all rows to temp
List<Row> rows = Lists.newArrayList(sheet.rowIterator());
//sort rows in the temp
rows.sort(Comparator.comparing(cells -> cells.getCell(2).getStringCellValue()));
//remove all rows from sheet
removeAllRows(sheet);
//create new rows with values of sorted rows from temp
for (int i = 0; i < rows.size(); i++) {
Row newRow = sheet.createRow(i);
Row sourceRow = rows.get(i);
// Loop through source columns to add to new row
for (int j = 0; j < sourceRow.getLastCellNum(); j++) {
// Grab a copy of the old/new cell
Cell oldCell = sourceRow.getCell(j);
Cell newCell = newRow.createCell(j);
// If the old cell is null jump to next cell
if (oldCell == null) {
newCell = null;
continue;
}
// Copy style from old cell and apply to new cell
CellStyle newCellStyle = workbook.createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
newCell.setCellStyle(newCellStyle);
// If there is a cell comment, copy
if (oldCell.getCellComment() != null) {
newCell.setCellComment(oldCell.getCellComment());
}
// If there is a cell hyperlink, copy
if (oldCell.getHyperlink() != null) {
newCell.setHyperlink(oldCell.getHyperlink());
}
// Set the cell data type
newCell.setCellType(oldCell.getCellType());
// Set the cell data value
switch (oldCell.getCellType()) {
case BLANK:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
case NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
}
}
// If there are are any merged regions in the source row, copy to new row
for (int j = 0; j < sheet.getNumMergedRegions(); j++) {
CellRangeAddress cellRangeAddress = sheet.getMergedRegion(j);
if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
(newRow.getRowNum() +
(cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow()
)),
cellRangeAddress.getFirstColumn(),
cellRangeAddress.getLastColumn());
sheet.addMergedRegion(newCellRangeAddress);
}
}
}
}
private static void removeAllRows(Sheet sheet) {
for (int i = 0; i < sheet.getLastRowNum(); i++) {
sheet.removeRow(sheet.getRow(i));
}
}
Original source: Apache-POI sorting rows in excel
I got following error message during execution:
org.apache.xmlbeans.impl.values.XmlValueDisconnectedException
at org.apache.xmlbeans.impl.values.XmlObjectBase.check_orphaned(XmlObjectBase.java:1258)
at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTRowImpl.getR(Unknown Source)
at org.apache.poi.xssf.usermodel.XSSFRow.getRowNum(XSSFRow.java:378)
at WriteToExistingFile.sortSheet(WriteToExistingFile.java:234)
at WriteToExistingFile.write(WriteToExistingFile.java:145)
Exception is thrown at this line:
if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
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...