ChatGPTに頼んで「汎用的なデータ集計マクロ」を作ってもらいました

こんにちは

今回は今話題の**ChatGPT**を使って日々の業務で楽をしてみましたので、それについて書こうと思います。

:::note warn
今回の記事は、ある程度自分でVBAのコードが書ける、もしくは理解できる人に向けた内容なので、「マクロに一切触れたことが無い」という人はもしかしたら100％の再現はできないかもしれません。
:::

修正等
2023/8/21：記事の本文により合致するようタイトルを変更しました。

## 出来上がったマクロはこんな感じ -動画-
まずはじめに完成したマクロの挙動をお見せします。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ChatGPTにマクロ組んでもらいました<br>同一フォルダ内のエクセルを全て開き、指定した項目の集計をしてくれます<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/%E3%83%9E%E3%82%AF%E3%83%AD?src=hash&amp;ref_src=twsrc%5Etfw">#マクロ</a> <a href="https://twitter.com/hashtag/VBA?src=hash&amp;ref_src=twsrc%5Etfw">#VBA</a> <a href="https://t.co/Z9fJ1Lpdfd">pic.twitter.com/Z9fJ1Lpdfd</a></p>&mdash; go west (@west_twitt) <a href="https://twitter.com/west_twitt/status/1690923222492188672?ref_src=twsrc%5Etfw">August 14, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## 今回やったこととその準備

### 背景　「マクロを作るのもめんどくさい」
さて、今回の背景をまずざっくり説明しておきます。
僕は普通にサラリーマンをしているのですがこの度、うちの会社の「支社ごとの実働時間の合計」が必要になりました。
手元にあるデータは、従業員ごとの実働時間を一覧にした支社ごとのエクセルだけで、あらかじめ合計時間が記されたものはありませんでした。

ひとつひとつ開いて計算するのも面倒なので、マクロでやってしまおうと考えたのですが、ここである思いがよぎります。

**マクロを作るのもめんどくさい**

この作業はそもそも頻繁に発生するものではないし、
VBAコードの処理手順はイメージできるけど、いちいち手で書くのもめんどくさいし、

というわけで今話題の**ChatGPT**にサッと作ってもらう事にしました。

### マクロの処理の流れと注意点をまとめる
まずは今回やりたい事と、注意点をまとめておきます。

1. 支社ごとのエクセルを全て開き、「実働時間」の項目を合計した数字を順番に新規ブックに書き出す
1. 「実働時間」の項目が入力されている列が違う支社も存在する
1. それぞれのエクセルには同じパスワードがかけられている

こんなところでしょうか。
2番については、そもそもデータの形が統一されていれば無視できた問題ですが、現状そうなっていないのでとりえず対応するしかなさそうです。

### さらに欲を出してみる
上の1～3に沿った処理を作ってもらうために**ChatGPT**に入力していた途中で、さらなる欲が出てきました。なので今回はそれも一緒にお願いしてみる事にします。
追加した要望とは次の通りです。

1. もしかしたら同様の処理を今後行うかもしれないので、この処理は個人用マクロブックに保存して使える形にしたい
1. 今回は**実働時間**を集計するが、別の項目でも集計する必要があるかもしれないのでそれにも対応可能にしたい
1. **合計**だけでなく、**平均**とか**最大値**が欲しくなることもあるかもしれないので、それにも対応させたい

かなり欲張ってみました。

## ChatGPTにお願いする
### 実際に書いたお願い（プロンプト）がこちら
![ChatGPT 質問.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467782/de73d7e2-e244-a451-9613-99e9c6914593.png)


もしご自身でも再現してみたい場合は以下をコピーしてお使いください。

~~~:実際のプロンプト
次のようなvbaコードを書いて

#やりたいこと
・同一フォルダ内のエクセルファイルについて処理を繰り返し
・エクセルファイル内の「実働時間」の列の合計を新規ブックに全て転記

#その他の条件
・エクセルファイルには全て同一のパスワードがかかっている
・「実働時間」の列はファイルによって違う
・「実働時間」という項目名は全てのファイルに置いて共通
・この処理は、個人用マクロブックに保存して汎用的に使える形にしたい

#使用イメージ
1マクロを起動
2処理を行うフォルダを僕が選択
3集計する項目を僕が指定
4集計内容を僕が選択（合計、平均、最大値、など）
~~~

このようにお願いする内容をカテゴリごとに箇条書きでまとめると、こちらの要望を汲み取ってくれる確率が高くなるような気がします。

:::note warn
行き当たりばったりで書いたので、`#やりたい事`と`#使用イメージ`で言っていることが微妙に食い違っています。
今回はうまく解釈してもらえましたが、本来はこのような食い違いは無い方が良いです。
:::

### ChatGPTが書いてくれたVBAコード
で、返ってきた答えがこちらです。

![ChatGPT 回答.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467782/ee88e0ac-ab8a-7bde-6c2b-35fdbfe7cf6e.png)

コードが長いので収まりませんでした。
全文は以下の通りです。

```vb:ファイル名変換
Sub AggregateWorkHours()
    Dim folderPath As String
    Dim columnName As String
    Dim aggregateType As String
    Dim password As String
    
    ' ユーザーにフォルダパス、列名、集計内容、パスワードを入力させる
    folderPath = InputBox("処理を行うフォルダのパスを入力してください:")
    columnName = InputBox("集計する項目名（実働時間を含む列名）を入力してください:")
    aggregateType = InputBox("集計内容を選択してください（合計、平均、最大値、最小値など）:")
    password = InputBox("ファイルのパスワードを入力してください:")
    
    ' 新規ブックを作成してシートを追加
    Dim newWorkbook As Workbook
    Set newWorkbook = Workbooks.Add
    Dim newSheet As Worksheet
    Set newSheet = newWorkbook.Sheets(1)
    
    ' 指定したフォルダ内のファイルを処理
    Dim fileName As String
    fileName = Dir(folderPath & "\*.xls*")
    Do While fileName <> ""
        ' パスワードを設定してファイルを開く
        Workbooks.Open fileName:=folderPath & "\" & fileName, password:=password
        Dim openedWorkbook As Workbook
        Set openedWorkbook = Workbooks(fileName)
        
        ' 列番号を取得
        Dim columnNumber As Integer
        columnNumber = Application.Match(columnName, openedWorkbook.Sheets(1).Rows(1), 0)
        
        ' 集計処理を行う
        Dim aggregateValue As Double
        Select Case aggregateType
            Case "合計"
                aggregateValue = Application.WorksheetFunction.Sum(openedWorkbook.Sheets(1).Columns(columnNumber))
            Case "平均"
                aggregateValue = Application.WorksheetFunction.Average(openedWorkbook.Sheets(1).Columns(columnNumber))
            Case "最大値"
                aggregateValue = Application.WorksheetFunction.max(openedWorkbook.Sheets(1).Columns(columnNumber))
            Case "最小値"
                aggregateValue = Application.WorksheetFunction.Min(openedWorkbook.Sheets(1).Columns(columnNumber))
            ' 他の集計内容を追加する場合はここにCaseを追加
        End Select
        
        ' 集計結果を新しいシートに書き込む
        newSheet.Cells(newSheet.Cells.Rows.Count, 1).End(xlUp).Offset(1, 0).Value = fileName
        newSheet.Cells(newSheet.Cells.Rows.Count, 2).End(xlUp).Offset(1, 0).Value = aggregateValue
        
        ' ファイルを閉じる
        openedWorkbook.Close SaveChanges:=False
        
        ' 次のファイルへ
        fileName = Dir
    Loop
    
    ' 新しいブックを表示
    newWorkbook.Activate
End Sub
```

うん。なんかもうこのままで良さそうですね。
というわけでこのコードをコピーして、個人用マクロブックの標準モジュールに貼り付けて使ってみましょう。

:::note warn
コードをどこに貼ればいいか分からない方は、さらに追加で**ChatGPT**に質問しましょう。
「このコードをどこに貼ればいいの？」といった具合で質問すると教えてもらえます。
:::


## 実行前の事前準備
コードはもう用意できたので、実行ボタンを押す前にもうちょっとだけ準備をしておきます。

### 準備1.集計したいエクセルを用意する
まずは集計したいエクセルを用意しましょう。
以下にその内の2つをサンプルとして表示しておきます。

**支社1のエクセルの中身**
![データ中身　支社1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467782/cf7763be-67d3-4584-ef4c-bbf40123c433.png)

**支社5のエクセルの中身**
「実働時間」の列が支社1のエクセルとは異なりますが、エクセルごとに「実働時間」の列が異なっていても集計できるように作ってもらったので大丈夫です。
![データ中身　支社5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467782/d81cee0e-0481-7954-e1cf-222e6e744e6b.png)

### 準備2.そのエクセルを同じフォルダに入れる
下の画像の様に、集計したいエクセルを全て同じフォルダに入れておきます。
![集計データ格納フォルダ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467782/c721a391-33bc-29d9-0fc6-0a5766fe34f1.png)

:::note warn
この時、集計したいエクセル以外のエクセルはこのフォルダに入れないようにしましょう。
:::

## 処理を実行する
### 実際の挙動 -動画-

実行したら、こちらがやることは次の4つです。
1. 集計したいエクセルが保存されているフォルダのパスを入力（事前にフォルダパスをコピーしておきましょう）
1. 集計したい項目名を入力
1. `合計`、`平均`、`最大値`、`最小値`の中からやってほしい集計を入力
1. パスワードがかかっている場合はそのパスワードを入力

実際に動かした動画はこちら

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ChatGPTにマクロ組んでもらいました<br>同一フォルダ内のエクセルを全て開き、指定した項目の集計をしてくれます<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/%E3%83%9E%E3%82%AF%E3%83%AD?src=hash&amp;ref_src=twsrc%5Etfw">#マクロ</a> <a href="https://twitter.com/hashtag/VBA?src=hash&amp;ref_src=twsrc%5Etfw">#VBA</a> <a href="https://t.co/Z9fJ1Lpdfd">pic.twitter.com/Z9fJ1Lpdfd</a></p>&mdash; go west (@west_twitt) <a href="https://twitter.com/west_twitt/status/1690923222492188672?ref_src=twsrc%5Etfw">August 14, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

### 一応チェックをしておきましょう
念のため、マクロで集計された数字と、関数を使って手で計算した数字を比較してみました。

左半分：マクロで計算された「実働時間の合計」
右半分：支社1のエクセル内で`SUM`関数で計算した「実働時間の合計」
![合計時間チェック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467782/5c8523dc-8d9e-dadc-2a04-1aabf41014d9.png)

良い感じですね。
このまま支社2～5まで全てチェックしましたが、きちんと計算されていました。


## ChatGPT かなり便利です
今回、**ChatGPT**を使ってササっとマクロを作ってみましたが、これ、かなり便利です！
想像以上に期待通りの動きをしてくれました。

### 上手く出来ない事もある
ただ、今回はかなり正確にこちらの要望通りのコードを作ってくれましたが、こちらが期待した通りのコードを作ってくれない事もよくあります。
条件が1つだけ抜けていたり、全く違う内容でコードを書いてきたり

なので初めにも書いた通り、やはり現状は「ある程度VBAコードが書ける、理解できる人」じゃないと使いこなすことは難しいかもしれません。

### それでも相当な時短が期待できる
とはいえ、「ある程度」のレベルさえわかっていれば大体のことが出来るようになりますので、相当画期的なツールだということには変わりません。

ちなみに僕はこの便利さを味わってからは「とりあえず**ChatGPT**に土台を書いてもらう」ようになりました。
一発で100点の物は作れないにしても、70点～95点くらいの物なら一瞬で作ってくれるので、**ChatGPT**が書いてくれたコードをちょこっと修正して使用するという使い方をしています。

あれやこれや調べる必要もないので、体感ですがコードを書く時間が1/3くらいにはなったような気がしています。

### 浮いた時間で
こんな風にして時間を浮かせることができるので、最近は部内での業務改善の考案とその提案に時間が使えるようになりました。

今まではとりあえず日常の業務をこなすことで精いっぱいだったのですが、そもそもの業務手順を見直したり、新しく何かを始めるための提案資料作りに時間を使っています。

さらにその提案資料も**ChatGPT**で作ってもらえないかとも考え、現在試行錯誤中です。


というわけで今更ですが、**ChatGPT**の凄さに感動したので記事にまとめてみました。

それではまた