シフト希望フォームの作り方・自動リマインドの設定手順
紙もLINEのバラバラ連絡もやめて、「回答フォーム」で集めて自動で催促する。手を動かせば同じ仕組みが作れる設定ガイドです。
1. つくる仕組みの全体像
この記事では、架空の「みやこ旅館」を例に、スタッフのシフト希望をLINEのフォームで集め、出していない人には自動で催促(リマインド)する仕組みを作ります。役割分担はシンプルです。
| 担当 | 役割 |
|---|---|
| エルメ | シフト希望フォームの受付・回答の記録・タグ付け・リマインド配信 |
| スプレッドシート | 回答の保存台帳(シフト希望台帳)と、スタッフ名簿 |
| GAS(Google Apps Script) | 締切後に「誰が出した/出していない」を集計し、管理者へLINEで自動通知 |
いちばん大事な前提:Webhookは1つ
LINE公式アカウントで「メッセージの受信を通知する先(Webhook〔ウェブフック〕)」は1つしか設定できません。エルメを使うと、その1枠はエルメが占有します。だからこの設計では、受信はすべてエルメに任せ、GASは「こちらから送る(push)」ことしかしません。GASに受信させようとすると、エルメと取り合いになって動かなくなります。
2. エルメで「シフト希望フォーム」を作る
エルメにはフォーム作成という機能があり、無料プランでもアンケート形式の入力フォームが作れます。まずシフト希望を入力してもらうフォームを1枚作ります。
設定の手順
操作場所:エルメ管理画面 > フォーム作成 > 新規作成
- 「新規作成」をクリックし、フォーム名を「シフト希望(管理用の名前)」とつける
- フォームのタイトルを「〇月シフト希望の提出」、説明文に締切日(例:毎月20日)を書く
- 下の表のとおり質問項目を追加する(質問名はそのままの文字で作る。あとでシートの見出しになります)
- 「メッセージ・アクション設定」タブを開き、回答後のアクションで「タグを付ける」を選び、タグ名を シフト_提出済 にする
- 同じ画面で、回答後に表示するお礼メッセージ(下のテンプレ)を設定して保存する
フォームの質問項目
| 質問名 | 形式 | 補足 |
|---|---|---|
| 氏名 | 自由入力(必須) | 名簿と突き合わせるので、いつも同じ表記で書いてもらう |
| 対象月 | 選択(必須) | 選択肢は「2026年8月」の形で作る(詳細は第6章のGASと合わせる) |
| 希望休 | 自由入力 | 例:3日、10日、17日 |
| 勤務NGの時間帯 | 自由入力 | 例:平日の朝は不可 など |
| 備考 | 自由入力(任意) | 連休希望・引き継ぎ事項など |
回答後のお礼メッセージ(コピペ用)
3. フォームの回答をスプレッドシートに連携する
エルメのフォームは、Googleスプレッドシートと連携しておくと回答があるたびに1行ずつ自動で記録されます。これが「シフト希望台帳」になります。
連携の手順
操作場所:エルメ管理画面 > フォーム作成(一覧) > スプレッドシート
- フォーム作成の一覧ページで、対象フォームの「スプレッドシート」をクリック
- 連携したいGoogleアカウントでサインインし、連携を許可する
- 連携後、テストで1回フォームに回答してみる(この操作でシートに見出し行が作られます)
- 作られたシートのタブ名を シフト希望台帳 に変更する
できあがる台帳(シフト希望台帳)
エルメはフォームの質問名を、そのまま見出しにして列を作ります。おおよそ次のような並びになります(先頭に回答日時が入ります)。
| 見出し | 中身 |
|---|---|
| 回答日時 | エルメが自動記録 |
| 氏名 | フォームの回答(名簿と突き合わせるキー) |
| 対象月 | 例:2026年8月 |
| 希望休 | 例:3日、10日、17日 |
| 勤務NGの時間帯 | 例:平日の朝は不可 |
| 備考 | 任意 |
4. フォームをスタッフに配布する
フォームには「配信用URL」があります。これをスタッフに配るだけで受付が始まります。配り方は2つ用意しておくと便利です。
① 毎月の配布(予約配信で自動化)
操作場所:エルメ管理画面 > メッセージ配信 > 新規作成
- 「新規作成」→ 管理用タイトルを「シフト希望フォーム配布」にする
- メッセージ本文に、第2章で作ったフォームの配信用URLを貼る(下のテンプレ)
- 配信対象は「全員(スタッフのタグを付けているなら、そのタグで絞り込み)」
- 「配信予約」を選び、毎月1日など、締切より前の日時を指定して登録する
② いつでも出せる入口(リッチメニュー)
操作場所:エルメ管理画面 > リッチメニュー
リッチメニューに「シフト希望を出す」ボタンを作り、タップ先にフォームの配信用URLを設定しておくと、スタッフが思い立ったときにいつでも提出できます。
5. 未提出のスタッフだけに自動リマインド
ここが「自動リマインド」の中心です。第2章で、フォームに回答した人には シフト_提出済 タグが自動で付くようにしました。つまりこのタグが付いていない人=まだ出していない人です。エルメの予約配信で「このタグが付いていない人だけ」に送れば、未提出者への催促が自動化できます。
リマインドの予約配信を作る
操作場所:エルメ管理画面 > メッセージ配信 > 新規作成
- 「新規作成」→ タイトルを「シフト未提出リマインド(15日)」にする
- 本文に催促メッセージ(下のテンプレ)とフォームURLを入れる
- 配信対象の絞り込みで「タグ」を選び、シフト_提出済 が付いていない人を条件にする
- 「配信予約」で毎月15日の朝などを指定して登録する
- 同じ要領で「19日(締切前日)」用のリマインドをもう1本作っておく
6. 締切後の提出状況を管理者に自動通知(GAS)
第5章までで、スタッフ側の受付とリマインドは完成です。最後に管理側の自動化として、締切後に「提出〇名/未提出〇名(+未提出者の名前)」を、店長のLINEへ自動で送る仕組みをGASで足します。誰を追いかければいいか、一目で分かります。
準備1:名簿シートを作る
台帳(エルメ連携シート)とは別のタブで、スタッフ全員の名簿を手で作ります。こちらは自由に編集して構いません。タブ名は 名簿 にします。
| 列 | 見出し | 中身 |
|---|---|---|
| A | スタッフID | 任意の社員番号(同姓同名の区別用。無ければ空でも可) |
| B | 氏名 | フォームで入力してもらう氏名と同じ表記にする |
準備2:管理者のLINEユーザーIDと、チャネルアクセストークン
- 管理者のLINEユーザーID:LINE Developersコンソールの対象チャネルの基本設定に「あなたのユーザーID(Uから始まる文字列)」が表示されます。これを控えます。
- チャネルアクセストークン:同じくLINE Developersコンソールの「Messaging API設定」で発行します。GASが送信(push)に使います。これはエルメが使う受信(Webhook)とは別物なので、エルメと競合しません。
GASを貼り付ける
操作場所:スプレッドシート > 拡張機能 > Apps Script
- Apps Scriptを開き、最初のコードを全部消して、下のコードを丸ごと貼り付ける
- 先頭の設定3か所(トークン・管理者ID・リマインド日)を自分の値に書き換える
- 保存し、時計マーク(トリガー)>「トリガーを追加」で dailyCheck を「時間主導型 > 日タイマー > 午前9〜10時」に設定する
/**
* シフト希望の集計を管理者へ自動通知(push専用・時刻トリガー起動)
* ※このGASは受信しない。Webhookはエルメが占有。時刻でこちらからpushするだけ。
* ※台帳シートはエルメ連携シート。GASは「読むだけ」で、絶対に書き込み・編集しない。
*/
// ▼ 設定(自分の環境に合わせて3か所を書き換える)
const CHANNEL_ACCESS_TOKEN = 'ここにチャネルアクセストークンを貼る';
const ADMIN_USER_ID = 'Uxxxxxxxxxxxxxxxx'; // 管理者のLINEユーザーID
const REMIND_DAYS = [15, 19]; // この日に「未提出者一覧」を管理者へ
const SUMMARY_DAY = 21; // 締切(20日)の翌日に「最終集計」を管理者へ
// シート名(第3章・第6章で決めたタブ名)
const SHEET_ROSTER = '名簿';
const SHEET_LEDGER = 'シフト希望台帳';
// 台帳の見出し名(第2章のフォーム質問名と一致させる)
const COL_NAME = '氏名';
const COL_MONTH = '対象月';
// 集める対象月のラベル(翌月)。例:7月に実行 → 「2026年8月」
function targetMonthLabel_() {
const now = new Date();
let y = now.getFullYear();
let m = now.getMonth() + 2; // getMonthは0始まりなので +2 で翌月
if (m > 12) { m -= 12; y += 1; }
return y + '年' + m + '月';
}
// 台帳から「当月の提出済み氏名」を集める(見出しで列を探すので列位置がずれても動く)
function submittedNames_() {
const sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_LEDGER);
const v = sh.getDataRange().getValues();
const h = v[0];
const iName = h.indexOf(COL_NAME);
const iMonth = h.indexOf(COL_MONTH);
const month = targetMonthLabel_();
const set = {};
for (let r = 1; r < v.length; r++) {
if (v[r][iMonth] === month && v[r][iName]) {
set[String(v[r][iName]).trim()] = true;
}
}
return set;
}
// 名簿の全氏名(B列)を配列で返す
function rosterNames_() {
const v = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_ROSTER).getDataRange().getValues();
const names = [];
for (let r = 1; r < v.length; r++) { // A=スタッフID / B=氏名
const name = String(v[r][1] || '').trim(); // B列=氏名
if (name) names.push(name);
}
return names;
}
// 毎朝この関数をトリガーで起動する(日付で自動的に出し分け)
function dailyCheck() {
const day = new Date().getDate();
if (REMIND_DAYS.indexOf(day) !== -1) { notifyAdmin_(false); return; }
if (day === SUMMARY_DAY) { notifyAdmin_(true); return; }
}
// 管理者へ提出状況をpush(final=true なら締切後の最終集計)
function notifyAdmin_(final) {
const submitted = submittedNames_();
const names = rosterNames_();
const month = targetMonthLabel_();
const notYet = names.filter(function(n){ return !submitted[n]; });
const done = names.length - notYet.length;
const head = final ? '【最終集計】' : '【途中経過】';
const body = head + month + ' シフト希望\n'
+ '提出 ' + done + ' / ' + names.length + '名\n'
+ '未提出:' + (notYet.length ? notYet.join('、') : 'なし');
pushText_(ADMIN_USER_ID, body);
}
// LINE Messaging API の push(受信しない・こちらから送るだけ)
function pushText_(userId, text) {
UrlFetchApp.fetch('https://api.line.me/v2/bot/message/push', {
method: 'post',
contentType: 'application/json',
headers: { 'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN },
payload: JSON.stringify({ to: userId, messages: [{ type: 'text', text: text }] }),
muteHttpExceptions: true
});
}
7. 動作テストとよくあるつまずき
公開前のテスト手順
- 自分(またはテスト用アカウント)でフォームに1回回答し、台帳シートに行が増えることを確認する
- 回答後、自分に シフト_提出済 タグが付いているか、友だち情報で確認する
- 第5章のリマインド配信を「テスト配信」で送り、タグ無しの人にだけ届くか確認する
- 第6章のGASで dailyCheck を手動実行し、管理者のLINEに集計が届くか確認する(初回は権限の承認を求められます)
よくあるつまずき
| 症状 | 原因と対処 |
|---|---|
| 台帳に回答が増えない | 連携シートを手で編集した可能性。第3章の注意のとおり編集しない。1回テスト回答すると復旧します。 |
| 提出済みの人にも催促が届く | 前月の シフト_提出済 タグを外し忘れ。第5章の運用注意を確認。 |
| 集計の人数が合わない | フォームの氏名表記と名簿B列の表記が違う(例:スペースの有無)。表記を揃える。 |
| GASの集計が「対象月」を拾わない | フォームの対象月の選択肢が「2026年8月」の形になっているか確認(08月やスペース混入に注意)。 |
| GASでLINEに送れない | チャネルアクセストークンの貼り間違い、または管理者ユーザーIDの誤り。両方を再確認。 |
まとめ
フォームで集める → タグで「出した人/出していない人」を分ける → 未提出者にだけ自動で催促、という流れで、シフト希望集めの声かけがほぼゼロになります。まず最初の一手は、第2章のフォームを1枚作って自分で回答してみること。ここまで動けば、あとは配信予約とGASを足すだけです。集計通知(第6章)は後回しでも、第5章までで十分に回り始めます。







