人間とAIで勝負
最近めっきりYahoo!知恵袋のBisualBasicカテゴリの質問が減りました。chatGPTのせいでしょうか?ということで、chatGPTと人間様のどちらが優秀か、勝手に勝負してみました。
勝負の仕方
Yahoo!知恵袋で見つけた下記質問↓に答えるのに対し、早さと正確性で勝負します。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12275863032
マクロに関する質問です。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12275863032
とあるシートの2行目(横)に特定の文字列が含まれているかを判定し、含まれていたらその行(縦)をコピーして既存の別シートの指定された列(セル)に貼り付ける、という処理を行いたいのですがどのようにマクロを組めばいいか悩んでいます。文字列は複数条件指定したいと考えているのですが、ご助力頂けないでしょうか。
時間
よーーい、どん!で私もコーディングを始めました。私がかかった時間が25分
終わってすぐにchatGPTをのぞいてみたら、すでに回答済みになっていました。
だから正確な時間は測ることができていませんが、おそらくchatGPTの圧勝でしょう。さすがにAIは早い!(あとで測りなおしたら3分でした。早いっ!)
正確性
さて問題は正確性です。
今回次のようなシートを用意しました。
もう一つ、既存の別シートとしてシート2を用意しました。こちらは何も書いていない真っ白な状態。
私が作ったマクロとchatGPTが作ったマクロをそれぞれ実行してみて、実行結果が質問者さんの期待した形に近いかどうかを検証します。
まずは、私。
Option Explicit
'stVar 配列。文字列が複数入っているはず。
Private Sub 特定の文字列が2行目に含まれていたらその列をコピーして既存の別シートに貼り付ける(stVar As Variant)
Dim tSh As Worksheet 'とあるシート
Set tSh = ThisWorkbook.Worksheets(1) 'とありえずこのブックのシートの最初のもの
Dim anotherSh As Worksheet '既存の別のシート
Set anotherSh = ThisWorkbook.Worksheets(2) 'とりあえずこのブックの2番目のシートを別の既存のシートに指定
Const clRow As Long = 2 'とあるシートの2行目(横)
Dim lLowCnt As Long, lUboundCnt As Long
lLowCnt = LBound(stVar)
lUboundCnt = UBound(stVar)
Dim lEndCol As Long 'とあるシートの2行目における最終列番号
lEndCol = tSh.Cells(clRow, tSh.Columns.Count).End(xlToLeft).Column
Dim ii As Long, jj As Long
Dim anotherCol As Long '既存の別シートにおける貼り付け先セルの列番号
anotherCol = 1
Application.ScreenUpdating = False '画面制御禁止
For ii = 1 To lEndCol
For jj = lLowCnt To lUboundCnt
If InStr(tSh.Cells(clRow, ii).Value, stVar(jj)) > 0 Then
tSh.Cells(clRow, ii).EntireColumn.Copy anotherSh.Cells(1, anotherCol)
anotherCol = anotherCol + 1
End If
Next jj
Next ii
Application.ScreenUpdating = True '画面制御復活
Application.CutCopyMode = False 'コピペモードを解除
Set tSh = Nothing
Set anotherSh = Nothing
End Sub
Public Sub 文字列を指定して検索するテスト()
Dim stVar(2) As Variant
stVar(0) = "もも"
stVar(1) = "梅"
stVar(2) = "みかん"
Call 特定の文字列が2行目に含まれていたらその列をコピーして既存の別シートに貼り付ける(stVar)
End Sub
テスト用に用意した文字列配列「もも」「梅」「みかん」が含まれるセルの存在する列だけがコピーされています(実際にはみかんが含まれるセルは存在しないので、ももと梅だけ)。
次にchatGPTの方を実験してみます。chatGPTが作った生のままのコードでは動かないので、シート名やキーワード部分を修正してから実験しました。↓
Option Explicit
Sub CopyRowsToAnotherSheet()
Dim strConditions() As String '検索条件を格納する配列
Dim wsSource As Worksheet '元データのシート
Dim wsTarget As Worksheet 'コピー先のシート
Dim rngSource As Range '元データの範囲
Dim rngTarget As Range 'コピー先の範囲
Dim lngLastRow As Long '元データの最終行
Dim i As Integer 'ループ変数
Dim j As Integer 'ループ変数
Dim strCondition As String '検索条件
'検索条件を配列に設定
' strConditions = Split("条件A,条件B,条件C", ",") '条件をカンマ区切りで指定
strConditions = Split("もも,梅,みかん", ",") '条件をカンマ区切りで指定
' '元データのシートを設定
' Set wsSource = ThisWorkbook.Sheets("元データのシート名")
Set wsSource = ThisWorkbook.Sheets(1)
'コピー先のシートを設定
' Set wsTarget = ThisWorkbook.Sheets("コピー先のシート名")
Set wsTarget = ThisWorkbook.Sheets(2)
'元データの範囲を設定
lngLastRow = wsSource.Cells(Rows.Count, 1).End(xlUp).Row '最終行を取得
Set rngSource = wsSource.Range("A2:A" & lngLastRow) 'A列の2行目から最終行までの範囲を設定
'コピー先の範囲を設定
Set rngTarget = wsTarget.Range("A2") 'A列の2行目から開始
'検索条件に一致する行をコピーする
For i = 1 To UBound(strConditions)
strCondition = strConditions(i)
For j = 1 To lngLastRow - 1 '最終行は除外
If InStr(1, rngSource(j), strCondition, vbTextCompare) > 0 Then '条件に一致する場合
rngSource(j).EntireRow.Copy rngTarget '行をコピー
Set rngTarget = rngTarget.Offset(1, 0) '次の行へ移動
End If
Next j
Next i
End Sub
ありゃ、全部コピーされてしまった!?
どういうことだとコードを見たら、行コピーになっていました。
rngSource(j).EntireRow.Copy rngTarget '行をコピー
Set rngTarget = rngTarget.Offset(1, 0) '次の行へ移動
検索対象も2行目から最終行までとなっていました。
なるほど・・・。
質問者さんが「含まれていたらその行(縦)をコピーして既存の別シートの指定された列(セル)に貼り付ける」と書いてあるので、私は列コピーと解釈しましたが、AIは行コピーと判断してしまったようです。
文脈から列コピーの方が正しいのですが、これは質問の仕方が悪かったようです。
改めて質問を変えてchatGPTにぶつけてみたところ、今度は列コピーするコードを吐き出してくれました。
このときコードと解説の文章を吐き出す時間を計測したら、およそ3分でした。はやっ!
Option Explicit
Sub CopyColumnsToAnotherSheet()
Dim strConditions() As String '検索条件を格納する配列
Dim wsSource As Worksheet '元データのシート
Dim wsTarget As Worksheet 'コピー先のシート
Dim rngSource As Range '元データの範囲
Dim rngTarget As Range 'コピー先の範囲
Dim lngLastColumn As Long '元データの最終列
Dim i As Integer 'ループ変数
Dim j As Integer 'ループ変数
Dim strCondition As String '検索条件
'検索条件を配列に設定
strConditions = Split("もも,梅,みかん", ",") '条件をカンマ区切りで指定
'元データのシートを設定
Set wsSource = ThisWorkbook.Sheets(1)
'コピー先のシートを設定
Set wsTarget = ThisWorkbook.Sheets(2)
'元データの範囲を設定
lngLastColumn = wsSource.Cells(2, Columns.Count).End(xlToLeft).Column '2行目から最終列を取得
Set rngSource = wsSource.Range(wsSource.Cells(2, 1), wsSource.Cells(2, lngLastColumn)) '2行目から最終列までの範囲を設定
'コピー先の範囲を設定
Set rngTarget = wsTarget.Range("A1") 'A列の1行目から開始
'検索条件に一致する列をコピーする
For i = 1 To UBound(strConditions)
strCondition = strConditions(i)
For j = 1 To lngLastColumn '最終列まで
If InStr(1, rngSource(1, j), strCondition, vbTextCompare) > 0 Then '条件に一致する場合
rngSource(1, j).EntireColumn.Copy rngTarget '列をコピー
Set rngTarget = rngTarget.Offset(0, 1) '次の列へ移動
End If
Next j
Next i
End Sub
ただこれも実験するとまだ不十分でした。
なぜか梅だけ抽出され、ももは抽出されませんでした。
なぜかというと、コードの一部に誤りがあったからです。
'検索条件に一致する列をコピーする
For i = 1 To UBound(strConditions)
配列strConditionsを1から開始していますが、正しくは0から開始しないとダメなのでした。
ということで、さらに手直しして実験してみた結果がこちら↓
For i = LBound(strConditions) To UBound(strConditions)
無事ももと梅が抽出できました。
感想
chatGPTが吐き出したコードはそのまま使うにはまだ危険性を感じます。しかし、人間がコーディングするよりはるかに速いので、まずchatGPTにコードを吐き出させ、人間がデバッグ、微修正するというやり方をすると効率的にプログラミングができるんじゃないかと思いました。
でも、これも今だけのような気がします。いずれAIはもっと進化し、今回かかえていた問題(配列要素のスタートを1とするとか)も修正され、より洗練されたコードを吐き出すようになるんじゃないかという可能性を感じました。
そうなったら、コーディング現場において人間様の出番はないですね。より高次元の設計工程などに人間様の脳みそを専念させることができるようになると思うので、だいぶコストカットできるような気がしています。
追記
chatGPTにLbound使えよとチャットしたら帰ってきた回答がこちら↓
なおってるし!正確に私の指摘を理解しているし!なにこれすごい!!と、感動いたしました。
-
前の記事
流行に疎い 2023.02.20
-
次の記事
【VBA】クラスモジュールの使いどころ 2023.02.22