スプレッドシートにCSVをインポートする時にハマった話

# やりたかったこと

他のシステムで出力した、日付や開始時間・終了時間、内容、作業者、その他情報などが記載されたCSVを
スプレッドシートでアレンジしてカレンダー表示したい
(カレンダー表示は別記事で投稿します)

# 方法その①　手動でファイルをインポート

ファイル>>インポート　
でローカルからCSVをインポートする方法。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663663/f1974982-cc56-3767-700b-530c1c20ac2c.png)

#### 良い点
* 教えやすい
* ローカルでもDrive上でもファイルを指定できる

#### 悪い点
* インポートの方法(シートの指定や区切り文字の種類など)にバラツキがでる


その後のカレンダー表記にアレンジすることを考えると、
インポートできるシート名は統一したいし…
インポートしたCSVの全ての情報を使うわけではないので、
インポートされたらそのまま必要な情報だけをピックアップしたい…

となると、やはりGASを使うのが一番!!!
ということで、次の方法。

# 方法その②　GASのダイアログを使ってインポート

https://dev.classmethod.jp/articles/gas-ss-csv-create-invoice/
こちらを参考にさせていただき、作成しました！


ソースコードは省略させていただき、
結果として
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663663/3565263d-85af-dfa1-45af-ba3d5e733eec.png)

…うん、できない…
調べた結果分かったのは、
参考URLの冒頭にも書いてあったこれが原因かと

> V8のバグによりHTML内でファイルのアップロードができない疑いがあり、今回導入する処理を実現するためにはV8を無効にして進めることにしました。


GASを最近始めたヨワヨワな私は、V8しか知らなかったので、痛恨のミス
というか、もっとちゃんと文章を読んでおけよってやつですね。

2年前に発見されてるバグでも直らないもんなんですかね…
それとも違うやり方があるとか…？

良く分からなかったので、
**ローカルからCSVインポートするのやめました(あっさり)**

他のシステムからCSVを出力する時点で、
**Googleドライブの指定のフォルダに指定のファイル名**で入れてもらうことにします。


# 方法その③　GASでGoogleドライブフォルダ上のCSVをインポート

https://note.com/kawamura_/n/nd227dacbc847
こちらを参考にさせいていただきました！

```JavaScript
function importCSV() {

  var file = DriveApp.getFilesByName("CSVのファイル名").next();
  var csvData = Utilities.parseCsv(file.getBlob().getDataAsString("Shift_JIS"));

  const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート名');
  ss.getRange(1, 1, csvData.length , csvData[0].length).setValues(csvData);

}
```

CSVのファイルはスプレッドシートと同一のフォルダにあることを想定したため、
今回はフォルダIDの指定はしていません。

当初文字コードを指定していなかっため、文字化けが発生。
`file.getBlob().getDataAsString("Shift_JIS")` ここでShift_JISを設定することで回避。


### 上手くいったかのように思われたが…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2663663/749542d0-60bf-1568-56fe-bb16e0601c89.png)

あれ？区切り位置ずれてる？
なんで途中で区切れてる???
ん????

**Utilities.parseCsvは、項目内の改行に対応していない**
という事実を発見…


# 方法その④　GASでGoogleドライブフォルダ上のCSVをインポート(自作Parse使用編)

もうこれに関しては、自作Parseを制作する気力はないので、
先人の知恵を丸っとお借りしました。
https://qiita.com/weal/items/5aa94235c40d60ef2f0c


```JavaScript
function importCSV() {

  var file = DriveApp.getFilesByName("CSVのファイル名").next();
  //var csvData = Utilities.parseCsv(file.getBlob().getDataAsString("Shift_JIS"));
  var csvData = CSV.parse2(file.getBlob().getDataAsString("Shift_JIS"));

  const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート名');
  ss.getRange(1, 1, csvData.length , csvData[0].length).setValues(csvData);

}

//ここから下はそのまま使わせていただきました
var CSV = {};
CSV.parse2 = function(str) {
    var i, c, r, q, l, m, v, j, len=str.length, rows = [], row = [];
    m = (l = str.indexOf('\r\n')<0 ? str.indexOf('\r')<0 ? '\n' : '\r' : '\r\n').length; //改行記号を決定
    for(i=0,c=r=-1; i<len; i++) {
        if (str.charAt(i) === '"') { //quoted
            for(j=0,q=i+1; q<len; j++,q++) { //閉quotを探す
                q = (q=str.indexOf('"',q)) < 0 ? len+1 : q; //quotの位置、無いなら末尾まで
                if (str.charAt(++q) !== '"') {break;}       //""なら継続
            }
            row.push((v=str.substring(i+1,(i=q)-1),j) ? v.replace(/""/g,'"') : v);
        } else { //not quoted
            if (c<i) {c=str.indexOf(',',i);c=c<0?len:c;} //直近のカンマ位置と
            if (r<i) {r=str.indexOf(l,i);r=r<0?len:r;}   //直近の改行位置を調べ
            row.push(str.substring(i,(i=c<r?c:r)));      //そこまでを値とする
        }
        if (i === r || l === (m>1?str.substr(i,m):str.charAt(i))) {rows.push(row);row=[];i+=m-1;}
    }
    str.charAt(i-1) === ',' && row.push(''); //,で終わる
    row.length && rows.push(row);
   // str.substr(i-1,m) === l && rows.push([]); //最後の改行を無視する場合はコメントアウト
    return rows;
};

```

# 今後

ひとまずCSVをスプレッドにインポートできるようになったので、
次は必要な情報だけを抜き出して、カレンダーとして表示できるようにしたいと思います