カテゴリー: GAS・自動化

  • GASで営業リストを自動収集する仕組みを作った話

    GASで営業リストを自動収集する仕組みを作った話

    「営業リスト作成に毎週何時間もかけている」「手作業でのリスト収集は限界がある」と感じていませんか?本記事では、Google Apps Script(GAS)を使って営業リストを自動収集する仕組みを実際に作った過程を、コードとともに詳しく解説します。

    GASとGoogleスプレッドシートを組み合わせれば、Web上の公開情報を定期的に収集・整形して、常に最新の営業リストを自動更新する仕組みが作れます。ツール費用ゼロ、プログラミング初心者でも再現できる方法を紹介します。

    この記事でできること

    • GASを使ってWebページから企業情報を自動取得する
    • 取得データをスプレッドシートに整形して保存する
    • 重複チェック機能で同じ企業が二重登録されるのを防ぐ
    • 時間ベーストリガーで毎日自動実行する仕組みを構築する

    事前準備(10分)

    以下を用意してください:

    • Googleアカウント(無料)
    • Googleスプレッドシート(新規作成)
    • Google Apps Script(スプレッドシートから起動)
    • 収集対象となる公開Webページ(企業ディレクトリ・業界団体サイトなど)

    スプレッドシートを開き、メニューの「拡張機能」→「Apps Script」をクリックしてGASエディターを起動します。

    STEP 1:スプレッドシートのシート構成を設計する

    まず収集データを格納するシートを作成します。スプレッドシートに「営業リスト」シートを追加し、以下のヘッダーを1行目に入力してください:

    A列: 会社名
    B列: WebサイトURL
    C列: 業種
    D列: 所在地
    E列: 取得日時
    F列: ステータス(未対応/対応中/完了)

    次に「収集設定」シートも作成し、A列にターゲットURL、B列に収集ルールを記録できるようにしておきます。これで設定変更がコードを触らずにできるようになります。

    STEP 2:Webページから情報を取得するコードを書く

    GASのUrlFetchAppを使って対象ページのHTMLを取得し、正規表現でデータを抽出します。以下は基本的な取得コードです:

    function fetchSalesLeads() {
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const listSheet = ss.getSheetByName('営業リスト');
      const configSheet = ss.getSheetByName('収集設定');
      
      // 収集設定シートからURL一覧を取得
      const urls = configSheet.getRange('A2:A' + configSheet.getLastRow()).getValues()
        .filter(row => row[0] !== '')
        .map(row => row[0]);
      
      urls.forEach(url => {
        try {
          const response = UrlFetchApp.fetch(url, {
            muteHttpExceptions: true,
            headers: {
              'User-Agent': 'Mozilla/5.0 (compatible; GoogleBot/2.1)'
            }
          });
          
          if (response.getResponseCode() !== 200) {
            console.log('取得失敗: ' + url);
            return;
          }
          
          const html = response.getContentText('UTF-8');
          extractCompanyInfo(html, url, listSheet);
          
          // 連続アクセスを避けるため1秒待機
          Utilities.sleep(1000);
          
        } catch(e) {
          console.error('エラー: ' + url + ' / ' + e.message);
        }
      });
      
      console.log('取得完了: ' + new Date());
    }

    STEP 3:HTMLから企業情報を抽出してシートに書き込む

    正規表現を使ってHTMLから必要な情報を取り出し、スプレッドシートに書き込む関数を実装します:

    function extractCompanyInfo(html, sourceUrl, sheet) {
      // 企業名を抽出(例:h2タグ内のテキスト)
      const companyPattern = /<h2[^>]*class="company-name"[^>]*>([^<]+)<\/h2>/g;
      // 所在地を抽出
      const locationPattern = /<span[^>]*class="location"[^>]*>([^<]+)<\/span>/g;
      
      const companies = [];
      let match;
      
      while ((match = companyPattern.exec(html)) !== null) {
        companies.push({
          name: match[1].trim(),
          website: sourceUrl,
          location: ''
        });
      }
      
      // 重複チェックしながらシートに追記
      companies.forEach(company => {
        if (!isDuplicate(sheet, company.name)) {
          sheet.appendRow([
            company.name,
            company.website,
            '未設定',
            company.location,
            new Date(),
            '未対応'
          ]);
        }
      });
    }

    STEP 4:重複チェックと自動トリガーを設定する

    同じ企業が複数回登録されるのを防ぐ重複チェック関数と、毎日自動実行するトリガー設定を実装します:

    function isDuplicate(sheet, companyName) {
      const lastRow = sheet.getLastRow();
      if (lastRow < 2) return false;
      
      // A列(会社名)の全データを取得
      const existingNames = sheet.getRange('A2:A' + lastRow)
        .getValues()
        .map(row => row[0].toString().trim().toLowerCase());
      
      return existingNames.includes(companyName.trim().toLowerCase());
    }
    
    // 毎朝9時に自動実行するトリガーを設定
    function setupDailyTrigger() {
      // 既存のトリガーを削除
      ScriptApp.getProjectTriggers().forEach(trigger => {
        if (trigger.getHandlerFunction() === 'fetchSalesLeads') {
          ScriptApp.deleteTrigger(trigger);
        }
      });
      
      // 毎朝9時に自動実行
      ScriptApp.newTrigger('fetchSalesLeads')
        .timeBased()
        .everyDays(1)
        .atHour(9)
        .create();
      
      console.log('トリガー設定完了:毎日9時に自動実行');
    }

    動作確認とトラブルシュート

    GASエディターの「実行」ボタンでfetchSalesLeadsを手動実行して動作確認します。初回実行時は権限の承認が求められますので「許可」をクリックしてください。確認後、setupDailyTriggerを実行してトリガーを設定すれば完了です。

    よくあるエラーと対処法

    • 「Exception: Request failed」→ 対象サイトがボット対策をしている可能性。User-Agentを変更するか収集対象を見直す
    • 「文字化け」→ getContentText('Shift_JIS')など文字コードを明示的に指定する
    • 「実行時間超過(6分制限)」→ 1回の実行URL数を減らし複数トリガーに分割する
    • 「重複が登録される」→ 全角・半角正規化(normalize())を比較ロジックに追加する

    応用:さらに便利にする拡張アイデア

    • Slack通知連携:新規リスト追加時にSlackへ自動通知して営業担当に即報告
    • Gemini API連携:企業情報をAIが自動分析してアプローチ優先度を判定
    • Google Mapsリンク自動生成:所在地情報からリンクを作成して訪問計画を効率化
    • 業種フィルタリング:特定キーワードを含む企業だけを自動抽出してリスト品質を向上
    • メール自動通知:リスト追加をトリガーに担当者へメールで自動通知

    まとめ

    GASを使った営業リスト自動収集の仕組みを構築することで、毎週数時間かかっていたリスト作成作業をゼロにできます。

    • GASのUrlFetchAppでWebページを取得し、正規表現でデータ抽出
    • 重複チェック機能で同じ企業の二重登録を防止
    • 時間ベーストリガーで毎日自動実行し、常に最新リストを維持
    • 設定シートを分離することでコードを触らずURL追加が可能
    • Slack・Gemini APIと連携してさらに高度な自動化も実現できる

    業種・地域・規模など自社の営業戦略に合わせてカスタマイズすれば、質の高い営業リストを自動で維持できます。導入方法や自社への適用についてご相談があれば、お気軽にお問い合わせください。

    お問い合わせはこちら
  • GASで営業リストを自動収集する仕組みを作った話

    GASで営業リストを自動収集する仕組みを作った話

    Google Apps Scriptを使えば、Web上の企業情報を自動で収集してスプレッドシートに整理する営業リスト自動化の仕組みが無料で作れます。

    「新規営業のためにリストを作りたいけど、手作業で企業情報を集めるのが大変…」そんな悩みを持つ営業担当者や中小企業経営者は多いのではないでしょうか。

    実はGoogle Apps Script(GAS)を使えば、Googleスプレッドシート上で動く営業リスト自動収集ツールを無料で作れます。この記事では実際に筆者が作った仕組みの手順を公開します。

    この記事でできること

    • GASでWebサイトから企業情報を取得してスプレッドシートに保存
    • 業種・地域などの条件で絞り込んだリストを自動生成
    • 収集した情報に重複チェックを自動適用
    • 毎朝定時にリストを自動更新するトリガー設定

    事前準備

    必要なものはGoogleアカウントのみです。GASはGoogleスプレッドシートに標準搭載されているため、追加のツールや費用は一切かかりません。また、収集対象サイトの利用規約は必ず確認してください。

    STEP1: スプレッドシートとGASプロジェクトを準備する

    まず新しいGoogleスプレッドシートを作成し、「ツール」→「Apps Script」からGASエディタを開きます。シートには以下のヘッダー行を用意します。

    A列: 企業名 / B列: URL / C列: 業種 / D列: 所在地 / E列: 電話番号 / F列: 収集日時

    STEP2: ページ取得の基本コードを書く

    GASのUrlFetchAppを使ってWebページを取得し、正規表現でデータを抽出します。

    function fetchCompanyInfo(url) {
      var response = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
      if (response.getResponseCode() !== 200) return null;
      var html = response.getContentText();
      var telMatch = html.match(/\d{2,4}-\d{2,4}-\d{4}/);
      var tel = telMatch ? telMatch[0] : '';
      return { url: url, tel: tel };
    }

    STEP3: スプレッドシートへの書き込みと重複チェック

    取得したデータをシートに保存する関数と、URLベースの重複チェックを実装します。

    function saveToSheet(data) {
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
      var lastRow = sheet.getLastRow();
      var existingUrls = sheet.getRange(2, 2, lastRow, 1).getValues().flat();
      if (existingUrls.indexOf(data.url) !== -1) return false;
      sheet.appendRow([data.companyName, data.url, '', '', data.tel, new Date()]);
      return true;
    }

    STEP4: 定時自動実行のトリガーを設定する

    GASエディタの左メニューから「トリガー」→「トリガーを追加」を選択し、以下のように設定します。

    • 実行する関数: collectLeads
    • イベントのソース: 時間主導型
    • 時間ベースのトリガーのタイプ: 日タイマー
    • 時刻: 午前7時〜8時

    うまくいかないときのチェックリスト

    • 「アクセスが拒否されました」エラー → User-Agentヘッダーを設定しているか確認
    • 取得したHTMLが空 → JavaScriptレンダリング必須のサイトはGASでは取得不可
    • 1日の実行上限エラー → GASの無料枠は1日6分が上限。対象URLを絞るか頻度を下げる
    • データが重複して追加される → 重複チェック対象列のインデックスが正しいか確認

    応用・発展

    収集したリストをそのままGmailの差し込みメール送信と連携させることで、「リスト収集→メール送信」を完全自動化できます。また、Google Sheetsのフィルタ機能と組み合わせて、担当者ごとにリストを振り分ける仕組みも簡単に作れます。

    まとめ

    • GASのUrlFetchAppでWebの企業情報を自動収集できる
    • 重複チェック・定時実行を組み合わせれば完全自動の営業リスト生成が実現
    • 無料・ノーコードで始められ、他のGoogle Workspaceツールとの連携も容易
  • GASで月末営業成績レポートを自動生成する方法

    GASで月末営業成績レポートを自動生成する方法

    「月末になるたびに営業成績の集計に何時間もかかる…」そんな悩みを抱えていませんか?Google Apps Script(GAS)を使えば、スプレッドシートの営業データから月末レポートを自動生成し、メールで自動送信するまでを完全に自動化できます。

    本記事では、GASを使って月末営業成績レポートを自動生成する仕組みを、コード付きでゼロから解説します。プログラミング初心者でも30分あれば導入できる内容です。

    この記事でできること

    • スプレッドシートの営業データを自動集計して月次レポートを生成
    • 担当者別・商品別・地域別の売上サマリーを自動作成
    • 毎月末に自動でメール送信するトリガー設定
    • 前月比・達成率の自動計算と色分け表示

    事前準備(10分)

    以下を事前に用意してください。

    • Googleアカウント(Gmail含む)
    • 営業データを記録したGoogleスプレッドシート(日付・担当者・商品・金額の列が必要)
    • レポート送信先のメールアドレス

    スプレッドシートのシート名は「営業データ」とし、A列:日付、B列:担当者名、C列:商品名、D列:売上金額 という構成を想定します。

    STEP 1:GASエディタを開いてスクリプトを作成する

    スプレッドシートを開き、メニューから「拡張機能」→「Apps Script」をクリックします。エディタが開いたら、既存のコードを削除して以下のスクリプトを貼り付けてください。

    // 設定値
    const CONFIG = {
      sheetName: '営業データ',
      reportSheetName: '月次レポート',
      sendTo: 'manager@example.com', // 送信先メールアドレスに変更
      subject: '【自動送信】月次営業成績レポート',
    };
    
    // 月末に自動実行するメイン関数
    function generateMonthlySalesReport() {
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const dataSheet = ss.getSheetByName(CONFIG.sheetName);
    
      // 先月の年月を取得
      const now = new Date();
      const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
      const year = lastMonth.getFullYear();
      const month = lastMonth.getMonth() + 1;
    
      // データ取得
      const data = dataSheet.getDataRange().getValues();
      const rows = data.slice(1);
    
      // 先月データのみ抽出
      const monthlyData = rows.filter(row => {
        const date = new Date(row[0]);
        return date.getFullYear() === year && (date.getMonth() + 1) === month;
      });
    
      if (monthlyData.length === 0) {
        Logger.log('先月のデータが見つかりませんでした');
        return;
      }
    
      // 集計処理
      const summary = aggregateData(monthlyData);
    
      // レポートシートを作成・更新
      createReportSheet(ss, summary, year, month);
    
      // メール送信
      sendReportEmail(summary, year, month);
    
      Logger.log(year + '年' + month + '月の営業成績レポートを生成・送信しました');
    }
    
    // データ集計関数
    function aggregateData(data) {
      const byPerson = {};
      const byProduct = {};
      let totalSales = 0;
    
      data.forEach(row => {
        const person = row[1];
        const product = row[2];
        const amount = Number(row[3]) || 0;
    
        if (!byPerson[person]) byPerson[person] = 0;
        byPerson[person] += amount;
    
        if (!byProduct[product]) byProduct[product] = 0;
        byProduct[product] += amount;
    
        totalSales += amount;
      });
    
      return {
        totalSales,
        byPerson: sortByValue(byPerson),
        byProduct: sortByValue(byProduct),
        recordCount: data.length,
      };
    }
    
    // オブジェクトを値の降順でソート
    function sortByValue(obj) {
      return Object.entries(obj)
        .sort((a, b) => b[1] - a[1])
        .map(([key, value]) => ({ name: key, amount: value }));
    }
    
    // レポートシートを作成・更新
    function createReportSheet(ss, summary, year, month) {
      const sheetName = year + '年' + month + '月レポート';
    
      const existing = ss.getSheetByName(sheetName);
      if (existing) ss.deleteSheet(existing);
    
      const sheet = ss.insertSheet(sheetName);
    
      sheet.getRange('A1').setValue(year + '年' + month + '月 営業成績レポート');
      sheet.getRange('A1').setFontSize(16).setFontWeight('bold');
    
      sheet.getRange('A3').setValue('月間合計売上');
      sheet.getRange('B3').setValue(summary.totalSales).setNumberFormat('#,##0');
      sheet.getRange('A4').setValue('件数');
      sheet.getRange('B4').setValue(summary.recordCount);
    
      sheet.getRange('A6').setValue('担当者別売上').setFontWeight('bold');
      summary.byPerson.forEach((item, i) => {
        sheet.getRange(7 + i, 1).setValue(item.name);
        sheet.getRange(7 + i, 2).setValue(item.amount).setNumberFormat('#,##0');
      });
    
      const productStartRow = 8 + summary.byPerson.length;
      sheet.getRange(productStartRow, 1).setValue('商品別売上').setFontWeight('bold');
      summary.byProduct.forEach((item, i) => {
        sheet.getRange(productStartRow + 1 + i, 1).setValue(item.name);
        sheet.getRange(productStartRow + 1 + i, 2).setValue(item.amount).setNumberFormat('#,##0');
      });
    
      sheet.autoResizeColumns(1, 2);
    }
    
    // メール送信関数
    function sendReportEmail(summary, year, month) {
      const fmt = (n) => n.toLocaleString() + '円';
    
      let body = year + '年' + month + '月 営業成績レポート\n';
      body += '================================\n\n';
      body += '月間合計売上: ' + fmt(summary.totalSales) + '\n';
      body += '総件数: ' + summary.recordCount + '件\n\n';
    
      body += '担当者別売上ランキング\n';
      summary.byPerson.forEach((item, i) => {
        body += '  ' + (i + 1) + '位 ' + item.name + ': ' + fmt(item.amount) + '\n';
      });
    
      body += '\n商品別売上ランキング\n';
      summary.byProduct.forEach((item, i) => {
        body += '  ' + (i + 1) + '位 ' + item.name + ': ' + fmt(item.amount) + '\n';
      });
    
      body += '\n================================\n';
      body += 'このメールはGoogle Apps Scriptにより自動送信されました。';
    
      GmailApp.sendEmail(CONFIG.sendTo, CONFIG.subject + '(' + year + '年' + month + '月)', body);
    }

    STEP 2:自動実行トリガーを設定する

    毎月自動実行されるよう、時間ベーストリガーを設定します。GASエディタの左メニューから「トリガー(時計アイコン)」をクリックし、以下の設定でトリガーを追加してください。

    • 実行する関数: generateMonthlySalesReport
    • イベントのソース: 時間主導型
    • 時間ベースのトリガーのタイプ: 月ベースのタイマー
    • 日: 毎月1日(前月データを自動取得)
    • 時刻: 午前0時〜1時

    ポイント: 「月末最終日」はGASのトリガーで直接指定できません。「毎月1日」に設定して前月データを取得する方式が確実です。本コードはすでに「先月のデータを集計」する設計になっているので、毎月1日の実行で問題ありません。

    STEP 3:手動テスト実行で動作確認する

    トリガーを設定する前に、まず手動で動作確認しましょう。GASエディタで generateMonthlySalesReport 関数を選択し、「実行」ボタンをクリックします。

    初回実行時にはGoogleアカウントへのアクセス許可を求められます。「権限を確認」→「許可」の順にクリックしてください。実行後、スプレッドシートに「XXXX年XX月レポート」というシートが作成され、指定したメールアドレスにレポートが届けば成功です。

    STEP 4:動作確認チェックリスト

    トラブルシュートチェックリスト

    • 「シートが見つからない」エラー → CONFIG.sheetName がスプレッドシートのシート名と完全一致しているか確認
    • 「メールが届かない」→ CONFIG.sendTo のメールアドレスが正しいか、GmailApp の権限が付与されているか確認
    • 「データが0件」→ スプレッドシートのA列の日付形式が正しいか(yyyy/mm/dd または yyyy-mm-dd 形式を推奨)
    • 「金額がNaN」→ D列の売上金額が数値形式で入力されているか確認(文字列になっていないか)

    応用:さらに便利にする拡張アイデア

    • 前月比の自動計算: 前月のレポートシートと比較して増減率を自動算出する
    • グラフの自動生成: レポートシートに棒グラフ・円グラフを自動挿入してPDF化する
    • Slack通知との連携: GmailApp の代わりに Slack Incoming Webhookでチャンネルに通知する
    • 目標達成率の表示: 別シートに月次目標を設定しておき、達成率を自動計算して色分け(赤/黄/緑)で表示する
    • 複数拠点・部門対応: データに「部門」列を追加し、部門別サマリーを生成する

    まとめ

    GASを使えば、毎月手作業で行っていた営業成績レポートの集計・作成・送信をすべて自動化できます。

    • スプレッドシートのデータを自動集計し、月次レポートシートを生成
    • 担当者別・商品別の売上ランキングを自動作成
    • 毎月1日に前月レポートをメール自動送信するトリガー設定
    • コード全体で100行程度、初心者でも30分で導入可能

    「自社のスプレッドシート構成に合わせてカスタマイズしたい」「複数シートのデータを集約したい」など、ご要望があればお気軽にご相談ください。

    お問い合わせはこちら
  • AppSheetで営業日報アプリを作る【ゼロから解説】

    AppSheetで営業日報アプリを作る【ゼロから解説】

    「営業日報をExcelで管理しているが、集計が面倒」「入力が手間でメンバーが続かない」——そんな悩みをお持ちではないですか?Googleが提供するノーコードツール「AppSheet」を使えば、プログラミング不要で本格的な営業日報アプリを作れます。この記事では、Googleスプレッドシートをデータソースにした営業日報アプリの作り方をゼロから解説します。

    AppSheetはGoogleが2020年に買収したノーコードプラットフォームです。スプレッドシートをデータベースとして、スマートフォン・PCで動作するアプリを数時間で構築できます。無料プランでも十分な機能が使えるため、中小企業の業務改善に最適なツールです。

    この記事でできること

    • スプレッドシートと連携した営業日報アプリの構築
    • スマートフォンからの日報入力・閲覧
    • 上長への自動通知設定
    • 月次レポートの自動集計ビュー作成

    事前準備(10分)

    以下のものを用意してください。

    • Googleアカウント(無料)
    • Googleスプレッドシート(新規作成)
    • AppSheetアカウント(Googleアカウントで無料登録可)

    まずGoogleスプレッドシートに以下の列を作成します。

    A列: 日付
    B列: 担当者名
    C列: 訪問先
    D列: 活動内容(訪問/電話/メール)
    E列: 商談ステータス(初回面談/提案/見積/受注/失注)
    F列: 金額(円)
    G列: 次回アクション
    H列: 備考
    I列: 入力日時(自動)

    ヘッダー行を1行目に入力したら、シート名を「日報データ」に変更しておきましょう。

    STEP 1:AppSheetでアプリを作成する

    AppSheet(appsheet.com)にアクセスし、Googleアカウントでログインします。

    • 「Start for free」からログイン
    • 「Create」→「App」→「Start with your own data」を選択
    • 先ほど作成したGoogleスプレッドシートを選択
    • アプリ名を「営業日報」などに設定して「Create App」をクリック

    AppSheetがスプレッドシートの列を自動認識してアプリのひな形を作成します。この時点でスマートフォンからデータの入力・閲覧ができる基本アプリが完成しています。

    STEP 2:カラム設定を最適化する

    左メニューの「Data」→「Columns」から各列のデータ型を設定します。

    • 日付:Type を「Date」に変更
    • 活動内容:Type を「Enum」に変更し、「訪問」「電話」「メール」を選択肢として登録
    • 商談ステータス:Type を「Enum」に変更し、各ステージを登録
    • 金額:Type を「Price」に変更(自動でカンマ区切り表示)
    • 入力日時:Type を「DateTime」、Initial value を「NOW()」に設定(自動入力)

    担当者名は「担当者マスタ」シートを別途作成し、Refタイプで参照設定すると選択式になり入力ミスを防げます。

    STEP 3:ビュー(画面)を設計する

    左メニューの「UX」→「Views」からアプリの画面構成を設定します。

    • 日報入力フォーム:View Type「Form」で新規入力画面を作成
    • 日報一覧:View Type「Table」で一覧表示。Sort設定で「日付」降順にする
    • マイ日報:View Type「Gallery」、Filterで「担当者名 = USEREMAIL()」を設定して自分の日報だけ表示
    • 月次サマリー:View Type「Chart」で金額の月別積み上げグラフを作成

    「月次サマリー」ビューの設定例:

    Chart Type: Bar Chart
    X-axis: MONTH(日付)
    Y-axis: SUM(金額)
    Group by: 商談ステータス

    STEP 4:自動通知・承認フローを設定する

    左メニューの「Automation」→「Bots」から自動化を設定します。

    日報提出時のメール通知設定:

    • 「New Bot」を作成
    • Event:「When a row is added」(日報データシート)
    • Action:「Send an email」
    • Toに上長のメールアドレス、件名に「【日報】<<担当者名>>さんが日報を提出しました」を設定
    • 本文に各フィールドの値を埋め込む

    受注時のSlack通知(Webhookを使用):

    Event: When a row is added or updated
    Condition: [商談ステータス] = "受注"
    Action: Call a webhook
    URL: https://hooks.slack.com/services/YOUR_WEBHOOK_URL
    Method: POST
    Body: {"text": "🎉 受注!担当: <<担当者名>> 金額: <<金額>>円"}

    動作確認とトラブルシュート

    トラブルシュートチェックリスト

    • ✅ スプレッドシートへの書き込み権限があるか(Googleアカウントを確認)
    • ✅ Enumの選択肢が正しく登録されているか(Data → Columns で確認)
    • ✅ 通知メールが届かない場合は「Security → Require sign-in」を確認
    • ✅ スマートフォンで表示が崩れる場合はView設定のResponsiveを有効化
    • ✅ データが更新されない場合はSync間隔の設定(Manage → Integrations)を確認

    応用:さらに便利にする拡張アイデア

    • GPS位置情報の記録:LatLong型のカラムを追加し、訪問先の位置を自動記録する
    • 写真添付機能:Image型のカラムを追加してスマートフォンから名刺・提案資料を撮影保存
    • GASとの連携:月次になったタイミングでGASで集計しPDF化して自動メール送信
    • 承認フロー:ChangeData機能でワンクリック承認ボタンを設置して上長確認を効率化
    • 地図ビュー:Map Viewで営業活動エリアを可視化してテリトリー管理に活用

    まとめ

    AppSheetを使えばプログラミング不要で本格的な営業日報アプリが作れます。Googleスプレッドシートとシームレスに連携するため、既存のデータ資産をそのまま活用できる点も大きな強みです。

    • スプレッドシートをデータソースにしてノーコードでアプリ化
    • Enum型で入力ミスを防ぎ、データ品質を向上
    • Automation機能で日報提出時の通知・承認フローを自動化
    • Chart ViewやGASとの連携で月次分析も効率化
    • 無料プランで最大10ユーザーまで利用可能

    AppSheetの詳細な設定方法や、貴社の業務フローに合わせたカスタマイズについてお気軽にご相談ください。

    お問い合わせはこちら
  • Googleカレンダー×LINE Botで「今日のタスク」を自動通知する作り方

    Googleカレンダー×LINE Botで「今日のタスク」を自動通知する作り方

    「毎朝、今日の予定をLINEで確認できたら便利なのに…」と思ったことはありませんか?Googleカレンダーに登録したタスクを、毎朝自動でLINEに通知する仕組みをGAS(Google Apps Script)で構築できます。この記事では、LINE Messaging APIとGASを連携させて「今日のタスク自動通知Bot」を作る方法をゼロから解説します。

    設定は30〜60分程度で完了します。プログラミング経験がなくてもコピペで動く実用的なコードを用意しましたので、ぜひ最後まで読み進めてください。

    この記事でできること

    • 毎朝指定した時刻にLINEへ「今日の予定一覧」を自動送信
    • Googleカレンダーの複数カレンダーをまとめて取得・通知
    • 終日イベント・時間指定イベントを区別して見やすく表示
    • GASのトリガーで完全自動化(スマホ操作不要)

    事前準備(約20分)

    以下の準備が必要です。

    • LINEアカウント(個人アカウントでOK)
    • LINE Developersアカウント(無料)
    • Googleアカウント(Googleカレンダー・GASで使用)

    LINE DevelopersでMessaging APIチャンネルを作成し、「チャンネルアクセストークン(長期)」と自分のLINE「ユーザーID」を取得しておきます。ユーザーIDはLINE DevelopersのWebhook設定画面で確認できます。

    STEP 1:LINE Messaging APIのチャンネル作成

    LINE Developers(https://developers.line.biz/)にログインし、以下の手順でチャンネルを作成します。

    • 「プロバイダーを作成」→ 任意の名前を入力(例:MyTaskBot)
    • 「チャンネルを作成」→「Messaging API」を選択
    • チャンネル基本設定で「チャンネルアクセストークン(長期)」を発行してコピー
    • 「あなたのユーザーID」をメモ(例:Uxxxxxxxxxx形式)

    次に、作成したBotを自分のLINEに友だち追加します。チャンネルのQRコードをスキャンして追加してください。

    STEP 2:GASプロジェクトの作成

    Googleドライブにアクセスし、「新規」→「その他」→「Google Apps Script」でスクリプトエディタを開きます。プロジェクト名を「LINE Task Notifier」などに変更してください。

    まず、設定値(トークンとユーザーID)をPropertiesServiceで安全に管理します。スクリプトエディタの「プロジェクトの設定」→「スクリプトプロパティ」に以下を登録します。

    • プロパティ名:LINE_TOKEN 値:取得したチャンネルアクセストークン
    • プロパティ名:LINE_USER_ID 値:自分のユーザーID(U…)

    STEP 3:メイン通知スクリプトの実装

    以下のコードをそのままコピーして貼り付けてください。

    /**
     * Googleカレンダー×LINE Bot 今日のタスク通知
     */
    function notifyTodaysTasks() {
      var props = PropertiesService.getScriptProperties();
      var token = props.getProperty('LINE_TOKEN');
      var userId = props.getProperty('LINE_USER_ID');
    
      // 今日の開始・終了時刻を取得
      var today = new Date();
      var startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
      var endOfDay   = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59);
    
      // 日付フォーマット用ヘルパー
      var fmt = function(d) { return Utilities.formatDate(d, 'Asia/Tokyo', 'HH:mm'); };
      var dateStr = Utilities.formatDate(today, 'Asia/Tokyo', 'M月d日(EEE)');
    
      // カレンダーからイベント取得(デフォルトカレンダー)
      var cal = CalendarApp.getDefaultCalendar();
      var events = cal.getEvents(startOfDay, endOfDay);
    
      var message = '\uD83D\uDCC5 ' + dateStr + ' の予定\n';
      message += '─────────────\n';
    
      if (events.length === 0) {
        message += '今日の予定はありません。\n';
      } else {
        events.forEach(function(ev) {
          var title = ev.getTitle();
          if (ev.isAllDayEvent()) {
            message += '◆ [終日] ' + title + '\n';
          } else {
            var start = fmt(ev.getStartTime());
            var end   = fmt(ev.getEndTime());
            message += '◆ ' + start + '〜' + end + ' ' + title + '\n';
          }
        });
      }
    
      message += '─────────────\n';
      message += '良い1日を! \uD83D\uDE80';
    
      // LINE Push Message送信
      var payload = {
        to: userId,
        messages: [{ type: 'text', text: message }]
      };
    
      UrlFetchApp.fetch('https://api.line.me/v2/bot/message/push', {
        method: 'post',
        contentType: 'application/json',
        headers: { 'Authorization': 'Bearer ' + token },
        payload: JSON.stringify(payload)
      });
    
      Logger.log('通知送信完了: ' + message);
    }
    

    コードを貼り付けたら「Ctrl + S」で保存し、notifyTodaysTasks関数を選択して「▶ 実行」ボタンを押してテスト実行します。初回は「Googleカレンダーへのアクセスを許可」するダイアログが表示されるので「許可」をクリックしてください。

    STEP 4:毎朝自動実行するトリガーを設定

    手動実行で通知が届いたら、毎朝自動で動くようにトリガーを設定します。

    • GASエディタ左メニューの「トリガー(時計アイコン)」をクリック
    • 右下の「トリガーを追加」ボタンをクリック
    • 実行する関数:notifyTodaysTasks
    • イベントのソース:「時間主導型」
    • 時間ベースのトリガーのタイプ:「日タイマー」
    • 時刻:「午前7時〜8時」など希望の時間帯を選択
    • 「保存」をクリック

    これで毎朝指定した時間帯にGASが自動実行され、LINEに今日の予定が届くようになります。

    動作確認とトラブルシュート

    トラブルシュートチェックリスト

    • 「Authorization」エラーが出る:LINE_TOKENが正しいか確認。トークンを再発行して再設定してみる
    • 「予定はありません」と届くのに予定があるCalendarApp.getAllCalendars()で一覧を取得し、対象カレンダーのIDを指定する
    • 通知が届かない:BotをLINEで友だち追加しているか確認。ユーザーIDが正しいか再確認
    • 時刻がずれる:タイムゾーンをAsia/Tokyoに指定しているか確認(GASのプロジェクト設定でも確認)

    応用:さらに便利にする拡張アイデア

    • 複数カレンダー対応CalendarApp.getCalendarById('カレンダーID')で仕事・プライベートを分けて通知
    • 明日の予定も通知:夜21時に翌日の予定を送信するトリガーを追加
    • リマインダー機能:イベント開始30分前に再通知するスクリプトを追加
    • Flex Message対応:LINE Flex Messageを使ってカード形式の見やすいUIに変更
    • グループLINE通知:userId部分をグループIDに変えてチーム全員に通知

    まとめ

    GoogleカレンダーとLINE BotをGASで連携させることで、毎朝のタスク確認作業を完全自動化できます。一度設定してしまえばメンテナンスフリーで動き続ける、費用もかからない強力な仕組みです。

    • LINE Messaging APIでチャンネルとトークンを取得
    • GASにコードをコピペして認証を通す
    • 日次トリガーを設定して毎朝自動通知
    • 応用次第でチーム通知やリマインダーにも拡張可能

    GASを活用した業務自動化についてご相談がある方は、お気軽にお問い合わせください。貴社の状況に合わせた最適な自動化の仕組みをご提案します。

    お問い合わせはこちら
  • Gemini APIとGASで営業メールを自動生成する方法【プロンプト付き】

    Gemini APIとGASで営業メールを自動生成する方法【プロンプト付き】

    「提案メールを毎回ゼロから書いてる…」「顧客ごとに文面を変えるのが面倒」――そんな悩みをGemini APIとGoogle Apps Scriptで解決します。スプレッドシートに顧客情報を入力するだけで、パーソナライズされた営業メールを自動生成できる仕組みを、コードから丁寧に解説します。

    AIを使ったメール生成というと「ChatGPTに貼り付けて手動でコピー」というイメージがあるかもしれません。でも、GASと組み合わせればスプレッドシートのボタン1つで100件分の個別メールを自動生成できます。しかも無料(Gemini APIの無料枠内)で始められます。

    この記事でできること

    • スプレッドシートの顧客リストをもとにGemini APIで個別メール文面を自動生成
    • 生成したメールをGmailで自動送信(または下書き保存)
    • プロンプトを変えるだけで提案・フォローアップ・御礼メールにも対応
    • 実装に必要なGASコード一式を本記事で公開

    事前準備(10分)

    必要なものは以下の3つです。すべて無料で揃います。

    • Googleアカウント(Gmailアドレスがあれば可)
    • Gemini APIキー(Google AI Studioで取得・無料)
    • Googleスプレッドシート(GASプロジェクトを作成する)

    Gemini APIキーの取得方法

    1. Google AI Studio にアクセスし、Googleアカウントでログイン
    2.「Get API key」→「Create API key in new project」をクリック
    3. 表示されたAPIキー(AIzaで始まる文字列)をコピーして保存

    APIキーはスクリプトプロパティに保存します(コードに直書きしないこと)。GASの「プロジェクトの設定」→「スクリプトプロパティを追加」で GEMINI_API_KEY というキー名で貼り付けてください。

    STEP 1:スプレッドシートの準備

    新しいGoogleスプレッドシートを作成し、シート名を「顧客リスト」に変更します。1行目にヘッダーを作成してください。

    A列(会社名)B列(担当者名)C列(メールアドレス)D列(業種)E列(課題・ニーズ)F列(送信ステータス)
    株式会社〇〇山田 太郎yamada@example.com製造業月次レポート作成に毎月10時間かかっている(空欄)

    「課題・ニーズ」列がポイントです。ここに顧客の具体的な悩みを記入することで、AIがその悩みに刺さるパーソナライズメールを生成します。

    STEP 2:GASコードを貼り付ける

    スプレッドシートのメニュー「拡張機能」→「Apps Script」を開き、以下のコードを貼り付けます。

    /**
     * Gemini API x GAS 営業メール自動生成ツール
     */
    
    const SHEET_NAME = '顧客リスト';
    const SENDER_NAME = '松下 浩平';
    const YOUR_SERVICE = 'GASxAI業務自動化サービス';
    const DRAFT_MODE = true; // true=下書き保存, false=即送信
    
    function generateAndSendEmails() {
      const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
      const lastRow = sheet.getLastRow();
      if (lastRow < 2) {
        SpreadsheetApp.getUi().alert('顧客データがありません。');
        return;
      }
      const data = sheet.getRange(2, 1, lastRow - 1, 6).getValues();
      let successCount = 0;
      let skipCount = 0;
      data.forEach((row, index) => {
        const [company, name, email, industry, needs, status] = row;
        if (status === '送信済み' || !email) { skipCount++; return; }
        const emailContent = generateEmailContent(company, name, industry, needs);
        if (!emailContent) return;
        if (DRAFT_MODE) {
          GmailApp.createDraft(email, emailContent.subject, emailContent.body);
        } else {
          GmailApp.sendEmail(email, emailContent.subject, emailContent.body, { name: SENDER_NAME });
        }
        sheet.getRange(index + 2, 6).setValue(DRAFT_MODE ? '下書き保存済み' : '送信済み');
        successCount++;
        Utilities.sleep(1000);
      });
      SpreadsheetApp.getUi().alert('完了!
    生成: ' + successCount + '件
    スキップ: ' + skipCount + '件');
    }
    
    function generateEmailContent(company, name, industry, needs) {
      const apiKey = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
      if (!apiKey) { console.error('GEMINI_API_KEY が未設定'); return null; }
      const prompt = 'あなたは営業メールの専門家です。以下の顧客情報をもとに自然な営業メールを作成してください。
    
    【顧客情報】
    ・会社名: ' + company + '
    ・担当者名: ' + name + ' 様
    ・業種: ' + industry + '
    ・課題: ' + needs + '
    
    【提供サービス】
    ' + YOUR_SERVICE + '
    
    【ルール】
    ・件名は30文字以内
    ・本文は250〜350文字
    ・共感ファーストで書く
    ・返信促進文を末尾に
    ・署名不要
    
    【出力形式】
    件名: [件名]
    本文:
    [本文]';
      const url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key=' + apiKey;
      const payload = { contents: [{ parts: [{ text: prompt }] }], generationConfig: { temperature: 0.7, maxOutputTokens: 500 } };
      try {
        const response = UrlFetchApp.fetch(url, { method: 'POST', contentType: 'application/json', payload: JSON.stringify(payload) });
        const result = JSON.parse(response.getContentText());
        const text = result.candidates[0].content.parts[0].text;
        const subjectMatch = text.match(/件名:s*(.+)/);
        const bodyMatch = text.match(/本文:
    ([sS]+)/);
        return {
          subject: subjectMatch ? subjectMatch[1].trim() : company + ' ' + name + '様へのご提案',
          body: bodyMatch ? bodyMatch[1].trim() : text
        };
      } catch (error) {
        console.error('Gemini API エラー:', error);
        return null;
      }
    }
    
    function onOpen() {
      SpreadsheetApp.getUi()
        .createMenu('メール自動生成')
        .addItem('メールを生成・送信', 'generateAndSendEmails')
        .addToUi();
    }

    STEP 3:APIキーをスクリプトプロパティに登録する

    APIキーをコードに直書きするのはセキュリティ上NGです。必ずスクリプトプロパティに保存してください。

    1. GASエディタ左メニューの「プロジェクトの設定(歯車アイコン)」をクリック
    2. 「スクリプトプロパティ」セクションで「プロパティを追加」
    3. プロパティ名: GEMINI_API_KEY、値: 取得したAPIキーを貼り付け
    4. 「スクリプトプロパティを保存」をクリック

    STEP 4:動作確認

    1. スプレッドシートに戻り、顧客データを2〜3行入力する
    2. メニュー「メール自動生成」→「メールを生成・送信」をクリック
    3. 初回は権限の許可ダイアログが表示されます。「許可」をクリック
    4. 処理完了後、Gmailの「下書き」フォルダを確認する

    トラブルシュートチェックリスト

    • 「GEMINI_API_KEY が未設定」→ スクリプトプロパティのキー名を確認
    • 「Request failed」→ APIキーが正しいか、Gemini APIが有効か確認
    • 「下書きが届かない」→ DRAFT_MODE が true になっているか確認
    • API制限エラー → Utilities.sleep(4000) に変更して再試行

    応用:プロンプトを変えるだけで用途が広がる

    このツールの強みはプロンプトを変えるだけで用途が無限に広がる点です。

    • フォローアップメール:「先日ご提案した件について〜」の文体に変更
    • 御礼メール:「本日はお時間をいただきありがとうございました」に変更
    • リマインドメール:返信のない顧客への再アプローチ文
    • 件名A/Bテスト:複数パターンを生成してスプレッドシートに記録

    さらに発展させると、Gmailの送信記録をスプレッドシートに自動記録したり、返信があった顧客を自動でフラグ立てしたりすることも可能です。

    まとめ

    Gemini APIとGASを組み合わせることで、顧客の課題に合わせたパーソナライズ営業メールを自動生成できます。

    • スプレッドシートに顧客情報を入力するだけでOK
    • Gemini APIの無料枠で月数百件まで対応可能
    • プロンプト変更で提案・フォロー・御礼など多用途に展開できる

    「このコードをうちの営業フローに合わせてカスタマイズしてほしい」「CRMと連携させたい」という方は、下記からお気軽にご相談ください。

    お問い合わせはこちら
  • Googleスプレッドシートで営業進捗を自動集計する仕組みの作り方【GASコード付き】

    Googleスプレッドシートで営業進捗を自動集計する仕組みの作り方【GASコード付き】

    GAS×スプレッドシートで作る営業ダッシュボード|日報入力だけで自動更新・無料・実装コードつき

    「今月の営業進捗、今どこまで?」——この確認作業に、毎週30分以上かかっていませんか?

    担当者に声をかけてスプレッドシートを開き、バラバラの入力を手動でまとめる。この繰り返しは、忙しい管理職にとって地味に重いタスクです。

    この記事では、Google Apps Script(GAS)× Googleスプレッドシートを使って、営業担当者が日報を入力するだけでダッシュボードが自動更新される仕組みを実装する方法を解説します。コードはすべて掲載しているので、コピペで動かせます。

    この記事でできること

    • 営業担当者が「日報入力シート」に入力するだけで進捗が自動集計される
    • 担当者別・ステータス別の進捗をダッシュボードシートで確認できる
    • 1時間おきに自動更新(手動操作一切不要)
    • 初期費用0円・追加ツール不要(Googleアカウントだけ)

    事前準備(5分)

    必要なのはGoogleアカウントだけです。特別な知識は不要です。

    • Googleアカウント(無料)
    • Googleスプレッドシートの基本操作ができること

    STEP 1:スプレッドシートの準備

    新しいGoogleスプレッドシートを作成し、以下の2つのシートを用意します。

    シート1:日報入力

    1行目に以下のヘッダーを入力します。

    A列B列C列D列E列F列
    日付担当者顧客名ステータス金額(円)備考
    2026/04/01田中〇〇商事受注1500003ヶ月契約

    ステータスは「商談中」「受注」「失注」の3種類に統一してください。表記ゆれがあるとコードが正しく集計できません。

    シート2:ダッシュボード

    シート名を「ダッシュボード」にしておくだけでOKです。中身はGASが自動で書き込みます。

    STEP 2:GASのコードを貼り付ける

    スプレッドシートのメニューから「拡張機能 → Apps Script」を選択します。エディタが開いたら、デフォルトのコードをすべて削除して以下のコードを貼り付け、保存してください。

    /**
     * 営業進捗ダッシュボード自動更新スクリプト
     */
    
    function updateDashboard() {
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const inputSheet = ss.getSheetByName('日報入力');
      const dashSheet = ss.getSheetByName('ダッシュボード');
    
      if (!inputSheet || !dashSheet) {
        Logger.log('シート名を確認してください');
        return;
      }
    
      const data = inputSheet.getDataRange().getValues();
      if (data.length < 2) { Logger.log('データなし'); return; }
    
      const rows = data.slice(1).filter(row => row[0] !== '');
    
      const now = new Date();
      const thisYear = now.getFullYear();
      const thisMonth = now.getMonth();
    
      const thisMonthRows = rows.filter(row => {
        const date = new Date(row[0]);
        return date.getFullYear() === thisYear && date.getMonth() === thisMonth;
      });
    
      const summary = {};
      let totalAmount = 0;
    
      thisMonthRows.forEach(row => {
        const person = row[1];
        const status = row[3];
        const amount = Number(row[4]) || 0;
        if (!person) return;
        if (!summary[person]) {
          summary[person] = { '商談中': 0, '受注': 0, '失注': 0, '受注金額': 0 };
        }
        if (status in summary[person]) { summary[person][status]++; }
        if (status === '受注') {
          summary[person]['受注金額'] += amount;
          totalAmount += amount;
        }
      });
    
      dashSheet.clearContents();
    
      const monthLabel = thisYear + '年' + (thisMonth + 1) + '月 営業進捗サマリー';
      dashSheet.getRange('A1').setValue(monthLabel);
      dashSheet.getRange('A1').setFontSize(14).setFontWeight('bold');
      dashSheet.getRange('G1').setValue('最終更新: ' + now.toLocaleString('ja-JP'));
    
      const headers = ['担当者', '商談中', '受注', '失注', '受注率', '受注金額(円)'];
      dashSheet.getRange(3, 1, 1, headers.length).setValues([headers]);
      dashSheet.getRange(3, 1, 1, headers.length)
        .setBackground('#1a73e8').setFontColor('#ffffff').setFontWeight('bold');
    
      const outputRows = Object.entries(summary).map(([person, stats]) => {
        const total = stats['商談中'] + stats['受注'] + stats['失注'];
        const winRate = total > 0 ? Math.round((stats['受注'] / total) * 100) + '%' : '-';
        return [person, stats['商談中'], stats['受注'], stats['失注'], winRate, stats['受注金額']];
      });
    
      if (outputRows.length > 0) {
        dashSheet.getRange(4, 1, outputRows.length, headers.length).setValues(outputRows);
        for (let i = 0; i < outputRows.length; i++) {
          const color = i % 2 === 0 ? '#f8f9fa' : '#ffffff';
          dashSheet.getRange(4 + i, 1, 1, headers.length).setBackground(color);
        }
      }
    
      const totalRow = 4 + outputRows.length;
      dashSheet.getRange(totalRow, 1).setValue('合計');
      dashSheet.getRange(totalRow, 6).setValue(totalAmount);
      dashSheet.getRange(totalRow, 1, 1, headers.length)
        .setBackground('#e8f0fe').setFontWeight('bold');
    
      Logger.log('ダッシュボード更新完了: ' + now.toLocaleString('ja-JP'));
    }

    STEP 3:トリガーを設定して自動化する

    このままでは手動実行しかできません。1時間おきに自動実行するトリガーを設定しましょう。同じファイルの末尾に以下の関数を追加します。

    /**
     * 自動実行トリガーを設定する(1回だけ実行すればOK)
     */
    function setAutoTrigger() {
      // 既存トリガーを削除(重複防止)
      ScriptApp.getProjectTriggers().forEach(t => ScriptApp.deleteTrigger(t));
    
      // 1時間おきに updateDashboard を実行
      ScriptApp.newTrigger('updateDashboard')
        .timeBased()
        .everyHours(1)
        .create();
    
      Logger.log('トリガーを設定しました(1時間おき)');
    }

    コードを保存後、関数の選択ドロップダウンで「setAutoTrigger」を選んで▶ボタンで1回だけ実行します。これでトリガーが登録され、以降は自動で動き続けます。

    トリガーの確認方法

    左メニューの時計アイコン「トリガー」から設定済みのトリガーを確認できます。「updateDashboard - 1時間ごと」と表示されていれば設定完了です。

    STEP 4:動作確認

    「日報入力」シートにテストデータを数行入力してから、GASエディタで「updateDashboard」を手動実行します。「ダッシュボード」シートに担当者別の集計が表示されれば成功です。

    うまく動かないときのチェックリスト

    • シート名の確認:「日報入力」「ダッシュボード」と完全一致しているか(スペース・全角半角に注意)
    • ステータスの表記ゆれ:「商談中」「受注」「失注」以外の表記が混入していないか
    • 日付のフォーマット:日付列はテキスト型ではなく日付型で入力されているか
    • 権限の許可:初回実行時にGoogleアカウントへのアクセス許可ダイアログが表示されます。「許可」を選んでください

    応用:さらに便利にする拡張アイデア

    この仕組みは土台にすぎません。以下の拡張でさらに強力になります。

    • Slack通知連携:毎週月曜朝9時にサマリーをSlackチャンネルへ自動投稿
    • メール送信:月末に営業全員に個別レポートをGmailで自動送信
    • グラフの自動生成:スプレッドシートのグラフAPIで担当者別棒グラフを自動作成
    • Googleフォーム連携:担当者がフォームで入力すると日報シートに自動記録

    これらの実装方法は順次記事化していきます。「通知も自動化したい」という方はサイトをブックマークしておいてください。

    まとめ

    今回実装したのは以下の仕組みです。

    • 「日報入力」シートへの入力をもとに「ダッシュボード」シートが自動集計・更新される
    • 担当者別・ステータス別・受注率・受注金額を一覧で可視化
    • トリガー設定で1時間おきの自動実行を実現

    「すごいけど自分の環境に合わせるのが難しそう」「自社の業務フローに合わせてカスタマイズしたい」という方は、お気軽にご相談ください。業務フロー設計からGASの実装・運用定着まで一気通貫でサポートします。

    無料相談・お問い合わせはこちら
  • 毎朝の「進捗どう?」をなくす方法

    毎朝の「進捗どう?」をなくす方法

    あなたのチーム、こんな状況になっていませんか?

    • 毎朝 Slack で「今日の進捗どうですか?」と聞いて回っている
    • スプレッドシートの管理シートが「誰かが更新するまで古いまま」
    • 締め切り3日前になってはじめてタスクの遅延に気づく

    📊 インフォグラフィック挿入箇所

    【Before → After】GAS導入でチームの進捗管理がこう変わる
    ※画像生成後にこのブロックを差し替えてください

    そのムダ、全部なくせます。しかも月額0円で。

    この記事では、GAS(Google Apps Script)とGoogleスプレッドシートを組み合わせて、チームの進捗を自動集計するダッシュボードを作る方法を、実装コードつきで解説します。「コードは書いたことがない」という方でも、コピペ&数クリックの設定で完成します。

    📋 この記事でわかること

    • GAS + Googleスプレッドシートでプロジェクト管理ダッシュボードを作る手順
    • タスク進捗を担当者別に自動集計するコードの書き方
    • 期限が近いタスクをメールで自動通知する仕組み
    • 毎日自動実行するトリガーの設定方法

    ✅ こんな人に向けています

    • プロジェクトの進捗をチャットで毎回確認するのが面倒な方
    • 高額なプロジェクト管理ツールは使いたくない方
    • Google Workspaceは使っているが、もっと活用したい方
    • コードは書けないけど、こういう仕組みが欲しい方

    私自身が副業の現場で「タスクの進捗がメンバーごとにバラバラ」「進捗確認のたびにチャットで聞かないといけない」という状況を何とかしたくて作ったのがこのダッシュボードです。

    月額費用はゼロ。Googleアカウントさえあれば今日から動かせます。


    なぜGAS+スプレッドシートがプロジェクト管理に向いているのか

    世の中にはAsanaやNotionなど優れたプロジェクト管理ツールがたくさんあります。でも「5〜20人の中小チームでちょっとした進捗管理がしたい」だけなら、コストと学習コストが見合わないことが多いのです。

    😓 よくある課題

    • 月額費用が高い
    • チームへの導入ハードルが高い
    • 機能が多すぎて使いこなせない
    • データが外部に出るのが不安

    ✅ GAS+スプレッドシートなら

    • 月額ゼロ円(Googleアカウントのみ)
    • 全員がスプレッドシートを知っている
    • 自社の運用に合わせてカスタマイズ自由
    • データはGoogleドライブ内に留まる

    GASに限界があることも事実です。100人規模・複雑なワークフローには向きません。でも5〜20人規模なら十分すぎるくらい機能します


    全体の構成を把握しよう

    まず完成イメージを頭に入れてから作り始めましょう。システムは大きく3つのパーツで成り立っています。

    📋
    ①タスク一覧シート
    データを入力する場所
    ⚙️
    ②GASが自動処理
    集計・判定・通知
    📊
    ③ダッシュボード
    自動で更新される

    毎朝トリガーで①→②→③が自動的に実行されます

    3枚のシート構成

    シート名 役割 操作する人
    タスク一覧 タスクデータを入力・管理 メンバー全員
    ダッシュボード 集計結果を表示(自動更新) GASが自動で書き込む
    設定 アラート日数などの設定値 管理者のみ

    GAS導入でチームの進捗管理がこう変わる

    STEP 1:スプレッドシートの準備

    Googleドライブで新しいスプレッドシートを作成し、3枚のシートを用意します。まず「タスク一覧」シートの1行目にヘッダーとして以下の9項目を入力してください。

    A: タスク名 / B: 担当者 / C: ステータス / D: 優先度
    E: 開始日 / F: 期限 / G: 完了日 / H: 進捗率(%) / I: コメント

    💡 ポイント:ステータスの値を統一する

    ステータス列には「未着手」「進行中」「完了」「保留」の4つだけを使うようにルール化しましょう。スペルミスや表記揺れがあると集計が正確に動きません。


    STEP 2:GASでダッシュボードを自動更新する

    いよいよGASのコードを書いていきます。Google Apps ScriptはGoogleスプレッドシートのメニューから「拡張機能」→「Apps Script」で開けます。

    🚀 GASエディタの開き方

    1. Googleスプレッドシートを開く
    2. 上部メニュー「拡張機能」→「Apps Script」をクリック
    3. ブラウザの新しいタブでGASエディタが開きます

    コード①:ダッシュボードを自動更新する

    以下のコードをGASエディタに貼り付けて「実行」ボタンを押してください。

    function updateDashboard() {
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const taskSheet = ss.getSheetByName('タスク一覧');
      const dashSheet = ss.getSheetByName('ダッシュボード');
    
      // タスクデータ取得(2行目から最終行まで)
      const lastRow = taskSheet.getLastRow();
      const data = taskSheet.getRange(2, 1, lastRow - 1, 5).getValues();
    
      // 担当者ごとの進捗を集計
      const memberStats = {};
      data.forEach(row => {
        const [task, member, status] = row;
        if (!memberStats[member]) {
          memberStats[member] = { total: 0, done: 0 };
        }
        memberStats[member].total++;
        if (status === '完了') memberStats[member].done++;
      });
    
      // ダッシュボードに書き込み
      dashSheet.clearContents();
      dashSheet.getRange('A1').setValue('担当者');
      dashSheet.getRange('B1').setValue('タスク数');
      dashSheet.getRange('C1').setValue('完了数');
      dashSheet.getRange('D1').setValue('完了率');
    
      let row = 2;
      for (const [member, stats] of Object.entries(memberStats)) {
        const rate = Math.round((stats.done / stats.total) * 100);
        dashSheet.getRange(row, 1).setValue(member);
        dashSheet.getRange(row, 2).setValue(stats.total);
        dashSheet.getRange(row, 3).setValue(stats.done);
        dashSheet.getRange(row, 4).setValue(rate + '%');
        row++;
      }
    }

    ✅ 動作確認

    「実行」ボタンを押すと、ダッシュボードシートに担当者別の集計結果が自動入力されます。初回は「権限を確認」ダイアログが出るので「許可」をクリックしてください。

    コード②:期限リマインダーメールを送る

    期限3日前になったタスクの担当者へ、自動でメール通知します。

    function sendDeadlineReminder() {
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const sheet = ss.getSheetByName('タスク一覧');
      const lastRow = sheet.getLastRow();
      const data = sheet.getRange(2, 1, lastRow - 1, 5).getValues();
    
      const today = new Date();
      const threeDaysLater = new Date();
      threeDaysLater.setDate(today.getDate() + 3);
    
      data.forEach(row => {
        const [task, member, status, deadline, email] = row;
        if (status === '完了') return; // 完了済みはスキップ
    
        const deadlineDate = new Date(deadline);
        if (deadlineDate <= threeDaysLater && deadlineDate >= today) {
          GmailApp.sendEmail(
            email,
            `【期限注意】${task}`,
            `${member}さん\n\n「${task}」の期限が${deadline}です。\n進捗確認をお願いします。`
          );
        }
      });
    }

    ⚠️ 注意

    「タスク一覧」シートのE列に、担当者のメールアドレスを入力しておく必要があります。Gmail形式(例:yamada@gmail.com)で入力してください。


    STEP 3:トリガーを設定して自動実行にする

    コードを毎日手動で実行するのは手間がかかります。GASのトリガー機能を使えば、指定した時間に自動実行できます。

    🕐 トリガー設定の手順

    1. GASエディタ左メニューの「時計アイコン(トリガー)」をクリック
    2. 右下の「+トリガーを追加」ボタンをクリック
    3. 実行する関数:sendDeadlineReminder を選択
    4. イベントのソース:時間主導型 を選択
    5. 時間の種類:日タイマー、時刻:午前9時〜10時 に設定
    6. 「保存」をクリック → 毎朝9時に自動でリマインダーメールが送信されます

    GASでできること・できないこと

    GASは非常に便利ですが、万能ではありません。導入前に確認しておきましょう。

    ✅ GASが得意なこと

    • Googleスプレッドシートの自動集計
    • Gmailでのメール自動送信
    • Googleカレンダーへの自動登録
    • 定期的なバッチ処理
    • フォーム回答の自動仕分け

    ❌ GASが苦手なこと

    • リアルタイムの処理(遅延あり)
    • 大量データの高速処理
    • Google以外のサービス連携(要API)
    • 複雑なUI・アプリ画面の作成
    • 1回の実行が6分を超える処理

    まとめ

    📝 この記事のまとめ

    • GASとGoogleスプレッドシートで月額0円のプロジェクト管理ダッシュボードが作れる
    • 3シート構成(タスク一覧・ダッシュボード・設定)でシンプルに管理
    • 担当者別の進捗自動集計で管理者の確認作業を大幅削減
    • 期限リマインダーで期限切れタスクを事前に防止
    • トリガー設定で毎朝自動実行→完全ハンズフリー運用が可能

    「自分の会社の業務フローに合わせてカスタマイズしたい」「もっと複雑な集計ロジックを実装したい」という方は、お気軽にご相談ください。

    💼 業務自動化の相談はこちら

    GASやスプレッドシートを使った業務効率化を、現場に合わせて一緒に設計します。

    無料相談を申し込む →