経費精算の申請を毎日自動で確かめて、不備は申請者へ差し戻せます
経費の申請をGoogle スプレッドシートに集め、Google Apps Script(GAS)で毎日決まった時刻に確かめる仕組みの見本です。上限を超えた金額、領収書の添付もれ、同じ申請の二重登録を見つけて、申請者ごとに直してほしい点を知らせます。経理の担当者は、問題のない申請だけを承認に回せます。
画面は動きを再現したもので、データはすべて架空です
約3.5年、GASの仕組みを作って運用してきました。
- 1申請をシートに集める(フォームからでも可)
- 2毎日、上限・領収書・二重登録を確かめる
- 3不備は申請者へ知らせ、残りを承認に回す
再現画面※再現画面です(実際のGoogleの画面ではありません)。
経費の申請一覧(見本)
この一覧は交際費の上限を10,000円とした場合の確認結果の例です。JavaScriptが有効なら、上限を変えてチェックを試せます。
| 申請番号 | 申請者 | 利用日 | 科目 | 金額 | 領収書 | 確認結果 |
|---|---|---|---|---|---|---|
| E-1021 | 山田 | 2026-10-15 | 旅費交通費 | 2,860円 | あり | 問題なし |
| E-1022 | 佐々木 | 2026-10-16 | 交際費 | 18,400円 | あり | 上限超過 |
| E-1023 | 田村 | 2026-10-16 | 消耗品費 | 4,280円 | なし | 領収書なし |
| E-1024 | 山田 | 2026-10-17 | 交際費 | 7,600円 | あり | 問題なし |
| E-1025 | 中川 | 2026-10-18 | 旅費交通費 | 12,300円 | あり | 問題なし |
| E-1026 | 田村 | 2026-10-16 | 消耗品費 | 4,280円 | なし | 二重登録・領収書なし |
| E-1027 | 佐々木 | 2026-10-20 | 会議費 | 3,300円 | あり | 問題なし |
| E-1028 | 中川 | 2026-10-21 | 交際費 | 9,800円 | なし | 領収書なし |
- 問題なし4件
- 差し戻し4件
- 差し戻す人数3人
申請者へ送られる差し戻しの連絡(見本)
「チェックを実行」を押すと、不備のある申請について、申請者ごとの連絡文がここに出ます。
毎日動くGASの関数(抜粋)
時間主導型のトリガーで毎日17時に動かす想定です。科目ごとの上限や確かめる項目、連絡の送り方(メール、Google Chat など)は、実際の社内規程に合わせて変えます。
// 毎日17時にトリガーで実行
function checkExpenses() {
const sheet = SpreadsheetApp.getActive().getSheetByName('経費申請');
const rows = sheet.getDataRange().getValues().slice(1); // 見出し行を除く
const caps = { '交際費': 10000, '会議費': 5000 }; // 科目ごとの上限
const staff = getStaffAddresses_(); // 申請者名とアドレスの対応表
const seen = {};
const byPerson = {};
rows.forEach((r, i) => {
const [id, person, date, item, amount, receipt, result] = r;
if (!id || result) return; // 確認済みは飛ばす
const issues = [];
const key = [person, date, item, amount].join('|');
if (caps[item] && amount > caps[item]) issues.push('上限超過');
if (receipt !== 'あり') issues.push('領収書なし');
if (seen[key]) issues.push('二重登録(' + seen[key] + ')');
seen[key] = seen[key] || id;
sheet.getRange(i + 2, 7).setValue(issues.length ? issues.join('・') : '問題なし');
if (issues.length) {
(byPerson[person] = byPerson[person] || []).push(
`${id} ${item} ${amount.toLocaleString()}円:${issues.join('・')}`
);
}
});
Object.keys(byPerson).forEach(person => {
GmailApp.sendEmail(
staff[person],
'【経費精算】申請の内容をご確認ください',
`${person}さん\n\n次の申請に確認が必要な点があります。\n\n` +
byPerson[person].join('\n') +
'\n\n直したら、確認結果の欄を空にして保存してください。'
);
});
}
確認結果を一覧に書き込むので、同じ申請を毎日くり返し確かめることはありません。問題なしの申請は、承認の担当者がそのまま確認できます。