Google App Script(GAS)では、ユーザーに入力をしてもらうモーダルを表示することができます。
そして、モーダルに入力したデータに基づいて、スプレッドシートの中の該当するデータを引っ張ってきて表示することもできます。
ここではその方法について解説しています。
どんなことができるのか?
例えば、メニューの中にカスタムメニュー「プログラム」を作成し、その中の「データ取得」をクリックします。
すると入力ボックスがあるモーダルが表示されます。
この中に、データを見たいセル番号を入力し、ボタンをクリックします。
すると、モーダルの中に取得してきた結果を表示してくれます。
作成方法(コードとファイル)
GASでHTMLを指定してダイアログを作成するには、HTMLファイルとそれを呼び出す.gsファイルを作成する必要があります。
今回作成するのは以下の2つのファイルです。
それぞれのファイルのコードは以下になります。
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('プログラム');
menu.addItem('データ取得', 'showDialog');
menu.addToUi();
}
function showDialog() {
var html = HtmlService.createHtmlOutputFromFile('modal')
.setWidth(400)
.setHeight(300);
SpreadsheetApp.getUi()
.showModalDialog(html, 'セル番号を入力してください(例: A1)');
}
function getCellValue(e) {
let cell = e.inputData;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getActiveSheet();
let value = sheet.getRange( cell ).getValue();
return value;
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
.exec-btn {
display: block;
text-align: center;
vertical-align: middle;
width: 170px;
padding: 10px;
font-weight: bold;
border-radius: 100vh;
border-bottom: 7px solid #0686b2;
background: #27acd9;
color: #fff;
}
.exec-btn:hover {
margin-top: 6px;
border-bottom: 1px solid #0686b2;
color: #fff;
}
</style>
</head>
<body>
<form>
<input type="textbox" id="idName" size="20" name="inputData">
<br><br>
<input type="button" value="セルの値を取得"
onclick="google.script.run.withSuccessHandler(onSuccess).getCellValue(this.parentNode);"
class = "exec-btn"
/>
<br>
<div id="output"></div>
</form>
<script>
function onSuccess(cellVal) {
var div = document.getElementById('output');
var inputVal = document.getElementById('idName').value;
div.innerHTML = inputVal + 'セルの値:' + cellVal;
}
</script>
</body>
</html>
メニューを追加する方法
スプレッドシートにメニューを追加する関数は以下です。
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('プログラム');
menu.addItem('データ取得', 'showDialog');
menu.addToUi();
}
これで、「データ取得」というメニューをクリックすると「showDialog」という関数を実行します。
詳細については下記をご参考ください。
(参考)【GAS】メニューに自作した関数/プログラムを追加する方法を実例で解説
モーダルを開く|showModalDialogメソッド
function showDialog() {
var html = HtmlService.createHtmlOutputFromFile('modal')
.setWidth(400)
.setHeight(300);
SpreadsheetApp.getUi()
.showModalDialog(html, 'セル番号を入力してください(例: A1)');
}
showDialog関数でモーダルを開く処理を行います。
HtmlService
一番最初の「HtmlService」とはAppScriptが提供しているクラスで、スクリプトによってHTMLなどのテキストコンテンツを作成するものです。
HtmlService.関数名()
createHtmlOutputFromFile
createHtmlOutputFromFileはHtmlServiceクラスに用意されたメソッドです。
HtmlService.createHtmlOutputFromFile(ファイル名)
引数にhtmlファイル名を指定することで、指定したファイルの内容のオブジェクト(HtmlOutputオブジェクト)を作成します。※ファイル名の.htmlは省略できます。
指定したファイルのHTML形式が正しくない場合はエラーを返します。
(参考)Class HtmlService: createHtmlOutputFromFile(filename)
setWidthとsetHight
HtmlOutputクラスのsetWidthとsetHightメソッドを使うと対象のHtmlOutputオブジェクトの横幅と高さを指定することができます。
HtmlOutputオブジェクト.setWidth(整数)
HtmlOutputオブジェクト.setHeight(整数)
SpreadsheetApp
次に、スプレッドシートにサイドバーを実装するコードを見ていきます。
SpreadsheetApp.getUi().showModalDialog(html, 'セル番号を入力してください(例: A1)');
一番最初に出てくる「SpreadsheetApp」はGASでスプレッドシートを操作するためのクラスです。様々な便利なメソッドが用意されています。
getUi
getUiメソッドはSpreadsheetAppクラスに用意されたメソッドで、ユーザーインターフェースのインスタンスを取得します。
これで実際に表示されているスプレッドシートの画面を操作することがっできるようになります。引数は不要です。
showModalDialog
スプレッドシート上にモーダルを表示するにはshowModalDialogメソッドを使います。
基本構文は以下のようになります。
ユーザーインターフェース.showModelessDialog(HtmlOutputオブジェクト, タイトル)
ユーザーインターフェースとは、スプレッドシートであれば「SpreadsheetApp.getUi()」とします。
HtmlOutputオブジェクトとは、htmlファイルをオブジェクト化したものです。
なお、タイトルはモーダルの左上に表示される文字列で省略不可です。
以上でモーダルが完成します。
データ処理の流れ
続いて、モーダルの入力ボックスにセル番号を入力し、ボタンをクリックすると、スプレッドシートの対象のセルの値を取得してきてモーダル上に返す処理を行います。
まずはHTMLファイル上の処理が走ります。
<body>
<form>
<input type="textbox" id="idName" size="20" name="inputData">
<br><br>
<input type="button" value="セルの値を取得"
onclick="google.script.run.withSuccessHandler(onSuccess).getCellValue(this.parentNode);"
class = "exec-btn"
/>
<br>
<div id="output"></div>
</form>
<script>
function onSuccess(cellVal) {
var div = document.getElementById('output');
var inputVal = document.getElementById('idName').value;
div.innerHTML = inputVal + 'セルの値:' + cellVal;
}
</script>
</body>
onclickメソッド
コードの中でも最初に動くのがボタンクリック時のonclickメソッドです。
<input type="button" value="セルの値を取得"
onclick="google.script.run.withSuccessHandler(onSuccess).getCellValue(this.parentNode);"
class = "exec-btn"
/>
↓ onclickで実行する処理
google.script.run.withSuccessHandler(onSuccess).getCellValue(this.parentNode);
まずgetCellValueを実行し、その結果が問題なければonSuccessという関数を実行します。
以下でもう少し細かく解説します。
google.script.runとは何か?
onlickイベントで作動する処理の一番最初にgoogle.script.run
があります。
これはAppScriptで作成したHTMLファイルの中でAppScriptを実行できるとても便利な処理です。
App Scriptではファイルの種類として「スクリプト」と「HTML」を作成することができます。
このHTMLファイルの中で使う処理になります。
(参考)クラス google.script.run(クライアントサイド API)
withSuccessHandler
withSuccessHandlerはgoogle.script.runクラスの中で使えるメソッドです。
以下のように使用します。
google.script.run.withSuccessHandler(HTMLファイル上の関数).先に実行する関数
withSuccessHandlerを使うと、後ろに指定したサーバーサイド関数(AppScriptファイルの関数)が正常に返された場合に実行するコールバック関数(HTMLファイル上の関数)を設定することができます。
簡単に言うと、先に用意されている関数がエラーなく実行されたら次にこの処理を行うということです。
つまり、先にgetCellValue(this.parentNode)を実行し、その結果を受けてwithSuccessHandlerの処理を行うという処理になります。
(参考)クラス google.script.run: withSuccessHandler
this.parentNode
getCellValueを実行するときに、引数で「this.parentNode」を指定しています。
getCellValue(this.parentNode)
これは、現在のノードの親ノードを取得しています。parentNodeはセレクタに対して使用します。
セレクタ.parentNode
セレクタが「this」の場合、現在の要素を指します。
なお、親要素が存在しない場合はbodyを取得します。
今回の場合、parentNodeを指定しているinputタグの親要素はformタグになります。
<form>
<input type="textbox" id="idName" size="20" name="inputData">
<br><br>
<input type="button" value="セルの値を取得"
onclick="google.script.run.withSuccessHandler(onSuccess).getCellValue(this.parentNode);"
class = "exec-btn"
/>
<br>
<div id="output"></div>
</form>
getCellValue(this.parentNode)
ノードの要素.name属性の値(e.inputData)
先に実行するgetCellValue(this.parentNode)はAppScriptに記述してある処理になります。
function getCellValue(e) {
let cell = e.inputData;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getActiveSheet();
let value = sheet.getRange( cell ).getValue();
return value;
}
引数で渡された親ノード(this.parentNode)が変数eに入ります。
<form>
<input type="textbox" id="idName" size="20" name="inputData">
<br><br>
<input type="button" value="セルの値を取得"
onclick="google.script.run.withSuccessHandler(onSuccess).getCellValue(this.parentNode);"
class = "exec-btn"
/>
<br>
<div id="output"></div>
</form>
ポイントは入力ボックスとして表示しているinputタグです。
<input type="textbox" id="idName" size="20" name="inputData">
name属性に「inputData」とすることで、入力したデータのプロパティ名が「inuptData」入力値が値として格納されています。
このため、「e.inputData」とすることで、inputボックスに入力されたデータを取得できます。ここでは取得した値を変数「cell」に入れています。
let cell = e.inputData;
セルの値を取得して返す
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getActiveSheet();
let value = sheet.getRange( cell ).getValue();
return value;
SpreadsheetApp.getActiveSpreadsheet
で現在のスプレッドシートを取得し、ssという変数に入れます。
ss.getActiveSheet
で現在のシートを取得します。
sheet.getRange( cell ).getValue()
でinputボックスに入力したセルの値を取得します。
最後にreturnで結果を返します。
withSuccessHandlerの引数で指定した関数の実行(onSuccess関数)
getCellValue関数の処理が終わったら、withSuccessHandlerの引数で指定した関数onSuccessを実行します。
<body>
<form>
<input type="textbox" id="idName" size="20" name="inputData">
<br><br>
<input type="button" value="セルの値を取得"
onclick="google.script.run.withSuccessHandler(onSuccess).getCellValue(this.parentNode);"
class = "exec-btn"
/>
<br>
<div id="output"></div>
</form>
<script>
function onSuccess(cellVal) {
var div = document.getElementById('output');
var inputVal = document.getElementById('idName').value;
div.innerHTML = inputVal + 'セルの値:' + cellVal;
}
</script>
</body>
onSuccess関数はHTMLファイルのscriptタグの中に記述してあります。
<script>
function onSuccess(cellVal) {
var div = document.getElementById('output');
var inputVal = document.getElementById('idName').value;
div.innerHTML = inputVal + 'セルの値:' + cellVal;
}
</script>
戻り値を引数として受けとる
onSuccess(cellVal)の引数「cellVal」には、getCellValue関数のreturnの戻り値が入ります。
つまり、変数cellValの値は指定したセルの値になります。
document.getElementById
次にdocument.getElementByIdメソッドを使って、指定したIDをHTMLエレメントとして取得し、変数divに格納します。
var div = document.getElementById('output');
ここで取得しているid=”output”は以下のタグになります。
<div id="output"></div>
現時点ではid属性以外何もありません。
入力フォームの値を取得する|document.getElementById(‘id属性名’).value
入力フォームの値を取得するには.valueを使います。「.value」は対象のエレメントの中のvalueプロパティの値を取得するための記述です。
エレメント.value
ここではエレメントの指定にgetElementByIdメソッドを使い、ID名で指定しています。
document.getElementById('id属性名').value
innerHTML
最後にinnerHTMLを使って、指定したエレメントのHTML要素を変更しています。
エレメント.innerHTML = 変更後の文字列
ここではdocument.getElementById('output');
で取得したdivタグに対して値を指定しています。
div.innerHTML = inputVal + 'セルの値:' + cellVal;
inputValはinputボックスに入力された値、cellValはスプレッドシート上で対象のセルに入力されている値になります。
対象のdivタグが以下のように変化します。
<div id="output"></div>
↓ innerHTML実行後
<div id="output">[入力値]セルの値: [スプレッドシートのセルの値]</div>
これにより、モーダル上にスプレッドシートから取得してきた値が表示されます。
以上で解説は終わりです。
お疲れさまでした^^