GASで作成したファイルをダウンロードする

## Agenda

* はじめに

* やりたいこと

* どう実現するか

* 実装

* できた

* さいごに

## はじめに

今年7月入社のO84です
最近[Turing Complete](https://store.steampowered.com/app/1444480/Turing_Complete/?l=japanese)ってゲームにドハマりしてます

## やりたいこと

1. GASで生成した文字列をテキストファイルに変換
2. Google Driveを経由せずに上記ファイルをダウンロード

## どう実現するか

Blob型[^1]に変換すればファイルとしてダウンロードできるっぽい

JavaScript(ECMA)で定義されているBlobはGASに実装されてない[^2]らしいので、
サーバ側でBlobに変換するとクライアントに渡すのがめんどくさそう[^3]

サーバからはファイル名と中身を文字列で渡し、クライアント側でファイルに変換する方法でやってみる

## 実装

### サーバ側

```js:main.js
// スプレッドシートから開きたい
function onOpen() {
  const ui = SpreadsheetApp.getUi();
  const menu = ui.createMenu('自作ツール');
  menu.addItem('Download', 'showDialog');
  menu.addToUi();
}

function showDialog() {
  const html = HtmlService.createTemplateFromFile('download')
    .evaluate()
    .setWidth(400)
    .setHeight(300);
  SpreadsheetApp.getUi().showModalDialog(html, 'Download');
}

// こいつをクライアントから実行させる
function getFile() {
  return file = {
    filename: "任意のファイル名.txt",
    text: "任意の\n文字列",
  };
}
```

### クライアント側

```html:download.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <div id="downloadLinks"></div>
    <script type='text/javascript'>
      window.addEventListener('load', function() {
        const element = document.getElementById('downloadLinks');
        // ここでサーバ側のgetFile関数を実行
        google.script.run
          .withSuccessHandler(function(file) {
            // 文字列をBlob型にする
            const blob = new Blob([file.text], {type: 'text/plain'});
            
            // ダウンロードリンクを作成
            const link = document.createElement('a');
            link.download = file.filename;
            link.text = file.filename;
            link.href = window.URL.createObjectURL(blob);
            
            // リンクを子要素として追加
            element.appendChild(link);
            element.appendChild(document.createElement('br'));
          })
          .withFailureHandler()
          .getFile();
      });
    </script>
  </body>
</html>
```

## できた

![dekita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3527495/44bc326c-116b-d1ca-668e-841c7a5e8580.png)

## さいごに

**一緒に働く仲間を募集中です！**

リンクラフト株式会社では、組織拡大に伴い積極的な採用活動を行っています。
少しでも興味がある方はぜひご連絡ください。

▽会社ホームページ
https://lincraft.co.jp/

▽SNS
[X (旧Twitter)](https://twitter.com/lincraft_inc)
[Instagram](https://www.instagram.com/lincraft.inc/)
[Facebook](https://www.facebook.com/lincraft.inc/)

▽ご応募はこちらより
https://lincraft.co.jp/recruit

※カジュアル面談も受付中です。ご希望の方はHPのお問い合わせフォームよりご連絡ください。

[^1]: [Mozilla](https://developer.mozilla.org/ja/docs/Web/API/Blob)
[^2]: [GAS の Blob とファイル変換まとめ](https://qiita.com/a_eau_/items/01bc14bfc5cb5ef12e64#%E6%B3%A8%E6%84%8F:~:text=JavaScript%20(ECMA)%20%E3%81%AB%E5%AE%9A%E7%BE%A9%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%20Blob%20%E3%81%A8%E3%81%AF%E4%BC%BC%E3%81%A6%E9%9D%9E%E3%81%AA%E3%82%8B%E3%82%82%E3%81%AE%E3%81%A7%E3%81%99%E3%80%82%E3%81%93%E3%81%A1%E3%82%89%E3%81%AE%20Blob%20%E3%81%AF%20GAS%20%E3%81%A7%E3%81%AF%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%89%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82)
[^3]: [Google Workspace](https://developers.google.com/apps-script/guides/html/communication?hl=ja#parameters_and_return_values:~:text=form%20%E3%81%AE%E3%81%BB%E3%81%8B%E3%81%AB%E3%80%81Date%E3%80%81Function%E3%80%81DOM%20%E8%A6%81%E7%B4%A0%E3%80%81%E3%81%BE%E3%81%9F%E3%81%AF%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE%E7%A6%81%E6%AD%A2%E3%81%95%E3%82%8C%E3%81%9F%E3%82%BF%E3%82%A4%E3%83%97%EF%BC%88%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%BE%E3%81%9F%E3%81%AF%E9%85%8D%E5%88%97%E5%86%85%E3%81%AE%E7%A6%81%E6%AD%A2%E3%82%BF%E3%82%A4%E3%83%97%E3%82%92%E5%90%AB%E3%82%80%EF%BC%89%E3%82%92%E6%B8%A1%E3%81%9D%E3%81%86%E3%81%A8%E3%81%99%E3%82%8B%E3%81%A8%E3%80%81%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AF%E5%A4%B1%E6%95%97%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)