Excel creation with POI - java

I was using Apache POI 3.7 to create Excel with HSSF. It was working fine. But during load test, I realized that it is very slow. So I Googled and found I can use SXSSF. I changed my existing code to XSSF. The result was awesome.
But I stuck with a situation, autorezisecolum() is not functioning as expected. It displays large contents as #####, because the column width shrinks. I found it is a kind of a bug already raised.
Now my point is, is there any solution so that i can use SXSSF(very important for performance) with a nice output.
Note: I am using Windows 7, JDK 1.7.09 , POI-3.10.beta-2
Please help me.
Here is my code :
Main Function :
sxssfWorkbook = new SXSSFWorkbook(5);
sxssfSheet = (SXSSFSheet) sxssfWorkbook.createSheet(sheetName);
try {
// TO Write Header
//ew.writeHeaderRow(sheet, headerNames);
ew.writeHeaderRow(sxssfSheet, headerNames);
int rowNum = headerRow + 1;
for(Map.Entry<String, List<Object>> columnData : columnDataMap.entrySet()){
ew.writeNonHeaderRow(sxssfSheet, columnData.getValue(), rowNum);
rowNum++;
}
resizeXLSXColumns(sxssfSheet,rowNum-1);
sxssfWorkbook.write(outputStream);
outputStream.close();
public void writeHeaderRow(Sheet sheet, List<String> headerNames ) {
//public void writeHeaderRow(SXSSFSheet sxssfSheet, List<String> headerNames ) {
// LinkedHashMap<String,Object> mp = getFieldNames(obj);
// ArrayList<String> colNames = (ArrayList<String>) getColumnNames();
try {
XSSFCellStyle hCellStyle = getHeaderStyle();
SXSSFRow row = (SXSSFRow) sheet.createRow(headerRow);
for (int hCellInd = 0; hCellInd < headerNames.size(); hCellInd++) {
SXSSFCell cell = (SXSSFCell) row.createCell(hCellInd);
cell.setCellStyle(hCellStyle);
cell.setCellValue(headerNames.get(hCellInd));
//sheet.autoSizeColumn(hCellInd);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void writeNonHeaderRow(SXSSFSheet sxssfSheet, List<Object> rowObj, int rowIndex)
{
CreationHelper createHelper = sxssfWorkbook.getCreationHelper();
try {
SXSSFRow row = (SXSSFRow)sheet.createRow(rowIndex);
XSSFCellStyle normalStyle = getNormalStyle();
int count = 0;
for (int rCellInd = 0; rCellInd < rowObj.size(); rCellInd++) {
//Cell cell = row.createCell(rCellInd);
SXSSFCell cell = (SXSSFCell)row.createCell(rCellInd);
cell.setCellStyle(normalStyle);
Object cellData = rowObj.get(rCellInd);
if (cellData != null) {
if (cellData instanceof Double) {
cell.setCellValue((Double) cellData);
if((Double)cellData < 0){
cell.setCellStyle(getNegativeValueStyle());
}else if((Double)cellData == 0){
normalStyle.setDataFormat((short) SXSSFCell.CELL_TYPE_BLANK) ;
cell.setCellStyle(normalStyle);
}else
cell.setCellStyle(normalStyle);
} else {
//normalStyle.setDataFormat((short) HSSFCell.CELL_TYPE_BLANK);
cell.setCellType(SXSSFCell.CELL_TYPE_BLANK);
}
//sxssfSheet.autoSizeColumn();
//sxssfSheet.setColumnWidth(rCellInd, sxssfSheet.getColumnWidth(rCellInd));
//resizeXLSXColumns(sheet);
}
//autoResizeColumns(sxssfSheet);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void resizeXLSXColumns(Sheet sheet ,int rowNum){
SXSSFRow row = (SXSSFRow)sheet.getRow(rowNum);
Iterator<Cell> itr = row.cellIterator();
int max = 0;
while(itr.hasNext()){
Cell cell = itr.next();
int width = sheet.getColumnWidth(cell.getColumnIndex());
if(width > max){
max = width;
}
//sheet.setColumnWidth(cell.getColumnIndex(),max);
}
while(itr.hasNext()){
Cell cell = itr.next();
sheet.setColumnWidth(cell.getColumnIndex(),max);
}
}

Related

Not able to check in excel using Apache POI if specific cell as per row and column is empty in Selenium with Java

I'm trying to write data in excel while running my tests and in Excel Test Class I have written a code to check if specific row under column is empty then write data else increment the row by 1 and then check same and write data.
From another class I'm calling ExcelTest:
ExcelTest sfName = new ExcelTest("C:\\Users\\abc\\eclipse-workspace\\dgc\\src\\com\\dg\\base\\utility\\TestData.xlsx");
sfName.setCellData("Sheet1","SingleFactor Campaign",SFCampName);
ExcelTest Class
public class ExcelTest
{
public FileInputStream fis = null;
public FileOutputStream fos = null;
public XSSFWorkbook workbook = null;
public XSSFSheet sheet = null;
public XSSFRow row = null;
public XSSFCell cell = null;
String xlFilePath;
boolean isEmptyStringCell;
public ExcelTest(String xlFilePath) throws Exception
{
this.xlFilePath = xlFilePath;
fis = new FileInputStream(xlFilePath);
workbook = new XSSFWorkbook(fis);
fis.close();
}
public void setCellData(String sheetName, String colName, int rowNum, String value)
{
try
{
int col_Num = -1;
sheet = workbook.getSheet(sheetName);
row = sheet.getRow(0);
for (int i = 0; i < row.getLastCellNum(); i++)
{
if(row.getCell(i).getStringCellValue().trim().equals(colName))
{
col_Num = i;
}
}
sheet.autoSizeColumn(col_Num);
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
isEmptyStringCell=cell.getStringCellValue().trim().isEmpty();
if (this.isEmptyStringCell)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
else
{
j=j+1;
}
}
/*row = sheet.getRow(rowNum - 1);
if(row==null)
row = sheet.createRow(rowNum - 1);
cell = row.getCell(col_Num);
if(cell == null)
cell = row.createCell(col_Num);
cell.setCellValue(value);*/
System.out.println("The cell value is "+cell.getStringCellValue());
fos = new FileOutputStream(xlFilePath);
workbook.write(fos);
fos.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
If we remove the block comment(mentioned above in code and add then comment to this code listed below then it will just write data in cell whichever is provided while calling the function.
In below code I'm starting a loop till max 7 rows and then checking if the cell contains data then increment or write data and once it writes then exit the loop.
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
isEmptyStringCell=cell.getStringCellValue().trim().isEmpty();
if (this.isEmptyStringCell)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
else
{
j=j+1;
}
}
Expected: It should write data in a row which has no cell data.
Actual: It doesn't write anything.
I've found solution for the above question and only need to change few code and now it is working as expected:
for(int j=2; j<7; j++)
{
row = sheet.getRow(j - 1);
if(row==null)
row = sheet.createRow(j - 1);
cell = row.getCell(col_Num);
//it will check if cell contains no value then create cell and set value
if(cell == null)
{
cell = row.createCell(col_Num);
cell.setCellValue(value);
break;
}
}

Apache POI copy one row from Excel file to another new Excel File

I am using JAVA 8 and Apache POI 3.17. I have an Excel file and i want to keep only few lines and delete the others. But my Excel have 40K rows and deleting them one by one is quite long (nearly 30 min :/ )
So i try to change my way of doing it. Now i think it's better to only take rows that i need in the excel source and copy to another new one. But what i have tried so far is not efficient.
I have all my rows and want to keep in a List. But this not working and create me a blank excel :
public void createExcelFileFromLog (Path logRejetFilePath, Path fichierInterdits) throws IOException {
Map<Integer, Integer> mapLigneColonne = getRowAndColumnInError(logRejetFilePath);
Workbook sourceWorkbook = WorkbookFactory.create(new File(fichierInterdits.toAbsolutePath().toString()));
Sheet sourceSheet = sourceWorkbook.getSheetAt(0);
List<Row> listLignes = new ArrayList<Row>();
// get Rows from source Excel
for (Map.Entry<Integer, Integer> entry : mapLigneColonne.entrySet()) {
listLignes.add(sourceSheet.getRow(entry.getKey()-1));
}
// The new Excel
Workbook workbookToWrite = new XSSFWorkbook();
Sheet sheetToWrite = workbookToWrite.createSheet("Interdits en erreur");
// Copy Rows
Integer i = 0;
for (Row row : listLignes) {
copyRow(sheetToWrite, row, i);
i++;
}
FileOutputStream fos = new FileOutputStream(config.getDossierTemporaire() + "Interdits_en_erreur.xlsx");
workbookToWrite.write(fos);
workbookToWrite.close();
sourceWorkbook.close();
}
private static void copyRow(Sheet newSheet, Row sourceRow, int newRowNum) {
Row newRow = newSheet.createRow(newRowNum);
newRow = sourceRow;
}
EDIT : Change the method of copyRow it's better but the date have weird format and blank cells from the original row are gone.
private static void copyRow(Sheet newSheet, Row sourceRow, int newRowNum) {
Row newRow = newSheet.createRow(newRowNum);
Integer i = 0;
for (Cell cell : sourceRow) {
if(cell.getCellTypeEnum() == CellType.NUMERIC) {
newRow.createCell(i).setCellValue(cell.getDateCellValue());
} else {
newRow.createCell(i).setCellValue(cell.getStringCellValue());
}
i++;
}
}
EDIT 2 : To keep blank cell
private static void copyRow(Sheet newSheet, Row sourceRow, Integer newRowNum, Integer cellToColor) {
Row newRow = newSheet.createRow(newRowNum);
//Integer i = 0;
int lastColumn = Math.max(sourceRow.getLastCellNum(), 0);
for(int i = 0; i < lastColumn; i++) {
Cell oldCell = sourceRow.getCell(i, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
if(oldCell == null) {
newRow.createCell(i).setCellValue("");
} else if (oldCell.getCellTypeEnum() == CellType.NUMERIC) {
newRow.createCell(i).setCellValue(oldCell.getDateCellValue());
} else {
newRow.createCell(i).setCellValue(oldCell.getStringCellValue());
}
}
}

How to increment my row counter variable in my while loop?

I am trying to read in each row that has data in the first cell into an ArrayList of Objects. My problem is that my code doesn't seem to be incrementing my counter past the first row. Am I missing something simple?
Code
try
{
wb = new XSSFWorkbook(new FileInputStream(fileName));
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
XSSFSheet sheet = wb.getSheetAt(2);
ArrayList<Object> obj = new ArrayList<Object>();
int rowIndex = 0;
int cellIndex = 0;
XSSFRow row = sheet.getRow(rowIndex);
Iterator<Cell> rowItr = row.iterator();
while(rowIndex <= sheet.getLastRowNum())
{
if(row.getCell(0) == null)
{
continue;
}
else
{
while(rowItr.hasNext() && rowItr.next() != null)
{
XSSFCell cell = row.getCell(cellIndex);
if(cell == null)
{
continue;
}
else
{
obj.add(row.getCell(cellIndex).toString());
}
cellIndex++;
}
rowIndex++;
cellIndex = 0;
}
System.out.println(obj.toString());
}
rowIndex++;
}
}
Output
[ValuSmart Series 1120 Double Hung]
... I get this output 72 times since there are 72 rows in the sheet
Isolated Loop
ArrayList<Object> obj = new ArrayList<Object>();
int rowCounter = 16;
int x = 0;
while(rowCounter <= 21)
{
XSSFRow row = sheet.getRow(rowCounter);
Iterator<Cell> rowItr = row.iterator();
while(rowItr.hasNext() && rowItr.next() != null)
{
XSSFCell cell = row.getCell(x);
if(cell == null)
{
continue;
}
else
{
obj.add(row.getCell(x).toString());
}
x++;
}
rowCounter++;
x = 0;
}
System.out.println(obj.toString());
You're not select the next row anywhere, and your loops are confusing and switch between index- and iterator-based lookups. Try a simple enhanced for loop:
for (Row row : sheet) {
for (Cell cell : row) {
if (cell != null) {
obj.add(row.getCell(x).toString());
}
}
}
System.out.println(obj.toString());

Apache POI - Reading excel file in 2D array - returning null values

I am trying to read Excel -2*2 matrix through Apache POI. But the first value returned by 2D array is [null,null]. Please check my code and advise for suitable corrections.
public String[][] getDataArray(String sheetName)
{
String value ="";
String[][] data = null;
int rowCount = wb.getSheet(sheetName).getLastRowNum();
int colCount = wb.getSheet(sheetName).getRow(1).getLastCellNum()-1;
data = new String[rowCount][colCount];
for(int i=1; i<=rowCount;i++)
{
Row row = wb.getSheet(sheetName).getRow(i);
for(int j=0;j<colCount;j++)
{
Cell cell = row.getCell(j);
if(cell.getCellType()==Cell.CELL_TYPE_NUMERIC)
{
value = ""+cell.getStringCellValue();
}
else
{
value = cell.getStringCellValue();
}
data[i][j] = value;
}
}
return data;
}
The debug view where we can see that the first value stored in the variable data is null, null
The excel which i am trying to read. I need only the userName and password data(2*2) alone. Not the header and Run mode datas.
Of course the value in the index 0 will be null because the i starts from 1 and not 0
for (int i = 1; i <= rowCount; i++) //i starts from one
...
data[i][j] = value;
either initialize the i from 0 or do like this
data[i-1][j] = value;
public static String[][] getSheetData(final String fileName, final String workSheetName)
throws Exception {
Integer lastRow = null;
short lastCol = 0;
String[][] sheetData = null;
FileInputStream file=new FileInputStream(MettlTest.class.getClass().getResource("/" + fileName).getPath());
workbook = new XSSFWorkbook(file);
sheet = workbook.getSheet(workSheetName);
try {
XSSFRow row;
XSSFCell cell;
lastRow = sheet.getPhysicalNumberOfRows();
lastCol = sheet.getRow(1).getLastCellNum();
sheetData = new String[lastRow - 1][lastCol];
for (int r = 1; r < lastRow; r++) {
row = sheet.getRow(r);
if (row != null) {
for (int c = 0; c < lastCol; c++) {
cell = row.getCell(c);
if (cell == null) {
sheetData[r][c] = null;
} else {
sheetData[r-1][c] = new DataFormatter().formatCellValue(cell);
}
}
}
}
return sheetData;
}
catch (final Exception e) {
throw e;
}
finally {
try {
file.close();
} catch (IOException io) {
Reporter.log("Unable to close File : " + fileName);
throw io;
}
}

Creating multiple sheets using Apache poi and servlets

When i am creating multiple sheets using Apache poi and servlets. It is creating the sheet but not writing the data to file. I am trying to write the first 1000 records to sheet1 and next 1000 to sheet2 through below code, but not working
private void writeDataToExcelFile(String string,
ArrayList<ArrayList<String>> excelData, OutputStream outputStream) {
HSSFWorkbook myWorkBook = new HSSFWorkbook();
String sheetName = "";
sheetName = "Document-" + 0;
HSSFSheet mySheet = myWorkBook.createSheet();
HSSFRow myRow = null;
HSSFCell myCell = null;
for (int rowNum = 0; rowNum < excelData.size(); rowNum++) {
ArrayList<String> rowData = excelData.get(rowNum);
if(rowNum>0 && rowNum%1000 == 0)
{
sheetName = "Document-" + (rowNum/1000);
mySheet = myWorkBook.createSheet();
}
myRow = mySheet.createRow(rowNum);
for (int cellNum = 0; cellNum < rowData.size(); cellNum++) {
myCell = myRow.createCell(cellNum);
myCell.setCellValue(rowData.get(cellNum));
}
}
System.out.println("Last row:" + mySheet.getLastRowNum());
System.out.println("Row number:" + mySheet.rowIterator().next().getRowNum());
try {
myWorkBook.write(outputStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
What is wrong with my logic.Please do the needful help.
Thanks
When you loop through the dataset, you are wanting to split at row 1000 to start a new sheet, which is fine, however when you start the new sheet, the next row you create is row 1001 (the outer loop index variable)
myRow = mySheet.createRow(rowNum);
To get the effect you wish, change the loop to be something like this:
int currentRow = 0;
for (int rowNum = 0; rowNum < excelData.size(); rowNum++)
{
ArrayList<String> rowData = excelData.get(rowNum);
if(currentRow == 1000)
{
sheetName = "Document-" + (rowNum/1000);
mySheet = myWorkBook.createSheet();
currentRow = 0;
}
myRow = mySheet.createRow(currentRow);
for (int cellNum = 0; cellNum < rowData.size(); cellNum++)
{
myCell = myRow.createCell(cellNum);
myCell.setCellValue(rowData.get(cellNum));
}
currentRow++;
}
I haven't compiled this, so I don't know if it'll work right away, but it should point you in the right direction.
HTH
Edit
Thinking about this further, you could get the same effect from making a 1 line change to the original application (albeit losing a little bit of clarity):
myRow = mySheet.createRow(rowNum%1000);

Categories

Resources