「日報をChatwork(チャットツール)で報告しているけれど、過去の記録がどんどん流れていってしまい、誰がどれくらい投稿しているのか振り返りにくい…」 そんなお悩みはありませんか?
今回は、Googleの「GAS(Google Apps Script)」とAIアシスタント「Gemini」の力を借りて、Chatworkの日報をGoogleスプレッドシートに自動保存し、さらに見やすいダッシュボード(グラフ付き画面)まで作ってしまう方法をご紹介します。
Geminiに「こういうことがしたい!」と相談しながら進めた結果、あっという間に実用的なシステムが完成してしまいました。
その感動の体験と、実際の作り方をステップバイステップで解説します。
今回作るシステムの完成イメージ

-
自動蓄積: 社員が特定のChatworkグループに日報を投稿した瞬間、自動的にスプレッドシートへ時系列で保存されます。
-
ダッシュボード化: 保存されたデータをもとに、「社員別の投稿数ランキング(グラフ)」と「最新100件の投稿一覧」を表示する専用のWEB画面を生成します。

できあがったWEBアプリのダッシュボードはこんな感じです。
準備するもの
-
Googleアカウント(Google Workspace利用なら最適です)
-
Chatworkアカウント(管理者権限、またはAPI申請ができること)
-
Gemini(頼れるAIアシスタント!)
構築ステップ:たったの5ステップで完成!
Step 1:受け皿となるスプレッドシートの準備
-
Googleスプレッドシートを新規作成し、タイトルを「日報集計システム」などとします。
-
画面左下のタブをダブルクリックして、シート名を「日報DB」に変更します。
-
1行目〜2行目は自由に使ってOKです。(例:「A1: M社日報データベース」など)
-
-
新しいシートを追加し、シート名を「名簿」とします。
-
A列に「ChatworkのアカウントID」、B列に「氏名」を入力しておきます。(こうすることで、システムが自動でIDを名前に変換してくれます)
-
-
スプレッドシートのURLから、
/d/と/editの間にある長い文字列(スプレッドシートID)をコピーしてメモしておきます。
Step 2:Chatworkの情報(APIトークンとルームID)を取得
-
Chatworkを開き、右上のプロフィール名 >「サービス連携」>「APIトークン」から、APIトークンをコピーしてメモします。
-
日報を集約したい対象のグループチャットを開き、URLの
#!ridの後ろにある数字(ルームID)をメモします。(例:123456789)
Step 3:GAS(Google Apps Script)の設定
ここからがプログラミングの領域ですが、コードはすべてコピペでOKです!
-
スプレッドシートの上部メニュー「拡張機能」>「Apps Script」をクリックします。
-
無題のプロジェクトが開くので、最初から書かれているコードをすべて消し、以下のコードを貼り付けます。
JavaScript
// =========================================================
// ① Chatworkからの自動受信プログラム(Webhook用)
// =========================================================
function doPost(e) {
var json = JSON.parse(e.postData.contents);
var message = json.webhook_event.body;
var accountId = json.webhook_event.account_id;
var roomId = json.webhook_event.room_id;
var sendTime = json.webhook_event.send_time;
// ★あなたの対象ルームIDに変更してください
var targetRoomId = 123456789;
if (roomId === targetRoomId) {
var date = new Date(sendTime * 1000);
var formattedDate = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss');
// ★あなたのスプレッドシートIDに変更してください
var sheetId = 'YOUR_SPREADSHEET_ID_HERE';
var spreadsheet = SpreadsheetApp.openById(sheetId);
var sheet = spreadsheet.getSheetByName('日報DB');
var rosterSheet = spreadsheet.getSheetByName('名簿');
// 名簿から名前を検索
var rosterData = rosterSheet.getDataRange().getValues();
var senderName = "未登録";
for (var i = 1; i < rosterData.length; i++) {
if (String(rosterData[i][0]) === String(accountId)) {
senderName = rosterData[i][1];
break;
}
}
// シートに書き込み
sheet.appendRow([formattedDate, accountId, senderName, message]);
}
return ContentService.createTextOutput("OK");
}
// =========================================================
// ② ダッシュボード(画面)を表示するプログラム
// =========================================================
function doGet() {
return HtmlService.createHtmlOutputFromFile('index')
.setTitle('社内日報ダッシュボード')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
// =========================================================
// ③ ダッシュボードに集計データを送るプログラム
// =========================================================
function getDashboardData() {
// ★あなたのスプレッドシートIDに変更してください
const sheetId = 'YOUR_SPREADSHEET_ID_HERE';
const spreadsheet = SpreadsheetApp.openById(sheetId);
const sheet = spreadsheet.getSheetByName('日報DB');
const rosterSheet = spreadsheet.getSheetByName('名簿');
const rosterData = rosterSheet.getDataRange().getValues();
const counts = {};
for (let i = 1; i < rosterData.length; i++) {
const name = rosterData[i][1];
if (name) counts[name] = 0;
}
const values = sheet.getDataRange().getValues();
const dataRows = values.slice(2); // 3行目以降をデータとして扱う
dataRows.forEach(row => {
const name = row[2]; // C列(名前)
if (name && counts[name] !== undefined) {
counts[name] += 1;
} else if (name && name !== "未登録" && name !== "名前") {
counts[name] = (counts[name] || 0) + 1;
}
});
let sortedCounts = [];
for (let name in counts) {
sortedCounts.push({ name: name, count: counts[name] });
}
// 投稿数が多い順(降順)に並び替え
sortedCounts.sort((a, b) => b.count - a.count);
const chartData = [['名前', '投稿数']];
let currentRank = 1;
let previousCount = -1;
sortedCounts.forEach((item, index) => {
if (item.count !== previousCount) {
currentRank = index + 1;
}
item.rank = currentRank;
chartData.push([`${currentRank}位 ${item.name}`, item.count]);
previousCount = item.count;
});
const latestPosts = dataRows.reverse().slice(0, 100).map(row => {
return {
date: Utilities.formatDate(new Date(row[0]), "JST", "MM/dd HH:mm"),
name: row[2],
body: row[3]
};
});
return { chart: chartData, posts: latestPosts };
}
※コード内の 123456789(ルームID)と YOUR_SPREADSHEET_ID_HERE(スプレッドシートID)を、Step 1・2でメモしたものに書き換えてください。
Step 4:ダッシュボード画面(HTML)の作成
-
GASエディタの左側「ファイル」の横にある「+」を押し、「HTML」を選択します。
-
ファイル名を
indexにします。 -
以下のコードをすべて貼り付け、上部の「保存(フロッピーアイコン)」を押します。
HTML(index.html)
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<style>
body { background-color: #f8f9fa; font-family: 'Helvetica Neue', Arial, sans-serif; }
.container { max-height: 100%; padding-top: 30px; }
.dashboard-card { background: white; border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); padding: 20px; margin-bottom: 25px; }
.table-container { max-height: 500px; overflow-y: auto; }
h1 { color: #005088; font-weight: bold; margin-bottom: 0; }
.date-display { font-size: 1.2rem; color: #666; }
</style>
</head>
<body>
<div class="container">
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h1>社内日報ダッシュボード</h1>
<a href="https://www.chatwork.com/#!rid123456789" target="_blank" class="btn btn-outline-primary btn-sm mt-2">
Chatwork 日報ルームを開く
</a>
</div>
<div class="date-display" id="todayDate"></div>
</div>
<div class="dashboard-card">
<h3>投稿数ランキング</h3>
<div id="chart_div" style="width: 100%; height: 400px;"></div>
</div>
<div class="dashboard-card">
<h3>最新100件の投稿(新しい順)</h3>
<div class="table-container">
<table class="table table-hover">
<thead class="table-light" style="position: sticky; top: 0;">
<tr>
<th style="width: 20%;">日時</th>
<th style="width: 15%;">投稿者</th>
<th>内容</th>
</tr>
</thead>
<tbody id="postList"></tbody>
</table>
</div>
</div>
</div>
<script>
const now = new Date();
document.getElementById('todayDate').innerText = now.toLocaleDateString('ja-JP', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' });
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(refreshData);
function refreshData() {
google.script.run.withSuccessHandler(drawChart).getDashboardData();
}
function drawChart(data) {
const chartData = google.visualization.arrayToDataTable(data.chart);
const options = {
hAxis: { title: '投稿数', minValue: 0 },
vAxis: { title: '名前' },
legend: { position: 'none' },
colors: ['#005088'],
animation: { startup: true, duration: 1000, easing: 'out' }
};
const chart = new google.visualization.BarChart(document.getElementById('chart_div'));
chart.draw(chartData, options);
const listBody = document.getElementById('postList');
data.posts.forEach(row => {
const tr = document.createElement('tr');
tr.innerHTML = `<td>${row.date}</td><td><span class="badge bg-info text-dark">${row.name}</span></td><td>${row.body.replace(/\n/g, '<br>')}</td>`;
listBody.appendChild(tr);
});
}
</script>
</body>
</html>
-
画面右上の青いボタン「デプロイ」>「新しいデプロイ」をクリック。
-
歯車アイコンから「ウェブアプリ」を選択し、「アクセスできるユーザー」を「全員」にして「デプロイ」をクリックします。(アクセス承認が出たら許可します)
-
完了画面に表示される「ウェブアプリのURL」をコピーします。これがシステムとダッシュボードの窓口になります。
Step 5:ChatworkにWebhook(自動送信)を設定する
-
Chatworkの右上の名前 >「サービス連携」>「Webhook」>「新規作成」を開きます。
-
以下のように設定します。
-
Webhook URL: Step 4でコピーした「ウェブアプリのURL」を貼り付け。
-
イベント: 「ルームイベント」を選び、「メッセージ作成」にチェック。対象のルームID(例:123456789)を入力。
-
-
「作成」を押せば連携完了です!
試しにChatworkに投稿してみてください。数秒後、スプレッドシートにデータが自動で入り、ダッシュボードのURLを開くとグラフと一覧が表示されるはずです。
専属プログラマー「Gemini」との共同作業で感じたこと
実はこのシステム、私一人で作ったわけではありません。すべてAIアシスタントのGeminiに相談しながら作りました。
-
ざっくりした要望も形にしてくれる: 「ChatworkのIDじゃなくて名前にしたい」「グラフのランキングを1位から順に並べたい」といったフワッとした要望を伝えるだけで、Geminiが意図を汲み取ってコードを修正してくれました。
-
エラーが出ても安心: プログラムを実行して赤いエラー文字が出た時も、そのエラーメッセージをそのままGeminiにコピペするだけで、「これはこういう原因だから、ここを直せば大丈夫ですよ!」と優しく、的確に解決策を教えてくれました。

まるで、優秀で優しい専属のプログラマーがずっと隣にいて伴走してくれているような感覚です。 「やりたいことはあるけれど、技術的なハードルが高い」と感じている方は、ぜひGoogle Workspaceの環境とGeminiを活用して、業務効率化の第一歩を踏み出してみてはいかがでしょうか?
GASはAIエージェントにできます。

この記事を書いた遠田幹雄は中小企業診断士です
遠田幹雄は経営コンサルティング企業の株式会社ドモドモコーポレーション代表取締役。石川県かほく市に本社があり金沢市を中心とした北陸三県を主な活動エリアとする経営コンサルタントです。
小規模事業者や中小企業を対象として、経営戦略立案とその後の実行支援、商品開発、販路拡大、マーケティング、ブランド構築等に係る総合的なコンサルティング活動を展開しています。実際にはWEBマーケティングやIT系のご依頼が多いです。
民民での直接契約を中心としていますが、商工三団体などの支援機関が主催するセミナー講師を年間数十回担当したり、支援機関の専門家派遣や中小企業基盤整備機構の経営窓口相談に対応したりもしています。
保有資格:中小企業診断士、情報処理技術者など
会社概要およびプロフィールは株式会社ドモドモコーポレーションの会社案内にて紹介していますので興味ある方はご覧ください。
お問い合わせは電話ではなくお問い合わせフォームからメールにておねがいします。新規の電話番号からの電話は受信しないことにしていますのでご了承ください。

【反応していただけると喜びます(笑)】
記事内容が役にたったとか共感したとかで、なにか反応をしたいという場合はTwitterやフェイスブックなどのSNSで反応いただけるとうれしいです。
本日の段階で当サイトのブログ記事数は 6,924 件になりました。できるだけ毎日更新しようとしています。
遠田幹雄が利用しているSNSは以下のとおりです。
facebook https://www.facebook.com/tohdamikio
ツイッター https://twitter.com/tohdamikio
LINE https://lin.ee/igN7saM
チャットワーク https://www.chatwork.com/tohda
また、投げ銭システムも用意しましたのでお気持ちがあればクレジット決済などでもお支払いいただけます。
※投げ銭はスクエアの「寄付」というシステムに変更しています(2025年1月6日)
※投げ銭は100円からOKです。シャレですので笑ってご支援いただけるとうれしいです(笑)
株式会社ドモドモコーポレーション
石川県かほく市木津ロ64-1 〒929-1171
電話 076-285-8058(通常はFAXになっています)
IP電話:050-3578-5060(留守録あり)
問合→メールフォームからお願いします
法人番号 9220001017731
適格請求書(インボイス)番号 T9220001017731

