はじめに
JavaのExcelパスワード対応について色々なサイトを見ながら試してみましたが、POIやJavaのバージョン違いやExcelがxlsだと正常に動作する等古い情報が多く悩んでいましたがなんとか解決しました。コピペでうまく動かないのは記事が古かったりするからバージョン差異が生まれちゃうんですね。。
ソースコードサンプル
実装確認ソースは以下の通りです。
POM.xml
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency>
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.poifs.crypt.Decryptor; import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.crypt.Encryptor; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; public class ExcelPasswordTest { /** * Excel出力 */ public static void main(String args[]) { FileInputStream fi = null; POIFSFileSystem fileSystem = null; InputStream is = null; Workbook wb = null; try { // パスワード String password = "password"; String baseFile = "C:\\data\\tmp\\input\\input.xlsx"; String outFile = "C:\\data\\tmp\\output\\output.xlsx"; fi = new FileInputStream(baseFile); fileSystem = new POIFSFileSystem(fi); EncryptionInfo info = new EncryptionInfo(fileSystem); Decryptor d = Decryptor.getInstance(info); // inputファイルがパスワードで開けるか検証 if (d.verifyPassword(password) == false) { // inputが開けない場合、エラー throw new Exception("input開けない"); } is = d.getDataStream(fileSystem); wb = WorkbookFactory.create(is); Sheet sheet = wb.getSheet("sheet1"); sheet.getRow(0).getCell(0).setCellValue("test"); // 新規ファイルとして保存(この時点ではパスワード無し) FileOutputStream out = new FileOutputStream(outFile); wb.write(out); is.close(); wb.close(); POIFSFileSystem fs = new POIFSFileSystem(); Encryptor encryptor = info.getEncryptor(); encryptor.confirmPassword(password); OutputStream os = encryptor.getDataStream(fs); OPCPackage opcPackage = OPCPackage.open(new File(outFile), PackageAccess.READ_WRITE); opcPackage.save(os); opcPackage.close(); os.close(); // パスワード付き保存 FileOutputStream fos = new FileOutputStream(outFile); fs.writeFilesystem(fos); fs.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (wb != null) { wb.close(); } if (is != null) { is.close(); } if (fi != null) { fi.close(); } } catch (IOException e) { e.printStackTrace(); } } }