Google Apps Scriptで、S3のCSVをGoogleスプレッドシートに書き出す

# はじめに
Google Apps Script(GAS)を用いて、GoogleスプレッドシートからS3のCSVを取得する必要があったため、色々調べていました。
古いライブラリの情報等がヒットするなどで情報収集が大変でしたので、自分が調べた時点での方法を記事にしました。

# <font color="red">追記(2023.04.25)</font>
S3のファイルをGoogleDriveにダウンロードする方法も記事にしました。そちらも併せてご確認ください。

https://qiita.com/a_b_/items/6284d07cfb7185d7ccd5

# 参考

https://zenn.dev/tentel/articles/9fddc0c78ee8c9

https://tonari-it.com/gas-dialog-csv-parse-spreadsheet/

# やったこと

## AWS

### バケット、ユーザー作成
S3のバケットと接続用のユーザを、以下のCFnで作成します。
```yaml:createBucketAndUser.yaml
AWSTemplateFormatVersion: 2010-09-09

Resources:
  InputfileBucket:
    Type: AWS::S3::Bucket

  UserForGas:
    Type: AWS::IAM::User
    Properties:
      Policies:
       -  PolicyName: S3Access
          PolicyDocument:
            Version: 2012-10-17
            Statement:
             -  Effect: Allow
                Action: 
                 - s3:GetObject
                Resource:
                 - !Sub arn:aws:s3:::${InputfileBucket}/*
```
### アクセスキー作成
GASから接続する際に使用するため、ユーザのアクセスキーを作成し控えておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/447de7c9-472d-818b-6abd-a6a22d7c732e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/04f334e9-87f6-56c1-710c-1a213e49a87b.png)


以下のページでは、「Secret Access Keyにスラッシュがあるとエラーになる」とありますが、本記事の方法ではSecret Access Keyにスラッシュが入っていても問題ありませんでした。

https://qiita.com/aiko_han/items/3878ddcdc0d2f069ad36

:::note warn
最後の方に記載しますが、「ファイルパスに日本語が入っている場合」も同様のエラーが発生するので、このエラーが発生した場合はまずそちらを確認してください。
:::
### CSVデータ格納
テスト用に、以下のファイルをS3にアップします。
```:mobile-suit.csv
No,MOBILE SUIT,PILOT,AFFILIATION,型式番号,頭頂高,重量,DATA
1,ガンダム・エアリアル,スレッタ・マーキュリー,シン・セー開発公社,XVX-016,18.0m,43.9t,スレッタ・マーキュリーが学園に持ち込んだモビルスーツ。次世代群体遠隔操作兵器システム、ガンビットで構成されたシールドを装備している。
2,ディランザ グエル専用機,グエル・ジェターク,ジェターク寮,MD-0032G,18.2m,89.4t,ディランザをグエル向けにチューニングした仕様機。性能強化に留まらず、マゼンタの機体色や、華美な装飾なども施されている。
3,ガンダム・ファラクト,エラン・ケレス,ペイル寮,FP/A-77,19.1m,57.1t,ペイル社が開発したGUND-ARM。ブラストブースターの採用や、GUNDフォーマットによる慣性制御の高次化により、飛行性能が大幅に向上している。
4,ミカエリス,シャディク・ゼネリ,グラスレー寮,-,-,-,-
5,デミトレーナー チュチュ専用機,チュアチュリー・パンランチ,地球寮,MSJ-105CC,17.4m,63.5t,チュチュが搭乗する地球寮所属の機体。旧世代型のデミトレーナーをニカがカスタムした。
6,ディランザ,-,ジェターク寮,MD-0031,18.2m,85.3t,パワーに優れたジェターク社の汎用モビルスーツ。 積極的に要素を付加させる設計方針で、重量級のスタイルを得ている。
7,ザウォート,-,ペイル寮,-,-,-,ペイル社が開発したモビルスーツ。大型推進ユニットを装備し、 単独での飛行能力を有している。
8,ハインドリー,-,グラスレー寮,CFP-010,18.4m,52.0t,グラスレー社の量産モビルスーツ。ハンドガンとランスが組み込まれたランタンシールドを装備。
9,デミトレーナー,-,-,MSJ-121,16.2m,59.3t,ブリオン社製の学園内訓練用モビルスーツ。アスティカシア高等専門学園のあらゆるカリキュラムで運用されている。
10,デミギャリソン,-,-,-,-,-,デミシリーズの戦闘特化仕様。フロント管理社では警備モビルスーツとして正式運用されている。
11,ダリルバルデ,グエル・ジェターク,ジェターク寮,MD-0064,18.7m,72.8t,ジェターク社による第5世代実証機。意思拡張AIによって自律行動を行う新型ドローン兵器を装備している。
12,ディランザ・ソル,-,ジェターク・ヘビー・マシーナリー,-,-,-,ジェターク社の実戦用モビルスーツ。自動追尾タイプのクラスターミサイルを射出するHCミサイルランチャーを背面に装備している。
13,ザウォート・ヘヴィ,-,ペイル・テクノロジーズ,-,-,-,ペイル社の実戦用モビルスーツ。オプション装備のミサイルランチャーとビームキャノンによる重武装仕様を選択している。
14,ハインドリー・シュトルム,-,グラスレー・ディフェンス・システムズ,-,-,-,グラスレー社の実戦用モビルスーツ。中・長距離戦闘を主眼とした武装構成が採用された。
15,ディランザ ラウダ専用機,ラウダ・ニール,ジェターク寮,MD-0031L,18.2m,91.1t,ラウダの操縦特性に合わせて調整が施されたディランザの仕様機。大型ヒートアックスを装備している。
```
以下の様にバケットに配置します。
パスに日本語が混じっている場合、若干注意が必要なので、日本語フォルダ名の下に同じファイルを置いています。
```
[InputfileBucket]
├─g-witch
│   └─mobile-suit.csv
│
└─水星の魔女
    └─mobile-suit.csv
```

## Google スプレッドシート
適当なフォルダにスプレッドシートを作成します。

### Apps Script編集画面へ
[拡張機能]-[Apps Script]を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/1f3cf137-5046-9067-64fc-d92cac2901bd.png)

### S3ライブラリの追加
以下のページを参考に行います。

https://qiita.com/GoeMon564/items/851b76a5c78b22a64fe2

ライブラリを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/eb55b848-b0de-98b6-b121-e9204685fd3f.png)

スクリプトIDに`1Qx-smYQLJ2B6ae7Pncbf_8QdFaNm0f-br4pbDg0DXsJ9mZJPdFcIEkw_`を入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/9b58a938-5a7f-18c1-52e5-7b243d716a0f.png)

左に追加されていることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/d3550710-0563-623c-7f72-f41a6a224bee.png)

### スクリプト
以下のスクリプトをエディタ上に追記します。
バケット名、アクセスキー、シークレットアクセスキーは、使用する文字列に置き換えてください。
```javascript:コード.gs
function main(){
  const bucketName = "[InputfileBucket]";
  const fileName = "g-witch/mobile-suit.csv";

  const data = getS3File(bucketName, fileName);
  const values = Utilities.parseCsv(data.getDataAsString());
  SpreadsheetApp.getActiveSheet().getRange(1, 1, values.length, values[0].length).setValues(values);
 }

/**
 * S3からファイルをロード
 * @params {string} bucketName - 読み取りたいS3のバケット名
 * @params {string} fileName - 読み取りたいファイル名
 */
function getS3File(bucketName, fileName) {
  // S3の接続情報
  const ACCESS_KEY_ID = "[ACCESS_KEY]";
  const SECRET_ACCESS_KEY = "[SECRET_ACCESS_KEY]";

  const s3 = S3.getInstance(ACCESS_KEY_ID, SECRET_ACCESS_KEY); 
  // バケット名とファイル名を指定してファイルの中身を取得
  const data = s3.getObject(bucketName, fileName);
  return data;
}
```

### 実行
上部の”実行”から動かします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/e1634e9e-a0d2-df21-349e-32b17ab30290.png)
初回は承認が求められます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/13640988-b3cb-30ed-83e1-c611d8624b00.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/594eda8d-234d-3ebd-50aa-3021f8b38807.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/9e8f9320-4f74-23be-8f2d-b6c799f9ec2e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/0ea79d88-bf41-3a67-5fd2-f9e701189dda.png)

許可しますと、S3に置いたCSVのファイルがシート上に展開されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/7b5fc7e7-f8c8-c4d5-9b7b-3d54716b7afd.png)


### パスに日本語が混じっていた場合
ファイル名を以下の様に修正します。
```javascript
  // const fileName = "g-witch/mobile-suit.csv";
  const fileName = "水星の魔女/mobile-suit.csv";
```
この状態で実行すると、以下のようなエラーになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/3f8c8161-43f7-0356-ee2f-bee1ad7708ab.png)

この場合はURIエンコードします。
```javascript
  // const fileName = "g-witch/mobile-suit.csv";
  // const fileName = "水星の魔女/mobile-suit.csv";
  const fileName = encodeURI("水星の魔女/mobile-suit.csv");
```
もしくはS3の対象ファイルのオブジェクトURLのkey部分の文字列を使っても可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/516827db-0686-12bd-5a54-d57a707a0cc4.png)

取得できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/839e814f-1742-57aa-1063-f5c9b6b2d3cd.png)

# おわりに
Google Apps Scriptを初めて使いましたが、かなり便利と感じました。
他にも接続したいサービスがあるので、もっとモジュールがあると助かります。