概要
マクロを使ったことのない自分が、業務でマクロが必要になった
→とりあえず基礎文法を4時間だけ学習した。
→要件定義だけしたら、あとはChatGPTが全部コードを書いてくれた。
→コードだけならChatGPTがあれば人間いらない説。
やりたかったこと
顧客環境のメーラーをメンバーが開いているか、死活確認をする。
→そのために、自社環境メーラーから定期的に、開封確認付きのメールを送る。
環境
・Windows10 22H2
これに付随するMicrosoft365製品
使ったもの
・GPT4
・ExcelVBA
・Outlook(VBAを介して利用)
・タスクスケジューラ(VBAのキックに利用)
入出力のサンプル
以下は、要件と出力のサンプルなので、詳しく中身を読み込むというより「ふーんこんな感じに使えるんだ」という感じに読み進めてほしい。
#依頼
次の要件を満たすコードをVBAで出力してください。
その際の注釈は日本語で書いてください。
#要件
Outlookから動作時点のメールを送る。この際のToは「tanaka@example.com」
動作時点の日時を取得し、「yyyy年MM月dd日_HH時mm分」の形に変換してからString型変数「動作日時」に格納する。
Outlookから動作時点のメールを送る。この際のToは「tanaka@example.com」で、件名は「動作日時」変数に格納された値、本文はなしとし、開封確認を求めるプロパティ設定を行う。
動作時点から15分前の日時を取得し、「yyyy年MM月dd日_HH時mm分」の形に変換してからString型変数「判定日時」に格納する。
動作するExcelファイル上で、A列に入力のある一番最後のセルから10番目までに「判定日時」と一致するものがあるか確認する。
ある場合、その行のB列に含まれるセルの値がTRUEかを確認する。
TRUEの場合、動作終了する。
FALSEの場合、またはA列に入力のある一番最後のセルから10番目までに「判定日時」と一致するものがある場合、以降の処理を行う。
Outlookの受信ボックスで、最新のメールから20件に「判定日時」の日時を含むものがあるかを確認する。
含む場合は、A列に入力のある一番最後のセルの下のセルに「判定日時」の値を記載し、その右のセルにFALSEを記載する。
含まない場合は、メールを送る。この際のToは「tanaka@example.com」で、件名は「判定日時」変数に格納された値+「メールを開封してください」、本文はなしとし、開封確認を求めるプロパティ設定を行う。
'この要件を満たすVBAコードを作成します。
'このコードは、現在の日時を取得し、Outlookを介してメールを送信し、
'Excelファイルを操作して特定の条件を満たすかどうかを判定するものです。
Sub SendEmailBasedOnConditions()
' Outlookオブジェクトを設定
Dim olApp As Object
Set olApp = CreateObject("Outlook.Application")
' 現在の日時を取得して文字列に変換
Dim currentDateTime As String
currentDateTime = Format(Now, "yyyy年MM月dd日_HH時mm分")
' メールの新規作成
Dim olMail As Object
Set olMail = olApp.CreateItem(0) ' 0 = olMailItem
' メールのプロパティ設定
With olMail
.To = "tanaka@example.com"
.Subject = currentDateTime
.ReadReceiptRequested = True ' 開封確認の要求
.Send
End With
' 15分前の日時を取得
Dim judgmentDateTime As String
judgmentDateTime = Format(Now - TimeValue("00:15:00"), "yyyy年MM月dd日_HH時mm分")
' Excelの操作
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1) ' 1番目のシートを使用
' A列の最後のセルを検索
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
' A列の最後のセルから10番目までを確認
Dim i As Long
Dim proceed As Boolean
proceed = False
For i = lastRow To lastRow - 9 Step -1
If ws.Cells(i, 1).Value = judgmentDateTime Then
If ws.Cells(i, 2).Value = True Then
Exit Sub ' TRUEの場合、処理を終了
Else
proceed = True ' FALSEの場合、処理を継続
Exit For
End If
End If
Next i
' 判定日時が見つからない場合、またはFALSEの場合
If Not proceed Then
' Outlookの受信トレイを確認
Dim olNamespace As Object
Set olNamespace = olApp.GetNamespace("MAPI")
Dim olFolder As Object
Set olFolder = olNamespace.GetDefaultFolder(6) ' 6 = olFolderInbox
Dim olItems As Object
Set olItems = olFolder.Items
' 最新の20件のメールを確認
Dim olItem As Object
Dim found As Boolean
found = False
For i = 1 To 20
Set olItem = olItems(i)
If InStr(olItem.ReceivedTime, judgmentDateTime) > 0 Then
' 判定日時を含むメールが見つかった場合
ws.Cells(lastRow + 1, 1).Value = judgmentDateTime
ws.Cells(lastRow + 1, 2).Value = False
found = True
Exit For
End If
Next i
' 判定日時を含むメールが見つからない場合、新たにメールを送信
If Not found Then
Set olMail = olApp.CreateItem(0) ' 新しいメールアイテム
With olMail
.To = "tanaka@example.com"
.Subject = judgmentDateTime & " メールを開封してください"
.ReadReceiptRequested = True
.Send
End With
End If
End If
End Sub
'このコードは、以下の手順で動作します:
'現在の日時を取得し、メールを送信。
'15分前の日時を取得し、Excelファイルで特定の条件を確認。
'条件に応じて、Outlookの受信トレイを確認し、必要に応じてメールを送信。
こんなレベルのコードが30秒くらいで生成される。あとは人間が間違ってないか動作確認して、修正させる(自分で修正するのではなくGPTに修正させる)だけ。
考えりゃ書ける感はあるが、これを書くのは人間にはどう考えても30秒じゃ無理。(そして人間は、コードを書くよりも、要件をきちんと考える方をやるべき。)
修正の仕方
気になった点や分からない点は、こんな感じに修正させたり質問したりできる。修正コードの意味の解説もしてくれて非常に便利。
Outlookのオブジェクトを解放する必要はないのか
'Outlookのオブジェクトを使用した後、
'特に長期間実行されるアプリケーションや大量のメールを扱う場合には、
'オブジェクトを適切に解放することが推奨されます。
'これにより、リソースのリークを防ぎ、
'アプリケーションのパフォーマンスを維持することができます。
'VBAでオブジェクトを解放するには、
'Set ステートメントを使用してオブジェクトを Nothing に設定します。
'上記のコードにOutlookオブジェクトの解放を追加すると、次のようになります:
' ...
' メール送信後、Outlookオブジェクトを解放
Set olMail = Nothing
Set olApp = Nothing
' ...
' その他の処理後、再度使用したOutlookオブジェクトを解放
Set olMail = Nothing
Set olItems = Nothing
Set olFolder = Nothing
Set olNamespace = Nothing
Set olApp = Nothing
End Sub
'この追加により、各Outlookオブジェクトは使用後に適切に解放され、
'リソースのリークを防ぐことができます。
'コードのこの部分が何をやっているか分からないので解説してほしい。
For i = lastRow To lastRow - 9 Step -1
If ws.Cells(i, 1).Value = judgmentDateTime Then
If ws.Cells(i, 2).Value = True Then
Exit Sub ' TRUEの場合、処理を終了
Else
proceed = True ' FALSEの場合、処理を継続
Exit For
End If
End If
Next i
このコードのセクションはExcelシート内で特定の条件を確認するために使用されます。詳しく説明します:
1. For i = lastRow To lastRow - 9 Step -1:
この行はループを開始します。lastRow はExcelシートのA列における最後の入力セルの行番号を表します。
2. lastRow - 9 は、最後の入力セルから10番目のセルまでを含む範囲を指定します。
Step -1 はループを逆順に実行することを意味します。つまり、最後の行から開始して、10行分上に向かって確認を行います。
3. If ws.Cells(i, 1).Value = judgmentDateTime Then:
この行は、ループの各反復でA列(ws.Cells(i, 1))のセルの値が変数 judgmentDateTime(15分前の日時を文字列形式で格納)と一致するかどうかを確認します。
4. If ws.Cells(i, 2).Value = True Then:
同じ行のB列(ws.Cells(i, 2))の値が True かどうかをチェックします。
この値が True の場合、Exit Sub ステートメントによりサブルーチンから抜け出し(処理を終了し)、これ以上の操作は行いません。
5. Else proceed = True:
B列の値が True でない(つまり False または他の値)場合、変数 proceed に True をセットします。これは、後続の処理を継続する必要があることを示します。
6. Exit For:
一致する値が見つかった場合、これ以上のループの実行は必要ないので、For ループから抜け出します。
このセクションの目的は、指定された範囲内で judgmentDateTime と一致する日時があるかどうかを確認し、その行のB列が True か False かに基づいて異なるアクションを取ることです。
結論
ChatGPTがあれば、要件定義を文字でしてしまいさえすれば、いい感じにコードを出してくれる。
補足
あくまで今回のような「VBAを必要になったけど使ったことない」レベルの話なので、ゴリゴリの開発などの話は別の方の事例を参考にしてください。また、タイトルはあえて挑戦的にして、読者の皆様の興味を引き出すためのものです、あしからず。