質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.96%

【Google apps script】CSVから特定のデータを抽出し、書き込みたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,533

yskt

score 11

 前提・実現したいこと

ドライブ上にあるCSVファイルを特定のスプレッドシートの特定のシートに書き込みしたいです。
かつ、CSVデータも特定の条件で抽出して書き込みたいです。

列A 列B 列C
くだもの りんご 100円
やさい にんじん 100円
くだもの ぶどう 200円
くだもの いちご 300円
やさい キャベツ 200円
やさい なすび 150円
さかな さんま 200円

こんな感じの「たべもの.csv」というファイルがドライブ上にあったとした場合、
列Aが「くだもの」のデータだけを特定のスプレッドシートに書き込みたいです。

 該当のソースコード

  //書き込む対象のSpread Sheetを定義
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sh = ss.getSheetByName("シート名");

function importData() {
    var folderId = "フォルダID";
    var fileName = "たべもの.csv";
    var files = DriveApp.getFolderById(folderId).getFiles();

    while (files.hasNext()) {
      var file = files.next();
      if (file.getName() == fileName) {
        var data = file.getBlob().getDataAsString("Shift_JIS");
        var csv = Utilities.parseCsv(data);
          sh.getRange(1,1,csv.length,csv[0].length).setValues(csv);
    }
  }  
}

 わからないこと

上記コードだと全件が抽出、書き込みされます。
どこで指定してあげるべきか、書き方などがわかりません・・・
クエリなどを使用するのでしょうか?
できれば1件ずつループしてif分で判断するよりかは
クエリなどで抽出できるならばそちらがありがたいです(件数が多いため)
実現可or不可もわからないため教えていただきたいです。

 追加質問

列A 列B 列C 列D 列E
2018/09/02 101 くだもの りんご 100円
2018/09/12 102 やさい にんじん 100円
2018/10/31 101 くだもの ぶどう 200円
2018/11/13 101 くだもの いちご 300円
2018/11/30 102 やさい キャベツ 200円
2018/12/02 102 やさい なすび 150円
2018/12/24 103 さかな さんま 200円

条件指定の際に、他のシートのセルから取得した日付、数値をキーに検索したいです。
他のシートのセルA1には2018年9月30日 セルA2には数値:101の情報が記載されています。
日付は月末日になっているのですが列Aが2018年9月分かつ列Bが101のデータを取得したいです。

下記のように101をセルから取得し、変数valueに格納、
変数valueを条件に指定してみましたがうまくいきませんでした。

ここに言語名を入力
//値セル
var range = sh2.getRange("A2");
//値格納
var value = range.getValue();
```

また、日付の場合はセルから取得した年月のみで判定したいのですが
こちらの方法もわからない状況です。

よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • papinianus

    2018/10/17 11:42 編集

    要件は可能な限り明確化してください。また検索するものが文字なのか数値なのか **日付** なのかは非常に重要になり得ますので、雰囲気の例ではなく、可能な限りやりたことに添った仕様を書いたほうが有益な回答が得られます。

    キャンセル

  • yskt

    2018/10/17 12:58

    追加で記載させていただきました。もしご存知でしたらご教授願います。

    キャンセル

回答 2

checkベストアンサー

+2

forと比べて速度は変わらないかもしれないですが

if (file.getName() == fileName) {
  var data = file.getBlob().getDataAsString("Shift_JIS");
  var csv = Utilities.parseCsv(data);
  var val = sh.getRange(1,1).getValue();
  var setData = csv.filter(function(row) {
    return row[0] == val;
  });
  // ヘッダ
  sh.getRange(2,1,1,csv[0].length).setValues([csv[0]]);
  // ボディ
  if (setData.length) {
    sh.getRange(3,1,setData.length, setData[0].length).setValues(setData);
  }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/17 11:03 編集

    ご回答ありがとうございます!
    無事解決できました!
    追加で質問があるのですが、上記に記載させていただきました。
    もしよろしければこちらもご教授頂きたいです。

    キャンセル

  • 2018/10/17 15:42

    フィルタの結果がない場合にエラーを起こしていたので修正しました。
    変数にした場合、StringとNumberを比較できるように`==`に変更しました。
    日付の比較は(CSV側はnew Dateしてから)、それぞれgetFullYear()とgetMonth()の両方が一致する条件でいけると思いますよ。

    キャンセル

  • 2018/10/19 11:27

    やりたいことがすべて実現できました。
    ありがとうございます。

    キャンセル

+1

  • 実現可
  • 1件ずつループしてifで判断する
    →ifを使うかは実装依存ですが、csvである以上、queryのようなシート関数は使えない(はず)なので、全件チェックするしかないです。
    var csv = Utilities.parseCsv(data);のあとでcsvをフィルタする処理を書けばいいと思います。下記参考に
  • 一旦全てスプレッドシートに起こして、シート関数を使うという方法も可能なのではないかと思います

forは苦手なのであくまで参考として

const key = SpreadsheetApp.getActiveSheet().getRange("A1").getValue();
var ret = [];
for(var i = 0; i< csv.length;i++){
  if(csv[i][0] == key) {ret.push(csv[i]);} //===だと型比較になるからとりあえず==にしとく。
}
sh.getRange(1,1,ret.length,ret[0].length).setValues(ret);


動作確認はしていません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/17 11:07

    ご回答ありがとうございます!
    他の方法のご提案も感謝いたします!
    フィルタを使用してできました^^

    キャンセル

  • 2018/10/17 11:38

    今の時点では本来やりたいことはできてないように拝見するのは気のせいでしょうか?
    というか、変数でやりたいなら、最初から質問にその旨書いたほうがいいです。

    キャンセル

  • 2018/10/17 11:44

    すみません・・
    質問時にはそのことまで考えておらず・・
    質問に追記させていただきます><

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.96%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる