使用 Apache POI 更新和加密现有的 xlsx 文件



我有现有的xlsx电子表格。我正在使用Apache POI 3.17来阅读它,添加一些条目并将受密码保护的电子表格保存在新文件中。 运行程序后,新文件受密码保护,但我看不到新条目,只有以前存在的条目。这是该程序的简化版本,它打开空电子表格,写入新单元格并使用密码保存在新文件中。当我使用密码在Excel 2010中打开文件时,我仍然看到空的电子表格。 任何帮助将不胜感激。谢谢

public static void main(String[] args) {
try {
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("passw");

File is = new File("./empty.xlsx");
OPCPackage opc = OPCPackage.open(is, PackageAccess.READ_WRITE);
Workbook wb = WorkbookFactory.create(opc);
Sheet sheet  = wb.getSheetAt(0);
Row row = sheet.createRow(1);
Cell cell = row.createCell(1);
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue("CRYPT");
OutputStream encos = enc.getDataStream(fs);
opc.save(encos);
opc.close();
OutputStream fos = new FileOutputStream(new File("./f.xlsx"));
fs.writeFilesystem(fos);
fos.close();
}
catch (Exception ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
}

这里的问题是在XSSFWorkbook和它之间的OPCPackage之间提交更改的差异。XSSFWorkbook中的更改将仅在XSSFWorkbook.write时提交到OPCPackage。因此,如果您不(或不能(写出XSSFWorkbook,则OPCPackage保持不变。

另一方面,如果写出XSSFWorkbook,它始终会向创建工作簿的OPCPackage提交更改。因此,如果这是从File创建的OPCPackage,则始终会在工作簿可能写入另一个文件之前更新此文件。这也很烦人。

所以在我看来,它缺乏以编程方式影响XSSFWorkbook和它之间的提交过程的可能性OPCPackage.

但是你的代码的主要问题是你正在将没有更新的OPCPackage写入Encryptor的数据流。相反,您应该编写已更新的Workbook

所以例如:

import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.crypt.*;
import org.apache.poi.ss.usermodel.*;
import java.io.*;
class ExcelUpdateAndEncrypt {
public static void main(String[] args) throws Exception {
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("passw");
FileInputStream is = new FileInputStream("./empty.xlsx");
Workbook wb = WorkbookFactory.create(is);
Sheet sheet  = wb.getSheetAt(0);
Row row = sheet.createRow(1);
Cell cell = row.createCell(1);
cell.setCellValue("CRYPT");
OutputStream encos = enc.getDataStream(fs);
wb.write(encos); 
encos.close();
wb.close();
OutputStream os = new FileOutputStream(new File("./f.xlsx"));
fs.writeFilesystem(os);
os.close();
}
}

最新更新