Find Excel Cell by Text in Apache POI - java

I'd like to find a cell in an Excel sheet by its text. The text is something like %t:
sheet.findCell("%t"); // pseudo-code, not working
My goal is to enable the user to provide kind of template, in which data is written. Colours and fonts, as well as data's position can be configured by the user in an Excel file. This %t cell is the top-left corner of the data table.
Additional question: Is there a more elegant way to get this job done?
EDIT I'm iterating over the rows and cells to find it. I'm afraid it's not really efficient, but it works so far:
public static Cell findCell(XSSFSheet sheet, String text) {
for(Row row : sheet) {
for(Cell cell : row) {
if(text.equals(cell.getStringCellValue()))
return cell;
}
}
return null;
}

You can iterate through the cells of the sheet and investigate the contents. I don't think there is an easier method.

Its an old post but still i want to publish my code.
You can define a file path.
String inputFile = "src\main\resources\file.xlsx";
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new FileInputStream(inputFile));
DataFormatter formatter = new DataFormatter();
for (XSSFSheet sheet : xssfWorkbook) {
for (Row row : sheet) {
for (Cell cell : row) {
if (formatter.formatCellValue(cell).contains("name")){
cell.setCellValue("test");
}
}
}
}
xssfWorkbook.write(new FileOutputStream(inputFile));

Related

Java code to Split Workbook into multiple workbooks based on a cell value

I am looking for some help. I have an excel sheet A which has around 700 records. It has 5 columns where one of the column is Lifecycle. I want to split the file into two different files based on the Lifecycle cell value. For example if the cell value of Lifecycle column is X, put the record in A_X.xlsx file else put the records in A_Y.xlsx file.
I am using Apache POI.
Thanks in advance.
You can read from excel file using Workbook
Like this: Workbook workbook = WorkbookFactory.create(new File(EXCEL_FILE_PATH));
Then you need to get your sheet like this: Sheet sheet = workbook.getSheetAt(YOUR_SHEET_POSITION);
But remember that sheets position starts from 0.
Then you can iterate over rows and cells using Iterator, for-each, and Java 8 foreEach with Lamba
Like this:
Using Iterator
Iterator<Row> rowIterator = sheet.rowIterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
// there you can check if cell.someValue == yourNeed to save on files that you need
if(cell.yourValue == SOMETHING) {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_ONE);
} else {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_TWO);
}
}
}
Using for-each
for (Row row: sheet) {
for(Cell cell: row) {
// there you can check if cell.someValue == yourNeed to save on files that you need
if(cell.yourValue == SOMETHING) {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_ONE);
} else {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_TWO);
}
}
}
Using Java 8 forEach with lamdas
sheet.forEach(row -> {
row.forEach(cell -> {
// there you can check if cell.someValue == yourNeed to save on files that you need
if(cell.yourValue == SOMETHING) {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_ONE);
} else {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_TWO);
}
});
});
And in the end, don't forget to close the workbook using workbook.close()

Workbook takes long time to generate excel file

I'm trying to generate excel file with 200k records. But it is taking almost 2 hours to generate the file.
Here is my code of generating excel file.
Workbook workbook=null;
csvFileName = userId+"_Records_"+new SimpleDateFormat("yyyyMMddHHmmss")
.format(new Date())+".xls";
path = ReadPropertyFile.getProperties("download.reports.path");
misService.insertXLSRecord(ackNo,"-",null, VspCommonConstants.getIpFromRequest(request),
new Date(), userId,"N",userReportRoleId);
workbook = getWorkbook(path+csvFileName);
Sheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(studAppForm.get(0)
.getScheme_Id()+"_"+studAppForm.get(0).getEFP_Scholarship_Name(),'_'));
if(schemeQuestionData.containsKey(currSheetSchemeId))
createXLSHeaders(sheet,schemeQuestionData.get(currSheetSchemeId));
Row row = sheet.createRow(++rowCount);
currAppId=studAppForm.get(j).getApp_Id().toString();
jspTableAppIds.remove(jspTableAppIds.indexOf(new BigInteger(currAppId)));
writeBook(studAppForm.get(j), row);
Here is my createXLSHeaders method to create header
void createXLSHeaders( Sheet sheet, List<SchemeMasterBean> schemeMasterBeanList){
LOGGER.info("Creating XLS SheetHeaders for sheet "+sheet.getSheetName());
// Sheet sheet = workbook.createSheet();
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("APPLICATION ID");
header.createCell(1).setCellValue("APPLICATION STATUS");
header.createCell(2).setCellValue("APPLICATION DATE");
header.createCell(3).setCellValue("SCHEME/SCHOLARSHIP APPLIED");
header.createCell(4).setCellValue("SCHEME ID");
header.createCell(5).setCellValue("STUDENT ID");
header.createCell(6).setCellValue("STUDENT FULL NAME");
.
.
.
62 heading...
int i=73;
if(schemeMasterBeanList!=null)
for(SchemeMasterBean schemeMasterBean :schemeMasterBeanList){
if(!schemeMasterBean.getSmSchemeType().equals("5") &&
!schemeMasterBean.getSmSchemeType().equals("6")){
header.createCell(i).setCellValue(schemeMasterBean.getSmScholarshipName());
i++;
}
}
}
and finally writebook method
private void writeBook(StudentAppFormVsp saf, Row row) throws JSONException {
Cell cell = row.createCell(0);
cell.setCellValue(saf.getApp_Id()!=null?saf.getApp_Id().toString():"");
cell = row.createCell(1);
cell.setCellValue(saf.getApp_Status()!=null?getApplicationStatusMap().get(saf.getApp_Status()):"");
cell = row.createCell(2);
cell.setCellValue(saf.getCrtn_time()!=null?saf.getCrtn_time().toString():"");
cell = row.createCell(3);
cell.setCellValue(saf.getEFP_Scholarship_Name()!=null?saf.getEFP_Scholarship_Name().toString():"");
cell = row.createCell(4);
cell.setCellValue(saf.getScheme_Id()!=null?saf.getScheme_Id().toString():"");
cell = row.createCell(5);
cell.setCellValue(saf.getStud_Id()!=null?saf.getStud_Id().toString():"");
.
.
62 rows
}
How to reduce the excel sheet generation time?
First: play around with memory for the application if possible.
Then: the tip on using a profiler is really worth the effort.
Any DOM, XML, Excel or otherwise often suffer from location references searching from top to the actual position.
Creating a DOM instead of writing sequentially is costly with respect to memory, and can slow things down. Maybe consider this.
You could make two loop: writing to a CSV file, and then creating an XLS(X).
Then you know where the complexity resides.
The following (I rewrote a bit) is slightly suspect: toString + new BigInteger points to a conversion; I hope not from BigInteger to String to BigInteger.
StudentAppFormVsp saf = studAppForm.get(j);
currAppId = saf.getApp_Id().toString();
jspTableAppIds.remove(jspTableAppIds.indexOf(BigInteger.valueOf(currAppId)));
writeBook(saf, row);

How to loop over values of a certain column in an excel sheet to get the index of a value using java apache poi

I am still new to Java trying only to loop over an excel column.
The Excel sheet:
I want to have in HashMap or Array so that I can compare these dates later on with another column.
My Code is giving me yet a string as you see in the screenshot:
How can I change this String to a another Data structure to access the "index" of the values. Something like dates.get(0) --> So 01-Jul-2018. I would change the time format later.
The Code section:
XSSFWorkbook workbook = new XSSFWorkbook(fsIP);
XSSFSheet sheet = workbook.getSheetAt(0);
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
Row row = sheet.getRow(rowIndex);
if (row != null) {
Cell cell = row.getCell(0); // getColumn(0)
if (cell != null) {
System.out.print(cell);
}
}
}
What would you like to know further from me?
I would be thankful for every help!

Reading blank cell Apache POI 3.17

I'm using Apache POI 3.17 to read some excel data. My second column (index of 1 because of 0 index) is empty and I want to be able to read it, but can't get my code to read the cell as empty. I have this which isn't working:
Cell c = row.getCell(1, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// do whatever
}
But the second parameter can't be taken in. I get "RETURN_BLANK_AS_NULL cannot be resolved or is not a field"
The constants in the Row class itself were deprecated as of POI-3.15-beta2, marked for removal as of POI-3.17. This diff shows when those constants were deprecated in June 2016. They were removed in 3.17.
Before 3.17, the enum Row.MissingCellPolicy was already defined as a replacement. If you're using 3.17, then you must use that enum; it is defined as a member of the Row interface. Try
Cell c = row.getCell(1, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
Try using org.apache.poi.ss.usermodel.DataFormatter.
DataFormatter formatter = new DataFormatter();
Workbook workbook = WorkbookFactory.create(new File("yourFileName.xls"));
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
for(Cell cell : row)
{
String text = formatter.formatCellValue(cell);
System.out.println(text);
}
}
workbook.close();

Apache POI Excel - how to configure columns to be expanded?

I am using Apache POI API to generate excel spreadsheet to output some data.
The problem I am facing is when the spreadsheet is created and opened, columns are not expanded so that some long text like Date formatted text is not showing up on first glance.
I could just double click the column border in excel to expand or drag the border to adjust the column width but there could be 20+ columns and there is no way I want to do that manually every time I open the spreadsheet :(
I found out (though could be wrong method) groupRow() and setColumnGroupCollapsed() might be able to do the trick but no luck. Maybe I'm using it in wrong way.
Sample Code snippet
Workbook wb = new HSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper();
//create sheet
Sheet sheet = wb.createSheet("masatoSheet");
//not really working yet.... :(
//set group for expand/collapse
//sheet.groupRow(0, 10); //just random fromRow toRow argument values...
//sheet.setColumnGroupCollapsed(0, true);
//create row
Row row = sheet.createRow((short)0);
//put a cell in the row and store long text data
row.createCell(0).setCellValue("Loooooooong text not to show up first");
When this spreadsheet is created, the "Looooooong text not to show up first" string is in the cell but since the column is not expanded only "Loooooooo" is showing up.
How can I configure it so that when I open my spreadsheet, the column is already expanded???
After you have added all your data to the sheet, you can call autoSizeColumn(int column) on your sheet to autofit the columns to the proper size
Here is a link to the API.
See this post for more reference
Problem in fitting the excel cell size to the size of the content when using apache poi
Tip : To make Auto size work , the call to sheet.autoSizeColumn(columnNumber) should be made after populating the data into the excel.
Calling the method before populating the data, will have no effect.
If you want to auto size all columns in a workbook, here is a method that might be useful:
public void autoSizeColumns(Workbook workbook) {
int numberOfSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
Sheet sheet = workbook.getSheetAt(i);
if (sheet.getPhysicalNumberOfRows() > 0) {
Row row = sheet.getRow(sheet.getFirstRowNum());
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
int columnIndex = cell.getColumnIndex();
sheet.autoSizeColumn(columnIndex);
}
}
}
}
You can try something like this:
HSSFSheet summarySheet = wb.createSheet();
summarySheet.setColumnWidth(short column, short width);
Here params are:column number in sheet and its width
But,the units of width are pretty small, you can try 4000 for example.
For Excel POI:
sheetName.autoSizeColumn(cellnum);
sample code below
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("your sheet name");
HSSFRow row = sheet.createRow(0);
cell = row.createCell(0);
cell.setCellValue("A BIG NAME WITH AUTO SIZE FEATURE ENABLED");
//this is crucial
sheet.autoSizeColumn(0);
//argument must be cell number
cell = row.createCell(1);
cell.setCellValue("a big name without auto size feature enabled");
Check the output and go nuts :)
If you know the count of your columns (f.e. it's equal to a collection list). You can simply use this one liner to adjust all columns of one sheet (if you use at least java 8):
IntStream.range(0, columnCount).forEach(sheet::autoSizeColumn)
You can add this, after your loop.
for (int i = 0; i<53;i++) {
sheet.autoSizeColumn(i);
}
I use below simple solution:
This is your workbook and sheet:
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("YOUR Workshhet");
then add data to your sheet with columns and rows. Once done with adding data to sheet write following code to autoSizeColumn width.
for (int columnIndex = 0; columnIndex < 15; columnIndex++) {
sheet.autoSizeColumn(columnIndex);
}
Here, instead 15, you add the number of columns in your sheet.
Hope someone helps this.
You can use setColumnWidth() if you want to expand your cell more.
Its very simple, use this one line code
dataSheet.autoSizeColumn(0)
or give the number of column in bracket
dataSheet.autoSizeColumn(cell number )
You can wrap the text as well. PFB sample code:
CellStyle wrapCellStyle = new_workbook.createCellStyle();
wrapCellStyle.setWrapText(true);

Categories