【2025年8月】
AI(Copilot)を使えば、VBAを知らないシロウトでもマクロを作れる!って期待している方は多いでしょう。確かに便利なAIですが、はたして、そう上手くいくのでしょうか。実際に試してみましょう。
上図のデータで「A列が"田中"だったらB列の数値を2倍してC列に代入するマクロ」を作りたいです。なお、データの行数は分からないとします。まずは次のようなプロンプトで聞いてみましょう。
田中だったら2倍するマクロを作って
結果はこちら。
は?私「マクロを作って」って言いましたよね。う~ん、言い方が悪かったのかな。もう一度。
田中だったら2倍するVBAのコードを作って
Sub DoubleIfTanaka() Dim ws As Worksheet Dim i As Long Set ws = Worksheets("Sheet1") For i = 2 To 10 ' データ範囲A2:B10 If ws.Cells(i, 1).Value = "田中" Then ws.Cells(i, 2).Value = ws.Cells(i, 2).Value * 2 End If Next i End Sub
よかった、伝わったようです。でもこれ、B列の数値を2倍して、B列に上書きしちゃいます。いや、[結果]って列があるんだから、そこに代入して欲しかったんだけどな。実行したらB列の数値が変わっちゃうとこだった。危ない。でも、そういうのも言わないと察してくれないんですね。
田中だったら数値を2倍して結果に入れるVBAのコードを作って
ざけんなよ!さっき作ってくれたじゃん。だったら、もっと丁寧に言いましょうか。
A列の値が"田中"の行だけ、B列の数値を2倍して、C列に代入するVBAのコードを作ってください。お願いします。
以下はご要望のVBAコードです。A列が「田中」の行だけ、B列の値を2倍してC列に代入します。 Sub TanakaDouble() Dim lastRow As Long Dim i As Long lastRow = Cells(Rows.Count, 1).End(xlUp).Row For i = 2 To lastRow ' ヘッダーが1行目の場合 If Cells(i, 1).Value = "田中" Then Cells(i, 3).Value = Cells(i, 2).Value * 2 End If Next i End Sub
あざざます。完璧ですね。やっぱ、"親しき仲にも礼儀あり"みたいな。AIにも礼節を持って接しないといけませんね、人として。さて、コードの中で気になるのは「Cells(Rows.Count, 1).End(xlUp).Row」では?これの意味を聞いてみました。
「Cells(Rows.Count, 1).End(xlUp).Row」の意味を教えて
「Cells(Rows.Count, 1).End(xlUp).Row」は、 「A列(1列目)の一番下のセル(最終行)から上方向にデータがあるセルまで移動し、 そのセルの行番号を取得する」という意味です。 つまり、「A列で一番下までデータが入力されている行番号」を取得するVBAの書き方です。 データ範囲の最終行を調べるときによく使います。
なるほど、よく分かりました。
ポイント:
プロンプトの書き方によって、AIの回答は大きく異なります。「田中だったら数値を2倍して結果に入れる」では、どこの"田中"なのか、何の"数値"なのか、どこに"入れる"のかが定まりません。自分のやりたいことを詳細に記述するようにしましょう。
特定の行だけ、書式を設定してみましょう。条件は「E列が270以上」とします。該当する行全体の文字色を赤色にするマクロです。
E列の数値が「270以上」だったら、該当する行のA列からE列の文字色を、赤色にするVBAのコードを作って
E列の値が「270以上」の場合に、A列からE列の文字色を赤色にするVBAコードは以下の通りです。 Sub 赤文字にする() Dim i As Long For i = 2 To 10 ' データ範囲の行番号 If Cells(i, 5).Value >= 270 Then Range(Cells(i, 1), Cells(i, 5)).Font.Color = RGB(255, 0, 0) End If Next i End Sub
シンプルでいいですね。コードも無駄がなく完璧です。今回はデータの行数を10と特定してきました。もし、行数が不定だったら、先の「lastRow = Cells(Rows.Count, 1).End(xlUp).Row」と組み合わせればいいです。それくらいは、自分で考えましょう。私のセミナーでは毎回教えていますが「Range(Cells(i, 1), Cells(i, 5))」という書き方を、ご存じない方も多いかと。作ってくれたコードを、そのままコピーして満足するのではなく、分からないところを質問して、自分のVBA知識を高めることが重要ですね。
Range(Cells(i, 1), Cells(i, 5))は、どういう意味?
「Range(Cells(i, 1), Cells(i, 5))」は、VBAで「i行目のA列からE列まで (つまりi行目のA~Eセル)」をまとめて指定する書き方です。 たとえば、iが2の場合は「A2:E2」を指します。 Cells(i, 1)は「i行目のA列」、Cells(i, 5)は「i行目のE列」です。 この2つをRangeでつなぐことで、その範囲全体(横一列)をまとめて操作できます。
分かりやすいですね。あと、どうやら「RGB(255, 0, 0)」というのは"赤色"の意味らしいです。これも確認します。
「RGB(255, 0, 0)」は、赤色の意味?
はい、「RGB(255, 0, 0)」は赤色を意味します。 RGBは「Red(赤), Green(緑), Blue(青)」の頭文字で、 それぞれの値(0~255)で色を指定します。 「255, 0, 0」は赤が最大、緑と青が0なので、純粋な赤色になります。
赤・緑・青の割合を、それぞれ0~255で指定するらしいです。では、別の色だったら、それぞれの数値はいくつなのでしょう?
別の色の、赤・緑・青割合は、どうやって調べるの?
Excelで使う「赤・緑・青(RGB)」の割合は、各色ごとに0~255の数値で指定します。 たとえば、以下のような割合です: 赤 RGB(255, 0, 0) 緑 RGB(0, 255, 0) 青 RGB(0, 0, 255) 黄色 RGB(255, 255, 0) 水色 RGB(0, 255, 255) ピンクRGB(255, 0, 255) 黒 RGB(0, 0, 0) 白 RGB(255, 255, 255) グレーRGB(128, 128, 128) 他の色も、Webで「RGB カラーコード」などで検索すると、色見本や割合を調べられます。 ExcelのVBAや条件付き書式で色を指定する場合、このRGB値を使います。
なるほど勉強になりました。ちなみに、色を表す「赤・緑・青の割合」のことを"RGB値"と呼びます。まぁ、正確には「赤・緑・青の割合」によって計算される数値ですけど。気になった方は「"RGB値"って何?」で調べてください。
ポイント:
コードの中で不明なろころがあったら、追加で質問しましょう。作ってくれるコードは、単なる成果物ではなく、あなたにとっての"教材"です。せっかくですから、AIによる個人授業で、VBAスキルを高めましょう。
上図が、やりたいことの結果です。問題は、これをプロンプトとして、どう表現するかですね。
A列からD列の表で、C列の値が"A"の行だけ、セルF2から下方向にコピーするようなVBAのコードを作って
まずは、これでいってみましょう。
Sub CopyRowsWithAtoF2() Dim ws As Worksheet Dim srcLastRow As Long, destRow As Long Dim i As Long Set ws = Worksheets("Sheet3") srcLastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row destRow = 2 ' F2から開始 For i = 2 To srcLastRow If ws.Cells(i, 3).Value = "A" Then ws.Range(ws.Cells(i, 1), ws.Cells(i, 4)).Copy ws.Cells(destRow, 6) destRow = destRow + 1 End If Next i End Sub
さて、実務的に考えたとき、こうしたケースでは既存データの下に追記したいです。たとえば、前回の結果が4行目まであったら5行目から、10行目まであったら11行目から、みたいに。ややこしくなりますが、次のように聞いてみます。
A列からD列の表で、C列の値が"A"の行だけ、F列にコピーしたい。コピー先はすでに入力されている既存データの次行へ。たとえば、既存データが5行目まであったら6行目からコピーするようなVBAのコードを作って
ありゃ、なんと!まぁ、こういうときもありますよ。忙しいんでしょうね、きっと。もう一度聞いてみます。
Sub CopyRowsWithAtoF() Dim ws As Worksheet Dim lastRowSrc As Long, lastRowDest As Long, i As Long Set ws = ThisWorkbook.Sheets("Sheet3") ' コピー元の最終行(A列で判定) lastRowSrc = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row ' コピー先の最終行(F列で判定) lastRowDest = ws.Cells(ws.Rows.Count, "F").End(xlUp).Row If lastRowDest < 2 Then lastRowDest = 1 ' ヘッダーのみの場合 ' A列~D列のうち、C列が"A"の行だけF列以降にコピー For i = 2 To lastRowSrc If ws.Cells(i, "C").Value = "A" Then ws.Cells(lastRowDest + 1, "F").Value = ws.Cells(i, "A").Value ws.Cells(lastRowDest + 1, "G").Value = ws.Cells(i, "B").Value ws.Cells(lastRowDest + 1, "H").Value = ws.Cells(i, "C").Value ws.Cells(lastRowDest + 1, "I").Value = ws.Cells(i, "D").Value lastRowDest = lastRowDest + 1 End If Next i End Sub
上記は、AIの回答をそのままコピーしました。このコードを、そのままVBEのモジュールにコピーするとエラーになります。理由は「<」です。HTMLにおいて「<」「>」「"」「&」などは、特別な意味を持つ記号です。これらの記号をHTML内に(単なる文字のつもりで)直接記述してしまうと、ブラウザは特殊な記号と認識してしまいます。そこで、これらの記号を"単なる文字"として扱う仕組みを実体参照と呼びます。実体参照では「<→<」「>→>」「"→"」「&→&」という文字で記述します。上記コードでは、本来「If lastRowDest < 2 Then lastRowDest = 1」としたいところが、実体参照の文字が表示されてしまったのでしょう。なので、もし上記のコードをVBEにコピーするときは、「<」を「<」に書き換えてください。まぁ、HTMLあるあるです。
あと、細かいことが気になる人に向けて、ちょっと補足します。気にならない方はスルーしてください。今回のコードに限りませんが、AIが使う変数名は「lastRowSrc」のように、最初の単語の1文字目が小文字になっています。ちなみに「Src」は"Source"の略でしょう。「情報源・供給源」などの意味で、よくプログラミングでは「元データ」などとして使われます。また「lastRowDest」の「Dest」は、おそらく"Destination"の略でしょう。意味は「行き先・目的地」などを表します。今回のように"コピー先"などとして使われます。さて「lastRowSrc」は、"last"+"Row"+"Src"という3つの単語で構成されていますが、最初の単語「last」だけ1文字目が小文字です。このように、最初の単語だけ1文字目を小文字で記述するやり方を「キャメルケース」と呼びます。大文字のところが、ラクダのコブのように見えるからだそうです。変数名の記述ルールには、ほかにも「LastRowSrc」のように、すべての単語の1文字目を大文字にする「パスカルケース」や、「last_row_src」のように、単語間をアンダースコアでつないだ「スネークケース」などがあります。ヘビがくねっているように見えるからかな?一般的に、キャメルケースはJavaやJavaScriptなどでよく使われ、スネークケースはPythonなどで使われることが多いようです。
それでは、このコードの総評です。
ws.Cells(lastRowDest + 1, "F").Value = ws.Cells(i, "A").Value
これは、セルのコピーではなく「値(Value)の代入」です。両者は意味が異なります。セルのコピーは、コピー元とコピー先が、まったく同じ状態になりますが、値の代入では書式が反映されません。また、セルに数式が入力されている場合、値の代入では、数式ではなく数式の計算結果が代入されます。コピーするときは、次のように書きます。
ws.Cells(i, "A").Copy ws.Cells(lastRowDest + 1, "F")
ひとつつ前に提示されたコードで、複数セルの指定を次のようにしていました。
ws.Range(ws.Cells(i, 1), ws.Cells(i, 4))
だったら今回も次のようにできます。
ws.Range(ws.Cells(i, "A"), ws.Cells(i, "D")),Copy ws.Cells(lastRowDest + 1, "F")
これだけでマクロは、次のように短くなります。
Sub CopyRowsWithAtoF() Dim ws As Worksheet Dim lastRowSrc As Long, lastRowDest As Long, i As Long Set ws = ThisWorkbook.Sheets("Sheet3") ' コピー元の最終行(A列で判定) lastRowSrc = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row ' コピー先の最終行(F列で判定) lastRowDest = ws.Cells(ws.Rows.Count, "F").End(xlUp).Row If lastRowDest < 2 Then lastRowDest = 1 ' ヘッダーのみの場合 ' A列~D列のうち、C列が"A"の行だけF列以降にコピー For i = 2 To lastRowSrc If ws.Cells(i, "C").Value = "A" Then ws.Range(Cells(i, "A"), Cells(i, "D")).Copy ws.Cells(lastRowDest + 1, "F") lastRowDest = lastRowDest + 1 End If Next i End Sub
ひとつ前のコードでシートを指定するとき、次のように記述されていました。
Set ws = Worksheets("Sheet3")
今回はこうです。
Set ws = ThisWorkbook.Sheets("Sheet3")
厳密に言うと、SheetsとWorksheetsは異なります。Sheetsには、ワークシートだけでなくグラフシートなども含まれますが、Worksheetsはワークシートだけです。その違いを重要視するのなら、毎回Worksheetsと書くべきです。ちなみに、よくセミナーを受講された方々にプチアンケートを取っていますが、グラフシートを使っている人はほとんどいませんし、そもそも存在を知らない人が多いです。ブック内にグラフシートがないのなら、両者は同じです。だったらスペルの短いSheetsが良いかなと、もっぱら私はSheetsを使っています。どっちでもいいんです。このへんは、作者の主義・主張です。どっちでもいいんですが、ブレるのはいただけません。マクロの中にSheetsとWorksheetsが混在すると、読もうとするビギナーは「区別しているのには、何か理由があるのかも」と、不要の疑問を持ちます。読者に疑問を抱かせたら、作者の負けです。
これは好みの問題です。AIはよく、オブジェクト変数を使います。それ自体は、まったく悪くないのですが、Withステートメントを使う方が、全体的にスッキリすると私は感じています。たとえば、次の二つのコードは、どちらも同じ動作です。
Set ws As Worksheet Swt ws = Sheets("Sheet3") ws.Range("A1").Value = 100
With Sheets("Sheet3") .Range("A1").Value = 100 End With
今回のコードを、オブジェクト変数ではなく、Withステートメントで書くと次のようになります。
Sub CopyRowsWithAtoF() Dim lastRowSrc As Long, lastRowDest As Long, i As Long With ThisWorkbook.Sheets("Sheet3") ' コピー元の最終行(A列で判定) lastRowSrc = .Cells(.Rows.Count, "A").End(xlUp).Row ' コピー先の最終行(F列で判定) lastRowDest = .Cells(.Rows.Count, "F").End(xlUp).Row If lastRowDest < 2 Then lastRowDest = 1 ' ヘッダーのみの場合 ' A列~D列のうち、C列が"A"の行だけF列以降にコピー For i = 2 To lastRowSrc If .Cells(i, "C").Value = "A" Then .Range(Cells(i, "A"), Cells(i, "D")).Copy .Cells(lastRowDest + 1, "F") lastRowDest = lastRowDest + 1 End If Next i End With End Sub
Withステートメントは、ドット(.)で始まる書き方をしますので、慣れない方はイメージしにくいかもしれません。でも、少なくとも変数の宣言をしなくて済むので、コード全体がコンパクトになる効果があります。
以上、VBAのコードを作ってもらうときのポイントをまとめます。