I would like to add password protection to a xlsx file created with poi 3.14.
The documentation claims, that this is possible:
http://poi.apache.org/encryption.html
Using the example I tried it like this:
public static void main(String[] args)
{
try(Workbook wb = new XSSFWorkbook())
{
//<...>
try(ByteArrayOutputStream baos = new ByteArrayOutputStream())
{
wb.write(baos);
byte[] res = baos.toByteArray();
try(ByteArrayInputStream bais = new ByteArrayInputStream(res))
{
try(POIFSFileSystem fileSystem = new POIFSFileSystem(bais);) // Exception happens here
{
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("pass");
OutputStream encryptedDS = enc.getDataStream(fileSystem);
OPCPackage opc = OPCPackage.open(new File("example.xlsx"), PackageAccess.READ_WRITE);
opc.save(encryptedDS);
opc.close();
}
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
Unfortunately, the code in the example is not compatible to XLSX files and as a result I receive the following exception:
The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
Can anybody help please? I am unable to find the correct alternative for XLSX...
Thank you all for you help. Here is my working result:
public static void main(String[] args)
{
try(Workbook wb = new XSSFWorkbook())
{
Sheet sheet = wb.createSheet();
Row r = sheet.createRow(0);
Cell cell = r.createCell(0);
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue("Test");
try(POIFSFileSystem fileSystem = new POIFSFileSystem();)
{
EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("pass");
OutputStream encryptedDS = enc.getDataStream(fileSystem);
wb.write(encryptedDS);
FileOutputStream fos = new FileOutputStream("C:/example.xlsx");
fileSystem.writeFilesystem(fos);
fos.close();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
You've mis-read the documentation on encrypting in OOXML file. You're therefore incorrectly trying to load your file using the wrong code, when you just need to save it
Without any error handling, your code basically wants to be
// Prepare
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile, CipherAlgorithm.aes192, HashAlgorithm.sha384, -1, -1, null);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("foobaa");
// Create the normal workbook
Workbook wb = new XSSFWorkbook();
Sheet s = wb.createSheet();
// TODO Populate
// Encrypt
OutputStream os = enc.getDataStream(fs);
wb.save(os);
opc.close();
// Save
FileOutputStream fos = new FileOutputStream("protected.xlsx");
fs.writeFilesystem(fos);
fos.close();
Related
I need to create a file .csv with apache-poi but this file is empty. For this example I want to create only header about this file so I do:
public byte[]...(File save_file) {
Workbook workbook = null;
Sheet sheet = null;
FileOutputStream outputStream=null;
try {
workbook = new HSSFWorkbook();
sheet = workbook.createSheet();
createHeader(0,sheet);
outputStream = new FileOutputStream(save_file);
workbook.write(outputStream);
} catch (Exception exception) {
log.error("ERROR", exception);
} finally {
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayOutputStream.writeTo(outputStream);
log.info("SOTTO BYTE "+byteArrayOutputStream.toByteArray().length);
return byteArrayOutputStream.toByteArray();
}
and after the method "create_header":
private static void createHeader(int rowPosition,Sheet sheet) {
Row row = sheet.createRow(rowPosition);
Cell cell = row.createCell(1);
cell.setCellValue("DATE");
cell = row.createCell(2);
cell.setCellValue("EMAIL");
}
The problem is the file is empty. In the first method I need to return the byte[] that represents the csv file. Anyone can help me?
I want to read a excel file and if there is any data then I want to set it to null then start writing to it. This is what I have for setting excel sheet data to null. I able to write successfully but before write I want to set the value null.
FileOutputStream out = null;
try{
FileInputStream file = new FileInputStream(new File("/test.xls"));
HSSFWorkbook oldFile = new HSSFWorkbook(file);
HSSFSheet sheet = oldFile.getSheetAt(0);
file.close();
oldFile.write(null);
outFile.close();
} catch(Exception e){
e.printStackTrace();
}
One easy solution is to delete and create a sheet:
File destFile = new File("/test.xls");
FileInputStream fileStream = new FileInputStream(destFile);
POIFSFileSystem fsPoi = new POIFSFileSystem(fileStream);
HSSFWorkbook workbook = new HSSFWorkbook(fsPoi);
int index = 0;
HSSFSheet sheet = workbook.getSheet("Setup");
if(sheet != null) {
index = workbook.getSheetIndex(sheet);
workbook.removeSheetAt(index);
}
workbook.createSheet("Setup");
FileOutputStream output = new FileOutputStream(destFile);
workbook.write(output);
output.close();
I don't know why the file I write using POI cant be opened by Ms Excel 2013, but the file is still readable by POI. (cell value can be changed)
this is the error from file
here is the code
FileInputStream fis = null;
try {
fis = new FileInputStream(fileUri); //not error at fileUri
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String urii = fileUri.replace(".xls", "0.xls"); //not error
File fisx = new File(urii);
Workbook workbook = null;
workbook = new HSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
String p = cell.getStringCellValue();
TextView a = (TextView) findViewById(R.id.txtUri);
cell.setCellValue(new String("popo"));
String x = cell.getStringCellValue();
TextView b = (TextView) findViewById(R.id.txtFile);
a.setText(p);
b.setText(x);
OutputStream fos = null;
fos = new FileOutputStream(fisx);
workbook.write(fos); //main problem
fos.flush();
fos.close();
Thanks for your help!!
There are two issues with your code. Firstly this:
FileInputStream fis = null;
try {
fis = new FileInputStream(fileUri);
As explained in the Apache POI Docs, don't use an InputStream if you have a File!
Secondly, this:
Workbook workbook = null;
workbook = new HSSFWorkbook(fis);
That will only work for .xls files, not for .xlsx ones. Instead, you need to use WorkbookFactory which identifies the type and gives you the right workbook for the format
So, change your code to be
File file = new File(fileUri);
Workbook workbook = WorkbookFactory.create(file);
The major problem that i see here is:
Workbook workbook = null;
workbook = new HSSFWorkbook(fis);
Instead you have to use:
Workbook workbook = null;
workbook = new XSSFWorkbook(fis);
TO be readable by MS EXCEL 2013.
Solved :
by using real android device instead of bluestack emulator,
I dont know why, but it works!!
Thanks everyone :D
You are calling getSheetAt(0) but you did not create any sheet before (workbook.createSheet(“name”)
The solution is to use the .xls extension and NOT .xlsx, as outlined in this answer
I have a web application In which i have excel file(.xls) download option. Now I Have to provide that feature in .xlsx
I am trying to Use POI Jar. When I try to do that as a stand alone Application it works fine, but when I try to integrate that into a web application, I am getting an error as
Excel Found Unreadable Content in FILENAME.xlsx. do you want to recover the content of this workbook?
If you trust the source of this workbook click yes!
XSSFWorkbook w = FileName.createExcelWorkbookPosition(
request.getParameter("BSNS_DT"));
response.setContentType(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition","attachment;filename=filename.xlsx");
w.write(response.getOutputStream());
Here's the Java code where I create the spreadsheet:
public static XSSFWorkbook createExcelWorkbookPosition(String BsnsDate)
throws Exception
{
FileOutputStream out = new FileOutputStream("workbook.xlsx");
// create a new workbook
XSSFWorkbook wb = new XSSFWorkbook();
// create a new sheet
XSSFSheet s = wb.createSheet();
// declare a row object reference
XSSFRow r = null;
// declare a cell object reference
XSSFCell c = null;
// header row and columns
r = s.createRow(0);
c = r.createCell(0);
c.setCellValue("Business Date");
//c.setCellStyle(cs);
c = r.createCell(1);
c.setCellValue("Account No");
try {
wb.write(out);
out.close();
System.out.println("File writed");
} catch (Exception e) {
System.out.println("Error");
System.out.println(e);
}
return wb;
}
Can anyone please help? Sorry for any bad English! Thanks.
I had a quite similar issue, please have a look at Forcing the browser to download a docx file in JAVA generates a corrupted document. The point was to add the Content-Length header of the response.
Try to make createExcelWorkbookPosition returning the file instead of the XSSFWorkbook:
public static File createExcelWorkbookPosition(String BsnsDate) throws Exception {
File file = new File("workbook.xlsx");
FileOutputStream out = new FileOutputStream(file);
// ...
return file;
}
Then:
File file = FileName.createExcelWorkbookPosition(request.getParameter("BSNS_DT"));
// ...
response.setContentLength((int) file.length());
InputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
// if using Apache IO, the above code can be simplified to IOUtils.copy(in, out);
// if using Guava, Files.copy(file, out);
// don't forget to close your streams and flush the response buffer
I have to delete a sheet from the Excel file.
Here's my code snippet :
FileInputStream fileStream = new FileInputStream(destFile);
POIFSFileSystem fsPoi = new POIFSFileSystem(fileStream);
HSSFWorkbook workbook = new HSSFWorkbook(fsPoi);
int index = 0;
HSSFSheet sheet = workbook.getSheet("Setup");
if(sheet != null) {
index = workbook.getSheetIndex(sheet);
workbook.removeSheetAt(index);
}
return destFile;
After this I'm getting exactly the same workbook which I passed, without the removal of the sheet "Setup"
Help me resolve this. Any help would be appreciated
After editing your workbook, you need to write it again. Try this:-
FileOutputStream output = new FileOutputStream(destFile);
workbook.write(output);
output.close();
Edit:- After writing it back, you can return your destFile.
private void removeOtherSheets(String sheetName, XSSFWorkbook book) {
for(int i=book.getNumberOfSheets()-1;i>=0;i--){
XSSFSheet tmpSheet =book.getSheetAt(i);
if(!tmpSheet.getSheetName().equals(sheetName)){
book.removeSheetAt(i);
}
}
}
Delete a sheet using Apache POI
//Open file
FileInputStream inputStream = new FileInputStream(new File(filePath));
XSSFWorkbook workBook = new XSSFWorkbook(inputStream);
//Delete Sheet
workBook.removeSheetAt(resultWorkbook.getSheetIndex("SheetToBeDeleted"));
//Save the file
FileOutputStream outFile =new FileOutputStream(new File(filePath));
workBook.write(filePath);
outFile.close();