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

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

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

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

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

897閲覧

gas 埋め込みスクリプトをscriptタグに移動させたい

testtesttest11.

総合スコア4

Google Apps Script

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

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2023/03/19 13:28

実現したいこと

スプレッドシートにリストを持っている
html(gas作成)にスプレッドシートのリスト(jsで作成するカレンダーとマージして)を表示させたい

前提

予約システムを作成中
gasでHTMLを作成中(googlesフォームだとエラーチェックができないため)
詳しくないため、いろいろなページを見ながら作成中(なのでコードがごちゃごちゃしています)
スプレッドシートに予約可能数は保存されています

スプレッドシートイメージ
|日付|予約上限|予約数|予約可能数
|3/1|10|2|8
|3/2|10|3|7
|3/3|10|2|8
|3/4|30|28|2

※スプレッドシートの予約数は関数を組んで実際の予約から計算して表示しています
※予約可能数は予約上限-予約数です

できていること

◇カレンダーの表示
html(calender.html)にはJSを利用してカレンダーを表示しています
(一か月先まで受付可能としたく、2か月分のカレンダーを表示)

◇スプレッドシートデータ取得
bodyに<? ?>と埋め込み式に表示することは可能

こまっていること と やったこと

①<? の内容をJSに移動すると何も表示されなくなる
→var をconstにしたら改善したことがあったので変更してみましたがNGでした

②予約表は以前からの日付が入っており、カレンダーとマージしたい
→①ができないので実現できなかった。今日日付は取得できているので、スプレッドシートの値を入れたdateのdate[i][0]をforで回せば取得できますでしょうか?

③スプレッドシートの値(日付)が長くなる
:Wed Mar 01 2023 00:00:00 GMT+0900 (日本標準時)
→toStringDateや toDateが使えるとありましたがいずれもダメでした

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

エラーメッセージは表示されずそもそもカレンダーが表示されない

OKなソースコード(ただしカレンダーとリストが別々に表示される)

<!DOCTYPE html> <html> <head> <base target="_top"> </head> <body> <div id="calendar" class="field"></div> </body> <h2>Gas埋め込みテスト</h2> <br /> <? var ssId = 'XXXXXXXXXXXXXXXX'; var ss = SpreadsheetApp.openById(ssId); var sheetName = 'シート1'; var data = ss.getSheetByName(sheetName).getDataRange().getValues(); var result = '<table border="1">'; for(var i=0; i<data.length; i++){ result += '<tr>'; result += "<td>" + data[i][0].toString() + "</td>"; result += "<td>" + data[i][3].toString() + "</td>"; result += '</tr>'; } result += '</table>'; output._ = result; ?> <script> function goToNext() { google.script.run .withSuccessHandler(function(result) { // 成功 // resultとしてHTMLが返されます。 }) .withFailureHandler(function(result) { // 失敗 }).gotoSecondPages(/*渡したいデータ*/); } const weeks = ['日', '月', '火', '水', '木', '金', '土'] const date = new Date() let year = date.getFullYear() let month = date.getMonth() + 1 const config = { show: 2, } function showCalendar(year, month) { for ( i = 0; i < config.show; i++) { const calendarHtml = createCalendar(year, month) const sec = document.createElement('section') sec.innerHTML = calendarHtml document.querySelector('#calendar').appendChild(sec) month++ if (month > 12) { year++ month = 1 } } } function createCalendar(year, month) { const today_day = new Date().getDate() const today_month = new Date().getMonth() +1 const startDate = new Date(year, month - 1, 1) // 月の最初の日を取得 const endDate = new Date(year, month, 0) // 月の最後の日を取得 const endDayCount = endDate.getDate() // 月の末日 const lastMonthEndDate = new Date(year, month - 2, 0) // 前月の最後の日の情報 const lastMonthendDayCount = lastMonthEndDate.getDate() // 前月の末日 const startDay = startDate.getDay() // 月の最初の日の曜日を取得 let dayCount = 1 // 日にちのカウント let calendarHtml = '' // HTMLを組み立てる変数 calendarHtml += '<h1>' + year + '/' + month + '</h1>' calendarHtml += '<table>' // 曜日の行を作成 for (let i = 0; i < weeks.length; i++) { calendarHtml += '<td>' + weeks[i] + '</td>' } for (let w = 0; w < 6; w++) { calendarHtml += '<tr>' for (let d = 0; d < 7; d++) { if (w == 0 && d < startDay) { // 1行目で1日の曜日の前 let num = lastMonthendDayCount - startDay + d + 1 calendarHtml += '<td class="is-disabled">' + num  + '</td>' } else if (dayCount > endDayCount) { // 末尾の日数を超えた let num = dayCount - endDayCount calendarHtml += '<td class="is-disabled">' + num + '</td>' dayCount++ } else { if( month == today_month && dayCount <= today_day){ calendarHtml += `<td class="is-disabled">${dayCount}</td>` //calendarHtml += `<td class="calendar_td" data-date="${year}/${month}/${dayCount}">${dayCount}</td>` }else{ calendarHtml += `<td class="calendar_td" data-date="${year}/${month}/${dayCount}">${dayCount}</br>予約数</td>` } dayCount++ } } calendarHtml += '</tr>' } calendarHtml += '</table>' return calendarHtml } showCalendar(year, month) </script>

NGなソースコード(何も表示されない)

<!DOCTYPE html> <html> <head> <base target="_top"> </head> <body> <div id="calendar" class="field"></div> </body> <h2>Gas埋め込みテスト</h2> <br /> <script> function goToNext() { google.script.run .withSuccessHandler(function(result) { // 成功 // resultとしてHTMLが返されます。 }) .withFailureHandler(function(result) { // 失敗 }).gotoSecondPages(/*渡したいデータ*/); } const weeks = ['日', '月', '火', '水', '木', '金', '土'] const date = new Date() let year = date.getFullYear() let month = date.getMonth() + 1 const config = { show: 2, } function showCalendar(year, month) { for ( i = 0; i < config.show; i++) { const calendarHtml = createCalendar(year, month) const sec = document.createElement('section') sec.innerHTML = calendarHtml document.querySelector('#calendar').appendChild(sec) month++ if (month > 12) { year++ month = 1 } } } function createCalendar(year, month) { var ssId = 'XXXXXXXXXXXXXXXX'; var ss = SpreadsheetApp.openById(ssId); var sheetName = 'シート1'; var data = ss.getSheetByName(sheetName).getDataRange().getValues(); const today_day = new Date().getDate() const today_month = new Date().getMonth() +1 const startDate = new Date(year, month - 1, 1) // 月の最初の日を取得 const endDate = new Date(year, month, 0) // 月の最後の日を取得 const endDayCount = endDate.getDate() // 月の末日 const lastMonthEndDate = new Date(year, month - 2, 0) // 前月の最後の日の情報 const lastMonthendDayCount = lastMonthEndDate.getDate() // 前月の末日 const startDay = startDate.getDay() // 月の最初の日の曜日を取得 let dayCount = 1 // 日にちのカウント let calendarHtml = '' // HTMLを組み立てる変数 calendarHtml += '<h1>' + year + '/' + month + '</h1>' calendarHtml += '<table>' // 曜日の行を作成 for (let i = 0; i < weeks.length; i++) { calendarHtml += '<td>' + weeks[i] + '</td>' } for (let w = 0; w < 6; w++) { calendarHtml += '<tr>' for (let d = 0; d < 7; d++) { if (w == 0 && d < startDay) { // 1行目で1日の曜日の前 let num = lastMonthendDayCount - startDay + d + 1 calendarHtml += '<td class="is-disabled">' + num + '</td>' } else if (dayCount > endDayCount) { // 末尾の日数を超えた let num = dayCount - endDayCount calendarHtml += '<td class="is-disabled">' + num + '</td>' dayCount++ } else { if( month == today_month && dayCount <= today_day){ calendarHtml += `<td class="is-disabled">${dayCount}</td>` //calendarHtml += `<td class="calendar_td" data-date="${year}/${month}/${dayCount}">${dayCount}</td>` }else{ calendarHtml += `<td class="calendar_td" data-date="${year}/${month}/${dayCount}">${dayCount}</td>` } dayCount++ } } calendarHtml += '</tr>' } calendarHtml += '</table>' return calendarHtml } ) showCalendar(year, month) </script>

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

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

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

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

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

guest

回答1

0

ベストアンサー

①<? の内容をJSに移動すると何も表示されなくなる

1. まず、構文エラーがあるのでこの時点でうまく動きません。
下でコメントを付けた括弧は削除してください。

js

1 2 return calendarHtml 3} 4 5) # <--- 余計な括弧 6showCalendar(year, month) 7 8</script>

 

2. 前月の末日の計算が間違っています。2か月前の末日を取得しているように見受けられます。

js

1 const lastMonthEndDate = new Date(year, month - 2, 0); // 前月の最後の日の情報

 
ここは、下記のように直します。

js

1 const lastMonthEndDate = new Date(year, month - 1, 0); // 前月の最後の日の情報

 

3. ただし、上記を直しても、うまく動かないはずです。
理由は、JavaScript から Google Apps Script を直接呼び出すことはできないからです。
具体的には、NGとなっているコードの下記の部分

js

1function createCalendar(year, month) { 2 var ssId = 'XXXXXXXXXXXXXXXX'; 3 var ss = SpreadsheetApp.openById(ssId); 4 var sheetName = 'シート1'; 5 var data = ss.getSheetByName(sheetName).getDataRange().getValues();

ここは、google.script.run を使って呼び出す必要があります。
google.script.run は非同期呼び出しになるので、withSuccessHandler 内で処理が完結するように、コードの形を変える必要があります。
また、シートデータを呼び出す処理を index.html から GAS 側(コード.gs)に移す必要があります。
修正後の全体は下記になります。(②の分も含めて修正してます)

index.html

html

1<!DOCTYPE html> 2<html> 3 <head> 4 <base target="_top"> 5 </head> 6 <body> 7 <div id="calendar" class="field"></div> 8 <h2>Gas埋め込みテスト</h2> 9 <br /> 10 <script> 11 function goToNext() { 12 google.script.run 13 .withSuccessHandler(function(result) { 14 // 成功 15 // resultとしてHTMLが返されます。 16 }) 17 .withFailureHandler(function(result) { 18 // 失敗 19 }).gotoSecondPages( /*渡したいデータ*/ ); 20 } 21 22 const weeks = ['日', '月', '火', '水', '木', '金', '土']; 23 const date = new Date(); 24 let year = date.getFullYear(); 25 let month = date.getMonth() + 1; 26 const config = { 27 show: 2, 28 }; 29 30 31 /** 32 * 予約数を返す関数。 33 * year, month, date: 検索対象の年月日 34 * data: 予約表のデータ(2次元配列) 35 * return: 3列目の予約数 36 */ 37 function getNumberOfReservations(year, month, date, data) { 38 //予約表の1行目はラベルなので、2行目以降から検索 39 for (let i = 1; i < data.length; i++) { 40 const reservedate = new Date(data[i][0]); // 予約表の日付(1列目) 41 if (year == reservedate.getYear() + 1900 && 42 month == reservedate.getMonth() + 1 && 43 date == reservedate.getDate()) { 44 return data[i][2]; // 3列目の予約数を返す。 45 } 46 } 47 return 0; // 見つからなければ0を返す。 48 } 49 50 function showCalendar(year, month, data) { 51 for (i = 0; i < config.show; i++) { 52 const calendarHtml = createCalendar(year, month, data); 53 const sec = document.createElement('section'); 54 sec.innerHTML = calendarHtml; 55 document.querySelector('#calendar').appendChild(sec); 56 57 month++; 58 if (month > 12) { 59 year++; 60 month = 1; 61 } 62 } 63 } 64 65 function createCalendar(year, month, data) { 66 const today_day = new Date().getDate(); 67 const today_month = new Date().getMonth() + 1; 68 const startDate = new Date(year, month - 1, 1) // 月の最初の日を取得 69 const endDate = new Date(year, month, 0); // 月の最後の日を取得 70 const endDayCount = endDate.getDate(); // 月の末日 71 72 // const lastMonthEndDate = new Date(year, month - 2, 0); // 前月の最後の日の情報 73 const lastMonthEndDate = new Date(year, month - 1, 0); // 前月の最後の日の情報 74 75 const lastMonthendDayCount = lastMonthEndDate.getDate(); // 前月の末日 76 const startDay = startDate.getDay(); // 月の最初の日の曜日を取得 77 78 let dayCount = 1; // 日にちのカウント 79 let calendarHtml = ''; // HTMLを組み立てる変数 80 81 calendarHtml += '<h1>' + year + '/' + month + '</h1>'; 82 calendarHtml += '<table>'; 83 84 // 曜日の行を作成 85 for (let i = 0; i < weeks.length; i++) { 86 calendarHtml += '<td>' + weeks[i] + '</td>'; 87 } 88 89 for (let w = 0; w < 6; w++) { 90 calendarHtml += '<tr>'; 91 92 for (let d = 0; d < 7; d++) { 93 if (w == 0 && d < startDay) { 94 // 1行目で1日の曜日の前 95 let num = lastMonthendDayCount - startDay + d + 1; 96 calendarHtml += '<td class="is-disabled">' + num + '</td>'; 97 98 } else if (dayCount > endDayCount) { 99 // 末尾の日数を超えた 100 let num = dayCount - endDayCount; 101 calendarHtml += '<td class="is-disabled">' + num + '</td>'; 102 dayCount++; 103 } else { 104 if (month == today_month && dayCount <= today_day) { 105 calendarHtml += `<td class="is-disabled">${dayCount}</td>`; 106 //calendarHtml += `<td class="calendar_td" data-date="${year}/${month}/${dayCount}">${dayCount}</td>`; 107 } else { 108 // 予約数を表示 109 const reservations = getNumberOfReservations(year, month, dayCount, data); 110 calendarHtml += `<td class="calendar_td" data-date="${year}/${month}/${dayCount}">${dayCount}</br>予約数:${reservations}</td>`; 111 } 112 dayCount++; 113 } 114 } 115 calendarHtml += '</tr>'; 116 } 117 calendarHtml += '</table>'; 118 119 return calendarHtml; 120 } 121 122 google.script.run 123 .withSuccessHandler(function(data) { 124 showCalendar(year, month, JSON.parse(data)); 125 }).withFailureHandler(function(result) { 126 console.log("error!"); 127 console.log(result); 128 }).getData(); 129 130</script> 131</body>

コード.gs (doGet がある方)も下記のように直します。
具体的には、html 側から呼び出す getData() 関数を追加しています。
(一部推定している部分がありますが実際のコードに合わせてください)
※ 'シートID' の部分は実際のスプレッドシートIDに変えてください。

js

1// コード.gs 2function doGet() { 3 // 質問では明らかにされていないので仮 4 return HtmlService.createTemplateFromFile('index').evaluate(); 5} 6 7function goToNext() { 8 // 不明 9} 10 11function getData() { 12 const ssId = 'シートID'; 13 const ss = SpreadsheetApp.openById(ssId); 14 const sheetName = 'シート1'; 15 const data = ss.getSheetByName(sheetName).getDataRange().getValues(); 16 return JSON.stringify(data); 17}

②予約表は以前からの日付が入っており、カレンダーとマージしたい
今日日付は取得できているので、スプレッドシートの値を入れたdateのdate[i][0]をforで回せば取得できますでしょうか?

たとえば下記のようなデータがあるとして・・・

日付予約上限予約数予約可能数
3/231028
3/241037
3/251028
3/2630282

質問者さんのインスピレーションに従って for ループを使うなら
カレンダーに3月1日を書き込むとき→予約表の4行を走査して3月1日があるか調べる→ないので0
カレンダーに3月2日を書き込むとき→予約表の4行を走査して3月2日があるか調べる→ないので0
・・・
カレンダーに3月24日を書き込むとき→予約表の4行を走査して3月24日があるか調べる→あるので3列目の予約数を取得
・・・
というようにすればよいですね。

つまり「記入しようとしている年月日が予約表の中にあるかを検索して、
予約表の中にある日付であれば、予約表3列目を返す」というやり方ができそうです。
これを関数にすると以下のようになります。

js

1/** 2 * year, month, date: 検索対象の年月日 3 * data: 予約表のデータ(2次元配列) 4 * return: 3列目の予約数 5 */ 6function getNumberOfReservations(year, month, date, data) { 7 //予約表の1行目はラベルなので、2行目以降から検索 8 for (let i = 1; i < data.length; i++) { 9 const reservedate = new Date(data[i][0]); // 予約表の日付(1列目) 10 if (year == reservedate.getYear() + 1900 && 11 month == reservedate.getMonth() + 1 && 12 date == reservedate.getDate()) { 13 return data[i][2]; // 3列目の予約数を返す。 14 } 15 } 16 return 0; // 見つからなければ0を返す。 17}

getYear に 1900 を足す& getMonth に1を足す必要がある点に注意してください。

さらに index.html のカレンダー表示部分で上記の関数を呼びだすようにしています。
index.html

html

1<!DOCTYPE html> 2<html> 34 <script> 56... 7 } else { 8 // 予約数を表示 9 const reservations = getNumberOfReservations(year, month, dayCount, data); 10 calendarHtml += `<td class="calendar_td" data-date="${year}/${month}/${dayCount}">${dayCount}</br>予約数:${reservations}</td>`; 11 }

③スプレッドシートの値(日付)が長くなる

Utilities.formatDate() 関数を使いましょう。

質問文のOKバージョンを修正するなら、下記の様になります。

js

12<? 3 var ssId = 'シートID'; 4 var ss = SpreadsheetApp.openById(ssId); 5 var sheetName = 'シート1'; 6 var data = ss.getSheetByName(sheetName).getDataRange().getValues(); 7 8 var result = '<table border="1">'; 9 result += '<tr>'; 10 result += "<td>" + data[0][0] + "</td>"; 11 result += "<td>" + data[0][3] + "</td>"; 12 result += '</tr>'; 13 14 for(var i=1; i < data.length; i++){ 15 result += '<tr>'; 16 result += "<td>" + Utilities.formatDate(data[i][0],'Asia/Tokyo','yyyy年M月d日') + "</td>"; 17 result += "<td>" + data[i][3] + "</td>"; 18 result += '</tr>'; 19 } 20 result += '</table>'; 21 22 output._ = result; 23?> 24

投稿2023/03/20 11:30

編集2023/03/20 15:01
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

testtesttest11.

2023/03/26 12:20

ご回答ありがとうございます。 ③については綺麗に表示されることが確認できました。 >3. ただし、上記を直しても、うまく動かないはずです。 のところがうまくいきませんでした。 具体的にはカレンダーが表示されなくなりました。 シートIDの部分は上書きをしています。 何も表示されず何をしたらよいのか一週間考えましたが、抜け出せませんでした。。 ヒントいただけないでしょうか。 GASでデバッグの仕方がわからず、迷子になっています
testtesttest11.

2023/03/26 14:14

いろいろなサイトのスクリプトの寄せ集めのため、JSにconsole.logが残っておりそれが悪さをしておりました。 うまく表示されました! ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問