薄給SEの技術屋日記

何でもポジティブに | 3人家族+チワワと暮らすSE | 20代は休む間も無く仕事と飲み会 | 30代から株主優待に目覚め今では節約しながら配当金投資 | 目標は配当金投資で住宅費月7万を補うこと | 大宮アルディージャサポ | 度重なる過労で体調不良となり家族と自分の身体を優先する生活 | 最近米国株の購入を開始

【開発】JavaでExcelのパスワード設定

LOLIPOP

はじめに

JavaExcelパスワード対応について色々なサイトを見ながら試してみましたが、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>

Javaソースコード(java11)

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();
            }
        }
    }