概要
本記事では、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);
}
}