はじめに
こんにちは。普段は愛猫×2と、
わちゃわちゃ戯れている
社会人12年目のまろみいです。
今回は、普段の業務で何気に不便だと感じていることについて、記事にしてみました。
皆さんの会社でも、こんなことってありませんか?
チームメンバーの正確な勤務状況が分からない!
私は、現在総勢約30名の部内メンバーと共に仕事をしています💻
その中の拠点が3カ所あるグループに所属をしているのです
現状として私の部署は、勤務予定を
エクセル管理表での入力管理と社内の
ホワイトボードで勤務場所を一元化しています。
勤務予定のエクセル管理表、、、、
一元管理が出来て便利!ではあるのですが、googleカレンダーへの入力と二重
入力をしているグループもいるのです。
そしてホワイトボード転記用に月初に
一度出力されてしまうと、エクセルシート
の変更は誰も見ていないという現状があるのです。
はたまた、遠方の人は出力シートに反映ができない。。。
そこで、大変!〇〇さんの予定〇〇に
なっているけど、〇〇さん今日どこだっけ? が
発生してしまいます。
問題点
・グループによってスケジュールの変更が随時反映されていない。
・勤務状況を二重入力しているグループがいる。
・誰がどこで何をしているのかが詳細(時間単位)には分からないメンバーがいる。
・確認することに時間(手間)が発生している。
タイムリーにその日の状況が分かれば、
誰がどこで何をしているのかが一目瞭然!
お互いのスケジュール管理も出来て、
必要なタイミングで連絡も取りやすいのではないか。
そして、不要な連絡(電話)が減るのではないかと考えたわけです。
そこで、デジタルで勤務計画&勤務実績を
一括管理できないかと思いました。
実現したいイメージ
使用したツールはこちら
-Gmail
-Googleカレンダー
-google Spread Sheet(GAS)
実行すること:①全員がGoogleカレンダーに予定を入力
②googleカレンダーのスケジュールリストを毎朝リマインド
朝の予定をチームメンバーと自分のリマインドを兼ねてメール配信したい。
内容をChat GPTに聞いてみました。
出来たコードがこちら!
function sendDailyScheduleEmails() {
const spreadsheetId = "スプレッドシートIDをここに"; // スプレッドシートIDを入力
const sheetName = "シート名をここに"; // シート名を入力
const timeZone = "Asia/Tokyo";
const today = new Date();
const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59);
// スプレッドシートから対象者リストを取得
const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
const data = sheet.getDataRange().getValues();
const headers = data.shift(); // ヘッダー行を除外
// 各対象者のカレンダー予定を取得してメール送信
data.forEach(row => {
const [name, email, calendarId] = row;
if (name && email && calendarId) {
const calendar = CalendarApp.getCalendarById(calendarId);
if (calendar) {
const events = calendar.getEvents(startTime, endTime);
let eventDetails = events.map(event => {
return `・${event.getTitle()} (${formatDate(event.getStartTime(), timeZone)} - ${formatDate(event.getEndTime(), timeZone)})`;
}).join("\n");
// メール本文を作成
const subject = `本日の予定 (${formatDate(today, timeZone)})`;
const body = `${name}さん、\n\n以下は本日の予定です:\n\n${eventDetails || "本日の予定はありません。"}\n\nよろしくお願いいたします。`;
// メール送信
GmailApp.sendEmail(email, subject, body);
}
}
});
}
// 日付フォーマット関数
function formatDate(date, timeZone) {
return Utilities.formatDate(date, timeZone, "yyyy/MM/dd HH:mm");
}
// トリガーを設定 (毎日 8:30 に実行)
function createTrigger() {
ScriptApp.newTrigger("sendDailyScheduleEmails")
.timeBased()
.atHour(8)
.nearMinute(30)
.everyDays(1)
.create();
}
出来たコードがこちら!
function sendDailyScheduleEmailsToAll() {
const spreadsheetId = "スプレッドシートIDをここに"; // スプレッドシートIDを入力
const sheetName = "シート名をここに"; // シート名を入力
const timeZone = "Asia/Tokyo";
const today = new Date();
const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59);
// スプレッドシートから対象者リストを取得
const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
const data = sheet.getDataRange().getValues();
const headers = data.shift(); // ヘッダー行を除外
let allEvents = []; // 全員の予定を格納するリスト
data.forEach(row => {
const [name, email, calendarId] = row;
if (name && calendarId) {
const calendar = CalendarApp.getCalendarById(calendarId);
if (calendar) {
const events = calendar.getEvents(startTime, endTime);
if (events.length > 0) {
// 個人の予定をタイトル付きリストで表示
let eventDetails = `\n【${name}さんの予定】\n` + events.map(event => {
return ` - ${event.getTitle()} (${formatDate(event.getStartTime(), timeZone)} - ${formatDate(event.getEndTime(), timeZone)})`;
}).join("\n");
allEvents.push(eventDetails);
}
}
}
});
// メール本文を作成
const subject = `本日の全員の予定 (${formatDate(today, timeZone)})`;
const body = allEvents.length > 0
? `以下は本日の全員の予定です:\n${allEvents.join("\n")}\n\nよろしくお願いいたします。`
: `本日は全員の予定がありません。\n\nよろしくお願いいたします。`;
// 全員にメールを送信
const recipients = data.map(row => row[1]).filter(email => email); // メールアドレスのリストを作成
if (recipients.length > 0) {
GmailApp.sendEmail(recipients.join(","), subject, body);
}
}
// 日付フォーマット関数
function formatDate(date, timeZone) {
return Utilities.formatDate(date, timeZone, "yyyy/MM/dd HH:mm");
}
// トリガーを設定 (毎日 8:30 に実行)
function createTrigger() {
ScriptApp.newTrigger("sendDailyScheduleEmailsToAll")
.timeBased()
.atHour(8)
.nearMinute(30)
.everyDays(1)
.create();
}
そして、受信時のイメージを聞いてみるとこのように返事がありました!
ここで発生した問題点
・日時の表記をシンプルに分かりやすくしたい
・もし1人の予定が多い場合は、5件以内にしたい
・場所(会議室)も記載したい
上記3点を再度、chat GPTに聞いてコードを作成してもらいました!
function sendDailyScheduleEmailsToAll() {
const spreadsheetId = "1zTHZS7AbCPHFrwzAsR9beqp-bl1BSNsU7zhJB3tJeJs"; // スプレッドシートID
const sheetName = "対象者一覧"; // シート名
const timeZone = "Asia/Tokyo";
const maxEventsPerPerson = 5; // 各メンバーの最大表示件数
const today = new Date();
const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59);
// スプレッドシートから対象者リストを取得
const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
if (!sheet) {
Logger.log(`エラー: シート「${sheetName}」が見つかりません。`);
return; // シートが見つからない場合は処理を中止
}
const data = sheet.getDataRange().getValues();
const headers = data.shift(); // ヘッダー行を除外
let allEvents = []; // 全員の予定を格納するリスト
data.forEach(row => {
const [name, email, calendarId] = row;
if (name && calendarId) {
const calendar = CalendarApp.getCalendarById(calendarId);
if (calendar) {
const events = calendar.getEvents(startTime, endTime);
if (events.length > 0) {
// イベントを最大表示件数に制限
const limitedEvents = events.slice(0, maxEventsPerPerson);
const remainingEvents = events.length - limitedEvents.length;
let eventDetails = `\n【${name}さんの予定】\n` + limitedEvents.map(event => {
const start = formatTime(event.getStartTime(), timeZone);
const end = formatTime(event.getEndTime(), timeZone);
const timeText = event.isAllDayEvent() ? "終日" : `${start}-${end}`;
const location = event.getLocation(); // 場所を取得
const locationText = location ? ` (場所: ${location})` : ""; // 場所が設定されている場合のみ表示
return ` - ${event.getTitle()} (${timeText})${locationText}`;
}).join("\n");
// 他の予定がある場合に簡略化メッセージを追加
if (remainingEvents > 0) {
eventDetails += `\n 他 ${remainingEvents} 件の予定があります。`;
}
allEvents.push(eventDetails);
}
}
}
});
// メール本文を作成
const subject = `〇〇部 主要メンバー本日の予定一覧 (${formatDate(today, timeZone)})`;
const body = allEvents.length > 0
? `以下は本日の予定です:\n${allEvents.join("\n")}\n\nよろしくお願いいたします。`
: `本日はメンバーの予定がありません。\n\nよろしくお願いいたします。`;
// 全員にメールを送信
const recipients = data.map(row => row[1]).filter(email => email); // メールアドレスのリストを作成
if (recipients.length > 0) {
GmailApp.sendEmail(recipients.join(","), subject, body);
}
}
// 時間フォーマット関数 (短い時刻形式)
function formatTime(date, timeZone) {
return Utilities.formatDate(date, timeZone, "HH:mm");
}
// 日付フォーマット関数
function formatDate(date, timeZone) {
return Utilities.formatDate(date, timeZone, "yyyy/MM/dd");
}
// トリガーを設定 (毎日 8:30 に実行)
function createTrigger() {
ScriptApp.newTrigger("sendDailyScheduleEmailsToAll")
.timeBased()
.atHour(8)
.nearMinute(30)
.everyDays(1)
.create();
}
③トリガーの設定
GASのコード入力画面を開き、左側の🕔トリガーをクリックし、
上記図表の赤枠の仕様に設定をします! ※ここでは午前8時~9時の設定をしています。
④主要メンバーの予定を毎朝8:30
に勤務状況のリマインド配信!
ポイントは、毎朝のリマインド機能をつけることで、
主要メンバーの予定がメール配信され、最新情報を知ることが出来ることです💡
自動メール通知により、予定をチェックする手間が省け、管理がしやすくなります
退勤時は、勤怠入力も忘れずにリマインド!で業務時間管理
私たちの会社は、生産性向上に向けて、勤務時間の管理を徹底しています。
本社は、スーパーフレックスタイム制を導入し、
毎日勤怠状況を各自で上司と共有、把握することが求められています。
退勤時、毎日の勤務状態をリマインド機能で対象者全員にメール!
入力忘れによる記入漏れを防ぎます!
メールの本文に目的をしっかり伝えることで、
メンバーの皆さんへの意識付けにも繋がります。
初めの一歩👣は現状を認識することが大切です💡
全員が目的を認識し、意識付けができると行動にも繋がりやすくなります
まとめ 今後の改善にむけて
今回苦労したことは、トリガー⏰の設定です。
毎日同じ時刻に配信することでリマインドセットを試みましたが、
1時間単位の〇時~〇時の設定しか選択ができませんでした。
そこで、GASのコードにトリガーを埋め込んでみたら上手くいくのではないかと思い
Chat GPTに確認しながらコードへの入力を実行しました。
結果的には反映されず、設定時間の1時間のどこかのタイミングでメールが配信される
設定にしかできませんでした。2日~3日色んなパターンで試みましたが解決ができず、
まだ若干もやっとしています。引き続き、試行錯誤を繰り返します。
最終的には、定時設定でのメール配信ができるようになります!
また報告させてください
そして、上記内容について一部メンバーに話をしたところ、
勤務時間管理のリマインドメールには、目的が書かれていたほうが意識づけになるとの
フィードバックをもらい、早速、記載することにしました!✍
フィードバック&コーチャビリティ(素直に聞き入れること)を大切にします!
まろみいの紹介・記事についてはこちら!
Xはこちら☞ https://x.com/maromii_y
noteの記事はこちら!☞ https://note.com/yuri_kataoka35/all
Qiitaの 前回1回目の記事はこちら