I would like to delete a column in Excel (XLSX) with the Apache POI 5.0.0. I want to use the shiftColumns method, so affected formulas get adjusted automatically.
void shiftColumns(int startColumn, int endColumn, int n)
https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/Sheet.html
The documentation says that, if you want to shift left (overriding columns on the left side), you should use a negative number.
I tried the following example on the following Excel file:
String path = "pathOfTheExcelFile";
File file = new File(path);
Workbook wb = null;
try (FileInputStream inputStream = new FileInputStream(file)) {
wb = WorkbookFactory.create(inputStream); // read workbook
} catch (IOException e) {
e.printStackTrace();
}
if(wb == null)
return;
Sheet sheet = wb.getSheetAt(0); // read first sheet
// deleting / overriding 2nd column
sheet.shiftColumns(2, 5, -1); // shifting from 3rd to last column to the left
try (OutputStream fileOut = new FileOutputStream(path)) {
wb.write(fileOut); // writing the result in the Excel file (ERROR)
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (wb != null)
wb.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
Excel file I want to alter:
After executing the code, I get this error on line wb.write(fileOut);:
java.lang.IndexOutOfBoundsException
at org.apache.xmlbeans.impl.store.Xobj.removeElement(Xobj.java:2099)
at org.apache.xmlbeans.impl.store.Xobj.remove_element(Xobj.java:2130)
at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTRowImpl.removeC(CTRowImpl.java:173)
at org.apache.poi.xssf.usermodel.XSSFRow.fixupCTCells(XSSFRow.java:612)
at org.apache.poi.xssf.usermodel.XSSFRow.onDocumentWrite(XSSFRow.java:582)
at org.apache.poi.xssf.usermodel.XSSFSheet.write(XSSFSheet.java:3625)
at org.apache.poi.xssf.usermodel.XSSFSheet.commit(XSSFSheet.java:3570)
at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:465)
at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:470)
at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:221)
at test.App.main(App.java:38)
FYI, I use Java 11 and these libraries:
libraries
After execution, my file has 0KB.
I debugged into the Apache POI library while saving the workbook in the Excel file. This is where the problem starts. Maybe it helps you:
pic1
pic2
pic3
Yes, here are still problems in Sheet.shiftColumns even in latest version Apache POI 5.1.0. The shiftColumns does not removing the cells properly when negative shifted. That's why the error while writing then.
If you explicitly remove the cells of the column you want over-shfting, then the error is gone. So we need to remove all cells from second column (index 1) before shifting third column (index 2) to left.
But there are additional problems too. Even the last version does not update the calculation chain while shifting formulas. This is the problem of this Q/A: shiftColumn method is not working when cell has formula.
Complete example:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.model.CalculationChain;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import java.lang.reflect.Method;
public class ExcelShiftColums {
private static void removeCalcChain(XSSFWorkbook workbook) throws Exception {
CalculationChain calcchain = workbook.getCalculationChain();
Method removeRelation = POIXMLDocumentPart.class.getDeclaredMethod("removeRelation", POIXMLDocumentPart.class);
removeRelation.setAccessible(true);
removeRelation.invoke(workbook, calcchain);
}
private static void removeColumn(Sheet sheet, int column) {
for (Row row : sheet) {
Cell cell = row.getCell(column);
if (cell != null) {
row.removeCell(cell);
}
}
}
private static int getLastFilledColumn(Sheet sheet) {
int result = 0;
for (Row row : sheet) {
if (row.getLastCellNum() > result) result = row.getLastCellNum();
}
return result;
}
public static void main(String[] args) throws Exception {
String inFilePath = "./ExcelExampleIn.xlsx"; String outFilePath = "./ExcelExampleOut.xlsx";
//String inFilePath = "./ExcelExampleIn.xls"; String outFilePath = "./ExcelExampleOut.xls";
try (Workbook workbook = WorkbookFactory.create(new FileInputStream(inFilePath));
FileOutputStream out = new FileOutputStream(outFilePath ) ) {
Sheet sheet = workbook.getSheetAt(0);
int lastFilledColumn = getLastFilledColumn(sheet);
removeColumn(sheet, 1);
sheet.shiftColumns(2, lastFilledColumn, -1);
if (workbook instanceof XSSFWorkbook) removeCalcChain((XSSFWorkbook)workbook);
workbook.write(out);
}
}
}
Related
I am iterating through a list of data which I am sending from the runner file(FunctionVerifier.java).
When I am calling the function writeExcel() in excelHandler.java it is entering only the last data from the list that I am iterating through.
Can someone please let me know the reason and how to fix this
public void writeExcel(String sheetName, int r, int c, String data) throws IOException {
file = new FileInputStream(new File(inFilePath));
wb = new XSSFWorkbook(file);
Sheet sh;
sh = wb.getSheet(sheetName);
Row row = sh.createRow(r);
row.createCell(c).setCellValue(data);
closeExcelInstance();
FileOutputStream outputStream = new FileOutputStream(inFilePath);
wb.write(outputStream);
wb.close();
outputStream.close();
}
public void closeExcelInstance() {
try {
file.close();
} catch (Exception e) {
System.out.println(e);
}
}
FunctionVerifier.java
package Sterling.oms;
import Sterling.oms.Process.CouponValidationProcess;
import Sterling.oms.Utilities.ExcelHandler;
import java.util.ArrayList;
public class FuncVerify {
public static void main(String args[]) throws Exception {
String filePath = System.getProperty("user.dir") + "/src/test/resources/TestData/test.xlsx";
ExcelHandler excelHandler = new ExcelHandler(filePath);
excelHandler.readExcelData("Validation");
CouponValidationProcess couponValidationProcess = new CouponValidationProcess("OMS-T781");
excelHandler.createSheet();
// couponValidationProcess.enterValidationHeaderRowInExcel(filePath);
String sheet = "ValidationData";
if (excelHandler.getRowCountWhenNull(sheet) < 1) {
ArrayList<String> header = new ArrayList<>();
header.add("Test Case");
header.add("Coupon ID");
header.add("Grand Total");
header.add("Manual Grand Total");
for (int i = 0; i < header.size(); i++) {
// excelHandler = new ExcelHandler(filePath);
excelHandler.writeExcel(sheet, 0, i, header.get(i));
// excelHandler.closeExcelInstance();
}
}
}
}
The reason for only storing the last item is that Sheet.createRow as well as Row.createCell are doing exactly what their method names tell. They create a new empty row or cell each time they get called. So every times Row row = sh.createRow(r) gets called, it creates a new empty row at row index r and looses all former created cells in that row.
The correct way to use rows would be first trying to get the row from the sheet. And only if it is not present (null), then create a new row. The same is for cells in rows. First try to get them. And only if not present, then create them.
...
Sheet sh;
sh = wb.getSheet(sheetName);
Row row = sh.getRow(r); if (row == null) row = sh.createRow(r);
Cell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
cell.setCellValue(data);
...
That's the answer to your current question.
But the whole approach, to open the Excel file to create a Workbook, then set data of only one cell in and then write the whole workbook out to the file, and doing this for each cell, is very sub optimal. Instead the workbook should be opened, then all known new cell values should be set into the sheet and then the workbook should be written out.
Your approach is wrong, you open your files again for each line you want to write to Excel, then save again. You just have to create one FileInputStream and send it to your Workbook where you do all your Excel work. After you have finished writing all your lines, you can create only one FileOutputStream and export your changes in your Workbook to a file of your choice.
writeExcel()
public void writeExcel(String sheetName, int r, int c, ArrayList<String> data) throws IOException {
file = new FileInputStream(new File(inFilePath));
wb = new XSSFWorkbook(file);
Sheet sh;
sh = wb.getSheet(sheetName);
Row row = sh.createRow(r);
//Adding data column wise
for (String h : data) {
row.createCell(c++).setCellValue(h);
}
closeExcelInstance();
FileOutputStream outputStream = new FileOutputStream(inFilePath);
wb.write(outputStream);
wb.close();
outputStream.close();
}
I'm trying to create a .xlsx file using XSSFWorkBook in Java.
Using below code I'm trying
try
{
File tempFile = new File(validateFileUrl);
XSSFWorkbook workbook = null;
XSSFSheet sheet = null;
if(!rowList.isEmpty()) // rowList contains comma(,) separated string values
{
workbook = new XSSFWorkbook();
sheet = workbook.createSheet();
int rownum=0;
for(String rowStr : rowList)
{
XSSFRow row = sheet.createRow(rownum++);
String[] cellArr = rowStr.split(",");
int cellCount=0;
for(String cellStr : cellArr)
{
XSSFCell crrCell = row.createCell(cellCount++);
crrCell.setCellValue(cellStr);
}
}
FileOutputStream fos = new FileOutputStream(tempFile);
workbook.write(fos);
workbook.close();
}
}
catch(Exception e)
{
e.printStackTrace();
}
file got created successfully, but the problem is that created file is opening in Read only mode, How can I create this in writeable mode?
I have tried the below option also
tempFile.setWritable(true);
but its not working, please help on this. Thanks
Excel will not allow editing a file that some other application is still writing. Instead it is waiting for exclusive access.
You need to ensure in Java the file buffer gets closed when you are finished writing the file. This happens either when the JVM terminates or when your code explicitly closes the FileOutputStream. Note that explicitly calling close can be tricky in case exceptions get thrown. Here is a safe way that makes use of the AutoClose feature of FileOutputStream:
try {
File tempFile = new File(validateFileUrl);
XSSFWorkbook workbook = null;
XSSFSheet sheet = null;
if(!rowList.isEmpty()) { // rowList contains comma(,) separated string values
workbook = new XSSFWorkbook();
sheet = workbook.createSheet();
int rownum=0;
for(String rowStr : rowList) {
XSSFRow row = sheet.createRow(rownum++);
String[] cellArr = rowStr.split(",");
int cellCount=0;
for(String cellStr : cellArr) {
XSSFCell crrCell = row.createCell(cellCount++);
crrCell.setCellValue(cellStr);
}
}
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
workbook.write(fos);
}
workbook.close();
}
}
catch(Exception e) {
e.printStackTrace();
}
Note that vice versa, Excel is exclusively holding access to the file. So if you want to write it again from your application, ensure Excel has closed the document.
Fix is to close the FileOutputStream object
fos.close();
Sample Code:
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;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.List;
public class Excel {
public static void main(String[] args) {
String validateFileUrl = "so-excel.xlsx";
List<String> rowList = Arrays.asList("1", "2");
try
{
File tempFile = new File(validateFileUrl);
XSSFWorkbook workbook = null;
XSSFSheet sheet = null;
if(!rowList.isEmpty()) // rowList contains comma(,) separated string values
{
workbook = new XSSFWorkbook();
sheet = workbook.createSheet();
int rownum=0;
for(String rowStr : rowList)
{
XSSFRow row = sheet.createRow(rownum++);
String[] cellArr = rowStr.split(",");
int cellCount=0;
for(String cellStr : cellArr)
{
XSSFCell crrCell = row.createCell(cellCount++);
crrCell.setCellValue(cellStr);
}
}
FileOutputStream fos = new FileOutputStream(tempFile);
workbook.write(fos);
System.out.println("Workbook created!!");
workbook.close();
fos.close(); //To close the FileOutputStream object
System.out.println("File Output Stream closed!!");
}
Thread.currentThread().sleep(600000);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
i am trying to get all column records in excel using apache poi. But i am getting only last column data in excel.
Below is my code. In below code i am trying to create new row when it reaches specific number of columns. and in each row it as to put all column data.
public static ByteArrayInputStream export(List<String> records) {
int TOTAL_COLUMN = 8;
ByteArrayInputStream output = null;
XSSFWorkbook workbook = null;
InputStream inputStream = null;
try (ByteArrayOutputStream excelFileStream = new ByteArrayOutputStream();) {
inputStream =
new ClassPathResource(TEMPLATE_PATH).getInputStream();
workbook = new XSSFWorkbook(inputStream);
XSSFSheet sheet = workbook.getSheetAt(DATA_SHEET_INDEX);
XSSFCellStyle evenRowCellStyle = createCellStyle(workbook, EVEN_ROW_CELL_COLOR);
XSSFCellStyle oddRowCellStyle = createCellStyle(workbook, ODD_ROW_CELL_COLOR);
Integer rowIndex = STARTING_ROW;
int numberOfColumn = 0;
XSSFCellStyle cellStyle = oddRowCellStyle;
/**
* Populates row cell details with list data
*/
int totalColumn = TOTAL_COLUMN;
for (String data : records) {
if (numberOfColumn == totalColumn) {
rowIndex++;
numberOfColumn = 0;
}
cellStyle = (rowIndex % 2 == 0) ? evenRowCellStyle : oddRowCellStyle;
CellUtil.createCell(sheet.createRow(rowIndex), numberOfColumn, data, cellStyle);
numberOfColumn++;
}
workbook.write(excelFileStream);
output = new ByteArrayInputStream(excelFileStream.toByteArray());
} catch (Exception e) {
output = null;
log.info("Error occurred while exporting to excel sheet.");
} finally {
if (workbook != null) {
try {
workbook.close();
} catch (IOException e) {
log.error("Error occurred while closing excel.");
}
}
Utils.closeInputStream(inputStream);
}
return output;
}
above code is giving only last column data in each row.
In your code the call sheet.createRow(rowIndex) always creates a new empty row. So all formerly set cell values in that row get lost.
You are using CellUtil already. There is CellUtil.getRow what does the following:
Get a row from the spreadsheet, and create it if it doesn't exist.
This not always creates a new empty row. Instead it tries to get the row at first and only creates a new row if the row does not exists already,
So do using:
CellUtil.createCell(CellUtil.getRow(rowIndex, sheet), numberOfColumn, data, cellStyle);
I am reading excel file using POI library in my java code. So far fine. But now I have one requirement. The excel file contains many records (e.g. 1000 rows). It also has column headers (1st row). Now I am doing excel filtering on it. Say I have one 'year' column and I am filtering all rows for year=2019. I get 15 rows.
Question: I want to process only these 15 rows in my java code. Is there any method in poi library or way to know if the row being read is filtered or (the other way i.e. not filtered).
Thanks.
I already have working code but right now I am looking for how to read only filtered row. Nothing new tried yet other than searching in library and forums.
The below code is inside a method. I am not used to formatting with stackoverflow so kindly ignore any formatting issue.
// For storing data into CSV files
StringBuffer data = new StringBuffer();
try {
SimpleDateFormat dtFormat = new SimpleDateFormat(CommonConstants.YYYY_MM_DD); // "yyyy-MM-dd"
String doubleQuotes = "\"";
FileOutputStream fos = new FileOutputStream(outputFile);
// Get the workbook object for XLSX file
XSSFWorkbook wBook = new XSSFWorkbook(new FileInputStream(inputFile));
wBook.setMissingCellPolicy(Row.RETURN_BLANK_AS_NULL);
// Get first sheet from the workbook
//XSSFSheet sheet = wBook.getSheetAt(0);
XSSFSheet sheet = wBook.getSheet(CommonConstants.METADATA_WORKSHEET);
//Row row;
//Cell cell;
// Iterate through each rows from first sheet
int rows = sheet.getLastRowNum();
int totalRows = 0;
int colTitelNumber = 0;
Row firstRowRecord = sheet.getRow(1);
for (int cn = 0; cn < firstRowRecord.getLastCellNum(); cn++) {
Cell cellObj = firstRowRecord.getCell(cn);
if(cellObj != null) {
String str = cellObj.toString();
if(CommonConstants.COLUMN_TITEL.equalsIgnoreCase(str)) {
colTitelNumber = cn;
break;
}
}
}
// Start with row Number 1. We don't need 0th number row as it is for Humans to read but not required for processing.
for (int rowNumber = 1; rowNumber <= rows; rowNumber++) {
StringBuffer rowData = new StringBuffer();
boolean skipRow = false;
Row rowRecord = sheet.getRow(rowNumber);
if (rowRecord == null) {
LOG.error("Empty/Null record found");
} else {
for (int cn = 0; cn < rowRecord.getLastCellNum(); cn++) {
Cell cellObj = rowRecord.getCell(cn);
if(cellObj == null) {
if(cn == colTitelNumber) {
skipRow = true;
break; // The first column cell value is empty/null. Which means Titel column cell doesn't have value so don't add this row in csv.
}
rowData.append(CommonConstants.CSV_SEPARTOR);
continue;
}
switch (cellObj.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
rowData.append(cellObj.getBooleanCellValue() + CommonConstants.CSV_SEPARTOR);
//LOG.error("Boolean:" + cellObj.getBooleanCellValue());
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cellObj)) {
Date date = cellObj.getDateCellValue();
rowData.append(dtFormat.format(date).toString() + CommonConstants.CSV_SEPARTOR);
//LOG.error("Date:" + cellObj.getDateCellValue());
} else {
rowData.append(cellObj.getNumericCellValue() + CommonConstants.CSV_SEPARTOR);
//LOG.error("Numeric:" + cellObj.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_STRING:
String cellValue = cellObj.getStringCellValue();
// If string contains double quotes then replace it with pair of double quotes.
cellValue = cellValue.replaceAll(doubleQuotes, doubleQuotes + doubleQuotes);
// If string contains comma then surround the string with double quotes.
rowData.append(doubleQuotes + cellValue + doubleQuotes + CommonConstants.CSV_SEPARTOR);
//LOG.error("String:" + cellObj.getStringCellValue());
break;
case Cell.CELL_TYPE_BLANK:
rowData.append("" + CommonConstants.CSV_SEPARTOR);
//LOG.error("Blank:" + cellObj.toString());
break;
default:
rowData.append(cellObj + CommonConstants.CSV_SEPARTOR);
}
}
if(!skipRow) {
rowData.append("\r\n");
data.append(rowData); // Appending one entire row to main data string buffer.
totalRows++;
}
}
}
pTransferObj.put(CommonConstants.TOTAL_ROWS, (totalRows));
fos.write(data.toString().getBytes());
fos.close();
wBook.close();
} catch (Exception ex) {
LOG.error("Exception Caught while generating CSV file", ex);
}
All rows which are not visible in the sheet have a zero height. So if the need is only reading the visible rows, one could check via Row.getZeroHeight.
Example
Sheet:
Code:
import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.*;
class ReadExcelOnlyVisibleRows {
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));
DataFormatter dataFormatter = new DataFormatter();
CreationHelper creationHelper = workbook.getCreationHelper();
FormulaEvaluator formulaEvaluator = creationHelper.createFormulaEvaluator();
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
if (!row.getZeroHeight()) { // if row.getZeroHeight() is true then this row is not visible
for (Cell cell : row) {
String cellContent = dataFormatter.formatCellValue(cell, formulaEvaluator);
System.out.print(cellContent + "\t");
}
System.out.println();
}
}
workbook.close();
}
}
Result:
F1 F2 F3 F4
V2 2 2-Mai FALSE
V4 4 4-Mai FALSE
V2 6 6-Mai FALSE
V4 8 8-Mai FALSE
You have to use auto filter provided in Apache Poi library and also you have set the freezing. I provide below the brief code snippet, you can use accordingly.
XSSFSheet sheet = wBook.getSheet(CommonConstants.METADATA_WORKSHEET);
sheet.setAutoFilter(new CellRangeAddress(0, 0, 0, numColumns));
sheet.createFreezePane(0, 1);
I had to override some hooks and come up with my own approach to incorporate filtering of hidden rows in order to prevent processing of those. Below is code snippet. My approach consists of opening a second copy of the same sheet just so that I can query the current row getting processed to see if it's hidden or not. The answer above touches on this, the below expands on it to show how it can be nicely incorporated into the Spring batch excel framework. One drawback is that you have to open a second copy of the same file, but I couldn't figure out a way (perhaps there's none!) to get my hands on the internal Workbook sheet, among other reasons because org.springframework.batch.item.excel.poi.PoiSheet is package private (Note that below syntax is Groovy!!!):
/**
* Produces a reader that knows how to ingest a file in excel format.
*/
private PoiItemReader<String[]> createExcelReader(String filePath) {
File f = new File(filePath)
PoiItemReader<String[]> reader = new PoiItemReader<>()
reader.setRowMapper(new PassThroughRowMapper())
Resource resource = new DefaultResourceLoader().getResource("file:" + f.canonicalPath)
reader.setResource(resource)
reader.setRowSetFactory(new VisibleRowsOnlyRowSetFactory(resource))
reader.open(new ExecutionContext())
reader
}
...
// The "hooks" I overwrote to inject my logic
static class VisibleRowsOnlyRowSet extends DefaultRowSet {
Workbook workbook
Sheet sheet
VisibleRowsOnlyRowSet(final Sheet sheet, final RowSetMetaData metaData) {
super(sheet, metaData)
}
VisibleRowsOnlyRowSet(final Sheet sheet, final RowSetMetaData metaData, Workbook workbook) {
this(sheet, metaData)
this.workbook = workbook
this.sheet = sheet
}
boolean next() {
boolean moreLeft = super.next()
if (moreLeft) {
Row row = workbook.getSheet(sheet.name).getRow(getCurrentRowIndex())
if (row?.getZeroHeight()) {
log.warn("Row $currentRow is hidden in input excel sheet, will omit it from output.")
currentRow.eachWithIndex { _, int i ->
currentRow[i] = ''
}
}
}
moreLeft
}
}
static class VisibleRowsOnlyRowSetFactory extends DefaultRowSetFactory {
Workbook workbook
VisibleRowsOnlyRowSetFactory(Resource resource) {
this.workbook = WorkbookFactory.create(resource.inputStream)
}
RowSet create(Sheet sheet) {
new VisibleRowsOnlyRowSet(sheet, super.create(sheet).metaData, workbook)
}
}
I am trying to create one read only Excel-sheet using Apache POI 3.10.
private void lockAll(Sheet s, String password) throws Exception{
XSSFSheet sheet = ((XSSFSheet)s);
sheet.protectSheet(password);
sheet.enableLocking();
sheet.lockSelectLockedCells();
sheet.lockSelectUnlockedCells();
}
Now I am calling this method after creating my excel sheet using following.
private String generateExcel(List<Model> DataList) {
Workbook wwbook = null;
File ff = null;
try {
String filePath = // getting this path using ServletContext.
wwbook = new XSSFWorkbook();
Sheet wsheet = wwbook.createSheet("MyReport");
ApachePoiExcelFormat xlsxExcelFormat = new ApachePoiExcelFormat();
CellStyle sheetHeading = xlsxExcelFormat.SheetHeading(wwbook);
//My personal org.apache.poi.ss.usermodel.CellStyle here.
short col = 0, row = 0;
XSSFRow hrow = (XSSFRow) (XSSFRow) wsheet.createRow(row);
XSSFCell cell = hrow.createCell(col);
//My code here to iterate List and add data to cell.
FileOutputStream fileOut = new FileOutputStream(filePath.toString());
wwbook.write(fileOut);
lockAll(wsheet, "password"); //******calling the method to lock my sheet.
fileOut.close();
System.out.println("Excel Created");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return filePath;
}
Now while I am running this code to download the excel file. Then I am getting error on the webpage but not on my eclipse console.
Next I was trying to run the same code after commenting the following line in lockAll method. And then the excel downloading happens as required, but every cells in the sheet are editable.
sheet.protectSheet(password);