【MACRO】Google Apps Script 質問スレ【DRIVE】
Google Apps Script でのプログラミング等に関する質問スレです Excel や Access の VBA に不満のあるあなた web アプリだけでなくクライアントアプリからも利用したいあなた ローカルなデータベースやファイルだとバックアップに不安のあるあなた ム板に無かったので立ててみます Google Apps Script ttps://developers.google.com/apps-script/ Google Drive API ttps://developers.google.com/drive/ Getting Started with the Google Data Python Library ttps://developers.google.com/gdata/articles/python_client_lib ■関連スレ Google Maps API 質問箱 http://peace.2ch.net/test/read.cgi/tech/1131627583/ Microsoft SkyDrive API http://peace.2ch.net/test/read.cgi/tech/1385604796/ 【GoogleAppsScript】猿92【研究せよ!!!】 http://nozomi.2ch.net/test/read.cgi/php/1398600864/ GoogleAPIってどうよ? http://nozomi.2ch.net/test/read.cgi/php/1018614427/ Google App Engine for Python 6アプ目 http://nozomi.2ch.net/test/read.cgi/php/1358570953/ Google App Engine for java http://peace.2ch.net/test/read.cgi/tech/1317639323/ GoogleWebToolkit[GWT]について語ろう http://nozomi.2ch.net/test/read.cgi/php/1147975874/ >>783 キチンとhtml出力して、html内にウインドウ閉じるJavaScriptを入れるってのはダメですか? うわー皆さんいろいろアイディアありがとうございます. >>792 試してみたんですがAndroid環境だと画面閉じないですね… >>791 単純にうんこした時間をGoogleカレンダーに登録したいだけなんすよね… なのでスプレッドシートとかは使いたくなくて,コードは var date = new Date(); CalendarApp.getDefaultCalendar().createEvent("💩",date , date) こんな感じで十分なので,できればこれをandroid上でアイコンに割り当てて一発実行したいのです. >>788 ターミナル開く手間は避けたくて…… >>789 >>790 このどっちかででけそうな気がしてきたのでちょっと試してみます! 共有しているスプレッドシートの 「編集者は権限を変更して共有できます」のチェックボックスを外す(無効にする) ソースコードを教えてください setShareableByEditors(shareable) を使えばできるようなのですが 使い方が分かりません よろしくお願いいたしますm(_ _)m >>795 その関数の引数をfalseにするだけやろ グループ内で簡易なうpろだとして使いたいのですが、ファイルのアップロード、コメントが記入できて、 アップロード先のURLとコメントをスプレッドシートにリスト化してくにはどうしたらいいんでしょうか? ファイルのアップロード、コメント記入してそれをスプレッドシートにリスト化、それぞれは出来たんですが組合わせると動作しません。 なにかサンプルになるようなページを教えていただけると助かります… シートを作る うpするGASを書く アップロード先のURLとコメントをスプレッドシートにリスト化 >ファイルのアップロード、コメント記入してそれをスプレッドシートにリスト化、それぞれは出来たんですが もっと具体的に 出来ればソースとか晒すべき >>793 >>788 >ターミナルを開く手間は、避けたい どこかに、ショートカットを作れないの? 例えば、Windows ならデスクトップにショートカットを作って、 リンク先に、コマンドプロンプトを起動して、 Ruby でスクリプトファイルを実行する C:\Windows\System32\cmd@.exe /k "ruby C:/Users/Owner/Documents/script.rb" 注意。書き込めないので、間に@を入れました スプレッドシートのトリガー onSelectionChangeの挙動ホント悪すぎる ここらへんVBAと比べてダメ過ぎだな スプレッドシートのグラフもひどいよ。 setOption(‘vAxes.1.title’,’hoge’)とかも スプレッドシートとhtmlserviceで簡単なwebアプリ作ろうと思ったのですが、ユーザー毎のデータも扱う場合、どうやるのがいいんでしょうか。 アプリの実行者を「ログインしているユーザー」にすると、スプレッドシートへのアクセス件が必要だから、他の人のデータにアクセスされそうで怖い。 だからといって、実行者を「自分」(開発者)にすると、操作してるユーザーが誰なのかを判別できないし・・。 >>802 ユーザーごとのデータってどんなの? スプレッドシートの1行で表現できないもの? >>803 user | name | score aaa@gmail.com | taro | 85 bbb@gmail.com | jiro | 75 みたいにスプレッドシートをDBとして使うWEBアプリの場合、 アプリを「自分(開発者)」として実行すると、ログインユーザーのemailが取得できないから、スプレッドシートから当該ユーザーのデータを取得できない 「アクセスしているユーザー」として実行すれば、ログインユーザーのemailが取得できるけど、このスプレッドシートへのアクセス権を与えないといけないので、他のユーザーの情報も全て見れてしまう ので、普通はどうするものなのかが知りたいです。(有償のworkspaceは使わない前提です) >>804 なるほどね 普通がどうだかわからないけど メアド自動収集をあきらめてユーザーに入力させるか スプレッドシートをDBにするのをやめてCloudSQLを使う かなぁ GAS には、ユーザー認証機能があるの? 認証は、Firebase Authentication じゃないの? const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); const pivotSheet = spreadsheet.getSheetByName('a'); const pivotTables = pivotSheet.getPivotTables(); pivotTables.forEach(pivotTable => { const pivotValues = pivotTable.getPivotValues(); pivotValues.forEach(pivotValue => Logger.log(pivotValue)); }); こんなかんじでpivotTablから値をとりたいのですが、ログとしては pivotValueという値しか返ってこないのですが、なんででしょうか? pivotValue.getValue() のようなことがしたいんです。具体的な数値が返ってくるような。 >>807 何も調べてないうえにやったこともないけと、文脈から察すると Logger.log(pivotValue.getValue()) じゃない? >>808 getValue()は使えないみたいなんですよね、not a functionになって getValueでしてみたらnullが帰ってきて謎... ぐぐってもサンプルが出てこなくてまいりましたわ >>804 Webアプリのコードで自分の分だけしかアクセスできないように書けばいいだけだろ? それともクライアントから任意のコードをサーバ側で実行させられるわけなの? ピボットテーブルで出力したテーブルの特定の文字列のセルを非表示にしたいのですが やり方が御座いましたらご教示お願いいたします 条件付き書式で一致すれば文字を白にするといった「見えなくする」ではなく セルをコピーしてもコピーされない状態にしたいです よろしくお願いいたします 公式見てもわからなかったんですが、 新しいスプレッドシートを作る関数→できる そのスプレッドシートに何か書き込む関数→できる そのスプレッドシートのスクリプトエディタをいじってスクリプトを付ける関数→? できるんでしょうか? >>814 多分できない あらかじめコピー元テンプレート用のスプレッドシートを用意しておいて スクリプトも仕込んでおけばいけるかなと思ったけど 実行権限の付与ができないから無理じゃね はじめまして。 質問ですが、GoogleスプレッドシートのGAS(Google Apps Script)で、 「計算結果のみ」を別のスプレッドシートへコピーする方法を教えてください。 var ss_copyFrom = SpreadsheetApp.openById('コピー元のシートID'); var ss_copyTo = SpreadsheetApp.getActiveSpreadsheet(); var sheet_copyFrom = ss_copyFrom.getSheetByName('シート名'); var sheet_copyTo = ss_copyTo.getSheetByName('別のスプレッドシートのシート名'); var copyValue = sheet_copyFrom.getRange('W3:W200').getValues(); sheet_copyTo.getRange('B4:B201').setValues(copyValue); 上記でコピーそのものはできていますが、表示されるのが コピー元であるスプレッドシートに入力されている「=T4-U4-V4」の結果 (コピー先のT列、U列、V列には何も入っていないため、「1899/12/30」が表示されています)で、 本当に表示させたいのはコピー元のスプレッドシートで「=T4-U4-V4」が計算された結果の数値「1」なのです。 GASについてはド素人(今月から使い始めました)で、ネット検索で色々調べてみましたが、 これといった解決策がわからず、困り果てています。 何とかお知恵を貸していただけますよう、お願い致します。 >>816 単純にスプレッドシートの表示形式が数値か日付かって話じゃないの >>817 その通りでした...ありがとうございます。 表示形式を数値に変えたら、ちゃんと「1」がでました。 こんな単純なことに気づけないとは...失礼しました。 スプレッドシートのメニューバー変わりましたよね? 拡張機能からスクリプト画面選ぶようになってる… 調べたら10月から順次変わってる…?今日気付いたんですが2ヶ月掛かって更新されたってことでしょうか? web版のエディタが使いにくい。 ファイル+のとこのペイン?っていうの?あれが邪魔で小さくしたくてデベロッパーコンソールでイジってるんだけどどのcss変えれば小さくできますか? スライドからスクリプト開いてスクルプト書きました。 スライドからそのスクリプト実行したくて、onOpen()でスライド表示時の右サイドバーにスジュリプト起動ボタンを表示するようにしました。 ところが、スライド開いた時にこのonOpenが実行っされません。 トリガーに登録せよ!という情報もあったのですが、トリガー登録画面には、「スライドを開いた時」的なものは無く、 「カレンダーを開いた時」のようなものしかありませんでした。 スライドを開いた時に、スクリプト起動させるボタンのようなものを表示して、そこからスクチプトを起動したいです。 方法があれば教えてください。 解決しました。下記に載ってました。 Https://myfunc.jp/items/00015/index.html 指定した文字列Aと背景色の2条件で集計したいのですが、書き方を教えて下さい。 文字列Aだけ、背景色だけ、などはいくつか見つけられたのですが、組み合わせ方が分かりません…。 https://script.google.com/ このページって何処からたどり着くんですか? googleドライブとかから新規にスクリプトを作成するのは出来るんですけど 何処にも上記のリンクが無いです 出来そうで出来ないというか検索してもやりかたが見つからなかったので 知ってたら助けて欲しい 【やりたいこと】 エクセルファイルをGASでスプレッドシートに変換してスプレッドシートにする 但しエクセルファイルの各シートのセルにはエクセル特有の文法で記載された計算式や関数がふんだんに使われているものとする 【ひっかかっていること】 単純にGASでDriveAppやDrive.Filesを用いてエクセルファイルをスプレッドシートに変換するだけだと 変換されたスプレッドシートのセルにはエクセルの特有の文法で記載された計算式や関数が移植されてきただけで スプレッドシートではエクセル特有の文法で記載された計算式や関数は処理できないのでやりたいことが出来ない状態 なのでエクセルのセルに埋め込まれてる計算式で求められた計算値だけをスプレッドシートに移植したい 関数で計算されてるデータを全て数値などに置き換えた物をアップすれば簡単じゃね? データとして貼り付ければ一瞬だしマクロ組めるでしょ。 そのエクセルが他から提出されてくるもので数百単位であるので 個々にそのマクロを仕込んだものを実行するというのは大変かなぁ できればエクセルはそのままで一括で読み込んで GASのなかでやっちゃいたい 無理げかなぁ そういう後だしするからアドバイスするだけ無駄ってのが出てくるんだよね >>826 スプレッドシートでは処理できない、って言う時点でGASじゃ無理でしょ。 どうしてもやりたいなら、下記くらいしか思いつかない。 @その数式と同じ動きをする関数を自分でGASで実装する AWinのタスクスケジューラとか使って、VBAでExcel文字列化するなりCSV出力するなりして、それをGASでスプレッドシート化する。GoogleドライブアプリでWinとドライブを同期する しょうがないから一つヒント 同じフォルダ、若しくは特定のフォルダに入ってるExcelのファイルを全て文字に変換して保存するマクロを組めばOK 何百あろうが一瞬 全てのブックの全てのシートへループでぐるぐる回すだけだから、そんなに難しくないよ GASのソースコード内でタイムゾーンを変更することはできるのだろうか? GASのエディタにあるjsonに書いて指定するというのは見つけたが、それだとコード内でgoogleドライブから開いたスプレッドシートには適用されなかった GASのエディタではTokyoにしてても開いたスプレッドシートはPacificになってる もしくはGoogleアカウント設定のプロフィールのタイムゾーンいじると それ以降作成したスプレッドシートはデフォルト変わってるはず スプレッドシートの複数列を指定して二次元配列に入れる場合のやりかたはわかるんだけど 離れた二つの列を指定することって出来る? range = Sheet.getRange("D2:E1000"); array1 =range.getValues(); Logger.log(array1); 例えばこれだとD列2行目からE列1000行目までの2列分のデータを二次元配列に格納されるけど これをD列2行目からD列1000行目とN列2行目からN列1000行目のデータを二次元配列に入れたい D列とE列は隣り合ってるけど D列とN列は隣り合ってないからうまく実現できない const files1 = DriveApp.getFolderById(folderId1).getFiles(); const files2 = DriveApp.getFolderById(folderId2).getFiles(); こんな感じで異なるフォルダに格納されてるファイルをgetFiles取得した場合 その結果のfiles1とfiles2を合体させてfiles3にするようなことってできる? いまだとファイルの数だけ繰り返すっていうのでfiles1を回すループ処理とfiles2を回すループ処理という感じで見栄えが悪いから 2つをマージしたfiles3を回すループ処理って感じにしたい 無理なのでループ処理部分をメソッド化するなりしてどうぞ GASでセルの値を変更させて変更後の値を読み取ってって一連の処理をしたいんだけど 一連の処理が終わるまでシートに表示される値がリフレッシュされないらしく 処理としてはセルへ値を出力してるけど読み取る値が出力前の値になってる 強制的にシートに表示される値を最新にすることってできないの? setvalueで値をセルに入れるのってリアルタイム反映じゃなくて スタックしてて処理が終わるみたいな切りがいいところで まとめて反映する仕様じゃないのけ? クラウドベースの実行だからサーバー側の負荷軽減のためだと聞いたが コード云々でなんとかなるなら知りたい getValues()で取得したのはrangeで指定したのが1列分のデータであっても2次元配列になっちゃうけれど getValues()の後ろに続けて.flat().filter(String).map(String) と付ければ1次元配列に変換できることを ネット上で検索してたら見つけた range = sheet.getRange("C2:C1000"); result = range.getValues().flat().filter(String).map(String); 実際に上記のようなコードで試したところ確かに1次元配列に変換はされてるけど 空白セルの要素が配列から消滅してしまってる "A","B","","F","D" 上記のように要素数5個で3番目の要素が空欄の配列が欲しいのだが "A","B","F","D" 上記のように空欄の要素が消滅して前詰めされた要素数4個になってしまってる 空白セルの要素も残したいんだけど、どうやったらいいのだろうか? >>844 filter()とmap()要らなくない? result = range.getValues().flat() とりあえず .filter以下を消したら望んでた結果は得られた模様 セルに手入力された5:22とか8:24とかの見た目時間になってる単なる文字列を使って 時間の足し算をしたいんだが、なんかいいアイディアはないだろうか? 足し算自体はスプレッドシート上の計算式ではなく 値だけ変数に入れてhas上でやりたい スプレッドシートに数十個のボタンを図形描画してスクリプトの割り当てをしたんだが何回設定しても いつのまにかスクリプトの割り当てで割り当てたスクリプトが空欄に戻ってしまう これって何か制限があったりするのだろうか 一通り設定して最初のボタンから確認していくと空欄に戻ってしまってて ボタン押しても反応しない 設定した直後にボタン押すときはスクリプトが動いてるから最初から設定できてないわけではない ClassroomAPIを使って ----- Classroom.Courses.CourseWork.list(クラスルームのID).courseWork.forEach(w =>{ 〜〜〜〜〜〜 }) ----- ってかんじで受講しているクラスで出された課題それぞれに対して処理をしているんだけど、 これだと提出済み課題に対しても処理してしまう。 提出済みか判定して、除外するためにはどうしたらいい? 提出済みか判定して、除外す提出済みか判定して、除外すればいい 質問します ローカルにあるファイルをメールに添付して 指定時間に送信するみたいなことを gasでやりたいのですが、 ローカルファイルをGoogleドライブに取り込むところから躓いてます こういうやり方があるよ、とかこのHPが参考になる、みたいなのはありますか? m5stackでボタンを押す → スプレッドシートに書き込み → 編集をgmailで送信 というのをしたいなと。 参考にしたのはこのページ https://knt60345blog.com/m5stack-googlespreadsheet/ 要はボタンを押すとスマホに通知がくるシステムを作りたいのです。ところがgmailの送信がされません。 やったこと 1.スプレッドシートに編集があったときに通知する → 手入力だと通知される。しかし、scriptによる編集では通知されない。 2.gas上で編集をトリガーにしてsendgmailを使う →失敗。おそらく1と同じ理由 3.スプレッドシートを編集するスクリプトの中にsendgmailを記述する →編集はされるがメールは送信されない sendmailの使い方を間違えているのかと思いましたがメールを送るだけのコードを実行するときちんと送れていました。 ヒントをもらえるとありがたいです。よろしくお願いします。 >>856 簡単なのはGoogle DriveアプリでPCと同期させる方法かと思います。 >>856 ローカルファイルと言うことはトリガー実行じゃないんだよね? どういう操作を想定してるのかわからんけど、HTMLでダイアログ表示させるかdoGetでHTMLを表示させて そのHTMLとJSでローカルファイルは読めるよ https://tonari-it.com/gas-dialog-basic/ >>857 これで普通に出来たぞ function doPost() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1'); var range = sheet.getRange('A1'); var values = range.setValue('hoge'); GmailApp.sendEmail('test@example.com', 'subject', 'body'); } >>858-859 回答ありがとうございます もう回答もらえないのかな?と諦めておりました 実はローカルファイルをトリガー実行(時間指定)でメールに添付させたいというのが希望する処理なのです グーグルドライブアプリからならキーも取れそうですね 会社からグーグルドライブアプリの設置許可貰えたらやってみます >>861 なんだそれ怖いこと言うなよ ソースどこ? googleSpaceのタスクにGASでタスク登録って可能? 登録しようとしても GoogleJsonResponseException: API call to tasks.tasks.insert failed with error: Invalid task list ID って吐かれる IDはスペースのURL末尾を使ってる しばらく触ってないうちにスクリプトエディタが変わっていたんですが、新しいエディタでプロジェクトのコピーを保存したい場合ってどうしたら良いんでしょうか? 自作のスクリプトを使ってもらうのにコピーを保存してもらっていたので代わりの方法を探しています Googleスプレッドシートの件で質問します。 A11からF11の列に、IMPORTRANGE()によって、他のスプレッドから取り込んだデータが入っています。行の数は未定(約300件ぐらい)です。 このままでは、元データのシートが更新されると、合わせてデータも更新されてしまいます。 この現在表示されているセルの値をそのまま、文字列としてセルに上書きするコードを記入したいのですが、どのように記述するとよいでしょうか? やりたいことがわからないのでもう少し詳しく書いてください すみません。自己解決しました。 スレ汚し申し訳ありませんでした。 謝るより原因や解決方法を書いていってほしい 質問と解決法が揃ってればスレ汚しにならない 初心者で勉強中ですがplain bodyとかの正規表現が難しくて泣きそう 1日一回gmailの中のメールをフィルタリングして集計してメールを遅るスクリプトを動かしてます。 今日までは毎日1回動いてましたが 本日近い時間帯で4回トリガーされていました。 このようなことが起こった方他におられませんでしょうか。 ボタンを押下したらテーブルを表示させたいんだけど、どうすればいいのでしょうか? 毎月の商品ごとの売上グラフを作ってるんですけどAには赤、Bには青、Cには黃というように色指定は出来ますか? グラフの並び順に1番目から赤、青、黃という順序では出来るんですけど、順番が変動しても大丈夫にしたいです A2= if "A", Red "B", Blue "C", Yellow みたいに出来たらいいなと思ってます 二次配列の中の特定要素を一個だけじゃなくて任意の数があるか確認する方法ってある? どういうこと? 何か日本語不得意なやつ多すぎね? 上手く質問できないなら具体例を書けよ 例えば [ [1, 2, ...], [3, 4, ...] ] という二次元があったとき、 ○○が○○であることを確認する方法ってある? みたいな 日本語というかこういうのはちゃんと説明できないからコード書けないんでは ボタンが押下されたら表が動的に表示されるようにしたいのですが、動的に作成された表の値がundefinedになります。 下記の通りに書いたのですが、何故undefinedになるのでしょうか? <script> function displayTable() { var htmlTable = google.script.run.getTable_Area(); document.getElementById("createdTable").innerHTML = htmlTable; } </script> function getTable_Area() { return '<table>' + '<thead>' + '<tr>' + '<th>Result</th>' + '</tr>' + '</thead>' + '<tbody>' + '<tr>' + '<td>Date</td>' + '<td><input value=<?= new Date();?>></input></td>' + '</tr>' + '<tr>' + '<td>Area</td>' + '<td><input value=<?= getArea();?>></input></td>' + '</tr>' + '</tbody>' + '</table>'; } >>878 パッと見だけど displayTableはフロント側の関数だよね getTable_Areaはgoogle.script.run経由で呼び出してるからgs(バックエンド側)の関数だよね google.script.runはwithSuccessHandlerのコールバックでレスポンス受け取るから、変数htmlTableはundefinedになるんじゃね? >>879 >displayTableはフロント側の関数だよね >getTable_Areaはgoogle.script.run経由で呼び出してるからgs(バックエンド側)の関数だよね はい。それぞれフロントとバックエンド側になります。 withSuccessHandlerを以下の通りに使用し、実行したところundefinedは表示されなくなったのですが、表が表示されないということはcalculateArea()の書き方がいけないのでしょうか? <script> function calculateArea() { var htmlTable = ""; google.script.run.withSuccessHandler(function(data) { htmlTable = data; }).getTable_Area(); document.getElementById("createdTable").innerHTML = htmlTable; } </script> >>880 こうしてみて function calculateArea() { google.script.run.withSuccessHandler(function(data) { document.getElementById("createdTable").innerHTML = data; }).getTable_Area(); } >>881 ありがとうございます!表が表示されるようになりました! もし可能であれば、もう1点教えていただきたいのですが、 上記 function getTable_Area()には '<td><input value=<?= getArea();?>></input></td>' のようにgetArea()などの関数を表が作成される際に呼ばれるよにしています。 しかし、表示されたタブをみてみると <input value="<?=" getarea();?=""> になっており、エスケープ処理?がされているみたいです。 実際にアプリを開発する際は、何か別の方法でinputの値に関数の戻り値を代入しているのでしょうか? >>882 そのgetAreaはどっちの関数? フロント?バック? >>884 これで良くない? function getTable_Area() { const a = new Date(); const b = getArea(); return '<table>' + '<thead>' + '<tr>' + '<th>Result</th>' + '</tr>' + '</thead>' + '<tbody>' + '<tr>' + '<td>Date</td>' + '<td><input value="' + a + '"></input></td>' + '</tr>' + '<tr>' + '<td>Area</td>' + '<td><input value="' + b + '"></input></td>' + '</tr>' + '</tbody>' + '</table>'; } >>885 なるほど。そのようにすればよかったのですか。 ありがとうございます!大変勉強になりました! >>887 いえいえ。重ね重ね、ありがとうございます! テンプレートリテラルを勉強して使ってみようと思います。 またご推察の通り、同期の問題も発生しておりますので、それも合わせて勉強してみます。 ERB(埋め込み・Embedded RuBy)なら、HTML 内で、 <% 〜 %> でRubyのコード片を実行するだけ(出力はしない)。 <%= 〜 %> でRubyのコード片を実行して出力する 例えば、a.html.erb が以下なら、 <% ary = [ "<a>", "あ" ] %> <% ary.each do |item| %> <input type="text" value="<%= item %>"> <% end %> a.html は、以下のように出力される <input type="text" value="<a>"> <input type="text" value="あ"> やりたいこと: Maps.newStaticMap()で作成した画像?をHTML上に表示させたい。 試したこと: index.htmlから呼ばれるtest.gsの関数内で var googleMap = Maps.newStaticMap().setCenter(centreY,centreX) を定義して return googleMap.getMapUrl(); でそのURLを取得しました。 そのURLをHTMLのIMGタグに <img src="〇〇〇" width="100px" height="100px"> と入れても画像が表示されませんでした。 HTML上でbodタグの中に画像を表示させようとしているのですが、ファイルアイコンが半分に敗れたものが表示されています。 >>891 getUrlで取得されたURLにあるものって画像じゃないよね 画像じゃないものをimgタグにセットしても表示されないよ URLにあるものを画像化するか iframe使って表示させるか(未検証) どっちかのアプローチじゃないかな read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる