請求漏れをスプレッドシートで防ぐ仕組みをGASで作ってみた記録

「スプレッドシートの画面を背景に立つ作業着姿の男性。『請求漏れをスプレッドシートで防ぐ仕組みをGASで作ってみた記録 第184話』のアイキャッチ画像 AI活用

皆さんこんにちは、横浜で清掃業をしているヤスです。

前回はDifyでプロンプトの変数が反映されない?原因は「-変数:説明」という書き方だった

の記事でしたね。今回はこちらです。

スプレッドシートを見に行かなくても、「今日やること」が毎朝届くようになった

作ったのは、案件管理表から「対応待ちの案件」だけを自動で拾い出し、担当者ごとに仕分けて、毎朝メールで送ってくれる仕組みです。使ったのはGAS(Google Apps Script=スプレッドシートなどを自動で動かせる、Googleの無料のプログラミング機能)だけ。外部サービスもAIも使っていません。

なお、今回作ったデータや会社名等は全てダミーです。

「GASで自動化して作成した対応待ち案件一覧のスプレッドシート画面」

たとえばテスト運用でこんな一覧が届きました。

【対応待ち一覧】9/20 時点

●《田中》 4件

 ■ 着手漏れ(工事予定日が近い)
 2026-013 木村アパート 水漏れ修理 9/23(3日後)

 ■ 請求漏れ(完了済・未請求)
 2026-012 井上物流センター 換気ダクト工事 完了 8/1(50日経過)
 2026-004 株式会社ミドリ商事 空調機入替 完了 8/22(29日経過)
 2026-006 伊藤ビルサービス 配管清掃 完了 9/16(4日経過)

※これは検証用に自分で作った架空の案件管理表(設備工事会社を想定したダミーデータ)を流した結果です。実在の企業・人物ではありません。

100行あるシートから「今日やること」を目視で拾うのは大変で、見落としも起きます。その抽出作業をGASに任せた、という話です。

応募しなかった案件が、最高の練習教材になった

クラウドワークスで見つけたのは、設備工事会社の業務効率化案件でした。内容は、メールからの案件情報抽出、スプレッドシートへの登録、対応漏れの検出、見積書への転記、ファイルの自動分類など。報酬は月5〜10万円、稼働は平日1日5時間程度とのことでした。

応募はしませんでした。自分の稼働時間(週10時間程度)と合わなかったからです。

ただ、案件の内容そのものが「実務で本当に困っていることのリスト」になっていました。架空の課題を自分で考えるより、はるかに良い練習教材だと思いました。そこで、案件に書かれていた業務のうち、最初に挙げられていた「日報・対応待ち一覧の作成」を、練習として実際に作ってみることにしました。

作り方①:ダミーデータに「問題のある案件」をわざと仕込む

まず、案件番号・顧客名・工事内容・受注日・工事予定日・ステータス(見積中/受注済/施工中/完了/請求済)・担当者・最終更新日・金額・備考、という10列の案件管理表を、架空のデータ15件で用意しました。

ここで意識したのは、正常な案件だけでなく「引っかかるべき案件」を意図的に混ぜておくことです。工事予定日が近いのに未着手のもの、更新が長期間止まっているもの、完了しているのに未請求のものなどです。正常なデータだけでテストすると、ルールが動いているのか、たまたま何も引っかからないだけなのかが分かりません。

「顧客名やステータスを管理する『日報・対応待ち一覧』のスプレッドシート画面」

作り方②:何を「対応待ち」とするか、4つのルールを決める

次に、抽出ルールを4つ決めました。

  • 着手漏れ:工事予定日が3日以内なのに「受注済」のまま
  • 放置案件:最終更新から14日以上経過していて、ステータスが完了・請求済以外
  • 請求漏れ:ステータスが「完了」のまま「請求済」になっていない
  • 見積放置:「見積中」のまま最終更新から10日以上経過

3日や14日という数字は、資材手配に必要な最低日数や、拾いすぎて一覧が埋もれない範囲を考えて決めた自分なりの基準です。特に請求漏れのルールは、自分が個人事業主として請求作業の大変さを知っているからこそ思いついたものでした。工事が終わっているのに請求していない=入金されない、という経営インパクトの大きさは、実務を知らないと発想しにくい部分だと思います。

作り方③:GASで判定して、担当者別・色分けして出力する

Google Apps Script(GAS)のエディター画面。「日報・対応待ち一覧」というプロジェクトが開かれており、スプレッドシートの「案件管理」シートからデータを読み込み、担当者ごとにタスクを分類するためのJavaScriptコードが記述されている様子。

スプレッドシートの「拡張機能」→「Apps Script」からエディタを開き、案件管理シートを1行ずつ読み込んで、4つのルールに照らして判定するコードを書きました。

日付の比較では、時刻情報をリセットしないと日数がずれるので注意が必要でした。

function daysBetween(from, to) {
  const d1 = new Date(from);
  const d2 = new Date(to);
  d1.setHours(0, 0, 0, 0);
  d2.setHours(0, 0, 0, 0);
  return Math.round((d2 - d1) / (1000 * 60 * 60 * 24));
}

全件を一つの一覧に出すと見づらかったので、担当者をキーにしたオブジェクトを作り、担当者ごとに区分別の配列を持たせる形に変更しました。

const byTantou = {};

function addItem(tantou, kubun, item) {
  if (!byTantou[tantou]) {
    byTantou[tantou] = {
      chakushu: [],
      seikyu: [],
      houchi: [],
      mitsumori: []
    };
  }
  byTantou[tantou][kubun].push(item);
}

これで担当者ごとの件数が見えるようになり、テストデータでは「田中さんに請求漏れが3件集中している」といった負荷の偏りが一目で分かるようになりました。さらに、経過日数に応じて背景色(赤・オレンジ・黄色)を変える処理と、Gmailで毎朝自分宛てに送る処理を追加し、最後にトリガー機能で毎朝7〜8時に自動実行するよう設定しました。

function dailyTask() {
  createTodoList();
  sendTodoMail();
}

[スクショ:トリガー設定画面]

つまずきポイント:「実行中」のまま止まって、原因が全く分からなかった

一番焦ったのは、最初に実行したときでした。エディタ上で「実行中」の表示のまま、いつまで経っても終わらないのです。エラーも出ない。フリーズしたのかと思い、何度か再実行しましたが同じでした。

原因は、コードに入れていた SpreadsheetApp.getUi().alert() でした。Apps Scriptエディタから直接実行すると、alertのダイアログは「エディタの画面」ではなく「スプレッドシート側」に表示されます。エディタばかり見ていたので、ダイアログが出ていることに気づかず、OKを押されるまでずっと「実行中」のままだったのです。ブラウザのタブを切り替えて、ようやく気づきました。

対処は単純で、エディタから実行するときはalertを使わず、Logger.log() か throw new Error() にすること。教訓は、GASのUIは実行元(エディタから動かすか、メニューから動かすか、トリガーで自動実行するか)によって挙動が変わる、ということでした。実際、後で毎朝の自動実行を設定する際も、トリガー実行では画面を誰も見ていないため、alertが残っていたらそこでエラーになるところでした。

もうひとつは、単純に「『案件管理』シートが見つかりません」というエラーです。コード上ではシート名を 案件管理 で探していましたが、実際のスプレッドシートのシート名が初期値の「シート1」のままでした。シート名を揃えるだけで解決しましたが、名前の不一致はGASでありがちなつまずきポイントだと思います。

応用:この仕組みは「一つのアプリ」ではなく「一つの型」だった

作り終えてから気づいたことがあります。今回作ったのは、案件管理表専用のアプリではありませんでした。

やっていることを分解すると、こうなります。

  1. 一覧表を1行ずつ読む
  2. 条件に当てはまるものだけを拾う
  3. 緊急度の順に並べる
  4. 必要な人に知らせる

この構造は、案件管理以外の業務にもそのまま使えます。変えるのは「条件」の部分だけです。

他の業務に置き換えると

業務拾い出す条件の例
顧客リスト最終接触から3か月以上経っている顧客
在庫管理在庫数が発注点を下回った商品
契約管理更新期限まで30日を切った契約
スタッフ管理資格や免許の有効期限が近い人
請求管理入金予定日を過ぎても未入金の請求
設備点検前回点検から既定の期間が過ぎた設備

どれも「一覧から条件に合うものだけ抽出して、知らせる」という同じ仕組みです。

私の清掃業でいえば、定期清掃のお客様リストに「前回訪問から◯日以上空いているお客様」という条件を入れれば、フォロー漏れを防げそうです。

応用するときのコツ

条件は日本語で先に書く
コードを書く前に「何を拾いたいか」を言葉にします。今回もルール設計に一番時間を使いました。ここが決まれば、GASの部分はほぼ同じコードの流用で済みます。

「見落とすと困るもの」から始める
全部を自動化しようとせず、一番見落としたくない条件を1つだけ選びます。今回で言えば請求漏れです。お金に直結するものほど、自動化の効果を実感しやすいと思います。

管理表の更新とセットで考える
この仕組みは、元の一覧表が正しく更新されている前提で動きます。ステータスの更新を忘れている案件は、正しく拾えません。仕組みを入れるなら、「一覧表を更新する習慣」も一緒に作る必要があります。

道具を作るより、使い続けられる運用を作るほうが大事なのかもしれません。

まとめ:技術より、ルール設計と実務の知識が効いた

今回いちばん時間がかかったのは、コードを書くことより「何を対応待ちと判断するか」を決めることでした。日数の設定ひとつで、拾いすぎたり見落としたりします。そして、そのルールを思いつけるかどうかは、技術力より「その業務を知っているかどうか」に左右されると感じました。

私はこの業界ではないのでAIに聞きながらルール作りをしたので実際に作る時は担当者と話しながら決めると思うのでもっとスムーズで的確なアプリが作れると思います。

もし同じように案件管理表やスプレッドシートで「対応漏れ」「請求漏れ」に心当たりがある方は、いきなり全部を自動化しようとせず、まず自分の管理表にある項目のうち「これだけは見落としたくない」というルールを1つだけ言葉にしてみることをおすすめします。それができれば、GASに落とし込む作業は、あとからでも十分間に合います。

外部サービスやAIを使わなくても、GASの標準機能だけでここまでできました。AIを使うこと自体を目的にせず、業務を楽にするために必要な道具だけを使う、という判断も今回の収穫のひとつでした。

次におすすめの記事はこちら

「GASって結局何?」が10分で分かる!未経験の僕がDify連携で使い倒した基本とメリット

次回はメールからの案件情報抽出できるアプリを作ろうと思います。是非お楽しみに!

コメント

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