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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google ドライブ

Google ドライブは、Google社が提供するオンラインストレージサービス。オンラインストレージ上に、画像や動画、テキスト、Word/PDFのファイルなどさまざまなファイル保存することができます。また、他のユーザーと共有することも可能です。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

1138閲覧

Googleドライブ上にある大量のcsvデータを一つのまとめ、スプレッドシートに取り込むGAS

Nozomi0302

総合スコア12

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google ドライブ

Google ドライブは、Google社が提供するオンラインストレージサービス。オンラインストレージ上に、画像や動画、テキスト、Word/PDFのファイルなどさまざまなファイル保存することができます。また、他のユーザーと共有することも可能です。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

2クリップ

投稿2020/04/23 11:14

編集2020/04/27 03:09

GASが初心者のため、分からず悩んでおります。
申し訳ありませんが、教えていただきたいです。

前提・実現したいこと

①共有のGoogleドライブのフォルダに毎日保存される大量のcsvデータを
月ごとの一つのcsvデータにしたいです。
②毎日保存される大量のcsvデータを削除したいです。
③その後、月ごとにまとめられたcsvデータを特定のスプレッドシートに張り付けたいです。

今現状、手作業で①、②、③を行っており、工数が増えております。

毎日保存される大量のcsvデータの詳細

[大量のcsvデータの保管場所]
共有ドライブ>データ保管場所>データ登録

[大量のcsvデータのドキュメント名]
パターンが2つありました。
20200423_テスト1Record1.csv
↑ここが日付になり、日々変わっていきます。
Record
1の1部分は、連番になっております。
20200423_テスト1Record.csv
番号が入っていない場合もあります。
1回のスクリプトで対応できる方法はありますでしょうか。

月ごとにまとめられたcsvデータの詳細

[月ごとにまとめられたcsvデータの保管場所]
共有ドライブ>データ保管場所>テスト1のアーカイブ

[月ごとにまとめられたcsvデータのドキュメント名]
202004月_テスト1Record.csv
↑ここが月になります。

できないこと

・以下のソースコード記載時①→③で考えていたが、①のデータ量が膨大のため、
①→②を挟む必要があり、①→②コードの書き方がわかりません。
・①のドキュメント名が日々変更されるため、曖昧検索で【_テスト1Record.csv】に一致するものの指定方法を教えていただきたいです。

該当のソースコード

ネットで検索してソースコードを持ってきました。

var ss = SpreadsheetApp.getActiveSpreadsheet(); var sh = ss.getActiveSheet(); function test() { // 対象のCSVファイルが置かれているフォルダ名、ファイル名を定義 const sheet = SpreadsheetApp.getActiveSheet(); const csvFolderName = "test"; const fileName = /20200316_テスト1Record_1.csv/; //20200316_テスト1Record_1 const rootFolderId = "フォルダid"; // ルートフォルダのID(test)、マイドライブは"root" const root = DriveApp.getFolderById(rootFolderId); var rootFolders = root.getFolders(); while(rootFolders.hasNext()) { var folder = rootFolders.next(); if(folder.getName() === csvFolderName) { // 直下のファイル取り込みを実施 importCSV(folder); } else { // 直下のフォルダにcsvがあるか調べる var csvFolder = folder.getFoldersByName(csvFolderName); while(csvFolder.hasNext()) { // 直下のファイル取り込みを実施 importCSV(csvFolder.next()); } } } function importCSV(folder) { var files = folder.getFiles(); while(files.hasNext()) { var file = files.next(); if (file.getName().match(fileName)) { // 取り込み処理を実施 var data = file.getBlob().getDataAsString("UTF-8"); var csv = Utilities.parseCsv(data); var ALastRow = sheet.getLastRow(); //CSV書き込み sheet.getRange(ALastRow + 1,1,csv.length,csv[0].length).setValues(csv); } } } }

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

draq

2020/04/23 20:45

具体的に何が問題なんでしょうか。
Nozomi0302

2020/04/24 00:12

draqさん! ご連絡ありがとうございます。 大事なところ、失念しておりました。。!記載いたしました!
guest

回答1

0

ベストアンサー

こんなイメージでしょうか。
月次CSVが大きくなりすぎると処理時間やメモリが問題になるかもしれません。
あと処理するファイルの順番は気にしていないので必要なら事前にソートしてください。

JavaScript

1function myFunction() { 2 const parentFolder = DriveApp.getFolderById("...."); 3 4 //指定したフォルダ以下のCSVファイルを列挙するイテレータを取得する 5 //※全フォルダを対象にしたい場合は parentFolder のかわりに DriveApp を指定する 6 const dailyFiles = parentFolder.getFilesByType(MimeType.CSV); 7 8 while(dailyFiles.hasNext()) { 9 const dailyFile = dailyFiles.next(); 10 11 //ファイル名がマッチするか正規表現でテストする 12 const result = /^([0-9]{4})([0-9]{2})[0-9]{2}_テスト1Record(~[0-9]+)?.csv/i.exec(dailyFile.getName()); 13 if(result && 0 < result.length) { 14 //ファイル名から年月を取り出し 15 const year = Number.parseInt(result[1]); 16 const month = Number.parseInt(result[2]); 17 const date = new Date(year, month - 1, 1); 18 const dailyData = dailyFile.getBlob().getDataAsString(); 19 20 //月次ファイル名 21 const monthlyFilename = Utilities.formatDate(date, "JST", "YYYYMM") + "_テスト1Record.csv"; 22 23 //データ読み出して、年月別のファイルを作成または追記 24 const monthlyFiles = parentFolder.getFilesByName(monthlyFilename); 25 if(monthlyFiles.hasNext()) { 26 const file = DriveApp.getFileById(monthlyFiles.next().getId()); 27 const monthlyData = file.getBlob().getDataAsString(); 28 file.setContent(monthlyData + "\r\n" + dailyData); 29 } 30 else { 31 parentFolder.createFile(monthlyFilename, dailyData); 32 } 33 34 //ファイルを削除 35 parentFolder.removeFile(dailyFile); 36 } 37 } 38}

投稿2020/04/24 10:51

編集2020/04/27 16:03
draq

総合スコア2573

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Nozomi0302

2020/04/27 02:46

draqさん 返信遅くなり申し訳ありません! ご回答ありがとうございます!想定の動きができそうです! もう1点ほど、ご質問させていただいてよろしいでしょうか・・? 《ドキュメント名について》const result = /^([0-9]{4})([0-9]{2})[0-9]{2}_テスト1Record.csv/i.exec(dailyFile.getName()); この部分なんですが、 実際、名前が20200423_テスト1Record.csvではなく、 20200423_テスト1Record~1.csvとなり、ドキュメント名の末に【~1】があり、1の数字部分が連番になっております。 この場合は、どのようなスクリプトを記載すればよろしいでしょうか。。 何度もご質問申し訳ありません! 本文のほうも編集しておきます!
draq

2020/04/27 08:54

ファイル名に連番がついている場合に対応した回答に変更しました。
Nozomi0302

2020/04/27 09:14

draq様ありがとうございます!!!! 心より感謝申し上げます。
Nozomi0302

2020/04/27 13:44

draqさん お世話になります。 もう1点ご質問させていただいてもよろしいでしょうか? いただいたスクリプトをもとに、 以下のドキュメント名についても同様の処理を行いたいと考えているのですが、 ドキュメント名が「EVENT_20200422_082751_266_3_IN」の場合は、以下のスクリプト部分はどのように変更したらよいでしょうか? const result = /^([0-9]{4})([0-9]{2})[0-9]{2}_テスト1Record(~[0-9]+)?.csv/i.exec(dailyFile.getName()); EVENT→固定 20200422→日付 082751→時間 266→連番のため変わっていきます。1桁~4桁になることがあります。 3→ここも連番となり、変わっていきます。1桁~3桁になることがあります IN→固定
Nozomi0302

2020/04/28 06:21

drapさん ご回答に感謝いたします! 正規表現についても、リンクありがとうございます。 勉強します!
Nozomi0302

2020/04/30 07:05

drapさん お世話になります。先日はご教示いただき、ありがとうございました。 正規表現については理解できたのですが、以下のスクリプトを動かしたところ、挙動がなぜかうまくいきません。これはなぜなのでしょうか。 お忙しい中恐縮ですが、教えていただけませんでしょうか。 何卒宜しくお願い致します。 function myFunction() { const parentFolder = DriveApp.getFolderById("フォルダID名");/*テストフォルダ*/ //指定したフォルダ以下のCSVファイルを列挙するイテレータを取得する //※全フォルダを対象にしたい場合は parentFolder のかわりに DriveApp を指定する const dailyFiles = parentFolder.getFilesByType(MimeType.CSV); while(dailyFiles.hasNext()) { const dailyFile = dailyFiles.next(); //ファイル名がマッチするか正規表現でテストする const result = /^EVENT_([0-9]{4})([0-9]{2})[0-9]{2}_[0-9]{6}_[0-9]{1,4}_[0-9]{1,3}_IN.csv/i.exec(dailyFile.getName()); if(result && 0 < result.length) { //ファイル名から年月を取り出し const year = Number.parseInt(result[1]); const month = Number.parseInt(result[2]); const date = new Date(year, month - 1, 1); const dailyData = dailyFile.getBlob().getDataAsString(); //月次ファイル名 const monthlyFilename = Utilities.formatDate(date, "JST", "YYYYMM") + "_ログRecord.csv"; //データ読み出して、年月別のファイルを作成または追記 const monthlyFiles = parentFolder.getFilesByName(monthlyFilename); if(monthlyFiles.hasNext()) { const file = DriveApp.getFileById(monthlyFiles.next().getId()); const monthlyData = file.getBlob().getDataAsString(); file.setContent(monthlyData + "\r\n" + dailyData); } else { parentFolder.createFile(monthlyFilename, dailyData); } //ファイルを削除 parentFolder.removeFile(dailyFile); } } }
draq

2020/04/30 09:21

なぜかうまく行かないだけでは何も回答できません。具体的にうまく行かない点とどこまでは想定通りに動いているのかをきちんと確認してください。
Nozomi0302

2020/04/30 11:11

draqさん お返事ありがとうございます!至らない点があり、申し訳ございません! 挙動について: トリガーの実行数で確認したところ、エラーにはなっておらずステータスも完了となっておりました。 上手くいかない点: ①ドキュメント名が【EVENT_20200430_082913_377_3_IN.csv】と【EVENT_20200430_082751_266_3_IN.csv】のファイルを一つにまとめたかったのですが、 202004_ログRecordのファイルが作られませんでした。 ②【EVENT_20200430_082913_377_3_IN.csv】と【EVENT_20200430_082751_266_3_IN.csv】のファイルの削除もなされておりませんでした。 何卒宜しくお願い致します。
draq

2020/04/30 11:18

まだ確認が足りていません。 例えば、while(dailyFiles.hasNext()) {} ループ無いで想定通りファイルが列挙されているかログ出力してみるとか確認できることはあります。 ①も②もファイルが対象となっていないだけかもしれませんし。
Nozomi0302

2020/04/30 14:20

console.logですね!!!確認してみてみます!!! たくさん、ありがとうございます!
Nozomi0302

2020/04/30 15:00

draqさん! できました!! タイトルのところで、私が文字を押し間違えていたようで、変な文字が入っていたことが原因でした。。 ご迷惑おかけしました。 concole.logをしたことで、結果がnullだったので発見することができました。。。! 本当にありがとうございました!!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問