Reading excel files .xlsx via Java - java

So my excel file is relatively small in size. It contains 8 sheets. Each sheet has "records" of data which i need to read. Each sheet also has the first row reserved for headers which i skip; so my data will begin from the 2nd row (1st index) of each sheet and end on the last record.
So, below is my code to iterate through the sheets and read each row however it fails to read each sheet. And i can't seem to figure out why. Please have look and any suggestions will be appreciated.
Thanks!
FileInputStream fis = new FileInputStream(new File(filePath));
XSSFWorkbook wb = new XSSFWorkbook(fis);
DataFormatter formatter = new DataFormatter();
//iterate over sheets
for (int i=0; i<NUM_OF_SHEETS; i++) {
sheet = wb.getSheetAt(i);
sheetName = sheet.getSheetName();
//iterate over rows
for (int j=1; j<=lastRow; j++) { //1st row or 0-index of each sheet is reserved for the headings which i do not need.
row = sheet.getRow(j);
if (row!=null) {
data[j-1][0] = sheetName; //1st column or 0th-index of each record in my 2d array is reserved for the sheet's name.
//iterate over cells
for (int k=0; k<NUM_OF_COLUMNS; k++) {
cell = row.getCell(k, XSSFRow.RETURN_BLANK_AS_NULL);
cellValue = formatter.formatCellValue(cell); //convert cell to type String
data[j-1][k+1] = cellValue;
}//end of cell iteration
}
}//end of row iteration
}//end of sheet iteration
wb.close();
fis.close();

At least there is one big logical error. Since you are putting the data of all sheets in one array, this array must be dimensioned like:
String[][] data = new String[lastRow*NUM_OF_SHEETS][NUM_OF_COLUMNS+1];
And then the allocations must be like:
...
data[(j-1)+(i*lastRow)][0] = sheetName; //1st column or 0th-index of each record in my 2d array is reserved for the sheet's name.
...
and
...
data[(j-1)+(i*lastRow)][k+1] = cellValue;
...
With your code, the allocations from second sheet will overwrite the ones from the first sheet, since j starts with 1 for every sheet.

Related

How to add columns to an existing large excel file using SXSSF Apache POI?

I am working with a large excel file ( larger than 40 Mb , more than 100k rows and 50 columns ). I am successfully reading it using POI ( 3.10.1 version ) event stream and then doing some calculation and storing result into a List.
Now I have to append this List as a column in the same file. In this part I am facing issue.
I have tried to achieve this by using the below code
FileInputStream excelFile = new FileInputStream(new File(pathToFile));
Workbook workbook = new XSSFWorkbook(excelFile);
Sheet datatypeSheet = workbook.getSheetAt(0); // Get first sheet
Iterator<Row> iterator = datatypeSheet.iterator();
int i=0;
while (iterator.hasNext()) { // Loop over each row
Row currentRow = iterator.next();
Cell cell = currentRow.createCell(currentRow.getLastCellNum());
cell.setCellType(Cell.CELL_TYPE_STRING);
if(currentRow.getRowNum() == 0)
cell.setCellValue("OUTPUT-COLUMN"); // set column header for the new column
else {
cell.setCellValue(list.get(i)); // list contains the output to populate in new column
i++;
}
}
FileOutputStream fos = new FileOutputStream(new File(pathToOutput));
workbook.write(fos);
fos.close();
It is working fine with smaller files But the issue is that I am getting Out of memory for the larger files. Now I tried to modify this and use SXSSF in place of XSFF to get over the memory issue (See below code). But while testing even for smaller files I am getting output file same as the input file.
FileInputStream excelFile = new FileInputStream(new File(pathToFile));
XSSFWorkbook xwb = new XSSFWorkbook(inputStream);
inputStream.close();
SXSSFWorkbook wb = new SXSSFWorkbook(xwb,100);
wb.setCompressTempFiles(true);
SXSSFSheet sh = (SXSSFSheet) wb.getSheetAt(0);
Iterator<Row> iterator = datatypeSheet.iterator();
int i=0;
while (iterator.hasNext()) { // Loop over each row
Row currentRow = iterator.next();
Cell cell = currentRow.createCell(currentRow.getLastCellNum());
cell.setCellType(Cell.CELL_TYPE_STRING);
if(currentRow.getRowNum() == 0)
cell.setCellValue("OUTPUT-COLUMN"); // set column header for the new column
else {
cell.setCellValue(list.get(i)); // list contains the output to populate in new column
i++;
}
}
FileOutputStream fos = new FileOutputStream(new File(pathToOutput));
wb.write(fos);
fos.close();
Using a db is not suitable in my use case and i want to avoid using a temporary data structure to hold data for writing due to memory constraint.
Is there a way to write in output workbook while streaming ? Here is the code that I am using to read using POI Streaming API
private class ExcelData implements SheetContentsHandler {
LinkedHashMap<Strin, String> rowMap;
public void startRow(int rowNum) {
}
public void endRow(int rowNum) {
// Process the row
// Handle write to output workbook ??
}
public void cell(String cellReference, String formattedValue,
XSSFComment comment) {
// Save current row in rowMap ( column name => cell value )
}
public void headerFooter(String text, boolean isHeader, String tagName)
{
}
}
It is not possible to add column to existing workbook using POI SXSSF. It only allows addition of new rows.
The only solution is to read the existing workbook and write to a new workbook with the added column.
To achieve this we can store the rows in a data structure or database in the endrow() method and then use the persisted data to write a new workbook.

How to read not unique named ranges from the one of the sheet of workbook

How to read the named range from one of the sheet in workbook.Named range is present in multiple sheet of workbook with same name.
I tried with the workbook as a whole,not able to set the scope at sheet level
String cname = "TestName";
Workbook wb = getMyWorkbook(); // retrieve workbook
// retrieve the named range
int namedCellIdx = wb.getNameIndex(cellName);
Name aNamedCell = wb.getNameAt(namedCellIdx);
// retrieve the cell at the named range and test its contents
AreaReference aref = new AreaReference(aNamedCell.getRefersToFormula());
CellReference[] crefs = aref.getAllReferencedCells();
for (int i=0; i<crefs.length; i++) {
Sheet s = wb.getSheet(crefs[i].getSheetName());
Row r = sheet.getRow(crefs[i].getRow());
Cell c = r.getCell(crefs[i].getCol());
// extract the cell contents based on cell type etc.
}

Java change cell content instead of creating new cells

I have a list of variables in an excel file which I use as input for an online app and generate a result. That occurs successfully however when I try to save the output in that same file by adding a new column and cells, the original content of the file would be deleted. I only want to add the info to the same document but the only option I found by googling is to create another file.
just to clarify:Variables for input
and instead of just adding the info this happens Changed document.
How can I fix it without adding more parameter and re-adding the info?
#Keyword
public void demoKey(String name) throws IOException{
FileInputStream fis = new FileInputStream("C://Users/i2srsm/Desktop/New Microsoft Excel Worksheet.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(fis);
XSSFSheet sheet = workbook.getSheet("Data for full set");
int columnNumber = sheet.getRow(0).getLastCellNum();
int firstRow = sheet.getFirstRowNum();
int lastRow = sheet.getLastRowNum();
sheet.createRow(firstRow).createCell(columnNumber).setCellValue('Proposta');
for (int rn=(firstRow); rn<=lastRow; rn++){
Cell cell = sheet.createRow(rn).createCell(columnNumber+1)
cell.setCellType(cell.CELL_TYPE_STRING);
cell.setCellValue(name);
FileOutputStream fos = new FileOutputStream("C://Users/i2srsm/Desktop/New Microsoft Excel Worksheet.xlsx");
workbook.write(fos);
fos.close();
}
}
}
don't use a sheet.createRow(row index) for update the existing excel file. this one create a new row. if you want to update the existing row in a sheet, firstly get related existing row and then create a new cell.
for get existing row
Row row = sheet.getRow(row index);
for create a new cell in above existing row
Cell cell = row.createCell(cell index);
try with this
sheet.getRow(firstRow).createCell(columnNumber).setCellValue("Proposta");
for (int i=(firstRow+1); i<=lastRow; i++){
Row row = sheet.getRow(i);
Cell cell = row.createCell(columnNumber);
cell.setCellType(cell.CELL_TYPE_STRING);
cell.setCellValue(name);
}
FileOutputStream fos = new FileOutputStream("C:/Users/LifeStyle/Documents/output.xlsx");
workbook.write(fos);
fos.close();

adding cells in excel with java apache

I am reading an already existing excel file and trying to add certain cells for example(C4-C15). I am having difficult manipulating the files through java. I am using apache poi, and would appreciate any help or direction.
In order to access a cell in Apache POI, you have to get a row first, and then get cell within chosen row. Below is example:
//Input file
InputStream inp = new FileInputStream("workbook.xls");
//Create workbook instance
Workbook wb = WorkbookFactory.create(inp);
//Create sheet instance
Sheet sheet = wb.getSheetAt(0);
for(int i = 3; i <= 16; ++i){ //Rows from 4 to 15 (Apache POI is zero based)
Row row = sheet.getRow(i);
Cell cell = row.getCell(2); //Column "C"
//Do something with cell
}
// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
Source (more examples here)

upload excel file validation in java

i am new for upload Excel file POI API so i need to validate duplicate cell in particular column . example like
String dupcolumn = myRow.getcell(0);
Iterator iter = new Iterator();
while(iter.hesnext())
{
myRow = (Row) iter.next();
dupcolumn.contains(iter.toString());
}
Above code cannot support to read in particular column , but always continuous reading column .
This code may helpful to you.
InputStream xlsStream = excelFileUpload.getInputstream();
XSSFWorkbook wb = new XSSFWorkbook(xlsStream);
XSSFSheet sheet = wb.getSheetAt(0);
Iterator<Row> rows=sheet.iterator();
//need to keep retrieved values in a collection to check duplicates.
Set<String> values = new HashSet<String>();
//check all rows in excel sheet
while(rows.hasNext()){
//get next row
XSSFRow row =(XSSFRow)rows.next();
//pass '0' means first cell (column) in current row. if you need to get other cell value, you can pass relevant cell number instead of '0'.
XSSFCell cell=row.getCell(0);
if(values.contains(cell.getStringCellValue())){
//duplicated value
}else{
values.add(cell.getStringCellValue());
}
}

Categories

Resources