rex0220 計算式プラグイン GPTs による計算式の改善

計算式プラグイン GPTs で、土日を除いた指定月のカレンダーをテーブルに作成します。
最初の分かりにくい計算式から、チャットを通して分かりやすい計算式に改善してみます。

# 概要

最初のプロンプトに対する計算式の回答は、学習した内容のままで、かなり分かりにくいものです。
分かりにくい計算式をチャットを通して改善を試みますが、そのやり取りの中で、改善のヒントを見つけることができます。
直接に回答を得られなくとも GPTs とのやり取りは、コードを考える手助けになります。
他の人とレビューを行って、いろいろ気づくのと同じような効果がありそうです。

# 変更前と変更後の計算式の比較

## 変更前

テーブル行毎に、前行の日付から次の平日になる日付を計算するため、処理が分かりにくい。

```変更前.JS
// 年月 DATE (editable)
DATE_FORMAT(年月,"YYYY-MM-01")

// テーブル SUBTABLE
LET(x,DATE_FORMAT(年月,"e"),
  y,DATE_ENDOF(年月, "month", "DD"),
  y-SWITCH(y,
    29,SWITCH(x,0,9,6,9,8),
    30,SWITCH(x,0,9,5,9,6,10,8),
    31,SWITCH(x,0,9,4,9,5,10,6,10,8),
    8)
)

// テーブル.番号 NUMBER
ROWNO(テーブル)+1

// テーブル.日付 DATE
LET(r,ROWNO(テーブル),
  IF(r=0,
    DATE_ADD(年月,TR_SUM(r,SWITCH(DATE_FORMAT(年月,"e"),0,1,6,2,0)),"day"),
    DATE_ADD(SUBTABLE(日付,r-1),
       IF(DATE_FORMAT(SUBTABLE(日付,r-1),"e")=5,3,1),"day")
  )
)

// テーブル.曜日 SINGLE_LINE_TEXT
MID("日月火水木金土",DATE_FORMAT(日付,"e")+1,1)
```

## 変更後

最初に指定月の日数分の日付を用意して、そこから土日の日付を削除するだけなので、処理が簡単。
その代わり、テーブル外に計算用の作業用項目追加が必要です。

```変更後.js
// 年月 DATE (editable)
DATE_FORMAT(年月,"YYYY-MM-01")

// テーブル SUBTABLE
ARRAY_COUNT(SPLIT(作業用項目,","))

// テーブル.番号 NUMBER
ROWNO(テーブル)+1

// テーブル.日付 DATE
LET(日配列,SPLIT(作業用項目,","),
  行位置, ROWNO(テーブル),
  ARRAY_GET(日配列,行位置)
)

// テーブル.曜日 SINGLE_LINE_TEXT
LET(日, 日付,
  曜, DATE_FORMAT(日, "e"),
  SUBSTR("日月火水木金土", 曜, 1)
)

// 作業用項目 SINGLE_LINE_TEXT
LET(
  開始日, 年月,
  月日数, DATE_ENDOF(開始日,"month", "DD"),
  日配列, ARRAY_FOR(月日数,x,DATE_ADD(開始日, x, "day")),
  ARRAY_FIL(日配列, x, NOT(IN(DATE_FORMAT(x,"e"),"0","6")))
)

```

# 最初のプロンプトと応答内容

```
# 課題
テーブルに指定月のカレンダーを作成する計算式を教えてください。
ただし、土日を除いたカレンダーです。

# アプリ構成
年月（日付項目）で指定月を入力。
テーブルに日付、曜日、備考を持ちます。

# 変数名のルール
変数名は、日本語で 6文字以内でつけてください

# 計算式コード内コメントのルール
計算式コード内に１行毎にコメントを付けてください
コメントは、「//」で始まり改行までがコメントになります。
各項目の計算式の先頭に、対象の項目名をコメントで入れてください。

# 処理時間を考慮
テーブル全体の処理を行う集計関数については、テーブル外に作業用項目を追加して、効率化を行ってください。

# マークダウン型式で計算式を回答してください。
各項目の計算式は、プラグイン設定でコピペがしやすいようにコードブロックで回答をお願いします。
一つのコードブロックに、各項目の計算式をまとめて、記述してください。
各項目の計算式を記述する順番は、処理の順番に合うように記述してください。

# 注意事項
変数名は、日本語で 6文字以内とします。
コメントは、日本語で 10文字以内とします。
```

```計算式1.js
// 年月: 入力された日にちを月の初日に変更
DATE_FORMAT(年月,"YYYY-MM-01") // 年月の計算

// テーブル行数: 月の日数から土日の日数を引いて行数を算出
LET(x,DATE_FORMAT(年月,"e"),
  y,DATE_ENDOF(年月, "month", "DD"),
  y-SWITCH(y,
    29,SWITCH(x,0,9,6,9,8),
    30,SWITCH(x,0,9,5,9,6,10,8),
    31,SWITCH(x,0,9,4,9,5,10,6,10,8),
    8)
) // テーブル行数の計算

// 日付: 年月にテーブル行位置を加算し、土日を除いた日付をセット
LET(r,ROWNO(テーブル),
  IF(r=0,
    DATE_ADD(年月,TR_SUM(r,SWITCH(DATE_FORMAT(年月,"e"),0,1,6,2,0)),"day"),
    DATE_ADD(SUBTABLE(日付,r-1),
       IF(DATE_FORMAT(SUBTABLE(日付,r-1),"e")=5,3,1),"day")
  )
) // 日付の計算

// 曜日: 日付から曜日を計算
MID("日月火水木金土",DATE_FORMAT(日付,"e")+1,1) // 曜日の計算
```

# 日付の計算式の改善1

>日付の計算式が分かりにくいので、関数のネストを減らしてください。

![2023-12-10_14h52_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/1b17825b-ea58-5214-840a-34a264de1e06.png)

# 日付の計算式の改善2

>ループ処理がテーブルの行数分発生するので、パフォーマンス改善のためにループ処理をテーブル外の作業項目に移動してください。

![2023-12-10_14h54_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/916a2a8b-ebaa-d198-9347-1db394a0ddbf.png)

# 日付の計算式の改善3

>作業用項目に配列をセットすると、カンマ区切りの文字列になります。
作業用項目を参照時は、配列に変換が必要です。

![2023-12-10_14h55_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/46fce251-a8db-bac6-4c33-3a6147cc6158.png)

# 日付の計算式の改善4

>ちょっと分かりにくいので、月の日数分の日付の配列を作ってから、土日を除いた日付にのみの配列に変換してください。

![2023-12-10_14h56_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/744fc730-3229-8f80-f69d-235a68d1b22e.png)

# 日付の計算式の改善5

>ARRAY_FORは、配列を返す関数なので、日付を返すだけでいいはずです

![2023-12-10_14h57_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/f457dbaf-3159-f3be-c463-73680be074fa.png)

# 日付の計算式の改善6

なかなか計算が簡単にならなかったのですが、テーブル外に月の土日を除いた情報を持つという考え方から、計算式を提案。

>作業用項目の計算式は下記でどうですか？
```.JS
LET(
  開始日, 年月,
  月日数, DATE_ENDOF(開始日,"month", "DD"),
  日配列, ARRAY_FOR(月日数,x,DATE_ADD(開始日, x, "day")),
  ARRAY_FIL(日配列, x, NOT(IN(DATE_FORMAT(x,"e"),"0","6")))
)
```

![2023-12-10_14h58_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/47a3951b-a794-a4d2-2de1-fa88125f1581.png)