LoginSignup
4
5

More than 1 year has passed since last update.

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

Posted at

やりたかったこと

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

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

ファイル>>インポート 
でローカルからCSVをインポートする方法。
image.png

良い点

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

悪い点

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

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

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

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

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

ソースコードは省略させていただき、
結果として
image.png

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

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

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

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

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

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

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

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

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

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

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

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

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

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をスプレッドにインポートできるようになったので、
次は必要な情報だけを抜き出して、カレンダーとして表示できるようにしたいと思います

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5