Excel 使用Apache POI更新和加密现有xlsx文件
我有现有的xlsx电子表格。我正在使用ApachePOI3.17阅读它,添加一些条目,并将其另存为新文件中受密码保护的电子表格。 运行程序后,新文件受密码保护,但我看不到新条目,只看到以前存在的条目。这里是程序的简化版本,它打开空的电子表格,写入新的单元格,并用密码保存在新文件中。当我使用密码在Excel 2010中打开文件时,仍然会看到空的电子表格。 任何帮助都将不胜感激。谢谢Excel 使用Apache POI更新和加密现有xlsx文件,excel,apache-poi,Excel,Apache Poi,我有现有的xlsx电子表格。我正在使用ApachePOI3.17阅读它,添加一些条目,并将其另存为新文件中受密码保护的电子表格。 运行程序后,新文件受密码保护,但我看不到新条目,只看到以前存在的条目。这里是程序的简化版本,它打开空的电子表格,写入新的单元格,并用密码保存在新文件中。当我使用密码在Excel 2010中打开文件时,仍然会看到空的电子表格。 任何帮助都将不胜感激。谢谢 public static void main(String[] args) { try { POIF
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
在提交更改时存在差异。xssf工作簿
中的更改将仅在XSSFWorkbook.write
时提交到OPCPackage
。因此,如果您没有(或无法)写出XSSFWorkbook
,则OPCPackage
将保持不变
另一方面,如果您写出XSSFWorkbook
,它总是提交对创建工作簿的OPCPackage
的更改。因此,如果这是从文件创建的OPCPackage
,则在工作簿可能写入另一个文件之前,始终会更新此文件。这也很烦人
因此,在我看来,它不可能以编程方式影响XSSFWorkbook
和它的OPCPackage
之间的提交过程
但是代码的主要问题是,您正在将未更新的OPCPackage
写入加密机的数据流。相反,您应该编写已更新的工作簿
例如:
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);
wb.close();
OutputStream os = new FileOutputStream(new File("./f.xlsx"));
fs.writeFilesystem(os);
os.close();
}
}
答案在@kiwiwings中:当关闭encos
:线程“main”org.apache.poi.EncryptedDocumentException:java.io.FileNotFoundException:/tmp/poifiles/encrypted_Package1071788535456764crypt(…)时,您的代码使用ApachePOI
版本失败在org.apache.poi.poifs.crypt.standard.StandardEncryptor$StandardCipherOutputStream.ProcessPoifsWriteEvent(StandardEncryptor.java:201)。。。在org.apache.poi.poifs.crypt.standard.StandardEncryptor$StandardCipherOutputStream.close(StandardEncryptor.java:169)
@AxelRichter:你说得对,我刚刚在主干上测试了代码,并且因为以下原因更改了关闭habbit。我需要在发行说明中更清楚地说明。@kiwiwings:好的。由于您正在工作簿wb=WorkbookFactory.create(新文件(“empty.xlsx”))中使用文件
,则empty.xlsx
也会更新,而wb.write
会更新OPCPackage
。因此在此之后,empty.xlsx
也包含B2
中的新值,并且不再是“空的”;-)。正如我在回答中所说,它不可能以编程方式影响XSSFWorkbook
和它的OPCPackage
之间的提交过程。我已经通过。。。我将通过