Spring BootでEasyExcelを使用したテンプレートによる複数シートのExcelエクスポート

概要

本記事では、Spring Boot環境でEasyExcelライブラリを利用してExcelテンプレートを複数のシートにデータを埋め込み、エクスポートする方法について解説します。

実装コード

Excelデータ埋め込み処理


/**
 * EasyExcelを利用してExcelファイルにデータを書き込みます
 * @param templatePath テンプレートファイルのパス
 * @param sheetDataMap シート名とデータのマップ、キーがシート名、値がデータリスト
 * @return 書き込み後のExcelバイト配列
 */
public byte[] populateExcelData(String templatePath, Map sheetDataMap) {
    try (
        ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
        ByteArrayOutputStream tempStream = new ByteArrayOutputStream();
        InputStream templateStream = getClass().getResourceAsStream(templatePath);
    ) {
        XSSFWorkbook workbook = new XSSFWorkbook(templateStream);
        int sheetIndex = 0;
        
        // テンプレートからシートを複製
        for (String sheetName : sheetDataMap.keySet()) {
            if (sheetIndex > 0) {
                workbook.cloneSheet(0, StringUtil.isNullOrEmpty(sheetName) ? ("Sheet" + sheetIndex) : sheetName);
            } else {
                workbook.setSheetName(0, StringUtil.isNullOrEmpty(sheetName) ? ("Sheet" + sheetIndex) : sheetName);
            }
            sheetIndex++;
        }
        
        // テンプレートを一時的に保存
        workbook.write(tempStream);
        byte[] templateBytes = tempStream.toByteArray();
        
        try (
            InputStream inputStream = new ByteArrayInputStream(templateBytes);
            ExcelWriter excelWriter = EasyExcel.write(resultStream)
                .withTemplate(inputStream)
                .excelType(ExcelTypeEnum.XLSX)
                .build()
        ) {
            sheetIndex = 0;
            for (Map.Entry entry : sheetDataMap.entrySet()) {
                String sheetName = entry.getKey();
                List<Object> dataList = entry.getValue();
                
                // シート名が31文字を超える場合、自動的に切り詰められるため手動でも切り詰める
                WriteSheet writeSheet = EasyExcel.writerSheet(
                    StringUtil.isNullOrEmpty(sheetName) ? ("Sheet" + sheetIndex) : StringUtil.truncate(sheetName, 31)
                ).build();
                
                excelWriter.fill(dataList, writeSheet);
                sheetIndex++;
            }
            excelWriter.finish();
        }
        
        return resultStream.toByteArray();
    } catch (IOException e) {
        throw new RuntimeException("Excel書き込みエラー: " + e.getMessage(), e);
    }
}

注意点:テンプレート内のプレースホルダーにListデータを埋め込む場合は、プレースホルダーの前に【.】を追加する必要があります。これを追加しない場合、単一のKeyValue形式のMapやエンティティクラスのみの埋め込みが可能です。

Excelエクスポート処理


@PostMapping("/exportExcel")
public void exportExcel(HttpServletResponse response) {
    
    String templateFilePath = "/templates/sample_template.xlsx";
    Map sheetData = new HashMap<>();
    sheetData.put("データシート1", new ArrayList<Object>());
    sheetData.put("データシート2", new ArrayList<Object>());
    
    // Excelデータを埋め込み、バイト配列を取得
    byte[] excelBytes = excelService.populateExcelData(templateFilePath, sheetData);

    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
    
    try {
        String encodedFilename = URLEncoder.encode("サンプルレポート", StandardCharsets.UTF_8.name());
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFilename + ".xlsx\"");
        
        try (InputStream inputStream = new ByteArrayInputStream(excelBytes);
             OutputStream outputStream = response.getOutputStream()) {
            StreamUtils.copy(inputStream, outputStream);
        }
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("ファイル名のエンコードに失敗しました", e);
    } catch (IOException e) {
        throw new RuntimeException("ファイルの書き込みに失敗しました", e);
    }
}

タグ: Spring Boot EasyExcel Excel Java Multi-sheet export

5月17日 20:06 投稿