Pleasanterのスクリプトでexcelを出力したい

## 概要
- Pleasanterを使い慣れてくると帳票出力がしたくなりますよね?
- データを整理して帳票として印刷したいという要望は多いと思います
- Webスクリプトでexcel帳票を出力してみたいと思います

## 準備

- Webスクリプト作成用のツールが必用となります
- 以下の資料を参考にして、TypeScriptでWebスクリプトをビルドできる環境を整えてください
- [PleasanterのスクリプトをTypeScriptで書きたい](https://qiita.com/yamada28go/items/1dde681e915edacebea1)
- [PleasanterのAPIの呼び出しコードを生成するツールを作った(Glue code生成プログラムを作ってみた)](https://qiita.com/yamada28go/items/b5e80ab39e59ce31d1c6)
- [Pleasanterのスクリプトをアップロードするコマンドを作った](https://qiita.com/yamada28go/items/a7d7e6d0bd644ef88f97)

## 成果物

成果物は以下に入れてあります。

[Pleasanter-Web-Excel-Sample](https://github.com/yamada28go/Pleasanter-Web-Excel-Sample)

## サンプルサイト構成

テーブルの構成は以下となります。

![スクリーンショット 2024-03-20 20.06.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63200/4fc37919-c853-70d4-6fb3-1558862b7711.png)

| テーブル名               | 説明                           |
|------------------|------------------------------|
| データレコード       | 帳票を出力する画面                 |
| テンプレートファイル   | 帳票用のテンプレートファイルを登録    |

---

### テンプレートファイル

帳票出力のひな形となるテンプレートファイルを登録します。
スクリプトはここからテンプレートファイルを取得して、必要な情報を埋め込み出力します。

![スクリーンショット 2024-03-20 20.07.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63200/c0341a4b-9885-af89-b68e-2587f911353a.png)

テンプレートファイル(Excel)の例です。
今回のサンプルでは「置換対象データ」というレコードをプリザンターの内部データで置換します。

![スクリーンショット 2024-03-20 20.15.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63200/78a416d6-cfe6-9c9a-2f96-2e28831a97f6.png)


### データレコード

こちらは帳票に埋め込むデータを登録するレコードとなります。
画面右下にある「帳票出力」というボタンを押下するとスクリプトが呼び出されて帳票が出力されます。

![スクリーンショット 2024-03-20 20.06.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63200/3312d05d-c956-85be-1b4b-81c1af1b4725.png)

今回のサンプルでは、各レコードの中の「置換用データ」という列を集計してExcelに埋め込みます。

![スクリーンショット 2024-03-20 20.30.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63200/e9fa3554-af0c-5abc-0d8a-f497da7caca3.png)


----
## 作り方

### グルーコードを生成

WebスクリプトからPleasanterのデータにアクセスする必要があります。以下の資料を参考にして、サイトのエクスポート情報からグループコードで生成してください。

[PleasanterのAPIの呼び出しコードを生成するツールを作った(Glue code生成プログラムを作ってみた)](https://qiita.com/yamada28go/items/b5e80ab39e59ce31d1c6)

今回のサンプルで使用したテーブル構成は以下サイトに存在します。

[git/data](https://github.com/yamada28go/Pleasanter-Web-Excel-Sample/tree/main/data)

### 出力ボタン追加

ここは単純にDOMを操作しているだけなので、
サンプルコードを参照してください。

[view.ts](https://github.com/yamada28go/Pleasanter-Web-Excel-Sample/blob/main/src/src/view.ts)

### 帳票テンプレートファイル

出力される帳票のテンプレートファイルを取得します。
生成されたグルーコードに含まれる、データアクセス用のサービスを使ってテーブルからテンプレートファイルを取得します。
テンプレートファイルのIDは直接指定します。

```TypeScript
// 添付ファイルからテンプレートファイルを読み込む
async function getTemplateFile(templateFileId: number) {
  // サービスを構築
  const s = new テンプレートファイルService();
  // pleasanterに登録されたテンプレートファイルを取得する(アイテムのIDは直接的に指定する)
  const data = await s.apiGet(templateFileId);

  // テンプレートファイルを取得
  const templateInfo = data.テンプレートファイル;
  if (templateInfo) {
    // テンプレートファイルの実態を取得する
    const templateFile = await apiGetAttachmentsDataAsync(templateInfo[0]);
    return templateFile;
  }

  throw new Error("テンプレートファイルが読み取れません");
}
```

### excelファイルの加工

excelファイルの加工には[exceljs](https://github.com/exceljs/exceljs)を使用します。
読み込んだテンプレートファイルを加工するコードは以下となります。
getTargetData()はプリザンターから適当にデータを取ってくる処理です。

```TypeScript
// エクセルデータを作成する
export async function makeExcelMain() {
  // Excelテンプレートファイルを読み込む
  const templateFile = await getTemplateFile(TemplateFileID);

  // ワークシートを読み込む
  const workbook = await new Workbook().xlsx.load(templateFile);

  // 指定されたシートを取得
  const worksheet = workbook.getWorksheet("Sheet1");
  if (worksheet) {
    //pleasanterから置換対象データを読み取る
    var dataStr = await getTargetData();

    // テンプレート内部の指定文字列を置換していく
    replaceTextInSheet(worksheet, "置換対象データ", dataStr);

    // 加工後のファイルをBlobとして保存し、ダウンロードさせる
    await createAndDownloadExcelFile(
      workbook,
      `outFile_${formatDateTime()}.xlsx`
    );

    return;
  }

  throw new Error("帳票作成処理に失敗しました。");
}

```

ポイントとなるのは、置換されたexcelファイルの取り扱い方法です。
以下のような関数を用意します。
これは、編集後のファイルをblobに変更し、リンクを生成する事で、ユーザーがダウンロードできるようにします。

```TypeScript
// Workbookをダウンロードさせる
export async function createAndDownloadExcelFile(
  workbook: Workbook,
  filename: string
) {
  const writeBuffer = await workbook.xlsx.writeBuffer();
  const blob = new Blob([writeBuffer], {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  });
  const link = document.createElement("a");
  link.href = window.URL.createObjectURL(blob);
  link.download = filename;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

```



## 感謝

本資料の作成に関して、以下記事を参考にさせていただきました。
ありがとうございました。

[PleasanterExcelMaker：PleasanterでExcel表を作成するJSライブラリ](https://qiita.com/Satoru_Sugamura/items/1dc8f0cdf74d5f300692)