Spring Boot + Excel Upload + CSV出力

#PostmanでエクセルをPOSTし、Spring側でCSV出力

末尾の参考サイトのソースをもとに、PostmanでExcelをPOSTし、受信側(spring boot)でCSVライブラリの「OrangeSignal CSV」を利用してCSV出力した。
CSVのヘッダに日本語の列名を指定するところで物凄くつまったので、サンプルソースを記載する。

```java
@Service
public class ExcelService {
  @Autowired TutorialRepository repository;
  public void save(MultipartFile file) {
    try {
      List<Tutorial> tutorials = ExcelHelper.excelToTutorials(file.getInputStream());
      repository.saveAll(tutorials);
      // 区切り文字と囲み文字、エスケープ文字を指定して CSV 形式設定情報を構築
      CsvConfig cfg = new CsvConfig(',', '"', '"');
      List<TutorialCSVData> tutorialCSVList =
          tutorials.stream().map(TutorialCSVData::toCSVDataFromPOJO).collect(Collectors.toList());
      File fileout = new File("Tutorial.csv");
      Csv.save(
          tutorialCSVList,
          fileout,
          cfg,
          new CsvEntityListHandler<TutorialCSVData>(TutorialCSVData.class));
    } catch (Exception e) {
      throw new RuntimeException("fail to store excel data: " + e.getMessage());
    }
  }
  public ByteArrayInputStream load() {
    List<Tutorial> tutorials = repository.findAll();

    ByteArrayInputStream in = ExcelHelper.tutorialsToExcel(tutorials);
    return in;
  }
  public List<Tutorial> getAllTutorials() {
    return repository.findAll();
  }
}
```


「OrangeSignal CSV」では、CSV出力にPOJOクラスが利用できる。
POJOクラスでは、<span>@</span>CsvEntity アノテーションと <span>@</span>CsvColumn アノテーションをつける。
<span>@</span>CsvColumn(name = "番号")とすると、CSVのヘッダ列の名前に"番号"を指定できる。
この指定をしない場合、CSVのヘッダ列の名前は、POJOクラスのフィールド名(この例では"id"）となる。

参考元ソースには、データベースに格納する「Tutorial」Entityがあるが、
CSVに日本語項目を出力したかったので、別途「TutorialCSVData 」を作成し、TutorialからTutorialCSVDataに変換している。

OrangeSignal CSVサイトのユーザーガイドにある「ColumnNameMappingBeanListHandler」を使って、
項目列とPOJOオブジェクトフィールド（の変数名）を対応付けていたが、CSVの列が１００以上の場合はしんどい。
１００項目の定義をしたくないので、なんとかならないか調べたところ、<span>@</span>CsvEntityを使っている場合は、
「CsvEntityListHandler」を使えばよいということがわかった。
ここはユーザーガイドにも説明があるので、私の理解力がなかったようです。（ちょっと試してうまくいかなかったのであきらめてた）
将来、同じように困る人用にサンプルを載せておきます。

ちなみに公式のユーザーガイドにあるColumnNameMappingBeanListHandler#addColumnメソッドは誤記で、正しくはcolumnメソッドでした。詳細はJavadoc参照。



```java
package com.bezkoder.spring.files.excel.model;

import com.orangesignal.csv.annotation.CsvColumn;
import com.orangesignal.csv.annotation.CsvEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@CsvEntity
public class TutorialCSVData {
  @CsvColumn(name = "番号")
  public String id;

  @CsvColumn(name = "タイトル")
  public String title;

  @CsvColumn(name = "詳細")
  public String description;

  @CsvColumn(name = "補足")
  public String published;

  public static TutorialCSVData toCSVDataFromPOJO(Tutorial tutorial) {
    return new TutorialCSVData(
        Long.toString(tutorial.getId()),
        tutorial.getTitle(),
        tutorial.getDescription(),
        String.valueOf(tutorial.isPublished()));
  }
}

```
CsvConfigクラスで””で囲ったり、改行コード(WIN, Mac, Linux）を指定できる。

#CSV出力結果

```Tutorial.csv
"番号","タイトル","詳細","補足"
"1","Spring Boot Tut#1","Tut#1 Description","false"
"2","Spring Boot Tut#2","Tut#2 Description","true"
"3","MySQL Database Tut#3","Tut#3 Description","true"
"4","Hibernate Tut#4","Tut#4 Description","false"
"5","Spring Cloud Tut#5","Tut#5 Description","true"
"6","Microservice Tut#6","Tut#6 Description","false"
"7","MongoDB Database Tut#7","Tut#7 Description","true"
"8","Spring Data JPA Tut#8","Tut#8 Description","true"
```

#補足情報
「OrangeSignal CSV」利用のためのpom.xmlの設定です。


```xml:pom.xml
<dependency>
  <groupId>com.orangesignal</groupId>
  <artifactId>orangesignal-csv</artifactId>
  <version>2.2.1</version>
</dependency>
```

:::note info
公式のクイックスタートではバージョンが「2.2.2-SNAPSHOT」となってますが、
Intellij環境ではmavenのエラーになり、読み込まれませんでした。
:::



参考：
Spring Boot: Upload/Import Excel file data into MySQL Database
https://www.bezkoder.com/spring-boot-upload-excel-file-database/

ソースを動かす場合、エクセルのシート名は
ExcelHelperクラスのSHEETで「Tutorials」に定義されているので注意。（POSTするエクセルのシート名に変更）

OrangeSignal CSV
http://orangesignal.github.io/orangesignal-csv/index.html
https://github.com/orangesignal/orangesignal-csv/issues/29


おわり。