会食メモをGoogleフォームで自動化する方法-ビジネスパーソン向け|会食後3分で記録できる仕組み-

GAS
スポンサーリンク
スポンサーリンク

はじめに|会食メモが続かない一番の理由は「入力の面倒さ」

会食(打ち合わせ)後にメモを取ることが大事だと分かっていても、続かない理由はシンプルです。

  • メモ帳アプリを開くのが面倒
  • 書く項目を毎回考えるのが面倒
  • 後から探せない

つまり、入力が重いのです。

そこでおすすめなのが、
Googleフォームで会食後に3分入力 → 自動でスプレッドシートに整理して保存する仕組みです。

この記事では、初心者でも再現できるように、
フォームの作り方からGAS(Google Apps Script)での自動転記まで、手順を分解して説明します。

この記事でできるようになること

  • 会食メモ入力用のGoogleフォームを作れる
  • フォーム送信時に、自動で Meetings シートへ整形して追記できる
  • 会食ログが蓄積され、後で検索・活用できる

最終的には「会食メモ × リマインド」構成の土台になります。
(会う前日に自動通知する仕組みは別記事で扱います)

仕組みの全体像(初心者向け)

流れはこれだけです。

  1. 会食後にGoogleフォームで入力
  2. 回答が「フォームの回答」シートに記録される
  3. GASが動いて Meetings シートに整形して追記する

「フォームの回答シート」はGoogleフォームが自動で作ります。
私たちが作るのは「整理用のMeetingsシート」と「自動転記スクリプト」です。

Step1:スプレッドシートを準備する

まずスプレッドシートを新規作成し、シート名を次のようにします。

  • Meetings(整理後の会食ログを入れる)
  • People(相手一覧。今回のテーマでは必須ではないが推奨)

Meetingsシートのヘッダー(1行目)

Meetings シートの1行目に、以下を貼り付けてください(タブ区切り)。

meeting_id	date	person_id	place	attendees	topics	takeaway	mood	next_action	created_at

「People」の詳細は以下で紹介しています。ご参照下さい。

Step2:Googleフォームを作る(会食ログ入力)

Googleフォームを作成し、フォーム名は例として

「会食ログ入力(Meetings)」

にします。

フォームの質問項目(この順番が重要)

この順番で作成してください。
(後でGASが e.values をこの並びで読み取ります)

  1. 日付(日付)
  2. 相手(選択)(プルダウン)
  3. 場所(店名)(短文)
  4. 同席者(短文・任意)
  5. 話題(箇条書き)(段落)
  6. 要点(次回に効く一言)(段落)
  7. 雰囲気(ラジオボタン)
    • 良い / 普通 / 微妙
  8. 次アクション(期限付き推奨)(短文 or 段落)
フォーム例
相手(選択)の値はこうする(重要)

プルダウンの選択肢を次の形式にします。

  • P0001|山田 太郎(○○商事)
  • P0002|佐藤 花子(△△製作所)

この形式にすると、送信時に P0001 の部分だけ抽出して person_id に入れられます。

Step3:フォームの回答先を「同じスプレッドシート」にする

フォーム画面で

回答 → スプレッドシート(緑のアイコン)

を選び、先ほど作ったスプレッドシートにリンクします。

すると自動で フォームの回答 1 のようなシートができます。

この「フォームの回答」シートは編集せず、
GASで Meetings に整形して追記するのがポイントです。

Step4:GASで「フォーム送信 → Meetings追記」を作る

スプレッドシート上部メニューから

拡張機能 → Apps Script

を開いて、以下のコードを貼り付けます。このとき、任意のgsで保存します。

任意の名前でコードを保存

コード:フォーム送信をMeetingsへ整形して追記(M0001自動採番)

/** ===== Googleフォーム→Meetings 自動転記(個人版A) ===== */

// フォーム回答シート名(必要なら変更)
const SHEET_FORM_RESPONSES = "フォームの回答 1";

// Meetingsシート名(既存で定義済みなら二重定義しない)
const SHEET_MEETINGS = "Meetings";

/**
 * フォーム送信時トリガーで動く関数
 */
function onFormSubmit(e) {
  // e.values: [タイムスタンプ, 日付, 相手, 場所, 同席者, 話題, 要点, 雰囲気, 次アクション]
  const v = e.values;
  if (!v || v.length < 9) return;

  const date = v[1];
  const personChoice = v[2];
  const place = v[3];
  const attendees = v[4];
  const topics = v[5];
  const takeaway = v[6];
  const mood = v[7];
  const nextAction = v[8];

  // "P0001|山田 太郎(○○商事)" → "P0001"
  const personId = extractPersonId_(personChoice);
  if (!personId) return;

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const shMeetings = ss.getSheetByName(SHEET_MEETINGS);

  const meetingId = generateNextMeetingId_(shMeetings); // M0001形式
  const createdAt = new Date();

  shMeetings.appendRow([
    meetingId,
    normalizeDate_(date),
    personId,
    place || "",
    attendees || "",
    topics || "",
    takeaway || "",
    mood || "",
    nextAction || "",
    Utilities.formatDate(createdAt, Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm")
  ]);
}

/**
 * 1回だけ実行:フォーム送信トリガーを作成
 */
function setupFormSubmitTrigger() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  ScriptApp.newTrigger("onFormSubmit")
    .forSpreadsheet(ss)
    .onFormSubmit()
    .create();
}

/** ===== util ===== */

function extractPersonId_(s) {
  if (!s) return null;
  const m = String(s).match(/^(P\d{4})\s*[||]/);
  return m ? m[1] : null;
}

function normalizeDate_(d) {
  const dt = (d instanceof Date) ? d : new Date(d);
  if (isNaN(dt.getTime())) return String(d);
  return Utilities.formatDate(dt, Session.getScriptTimeZone(), "yyyy-MM-dd");
}

function generateNextMeetingId_(shMeetings) {
  const lastRow = shMeetings.getLastRow();
  if (lastRow < 2) return "M0001";

  const lastId = shMeetings.getRange(lastRow, 1).getValue();
  const n = parseMeetingId_(lastId);
  const next = (n === null) ? 1 : (n + 1);
  return "M" + String(next).padStart(4, "0");
}

function parseMeetingId_(id) {
  const m = String(id || "").match(/^M(\d{4})$/);
  return m ? parseInt(m[1], 10) : null;
}

注意:すでに別のコードで SHEET_MEETINGS を定義している場合は二重定義しないでください。
SyntaxError: Identifier ... has already been declared の原因になります。

Step5:トリガーを設定する(必須)

このままでは自動では動きません。
最初に1回だけ setupFormSubmitTrigger() を実行します。

  1. Apps Scriptで setupFormSubmitTrigger() を選択
  2. 実行
  3. 権限許可を進める
「回答フォーム.gs」でコードを保存して、実行する例

これで、フォーム送信時に自動で onFormSubmit() が動きます。

動作確認

  1. Googleフォームから1件送信
  2. Meetings シートに行が増えれば成功
  3. meeting_idM0001 形式で入っている
  4. person_idP0001 になっている

よくあるエラーと解決策(初心者がつまずく所)

1) Identifier 'SHEET_MEETINGS' has already been declared

同じ定数名を二重に const 定義したときに出ます。

  • 対処:定数はプロジェクト内で1回だけ定義する
    → どちらかを削除してください。

2) Cannot read properties of undefined (reading 'values')

onFormSubmit() を手動実行したときに出ます。
フォーム送信時にしか e が渡されないためです。

  • 対処:手動実行しない。フォームから送信してテストする。

3) person_id が空になる

相手選択肢が P0001|... 形式になっていない可能性があります。

  • 対処:選択肢の形式を統一する

ここまでで「会食メモが資産化」する

この仕組みを入れるだけで、会食メモは次のように変わります。

  • 書き散らかしたメモ → 検索できるログ
  • 思い出せない → 次回の会話につながる
  • 続かない → 3分入力で継続できる

これが「会食メモ × リマインド」構成の土台です。

タイトルとURLをコピーしました