原点のカレンダー（組織のベーススケジュール）を作成せよ！ChatGPTと一緒に難題に挑戦！

# :calendar_spiral:みんなの原点となるカレンダー
みなさん、こんにちは、450（シンゴオー）です。
私は小売業に勤め、最近デジタルについて勉強している者です。
今回は、会議予定をカレンダーに自動入力するプロトタイプを作成しました。
題して「みんなの原点となるカレンダー作成」です。
## なぜカレンダーの自動入力？
理由は２つあります。
**①私の組織における役割が会議体に関するため**
**②会議案内がメールかつExcelで書式が複数あり、変更も起きるため**
この２点について具体的に説明します。
以下が私の所属している組織のイメージです。

![自分の組織のイメージ図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/68f27e1a-80f7-3cec-019b-6407d3037768.png)

私は小売業の食品商品部に所属しています。
そして私の役割は、調整係、図の「ピンク色の部分」です。
役割上、会議の運営や準備のほかに、会議日程の問い合わせも受けます。
問い合わせ内容の具体例としては、以下のようなものがあります。
・「明日の会議何時からだっけ？」
・「次の〇〇会議はいつ？」
・「あれ、その会議いつ日程変わったの？知らなかった。」
確認のための会話もありますが、最新の日程共有ができていないという状況も見受けられます。

以下の図が会議の案内連絡の現状図です。

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/85dd1841-6c3f-e0e0-2dd9-23c5b60737d0.jpeg)

・Excelで複数の書式がメールで案内される。
・様々な要因で日程変更が発生し、これもメールで案内される。
といった状況で、会議日程の確認の会話はよく起きます。

各チームも計画資料を作成しているので、会議日程は重要です。
会議日程の変更や、追加・漏れが起きれば
準備をしているメンバー全員に迷惑をかけてしまいます。

私は、この課題の解決に向けて糸口を見つけるため、組織の原点となるカレンダーの自動入力と共有について取り組みました。


## 改善効果の数値化
改善することでどれくらいのインパクトがあるのか数値化することで、この取り組みの重要性を説明します。
以下が想定される課題改善の効果です。

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/5eead787-a075-2901-58e0-623fb23ed032.jpeg)


ざっくりとした計算ですが、問い合わせの件数から算出します。
主に会議に参加するメンバーは部内で１５名、月度で会議は約１５回開催されます。１回の会議で約５名とスケジュール確認の会話をします。手帳を開いたり、確認の時間に約２分とします。
**・１５回×５名×２分＝１５０分**　
問い合わせの対応で月に**１５０分**費やしています。
ただし、これは私に対する問い合わせなので、他メンバーや参加者自身が確認している時間を踏まえると、これ以上の効果があると考えます。
また、この課題を解決できた時の改善効果は大きいと思います。
というのも、会議に参加する各チームのリーダーの元に５名ほどの部下がいます。例えば、お肉屋のリーダーがいて、その部下に５名います。その５名が手分けをして会議体の資料を作成しています。
**部内のチームは１１チーム×各チーム６名＝計６６名**
**会議のスケジュールは資料を作成している６６名に影響しており、
会議スケジュールの正確な共有でこの６６名も助かるという構図です。**
時間では表現できませんが、会議には食品商品部内の多くのメンバーが関わっており、常に最新のスケジュール共有は重要と考えます。


# 作成したものはこれ！

https://x.com/45O20/status/1828393190027665850


# :wrench:使用ツール
・[ChatGPT](https://chatgpt.com/g/g-FtfRzXHxO-tiyatuto-gpt-ri-ben-yu)
・Googleスプレットシート
・GAS（Google Apps Script）
・Googleカレンダー

# カレンダー入力「全体のイメージ図」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/174df58d-e43d-e760-fa0b-81ed524813c9.png)

・エクセルでのスケジュールデータ受取
　↓　①ChatGPTでGoogleスプレットシートへ貼り付けするための分類へ変更
・Googleスプレットシートへ貼り付け
　↓　②ChatGPTでシートの内容をGoogleカレンダーへ自動入力するコードを作成
・GAS（Google Apps Script）を実行
　↓
・Googleカレンダーへ自動入力
　上記が一連の流れとなります。
  ここからChatGPTで作成した①、②について詳しく説明したいと思います。
## :one:ChatGPTでの分類変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/2e3157fe-3b10-f319-143d-929b1e1200ca.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/88162567-d906-8235-0b8c-a1093a036228.png)

:::note warn
注意事項
ChatGPTはもちろん優秀ですが、よく間違いも起こります。
したがって、きちんと自分が指示した答えになっているか確認が重要となります。
ここからプロンプト入力してGoogleスプレットシート完成までの流れを説明します。
:::
<details>
<summary>Click!!（ChatGPTとの①の完成までやりとりはこちら）</summary>
Open!!


:::note info
プロンプト
GoogleAppsScriptのコードを書いてきます これはカレンダーの１か月の予定をGoogleスプレッドシートに転記するコードを書こうと思っています Googleカレンダーの予定から取得できるパラメーターの全てを書き出してください
:::
Googleカレンダーから予定を取得する際に使用できる主なパラメーターは、CalendarEventオブジェクトを通じてアクセスできます。以下に、Google Apps Scriptで使用可能なすべてのパラメーターをリストします。

CalendarEvent オブジェクトのパラメーター一覧
ID

getId(): イベントの一意のIDを取得します。
タイトル

getTitle(): イベントのタイトルを取得します。
説明

getDescription(): イベントの詳細説明を取得します。
場所

getLocation(): イベントの場所を取得します。
開始日時

getStartTime(): イベントの開始日時を取得します。
終了日時

getEndTime(): イベントの終了日時を取得します。
作成日時

getDateCreated(): イベントの作成日時を取得します。
最終更新日時

getLastUpdated(): イベントの最終更新日時を取得します。
参加者リスト

getGuestList(): 参加者リストを取得します。Guestオブジェクトを含む配列を返します。
参加者の応答状況

getGuestStatus(email): 指定したメールアドレスの参加者の応答状況を取得します（例：YES、NO、MAYBE）。
リマインダー

getReminders(): イベントに設定されているリマインダーを取得します。
カレンダー

getCalendar(): イベントが属しているカレンダーを取得します。
カラー

getColor(): イベントの色を取得します。
カスタムプロパティ

getTag(key): カスタムタグを取得します。
表示時間の設定

getVisibility(): イベントの表示設定を取得します（例：DEFAULT、CONFIDENTIAL、PRIVATE）。
有効期限

getAllDayEndDate(): 終日イベントの終了日を取得します。
作成者

getCreators(): イベントの作成者を取得します。
会議情報

getConferenceData(): イベントに関連する会議情報を取得します。
参加者にリクエストを送る

sendInvites(): 参加者にリクエストを送信します。
定員

getGuestsCanModify(): ゲストがイベントを編集できるかどうかを確認します。
通知設定

getNotificationSettings(): イベントの通知設定を取得します。
オプションフラグ

getGuestsCanInviteOthers(): ゲストが他の人を招待できるかどうかを確認します。
getGuestsCanSeeOtherGuests(): 他のゲストを確認できるかどうかを確認します。
繰り返しイベントのルール

getRecurrence(): イベントの繰り返しルールを取得します。
終日イベントかどうか

isAllDayEvent(): イベントが終日イベントかどうかを確認します。
キャンセルされているかどうか

isDeleted(): イベントが削除されているかどうかを確認します。
繰り返しイベントかどうか

isRecurringEvent(): イベントが繰り返しイベントかどうかを確認します。
ビデオ会議

getHangoutLink(): Googleハングアウトのリンクを取得します。

:::note info
プロンプト
以下9月度動物カンパニーの会議スケジュールです。このデータをGoogleスプレットシートへ転記するための表に変換してほしい　＋エクセル貼り付け
:::
以下のように、9月度動物カンパニーの会議スケジュールをGoogleスプレッドシートに転記するための表に変換しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/9d439913-0844-e794-77d4-f5a34ad876fd.png)

:::note info
プロンプト
会議内容の中を３つ列にわけてほしい　会議内容　開始時間　終了時間　（）内の内容が時間なので例えば（830-1230）は開始時間が8時30分で終了時間が12時30分となります　（13-）は終了時間が記入されていないので終了時間は空白でよいです
:::

以下のように、会議内容、開始時間、終了時間を3つの列に分けて表に変換しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/f876431f-0dd1-a86a-8ba9-c249fe6c7e42.png)

:::note info
プロンプト
にゃーにゃー会議やつる店オープンのところ　日付と曜日は全部入れてほしい
:::
すべての日付と曜日を埋めた表を以下に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/a86e0c99-62f7-e4c2-e82b-a44a5afa8496.png)
</details>

**ChatGPTとのやりとりで最終的にできあがったシートはこれ！**
最後にGoogleカレンダー入力する際、色わけしたい内容もプロンプトで指示しました。
この内容をGoogleスプレットシート貼り付けて①のステップは終了しました。
以下が最終のプロンプトとなります。

:::note info
プロンプト
スプレットシートの会議と〇〇店オープンのところ　Googleカレンダーでは色を変えたいのでそのためのスプレットシートを作成してほしい　さらに色をかえるコードも入れたjavascriptを作成してほしい　会議は青色　検討MTは黄色　〇〇店オープンは緑色にお願い
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/d5520dc2-de94-556a-f6cf-b1c45268d92b.png)

## :two:ChatGPTでGASのコード作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/db5b98ea-660f-0eb1-77dc-0a51077bbd6d.png)

<details>
<summary>Click!!（ChatGPTと②の完成までやりとりはこちら）</summary>
Open!!

:::note info
プロンプト
最終的に　GoogleスプレッドシートからGoogleスケジュールにこの表を連携したいと思いますがこの順番で大丈夫？
:::
GoogleスプレッドシートからGoogleカレンダーにスケジュールを連携する際、以下のステップで進めるとスムーズです。
ステップ 1: スプレッドシートの作成とデータ入力
スプレッドシートを作成：Googleスプレッドシートに、上記のような表形式で日付、曜日、会議内容、開始時間、終了時間の情報を入力します。
ステップ 2: Google Apps Script を使って連携する
Google Apps Script の準備：スプレッドシート上で「拡張機能」→「Apps Script」を選択し、新しいスクリプトを作成します。
コードの記述：Google Apps Scriptを用いて、スプレッドシートの内容をGoogleカレンダーに反映させるコードを書きます。以下は基本的な例です。

```Javascript
function addEventsToCalendar() {
  // スプレッドシートとシートの取得
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート名'); // シート名を適宜変更
  const calendar = CalendarApp.getCalendarById('カレンダーID'); // GoogleカレンダーIDを適宜変更
  const lastRow = sheet.getLastRow();
  
  // データをループで取得
  for (let i = 2; i <= lastRow; i++) { // 2行目からデータがあると仮定
    const date = sheet.getRange(i, 1).getValue();
    const title = sheet.getRange(i, 3).getValue();
    const startTime = sheet.getRange(i, 4).getValue();
    const endTime = sheet.getRange(i, 5).getValue();
    
    if (title) {
      const startDateTime = new Date(date);
      startDateTime.setHours(startTime.getHours());
      startDateTime.setMinutes(startTime.getMinutes());
      
      let endDateTime;
      if (endTime) {
        endDateTime = new Date(date);
        endDateTime.setHours(endTime.getHours());
        endDateTime.setMinutes(endTime.getMinutes());
      } else {
        endDateTime = new Date(startDateTime.getTime() + 60 * 60 * 1000); // デフォルトで1時間のイベント
      }
      
      // Googleカレンダーにイベントを作成
      calendar.createEvent(title, startDateTime, endDateTime);
    }
  }
}
```
ステップ 3: スクリプトを実行する
スクリプトの実行：記述したスクリプトを実行し、スプレッドシートのデータをGoogleカレンダーに反映させます。
自動化（オプション）：定期的にスプレッドシートからGoogleカレンダーに連携したい場合は、トリガーを設定して自動化します。
注意点
カレンダーのID: 必ず使用したいGoogleカレンダーのIDを取得し、スクリプトに適切に設定してください。
データ形式の確認: スプレッドシートのデータが正しく入力されていることを確認します。特に、日付や時間の形式がGoogleカレンダーで理解できる形式であることが重要です。
これで、スプレッドシートからGoogleカレンダーへのスケジュール連携が可能になります。順番としては、問題ありませんが、Google Apps Scriptを正しく書いて実行することが肝心です。

:::note info
プロンプト
コードの内容　新入社員でもわかるように説明してほしい
:::

GoogleスプレッドシートのデータをGoogleカレンダーに自動的に反映させるためのコードを、初心者でも分かるように説明します。

1. 基本の流れ
このコードは、Googleスプレッドシートの中にある会議の情報（日時、会議内容、開始時間、終了時間）をGoogleカレンダーに登録するためのものです。ステップごとにどう動くのかを説明していきます。

2. 各ステップの詳細説明
1. スプレッドシートとカレンダーを取得

```Javascript
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート名');
const calendar = CalendarApp.getCalendarById('カレンダーID');
```
⊡SpreadsheetApp.getActiveSpreadsheet()：これは、今開いているGoogleスプレッドシート全体を指します。
⊡getSheetByName('シート名')：スプレッドシートの中にある特定のシート（タブ）を選びます。シート名は実際に使用しているシートの名前に置き換えます。
⊡CalendarApp.getCalendarById('カレンダーID')：GoogleカレンダーのIDを使って、どのカレンダーにイベントを追加するかを指定します。

2. 最後のデータ行を取得
```Javascript
const lastRow = sheet.getLastRow();
```
⊡getLastRow()：スプレッドシートの中で、最後にデータが入力されている行番号を取得します。この情報を使って、データが入力されている範囲だけを処理します。
3. データを一行ずつ読み込んで、カレンダーに追加

```Javascript
for (let i = 2; i <= lastRow; i++) {
  const date = sheet.getRange(i, 1).getValue();
  const title = sheet.getRange(i, 3).getValue();
  const startTime = sheet.getRange(i, 4).getValue();
  const endTime = sheet.getRange(i, 5).getValue();
  
  if (title) {
    const startDateTime = new Date(date);
    startDateTime.setHours(startTime.getHours());
    startDateTime.setMinutes(startTime.getMinutes());
    
    let endDateTime;
    if (endTime) {
      endDateTime = new Date(date);
      endDateTime.setHours(endTime.getHours());
      endDateTime.setMinutes(endTime.getMinutes());
    } else {
      endDateTime = new Date(startDateTime.getTime() + 60 * 60 * 1000); // デフォルトで1時間のイベント
    }
    
    calendar.createEvent(title, startDateTime, endDateTime);
  }
}
```
forループ：2行目（タイトル行の次）から、最終行まで繰り返し処理を行います。

sheet.getRange(i, 1).getValue()：i行目の1列目（日付）を取得。
sheet.getRange(i, 3).getValue()：i行目の3列目（会議内容）を取得。
sheet.getRange(i, 4).getValue()：i行目の4列目（開始時間）を取得。
sheet.getRange(i, 5).getValue()：i行目の5列目（終了時間）を取得。
if (title)：もし会議内容が空でなければ、その行のデータをGoogleカレンダーに追加する準備を始めます。

⊡startDateTime：会議の開始日時を作成。日付（date）と開始時間（startTime）を組み合わせて作成します。
⊡endDateTime：会議の終了日時を作成。もし終了時間が指定されていない場合は、開始から1時間後を終了時間とします。
⊡calendar.createEvent(title, startDateTime, endDateTime)：Googleカレンダーに、指定された日時でイベント（会議）を作成します。
</details>

**ChatGPTとのやりとりで最終的にできあがったコードはこれ！**
実行することでGoogleカレンダーへ入力ができました！


```Javascript
function importEventsToCalendar() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート名'); // スプレッドシートのシート名を指定
  const calendar = CalendarApp.getCalendarById('カレンダーID'); // カレンダーIDを指定
  
  // 既存イベントの削除
  clearCalendar(calendar);

  const lastRow = sheet.getLastRow();
  
  for (let i = 2; i <= lastRow; i++) {
    const date = sheet.getRange(i, 1).getValue();
    const title = sheet.getRange(i, 3).getValue();
    const startTime = sheet.getRange(i, 4).getValue();
    const endTime = sheet.getRange(i, 5).getValue();
    const category = sheet.getRange(i, 6).getValue();
    const color = sheet.getRange(i, 7).getValue();
    
    if (title) {
      const startDateTime = new Date(date);
      
      // 〇〇店オープンのように時間が空白の場合
      if (!startTime) {
        const event = calendar.createAllDayEvent(title, startDateTime);
        setEventColor(event, color);
      } else {
        startDateTime.setHours(startTime.getHours());
        startDateTime.setMinutes(startTime.getMinutes());
        
        let endDateTime;
        if (endTime) {
          endDateTime = new Date(date);
          endDateTime.setHours(endTime.getHours());
          endDateTime.setMinutes(endTime.getMinutes());
        } else {
          endDateTime = new Date(startDateTime.getTime() + 60 * 60 * 1000); // デフォルトで1時間のイベント
        }
        
        const event = calendar.createEvent(title, startDateTime, endDateTime);
        setEventColor(event, color);
      }
    }
  }
}

function setEventColor(event, color) {
  // カテゴリに基づいて色を設定
  if (color === '青') {
    event.setColor(CalendarApp.EventColor.BLUE);
  } else if (color === '黄') {
    event.setColor(CalendarApp.EventColor.YELLOW);
  } else if (color === '緑') {
    event.setColor(CalendarApp.EventColor.GREEN);
  }
}

function clearCalendar(calendar) {
  // 指定した期間のすべてのイベントを削除
  const events = calendar.getEvents(new Date('2024-09-01'), new Date('2024-09-30'));
  
  for (let i = 0; i < events.length; i++) {
    events[i].deleteEvent();
  }
}
```
ちなみにGoogleカレンダーを期間を指定して白紙に戻すコードも作成しました。こちらになります。
```Javascript
function clearCalendar() {
  const calendar = CalendarApp.getCalendarById('カレンダーID');
  
  // 指定した期間のすべてのイベントを取得
  const events = calendar.getEvents(new Date('2024-09-01'), new Date('2024-09-30'));
  
  // 取得したすべてのイベントを削除
  for (let i = 0; i < events.length; i++) {
    events[i].deleteEvent();
  }
}
```
# :calendar_spiral:カレンダーの共有方法
ChatGPTを活用して制作をしたおかけで時間が捻出できたので、カレンダーの共有方法について、レビューをもらう時間としました。
職場のメンバーや制作仲間にもレビューをもらいカレンダーの共有方法についてアドバイスをもらいました。

:::note info
アドバイス事項
①Googleカレンダーの反映までOKだと思うけれど、みんながみんなGoogleカレンダーを活用しているわけではない。メールがOutlookなので、Microsoftのカレンダー機能を活用している人が多い。
②みんな習慣になっているから最終的に手帳に記入する人が多い。
:::

## 利用したGoogleカレンダーの共有機能はこれ！

https://x.com/45O20/status/1828396180457325013

GoogleカレンダーのリンクURLを取得する方法を発見し、実施したところ
上記動画の内容、月間・週間・予定リストが確認できました。
メンバーへのURLの配信だったり、teamsを活用して、URLを投稿する形でも共有ができます。メンバーへこのURLを最新情報として案内すれば、最新のスケジュール情報の共有につながると思います。

また、参考記事を読むとGoogleカレンダーの内容をMicrosoftカレンダーへの埋め込みもできることを知りました。
実際やってみたら以下映像、を自分のMicrosoftカレンダーより確認できました！！


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840316/b08a1fc2-bba7-4c45-c81d-8bfaa2f0619e.png)


Googleカレンダー共有に参考にした記事はこちら

[【デバイス別】 Google カレンダーの共有方法！ 表示されない場合の対策も](https://rakumo.com/hint/calendar/calendar-sharing/)

# :hugging:あとがき

「原点のカレンダー」という意味は、このカレンダーの情報が組織のベースとなるからです。
このベースを共有した後は、各人自分のやり方でスケジュール管理ができればいいと考えています。
やはり、習慣で手帳に最終記入する人も多いと思うので。
そして、変更があれば更新して共有される仕組みも重要。
ここについては今後さらに検討が必要だと思っています。

今回の制作を通じて、いろんなことができる驚きとChatGPTのすごさを実感しました。
また、プロトタイプを現場に適応させていく重要性も認識しました。


ありがとうございました。　まだまだ成長できるはず！！

# :green_book:参考にした情報
https://qiita.com/myzw1mt3/items/223e7c3b4e8f004cd636

https://cros.co.jp/2023/12/28/%E3%80%90%E6%A5%AD%E5%8B%99%E6%94%B9%E5%96%84%E3%80%91google%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E3%81%AE%E4%BA%88%E5%AE%9A%E3%82%92%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7/