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

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

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

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

Q&A

1回答

1613閲覧

html内のgoogle.script.runで呼び出す関数に値を引き渡したい

chocolatxx

総合スコア22

Google Apps Script

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

0グッド

0クリップ

投稿2022/08/01 15:16

編集2022/08/03 12:46

前提

GASで業務管理アプリを作成しています。

実現したいこと

調べた情報を元に最低限の機能については実装することができました。
もう1点見直しをしたい仕様があります。

現在は、
Session.getActiveUser().getEmail();
を使ってgoogleアカウントの判定をし、対象のhtml(※メインページ)を呼び出しています。
この仕様だと本人以外の業務のアサイン状況が確認できない仕様となっています。

以下の仕様で、googleアカウントに紐づく情報(※ID)を受け渡し、
各担当者のメインページを呼び出したいと考えていますがそもそも可能なのでしょうか。

画面遷移
1.本人のメインページを呼び出す。
2.メインページ内に各担当者のIDを含んだリンクを記述しておく。
3.リンクからhtmlを呼び出した際に、IDに基づいたメインページを呼び出す。
※ここでは自分以外の担当者のメインページを開く。

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

現状試してみた方法だと、IDの受け渡しができない状態です。
ページの情報はIDを元に、スプレッドシートを指定し、スプレッドシートの内容を
反映しているためメインページには何も表示されません。

該当のソースコード

index.html

1<!DOCTYPE html> 2<html> 3 <head> 4 <base target="_top"> 5 <?!= HtmlService.createHtmlOutputFromFile('css').getContent(); ?> 6 </head> 7 <body> 8 <div class='contents'> 9 <div class='main'> 10 <h3><?=name?>の管理</h3> 11 12 <div class='table_Layout'> 13 <p>業務1</p> 14 <table id='業務1'></table> 15 </div> 16 17 </div><br> 18 <div class="link"> 19 <a id="link" href="<?= getAppUrl() ?>?p=manage&n=hogehoge">このリンクから他の人のページに移動したい</a> 20 </div> 21 </div> 22 </body> 23</html> 24 25<!--jQueryのCDN読み込み--> 26<script 27 src="https://code.jquery.com/jquery-3.6.0.slim.min.js" 28 integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" 29 crossorigin="anonymous"> 30</script> 31 32<script> 33  34 //webページの読み込み時に実行 35 window.onload = function(){ 36 //エクセルDBからアサイン状況を表示 37 google.script.run.withSuccessHandler(function(dt) { 38 for(var i = 0; i<dt.length - 1; i++) { 39 var date = new Date(dt[i][0]); 40 var dateText = `${date.getMonth() + 1}月${date.getDate()}日`; 41 $('#業務1').append(`<input type="button" 42 id="${dt[i][3]}" 43 value="${dateText + '_' + 業務名をDB(スプレッドシート)から取得)'}" 44 onclick="window.open('<?= getAppUrl();?>?p=assign&d=${date}&f=${dt[i][1]}&n=${dt[i][2]}','_blank','width=280,height=400')">`); 45 } 46 }).values1get();

gs

1if(page == 'index' || page == null) { 2 const ssID = SpreadsheetApp.openById('1HCaDY19PHQLkWMKH7YqNlgyLX-GNSF4v6GKB8sRbLvQ'); 3 const sheetID = ssID.getSheetByName('ID'); 4 5 const rowCountID = sheetID.getLastRow(); 6 const regAccountID = sheetID.getRange(2,3,rowCountID - 1,1).getValues(); 7 var userID = Session.getActiveUser().getEmail(); 8 const regssDBName = sheetID.getRange(2,2,rowCountID - 1,1).getValues(); 9 10 for(let i = 0; i<= rowCountID - 1; i++) { 11 if(regAccountID[i] == userID) { 12 var ssDBName = regssDBName[i]; 13 break; 14 } 15 } 16 let htmlOutput = HtmlService.createTemplateFromFile('index'); 17 htmlOutput.name = ssDBName; 18 return htmlOutput.evaluate().setTitle('業務管理').addMetaTag('viewport', 'width=device-width,initial-scale=1'); 19 20 } 21

gs

1function values1get() { 2 //ログイン中のgmailアカウントを元に、IDファイルからデータベースのIDを取得 3 const ssID = SpreadsheetApp.openById('全担当者のIDを保存しているスプレッドシートのID'); 4 const sheetID = ssID.getSheetByName('ID'); 5 6 let rowCountID = sheetID.getLastRow(); 7 const regAccountID = sheetID.getRange(2,3,rowCountID - 1,1).getValues(); 8 const userID = Session.getActiveUser().getEmail(); 9 const regssDbID = sheetID.getRange(2,4,rowCountID - 1,1).getValues(); 10 11 for(let i = 0; i<= rowCountID - 1; i++) { 12 if(regAccountID[i] == userID) { 13 const ssDbID = regssDbID[i]; 14 15 //管理画面に業務進捗を出力 16 var ss = SpreadsheetApp.openById(ssDbID); 17 var sheet = ss.getSheets(); 18 19 //各シートのデータを配列に格納 20 var rowCount = sheet[0].getLastRow(); 21 var dataRange = sheet[0].getRange(2,1,rowCount,4); 22 const values1 = dataRange.getValues(); 23 24 return values1; 25 break; 26 } else { 27 //エラー時の処理いれる 28 } 29 } 30}

実現したいこと

indes.html内に仮で『n=hogehoge』と入れていますが、何らかの形でリンクを踏む際に担当者のID情報を受け渡す。
values1get()の関数で呼び出すスプレッドシートのIDをgetEmail()によるログイン中のIDを、リンクを踏んだ際に受け渡されたID情報を元に参照する担当者のDBを設定したい。

ご教授いただけますと幸いです。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2022/08/02 00:26 編集

そもそもの問題がどこにあるかの切り分けが必要かと思うのですが、 下記について確認されましたか? ・const userID = Session.getActiveUser().getEmail(); のところでメールアドレス(またはGoogleアカウントを区別するための文字列)が確実に取得できているか? (確認方法:values1get関数の冒頭で console.log(Session.getActiveUser().getEmail()); として保存、デプロイし、デプロイしたページを一度開いた後、GASエディタ左の「実行数」アイコンをクリックしてログを開いて、期待するuserIDがきちんと出力されているかをチェックする) ↓ それが取得できているならば、そのメールアドレス文字列をもとに、スプレッドシートからきちんと目当てのデータ(ID)が取得できているか ↓ IDがきちんと取得できているならば、gasのコードまではきちんと動いているということなので、あとはhtml側の問題となります。 たとえばページを開いた状態でctrl+shift+Iを押してデベロッパーツールを開いた際に コンソールに何かエラーが発生していればそれを書いてください。 (スプレッドシートの内容[どの行・どの列にどのようなデータが入っているのか]が一切記載されておらず、またhtmlのソースも一部しか記載されていないので現状はこちらで再現できず原因の追究のしようがありません) 「リンクから開いたhtml自体にはIDを受け渡すことはできました」というのは、getAppUrl()関数とdoGet関数が正しく動いていることだけしか証明していません。
chocolatxx

2022/08/02 00:33

回答ありがとうございます。 また、質問内容に不足が多々ある状況で申し訳ありません。 現状、getEmailからIDの紐付けをした場合、GASの処理は問題なく実行されています。 (複数アカウントで確認) 最後にいただいたご指摘はおっしゃる通りで、一旦はそのデータを渡せないかと考えましたが実現できず質問をさせていただきました。 今すぐにコードの貼り付けが難しいため、改めてコンソールのエラーも含め確認後、質問内容に追記したいと思います。 またお時間があれば回答いただけますと幸いです。
guest

回答1

0

たとえば、下記のような単純なWebアプリを考えてみます。


【要求】
・ユーザーがページにアクセスすると、自分のデータとともに、「ユーザA」、「ユーザB」、「ユーザC」「自分のページ」にジャンプする4つのボタンが表示される。
・各ボタンを押すと、その押したボタンに対応するユーザのデータを表示するページが開く(開いた先のページでも4つのボタンは同様に表示される)


 
【要件】
上記の動作を行わせるために、URLの特定のパラメータの有無で処理を分岐させるというやり方が考えられます。
具体的には、
① URL内に「user」パラメータが存在しない場合は、ログインしているユーザのデータを表示する。
② URL内に「user」パラメータにユーザID(メールアドレス)が設定されている場合は、その指定されたユーザIDのデータを表示する。

ということです。
例)

  → user パラメータが存在しないので、ログインしているユーザのデータを表示

  → user パラメータに指定されている「abc123@example.com」のデータを表示

なお簡便のため、この例における「ユーザのデータを表示」する処理とは、単純に「ユーザIDの文字列を表示するだけ」とします。
実際には、質問文記載のように、ユーザIDをもとにデータベース(スプレッドシート)からそれぞれのデータを引っ張ってきて加工・表示する処理になります。


それでは、上記のような動作をさせるために、さらに具体的にどのようなコードを書けばよいか?というのがここでの例題です。

回答例は下記になります。

code.gs

js

1function doGet(e) { 2 // user パラメータを取得。 3 let user = e.parameter.user; 4 5 if (user == null) { 6 // user パラメータが存在しない場合は、ログイン中のユーザIDを設定。 7 user = Session.getActiveUser().getEmail(); 8 } 9 let htmlOutput = HtmlService.createTemplateFromFile('index'); 10 htmlOutput.user = user; 11 return htmlOutput.evaluate(); 12} 13 14function getAppUrl() { 15 return ScriptApp.getService().getUrl(); 16}

index.html

html

1<!DOCTYPE html> 2<html> 3<head> 4 <base target="_top"> 5</head> 6 7<body> 8 表示中のデータ: 9 <br/> 10 ユーザー: <?= user ?> 11 <br/> 12 13 <input type="button" value="ユーザAのページを開く" 14 onclick="window.open('<?= getAppUrl();?>?user=user_a@example.com')"/> 15 <br/> 16 <input type="button" value="ユーザBのページを開く" 17 onclick="window.open('<?= getAppUrl();?>?user=user_b@example.com')"/> 18 <br/> 19 <input type="button" value="ユーザCのページを開く" 20 onclick="window.open('<?= getAppUrl();?>?user=user_c@example.com')"/> 21 <br/> 22 <input type="button" value="自分のページを開く" 23 onclick="window.open('<?= getAppUrl();?>')"/> 24 <br/> 25</body> 26</html>

--
コードをご覧になればお分かりかと思いますが、流れは下記のようになります。

① 「user」パラメータのないデプロイ URL をブラウザで開いた場合:
doGet 関数内で、user パラメータがないので if (e.parameter.user == null) が正となり
変数userに、ログイン中のユーザーのユーザID(メールアドレス)が設定されます。
そして、この 変数 user の値 がHTMLテンプレート内の user に渡されます。

inde.html内の スクリプトレット <?= user => の部分が、code.gsから渡された値(ログイン中のユーザのユーザID」)に置換されます。

② 「ユーザAのページにジャンプ」ボタンをクリックした場合
「user=user_a@example.com」というパラメータを含むURLがブラウザで開かれます。

doGet 関数内で、user パラメータに設定されている値(user_a@example.com)が、HTMLテンプレートの user に渡されます。

inde.html内の スクリプトレット <?= user => の部分が、code.gsから渡された値(user_a@example.com)に置換されます。

③ 「自分のページを開く」ボタンをクリックした場合は、ボタンのonclickに指定してある URL に、user パラメータが存在しないため、①と同様にログイン中ユーザのデータが表示されているページが開きます。


上記を応用すれば質問者さんの思うような動作を行わせることができるのではないでしょうか。


コメント内の後だし質問に対する回答

htmlのscript内で実行するGASに値を渡す方法がわからない

単純に、GAS側の関数に引数を渡して呼び出せばいいだけと思いますが。

index.html

12<script> 3 google.script.run.withSuccessHandler(function(dt) { 45 }).values1get(hikisuu); // 引数を付けてGASの関数を呼び出す 6} 7

gs

1function values1get(hikisuu) { // 引数を受け取る 23}

投稿2022/08/03 13:41

編集2022/08/05 14:33
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

chocolatxx

2022/08/03 13:58

誤記があり申し訳ありません。 現時点で、このhtml内にscriptについては既に問題なく動作しています。 今回行き詰った内容は、上記のコードでは担当者ごとに作成をしているDB(スプレッドシートで作成)のIDの取得をgetEmail()で行っているため、ログイン中のgoogleアカウントを参照したDBにしかアクセスできません。 これを見直すために、コードを修正し、リンクを経由することでログイン中のgoogleアカウント以外を参照できないかというところになります。 例として、質問内容文末のコメント内に記載しているように、リンクにn=hogehogeといった形でIDを埋め込み、その受け渡しにより参照できないかと一度試してみましたがこちらは上手くいかない結果でした。 ※なおこちらのコードは削除してしまったため、すぐに記載することは難しい状況です。 GASを書き始めて1か月ほどで不備が多々あり申し訳ありません。
退会済みユーザー

退会済みユーザー

2022/08/05 14:25 編集

修正しました。
chocolatxx

2022/08/05 13:00

今回コメントいただいたところまではこの質問をさせていただいた約1週間前には試してみた内容です。 初めにいただいたコメントで、 >>「リンクから開いたhtml自体にはIDを受け渡すことはできました」というのは、getAppUrl()関数とdoGet関数が正しく動いていることだけしか証明していません。 と記載いただいたように、その動作までは問題ありません。 リンクからIDを引き継ぐ仕様の場合、htmlまでは値を渡せますが、そのhtmlのscript内で実行するGASに値を渡す方法がわからないというところです。
退会済みユーザー

退会済みユーザー

2022/08/05 14:29 編集

追記しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.45%

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

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

質問する

関連した質問