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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Google Apps Script

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

Q&A

解決済

1回答

707閲覧

GASで各スプレッドシートよりセルの情報を集める

amnoskanae

総合スコア13

Google Apps Script

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

0グッド

0クリップ

投稿2019/02/04 02:08

前提・実現したいこと

#### 前提
わたしはプログラミング初心者で、毎日ググりながら、問題を解決を考える程度のスペックの持ち主です。
本当に初心者なので、全くいいプログラミングの書き方ではないのは百も承知ですが、だからこそ皆さんのお力をお借りできればと思います。

#### 現状
現在社内の業務効率化に向けてスプレッドシートの改良を行っています。
社員が毎月各スプレッドシートで勤務時間を記入するシートがあり、各々から数値を確認し、確からしいかチェックした後に、一括管理するスプレッドシートにコピペをします。

そのコピペの作業が面倒なので、一括管理するスプレッドシートからボタン一つで各スプレッドシートの特定のセルにある情報を吸い上げて、一覧にそのまま数値を反映させたいと思います。

数値を吸い上げるまではかなったのですが、それらを一括管理するスプレッドシートに反映させるのに困っています。

発生している問題・エラーメッセージ

エラーは出ていませんが、吸い上げたデータを配列に格納したいのですが、どうすればいいのかわかりません。

該当のソースコード

以下で、各社員のスプレッドシートが保存されているファイルを先月の月末の数字で名付けてあり、各社員のファイルは、作業月報_社員の苗字_月末の数字という名付け方です。

Google

1 function paidHolidaySet(){ 2 3 //社員を配列データとして格納 4 var users = [ 'akito','fujisawa','inoue']; 5 var file_names = users.map(function(element) { 6 7 //月末lmld=lastmonthlastday 8 var dt = new Date(); 9 var lmld = new Date(dt.getFullYear(), dt.getMonth(), 0) 10 11 // YYYYMMDD形式に変換 12 var year_str = lmld.getFullYear(); 13 var month_str = lmld.getMonth()+ 1; // monthはなんと0-11 14 var day_str = lmld.getDate(); 15 16 var month_str = ('0' + month_str).slice(-2); 17 var day_str = ('0' + day_str).slice(-2); 18 19 var format_str = 'YYYYMMDD'; 20 format_str = format_str.replace(/YYYY/g, year_str); 21 format_str = format_str.replace(/MM/g, month_str); 22 format_str = format_str.replace(/DD/g, day_str); 23 24   return "作業月報_" + element + "_" + format_str; 25   }); 26 27 Logger.log(file_names); 28 29 //フォルダーの中にある各ファイルにアクセスし、IDを取得 30 var fileIDs = file_names.map(function(element){ 31 //ファイル名をユーザー名・月末で指定する 32 //月末lmld=lastmonthlastday 33 var dt = new Date(); 34 var lmld = new Date(dt.getFullYear(), dt.getMonth(), 0) 35 36 // YYYYMMDD形式に変換 37 var year_str = lmld.getFullYear(); 38 var month_str = lmld.getMonth()+ 1; // monthはなんと0-11 39 var day_str = lmld.getDate(); 40 41 var month_str = ('0' + month_str).slice(-2); 42 var day_str = ('0' + day_str).slice(-2); 43 44 var format_str = 'YYYYMMDD'; 45 format_str = format_str.replace(/YYYY/g, year_str); 46 format_str = format_str.replace(/MM/g, month_str); 47 format_str = format_str.replace(/DD/g, day_str); 48 //フォルダーの名前を指定 49 var folderName = format_str ; 50 folderName = folderName.toString(); 51 52 //フォルダー名をドライブから検索し、IDを取得 53 var folderID = DriveApp.getFoldersByName(folderName).next().getId(); 54 // Logger.log(folderID); 55 return DriveApp.getFolderById(folderID).getFilesByName(element).next().getId(); 56 }); 57 Logger.log(fileIDs); 58 59 60 //スプレッドシートアプリから取得したIDのスプレッドシートを起動し、アクティブシート取得 61 var sheet = fileIDs.map(function(element){ 62 var sht= SpreadsheetApp.openById(element); 63 var st = sht.getActiveSheet(); 64 var array = []; 65 var latestPaidHour = st.getRange( 1,1 ).getValues(); 66 latestPaidHour = latestPaidHour.toString(); 67 for ( var i = 0; i < latestPaidHour.length; i++ ){ 68   return array.push(latestPaidHour); 69 } 70 Logger.log(latestPaidHour); 71 }); 72 Logger.log(sheet); 73 74} 75

試したこと

最初は配列一つで、その中で作業が完結されるような書き方をしたかったのですが、何度やっても失敗したので、配列の数値を、

1.ファイル名の指定
2.ファイルIDの指定
3.各ファイルにアクセスして、指定のセルから数値を取得し、配列に格納

という順序で更新していくような形にしてみました。
最後の段階で、指定のセルから数値を取得し、Logger.logには各値を反映できていますが、それを配列に格納できません。
もしくは配列でなくとも、そのまま数値を現在開いている一括管理するスプレッドシートの指定の位置にそのままsetValueできれば問題はないです。

しかし、いろいろと調べては試してみるも、何が合っていて、間違っているのか区別がつかず、途方に暮れています。

また動作が少し遅いのでもっとシンプルな文にならないかなと思いながらも、どう改良できるかわかりません。

わからないことだらけで、申し訳ございませんが、どうぞよろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

現在の質問だと問題点が見えないです

  • 「数値を吸い上げるまではかなった」

Logger.log(latestPaidHour);は動作してないはず。
となるとLogger.log(sheet);が出力をしているはずで、これは配列を出力しているはず(mapの結果なので)
であれば、「Logger.logには各値を反映できていますが、それを配列に格納できません」というのは整合性が取れません。
→出力サンプルを提示いただけませんか。

  • 書き込み

これを開いているシートなんだと思いますが、概念的には

javascript

1SpreadsheetApp.getActiveSheet.getRange(1,1,sheet.length, sheet[0].length).setValues(sheet);

なので、形をあわせるだけ。

  • 動作が少し遅いのでもっとシンプルな文

シンプルにしたりmapを組み合わせることでは早める効果は今回の例では薄いと思います。遅い原因は毎回ファイルとフォルダを名前から探したり、各ファイルから値を拾ってきたりするところなので、原理的に大幅な改善が難しいです。
ジャストアイデアですが、↓のような対策をすると改善が期待できると思います。
0. ファイル名の重複がおこらないようなルール(同姓だと重複する)にして、ファイルidの探査をやめる
(余談ですが、getFilesByNameはフォルダ無視して検索してくれるので、もし姓が重複しないなら、DriveApp.getFilesByNameとすることで、現在のコードでもフォルダを無視して取得可能なはず)
0. ファイルidやフォルダidはあらかじめ、管理シートに記録しておく(プログラムを書く)
(こちらは絶対量としてかかる時間はへらないのですが、例えば夜間に時間のかかる処理を逃がしておいて、ユーザが操作する時には応答を速くするという考えです。まあそもそも全体を夜間に処理したらいいのかもしれませんが)


今のコードの意味を(多分)破綻させないように縮約してみました。

javascript

1function paidHolidaySet(){ 2 3 //社員を配列データとして格納 4 var users = [ 'akito','fujisawa','inoue']; 5 var fileIDs = users.map(function(element) { 6 7 //月末lmld=lastmonthlastday 8 var dt = new Date(); 9 var lmld = new Date(dt.getFullYear(), dt.getMonth(), 0) 10 11 // YYYYMMDD形式に変換 12 var year_str = lmld.getFullYear(); 13 var month_str = lmld.getMonth()+ 1; // monthはなんと0-11 14 var day_str = lmld.getDate(); 15 16 var month_str = ('0' + month_str).slice(-2); 17 var day_str = ('0' + day_str).slice(-2); 18 return "作業月報_" + element + "_" + year_str + month_str + day_str; 19 }) 20 .map(function(element){ 21 //フォルダー名をドライブから検索し、IDを取得 22 var folderID = DriveApp.getFoldersByName(element).next().getId(); 23 // Logger.log(folderID); 24 return DriveApp.getFolderById(folderID).getFilesByName(element).next().getId(); 25 }); 26 Logger.log(fileIDs); 27 28 //スプレッドシートアプリから取得したIDのスプレッドシートを起動し、アクティブシート取得 29 var sheet = fileIDs.map(function(element){ 30 var sht= SpreadsheetApp.openById(element); 31 var st = sht.getActiveSheet(); 32 var array = []; 33 var latestPaidHour = st.getRange( 1,1 ).getValue(); //here getValuesをgetValueに変更 34 latestPaidHour = latestPaidHour.toString(); 35 Logger.log(latestPaidHour); 36 return latestPaidHour; //here forの意味がなさそうなのでやめた 37 }); 38 SpreadsheetApp.getActiveSheet.getRange(1,1,1,sheet.length).setValues([sheet]); 39 //here 最初の1,1はA1。3つめの1は、どうも1回の操作で横一列しか取らないっぽい。ので固定値。 40 Logger.log(sheet); 41}

投稿2019/02/04 02:40

編集2019/02/04 03:26
papinianus

総合スコア12705

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

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

amnoskanae

2019/02/04 02:57

papinianus 様 早速お返事いただきありがとうございます。 一度配列に格納しようとせず、ただ情報を抜き取れているかどうかチェックするために、以下のように書き換え、得られたログの出力情報はこちらです。 ```JavaScript //スプレッドシートアプリから取得したIDのスプレッドシートを起動し、アクティブシート取得 var sheet = fileIDs.map(function(element){ var sht= SpreadsheetApp.openById(element); var st = sht.getActiveSheet(); var array = []; var latestPaidHour = st.getRange( 1,1 ).getValues();    Logger.log(latestPaidHour); }); ``` ,,, > [19-02-04 11:47:53:754 JST] [[a]] > [19-02-04 11:47:54:339 JST] [[b]] > [19-02-04 11:47:54:538 JST] [[c]] > [19-02-04 11:47:54:539 JST] [null, null, null] また動作を早くすることに対してのアイデア誠にありがとうございます。 おそらく前者で、苗字がかぶらないようにしてあるので、それは問題なくできると思います。 ですので、一度ファイルの検索をなくしてみようと思います。 質問するのも初めてで、わかりづらい質問となってしまったのにも関わらず、ご回答いただきありがとうございます。 引き続き、お力添えいただけると助かります! よろしくお願いいたします。
papinianus

2019/02/04 02:59

> [19-02-04 11:47:53:754 JST] [[a]] > [19-02-04 11:47:54:339 JST] [[b]] > [19-02-04 11:47:54:538 JST] [[c]] この出力は、求めるものでしょうか? * 「この出力」というのは、社員ひとりずつについて、1つの値(aやbなど)が取れていくという結果のことです。
amnoskanae

2019/02/04 03:01

すみません。上記は間違えで、今削除リクエストをおくりました。
amnoskanae

2019/02/04 03:02

出力については求めるものです。サンプルの値がその値です。その取れた値を一括管理するスプレッドシートに入力したいです。
amnoskanae

2019/02/04 03:03

また最初の質問にあった通りに記入した際に、得られたログの出力がこちらです。  19-02-04 11:59:08:305 JST] [1.0, 1.0, 1.0] (これを先ほど追記としてお送りしようといたしました。使い慣れず、何度も送信してしまい、申し訳ございません。)
papinianus

2019/02/04 03:09 編集

回答を修正しました。 > 出力については求めるものです。 ということは > 19-02-04 11:59:08:305 JST] [1.0, 1.0, 1.0] は > [a, b, c] であれば求める値であるはずですよね?(aやb,cが1になることもあるのかもしれませんが) ………という方針で回答を修正しています。 (ちなみにコメントにマウスをあわせると鉛筆アイコンがあり、編集可能です。削除リクエストしても多分削除してくれません。このコメントのように時刻の右に「編集」とつきます)
amnoskanae

2019/02/04 03:47

何度もお返事いただき本当に助かります。 無事数値を指定の場所に入れることができました! https://qiita.com/ShishidoToru/items/0ab9de4ea281df9358f4 こちらも参考にしつつ、やってみました。 papinianus 様のおかげで、新たに多くのことを学べました。この調子で色々と実際にGASなどを動かしながら、プログラミングの勉強に力を入れてまいります。 誠にありがとうございました!
papinianus

2019/02/04 03:51

その引用リンクの件、あとから気付いてsetValues([sheet])と[]をつけました。もし的外れだったら無視してください。
amnoskanae

2019/02/04 04:36

ありがとうございます! なるほど、変換せずともそのように[]をつけるだけでいいんですね。 シンプルなプログラミング文が書けるように日々邁進します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問