生成AI活用研究
Geminiと100本ノック 4本目:セルの消去

Geminiを中心に生成AIの活用と研究の記録
公開日:2025-04-24 最終更新日:2025-05-08

Geminiと100本ノック 4本目:セルの消去


Googleが開発した生成AIモデルのGeminiにVBA100本ノックをやってもらいました。
AIがVBAをどこまで扱えるかの実証実験の4本目です。



VBA100本ノックの出題と解答

VBA100本ノック 4本目:セルの消去
・出題 ・頂いた回答 ・解説 ・補足 ・サイト内関連ページ


Geminiへの出題とGeminiの回答

Geminiの回答 Geminiへの出題
VBA マクロ Gemini 100本ノック

#Geminiと100本ノック 4本目
画像のように1行目に見出し、A列に№が入っています。
この表範囲の一部には計算式が入っています。
(画像の最下行とD列には数式が入っています。)
データ行数は毎回変化します。
見出し行とA列№と計算式は残し、定数値だけを消去してください。
※画像ならB2:C11を消去
VBA マクロ Gemini 100本ノック

OK、承知いたしました。Excel VBAで、指定した範囲の中から数式以外の定数だけをクリアするコードを作成します。

以下のコードを標準モジュールに貼り付けて実行してください。

VBA

Sub ClearConstantsOnly()

  Dim ws As Worksheet
  Dim lastRow As Long
  Dim dataRange As Range

  'アクティブなシートを対象とする
  Set ws = ThisWorkbook.ActiveSheet

  'A列の最終行を取得(データが入っている最後の行を想定)
  '画像の例であれば、"合計"の行の一つ上(11行目)を取得したい
  'A列の最終セルから上方向にデータを検索する
  If ws.Cells(Rows.Count, "A").End(xlUp).Value = "合計" Then
    lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Offset(-1).Row
  Else
    lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
  End If

  '定数値をクリアする範囲を設定(B列とC列の2行目から最終データ行まで)
  Set dataRange = ws.Range("B2:C" & lastRow)

  '指定範囲内の定数のみをクリア
  On Error Resume Next 'エラーが発生しても処理を続ける(定数がない場合など)
  dataRange.SpecialCells(xlCellTypeConstants).ClearContents
  On Error GoTo 0   'エラー処理を無効に戻す

  MsgBox "定数値のクリアが完了しました。"

End Sub

コードの解説:
  1. Set ws = ThisWorkbook.ActiveSheet: 現在アクティブになっているシートを操作対象とします。
  2. If ws.Cells(Rows.Count, "A").End(xlUp).Value = "合計" Then ... Else ... End If: A列の最後のセルから上にデータをたどり、"合計"という文字列があればその1つ上の行を最終データ行と判断します。なければA列のデータが入っている最後の行を最終データ行とします。これにより、データ行数が変動しても対応できます。
  3. Set dataRange = ws.Range("B2:C" & lastRow): クリアしたい範囲をB2セルから、計算で求めた最終データ行のC列までとして設定します。
  4. dataRange.SpecialCells(xlCellTypeConstants).ClearContents: ここがポイントです。SpecialCells(xlCellTypeConstants)を使うことで、dataRangeの中から「数式ではない定数値が入っているセル」だけを選択します。その選択されたセルの内容をClearContentsでクリアします。
  5. On Error Resume Next / On Error GoTo 0: もし指定した範囲(B2から最終行のC列)に一つも定数が入っていない場合、SpecialCells(xlCellTypeConstants)でエラーが発生します。そのエラーを無視して処理を続行するための記述です。
このコードを実行すると、見出し行、A列のNo.、そして数式が入力されているセル(画像でいう最下行の合計やD列の金額など)はそのままに、B列とC列の単価と点数(定数値)だけがクリアされます。

VBAは正しく動作するように書けてはいます。
しかし、"合計"行に対する考え方にずれがあります。
この点を指摘してVBAを修正させたいです。


GeminiへのVBAコードの改善提案

具体的にVBAコードで指摘してみました。
・・・
大したものですね。
反論してきました。

Geminiの回答 Geminiへの出題
VBA マクロ Gemini 100本ノック

If ws.Cells(Rows.Count, "A").End(xlUp).Value = "合計" Then
  lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Offset(-1).Row
Else
  lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
End If
この部分は、"合計"であるかないかの判定は不要で、単に、
lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
だけで良いのではないですか?
VBA マクロ Gemini 100本ノック

ご質問ありがとうございます。

確かに、単純にA列の最終行を取得するだけであれば、lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row だけで問題ありません。

しかし、前回のコードの目的は、**「見出し行とA列№と計算式は残し、定数値だけを消去」**することでした。そして、提供いただいた画像では最下行に「合計」があり、そこに計算式(または計算結果)が入っていると推測されます。

もし、最下行に「合計」があり、その行のB列やC列に手入力された値(つまり定数)や、数式で求められた結果が表示されている場合を考えます。

  1. lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row だけの場合:
    この場合、lastRow は「合計」の行番号(画像なら12)になります。
    定数をクリアする範囲は ws.Range("B2:C" & lastRow) となり、画像なら B2:C12 が対象になります。
    もしB12セルやC12セルに手入力した値(定数)があれば、それもクリアされてしまいます。また、SpecialCells(xlCellTypeConstants) は基本的に数式セルを選択しないので、数式が入っていればクリアされませんが、最終行の計算結果として表示されている値が定数として入力されていた場合はクリアされてしまいます。コードの意図としては「計算式を残す」なので、最終行の計算部分も残したいはずです。

  2. If ws.Cells(Rows.Count, "A").End(xlUp).Value = "合計" Then ... の判定を入れた場合:
    この判定を入れることで、A列の最後に「合計」がある場合は、lastRow をその一つ上の行(画像なら11)に設定します。
    定数をクリアする範囲は ws.Range("B2:C" & lastRow) となり、画像なら B2:C11 が対象になります。
    これにより、「合計」の行(画像なら12行目)はクリア対象から外れるため、その行に入っている計算式や値が誤ってクリアされることを防ぐことができます。

したがって、「合計」行を定数クリアの対象から除外し、計算式(やその行に入力された値)を確実に残したいという意図であれば、「合計」であるかどうかの判定は必要になります。

もし、最下行に「合計」という文字列が入ることはなく、A列の最後のデータが入っている行が常に定数クリアの対象範囲の最終行である、という仕様であれば、仰る通り lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row だけで十分です。

どちらの方法を選択するかは、実際のデータがどのように入力されるか、最下行の計算部分をどのように扱いたいかによって判断してください。前回のコードは、提供された画像の形式に合わせて、最下行の「合計」行をクリア対象から外すように考慮したものです。

もう少し丁寧に説明してみました。
きちんと理解したようです。

Geminiの回答 Geminiへの出題
VBA マクロ Gemini 100本ノック

「合計」の行には計算式が入っています。
仮に計算式が入っていないのであれば、本件の要件としてクリアしてよいと考えます。
そして、計算式が入っているのであれば、
SpecialCells(xlCellTypeConstants)
これによって対象外となるので正しく処理されるはずです。
VBA マクロ Gemini 100本ノック

なるほど、ご指摘の通りです。

最終行に計算式が入っているのであれば、SpecialCells(xlCellTypeConstants) メソッドがその計算式セルを自動的に除外するため、「合計」の行かどうかを判定する必要はありませんね。

A列のデータが入っている最終行(画像であれば「合計」がある12行目)を基準に範囲を設定し、その範囲内の定数だけをクリアする、というよりシンプルなロジックで問題ありません。

以下の修正したコードをお試しください。

VBA

Sub ClearConstantsSimplified()

  Dim ws As Worksheet
  Dim lastRow As Long
  Dim dataRange As Range

  'アクティブなシートを対象とする
  Set ws = ThisWorkbook.ActiveSheet

  'A列のデータが入っている最終行を取得(合計行を含める)
  lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row

  '定数値をクリアする可能性がある範囲を設定(B列とC列の2行目からA列の最終行まで)
  'この範囲内に数式があってもSpecialCellsが除外する
  Set dataRange = ws.Range("B2:C" & lastRow)

  '指定範囲内の定数のみをクリア
  On Error Resume Next 'エラーが発生しても処理を続ける(定数がない場合など)
  dataRange.SpecialCells(xlCellTypeConstants).ClearContents
  On Error GoTo 0   'エラー処理を無効に戻す

  MsgBox "定数値のクリアが完了しました。"

End Sub

こちらのコードの方が、目的がよりシンプルに達成できています。ご指摘いただき、ありがとうございました。

せっかくなので、もう少しVBAを教えておきました。
今後に生かされると良いのですが・・・

Geminiの回答 Geminiへの出題
VBA マクロ Gemini 100本ノック

以下のコードをどう思いますか?
Dim rng As Range
Set rng = Range("A1").CurrentRegion.Offset(1, 1)
On Error Resume Next
rng.SpecialCells(xlCellTypeConstants).ClearContents
VBA マクロ Gemini 100本ノック

このコードについての私の評価は以下の通りです。

良い点:

  1. 簡潔さ: CurrentRegionとOffsetを組み合わせることで、コードの記述量が少なく非常に簡潔です。
  2. 動的な範囲取得: CurrentRegionを使用しているため、データ範囲が変動する場合にも対応できます。
  3. SpecialCellsの活用: 定数のみを対象とするSpecialCells(xlCellTypeConstants)を効果的に使用しています。
  4. エラーハンドリング: On Error Resume Nextで、クリア対象の定数セルが見つからなかった場合のエラーを回避しています。

懸念点/注意点:
  1. CurrentRegionの挙動依存: CurrentRegionは、基準セル(ここではA1)を含む、空白行と空白列で囲まれた範囲を選択します。データがA1から途切れなく始まっていて、かつ隣接する列(D列など)にデータがある場合は意図した範囲(A1:D12など)になる可能性が高いですが、データの配置によっては想定外の範囲になるリスクがあります。例えば、A1の左や上にもデータがあったり、データ範囲内に空白行があったりすると、CurrentRegionの範囲が変わります。
  2. Offsetによる範囲の開始位置: Offset(1, 1)によって、範囲が基準(CurrentRegion)の1行下、1列右から始まります。これは見出し行(1行目)とA列を除外するという点では意図通りですが、CurrentRegionの結果に依存します。
  3. クリア対象列の限定が不十分: CurrentRegion.Offset(1, 1)で取得した範囲(画像例ならB2:E13のような範囲)全体に対してSpecialCells(xlCellTypeConstants)を適用します。もしC列の右隣(D列など)に定数として入力されたデータがあり、それが残しておきたいデータだった場合、そのデータもクリアされてしまいます。前回のコードのようにB2:C&lastRowのように列を明示的に指定する方が、クリア対象の列を正確にコントロールできます。画像例であれば、D列は数式なのでSpecialCells(xlCellTypeConstants)の対象外となりますが、D列にたまたま数式ではなく手入力の定数が入っていた場合はクリアされてしまいます。

まとめ:

提示されたコードは、VBAの便利な機能 (CurrentRegion, Offset, SpecialCells) を組み合わせて簡潔に記述されており、多くのケースで期待通りに動作する可能性が高いです。

しかし、データ配置の厳密性やクリア対象とする列をB列とC列のみに限定したいという要件においては、前回の lastRow を特定し、Range("B2:C" & lastRow) のように明確に列範囲を指定するコードの方が、より安全で意図を正確に反映していると言えます。

もし、データが常にA1から始まり空白行・列がなく、かつB列から右のどの列に定数があってもクリアして良い、という前提であれば、このコードは非常に有効です。しかし、B列とC列以外の列の定数は残したい、という場合は前回のコードの方が適しています。
VBA マクロ Gemini 100本ノック

D列に定数として入力されたデータがある場合を懸念していますが、
むしろ、表の列が増えた場合でも、定数値が消去されるようにしておいた方が変化に柔軟に対応できていると思います。
VBA マクロ Gemini 100本ノック

ご意見ありがとうございます。

確かに、将来的に列が増える可能性を考慮すると、クリア対象をB列とC列に限定するのではなく、データのある範囲内でA列とヘッダー行を除いた部分の定数をクリアする、という考え方のほうが柔軟性は高いと言えます。

その観点から見ると、提示いただいたコードは、CurrentRegion を起点としてデータ範囲を大まかに捉え、Offset(1, 1) でヘッダーとA列を除外した部分を対象に SpecialCells(xlCellTypeConstants) を適用するため、列が増えても自動的にその新しい列の定数もクリア対象に含めることができるという点で優れています。

VBA

Dim rng As Range
Set rng = Range("A1").CurrentRegion.Offset(1, 1) ' A1のCurrentRegionから1行下、1列右の範囲
On Error Resume Next
rng.SpecialCells(xlCellTypeConstants).ClearContents ' その範囲内の定数のみをクリア
On Error GoTo 0

このコードは、以下の前提で非常に効果的です。

データ範囲がA1セルから始まり、空白行や空白列で途切れることなく続いていること。(CurrentRegionが正しくデータ範囲全体を選択するため)
A列および1行目以外のセルに入力されている値のうち、「数式ではないもの」はすべてクリアして良いこと。
もし、データ範囲が常にA1から途切れず、かつA列と1行目以外の列の定数は全てクリアしたいという運用であれば、このコードは非常に簡潔でメンテナンス性も高いと思います。

ただし、前述の通り、CurrentRegionの挙動はデータの配置に依存するため、複雑なレイアウトの場合は注意が必要です。しかし、一般的な表形式であれば問題なく機能することが多いでしょう。

柔軟性という観点では、ご提示のコードは確かに合理的です。




同じテーマ「生成AI活用研究」の記事

Geminiと100本ノック 1本目:セルのコピー
Geminiと100本ノック 2本目:セルのコピー
Geminiと100本ノック 3本目:セルの消去
Geminiと100本ノック 4本目:セルの消去
Geminiと100本ノック 5本目:セルの計算
Geminiと100本ノック 6本目:セルに計算式
Geminiと100本ノック 7本目:日付データの扱い
Geminiと100本ノック 8本目:点数の合否判定
Geminiと100本ノック 9本目:フィルターコピー
Geminiと100本ノック 10本目:行の削除
Geminiと100本ノック 9本目:フィルターコピー


新着記事NEW ・・・新着記事一覧を見る

第5章:AI×VBAでつまづかない!トラブルシューティングとAIとの付き合い方 |生成AI活用研究(2025-05-20)
第4章:【事例で学ぶ】AIとVBAでExcel作業を劇的に効率化する! |生成AI活用研究(2025-05-20)
第3章:AIを「自分だけのVBA先生」にする!質問・相談の超実践テクニック|生成AI活用研究(2025-05-19)
第2章 VBAって怖くない!Excelを「言葉で動かす」(超入門)|生成AI活用研究(2025-05-18)
第1章:AIって一体何?あなたのExcel作業をどう変える?(AI超基本)|生成AI活用研究(2025-05-18)
AI時代のExcel革命:AI×VBAで“書かない自動化”超入門|生成AI活用研究(2025-05-17)
Geminiと100本ノック 23本目:シート構成の一致確認|生成AI活用研究(5月16日)
AIが問う出版の未来は淘汰か進化か:AIと書籍の共存の道とは|生成AI活用研究(2025-05-16)
Geminiと100本ノック 22本目:FizzBuzz発展問題|生成AI活用研究(5月15日)
すぐに使える!生成AI プロンプト作成 実践ガイド|生成AI活用研究(2025-05-15)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.繰り返し処理(For Next)|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.ひらがな⇔カタカナの変換|エクセル基本操作
6.RangeとCellsの使い方|VBA入門
7.メッセージボックス(MsgBox関数)|VBA入門
8.セルのクリア(Clear,ClearContents)|VBA入門
9.FILTER関数(範囲をフィルター処理)|エクセル入門
10.条件分岐(Select Case)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ