生成AI活用研究
第6章:AIとVBAを学び続ける!あなたの「超効率化」を止めないヒント

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

第6章:AIとVBAを学び続ける!あなたの「超効率化」を止めないヒント


これまでの章で、あなたはAIと共にExcelVBAの「書かない自動化」の基礎を習得し、コード生成からエラー解決までを経験しました。AIを「自分だけのVBA先生」として活用し、Excel作業を効率化するイメージは掴めたはずです。


第6章では、この学びをさらに一歩進め、より高度な自動化への挑戦と、実務でAI×VBAを安全かつ効率的に活用するための具体的な注意点に焦点を当てます。
この章を読み終える頃には、あなたは単にコードを生成できるだけでなく、AI×VBAを自身の業務課題にどう結びつけ、どのように安全に、そして継続的に活用していくかという実践的な視点を身につけているでしょう。あなたのExcel業務をAIと共にさらに加速させるための、具体的な一歩を踏み出す力を養うことが、この章の目標です。


目次



AIプロンプト最適化のヒント:さらに“伝わる”プロンプトの書き方

これまでの章で、あなたはAIに基本的な質問を投げかけ、VBAコードを生成させてきました。AIを「自分だけのVBA先生」として活用し、Excel作業を効率化するイメージは掴めたはずです。

しかし、AIとの対話を進める中で、「もっと複雑なことをAIに頼みたい」「こちらの意図がもっと正確に伝わるようにしたい」と感じることもあるでしょう。特に、これから挑戦するより高度な自動化事例では、AIに詳細な指示を与える機会が増えます。

そこで、ここからはさらに一歩進んで、AIがあなたの指示をより深く、正確に理解するためのプロンプト作成術を身につけましょう。ポイントは、AIにとっての「読みやすさ」を意識すること。そのための簡単なテクニックが、Markdown(マークダウン)という記述形式の活用です。

長いプロンプトは面倒? AIを活用する本当の価値

「こんなに長いプロンプトを入力するなら、自分でVBAを書いた方が早いんじゃない?」そう感じた方もいるかもしれません。しかし、そこにこそAIと“書かない自動化”の真価があります。

私たちがAIに入力しているのは、VBAの専門知識ではありません。求めているのは、「何をしてほしいか」という日本語の指示です。

VBAのコードをゼロから書く場合、あなたは以下のようなことを知っている必要があります。
  • ユーザーフォームを構成する各コントロールの名前やプロパティ(TextBox、ComboBox、Caption、Nameなど)。
  • それらのコントロールを操作するVBAのオブジェクトモデル(Me.txtDate.Valueなど)。
  • 入力チェックのためのIsDate、IsNumericといった関数や条件分岐の構文。
  • シートへのデータ転記における最終行の取得方法や、セルの値の代入方法。
  • エラーハンドリングやメッセージボックスの表示方法。

これら一つ一つを学習し、記憶し、正しい構文で記述し、そしてデバッグする労力は計り知れません。

一方、AIを使う場合、あなたはこれらの専門知識を覚える必要はありません。「日付を入力するテキストボックス」「氏名を選ぶドロップダウン」「必須入力にする」といった日常の言葉で要件を伝えるだけで、AIがその裏側にあるVBAの複雑なルールを理解し、コードに変換してくれるのです。

つまり、長いプロンプトは、あなたがVBAの**「専門家」になるための時間と労力**を肩代わりしてくれているのです。一度、具体的な要件を言語化する練習をすれば、次からはそのプロンプトを修正するだけで、さまざまな自動化に挑戦できるようになります。これは、VBAの学習コストを劇的に下げ、「書かない自動化」を実現する強力な武器となるはずです。

Markdownとは?(AIがプロンプトを「理解」するためのヒント)

Markdownは、テキストに簡単な記号を加えて、文章の構造や強調を示すための記述形式です。例えば、**これ**と書けば「これ」という文字を太字にする、といったルールです。

私たちのプロンプト入力ボックスでは、入力した文字が実際に太字になったり、色が変わったりすることはなくても、AIはあなたがMarkdownで書いた記号を**「指示の意図を示す情報(メタ情報)」**として認識しています。

AIはインターネット上の大量の文章を学習しており、その中にはMarkdownで書かれた文章も数多く含まれています。そのため、Markdownの記号を見ることで、AIは「この単語は強調されているな」「これは箇条書きの項目だな」といった、指示の「意味」や「構造」をより深く理解できるのです。

プロンプトでAIの理解を深めるシンプルなMarkdown活用術
複雑な指示や、AIに特に意識させたいキーワードを伝える際に、以下のシンプルなMarkdown記法が特に有効です。
  1. 太字(強調): **キーワード**
    • 記述方法: 強調したい単語やフレーズを **二重のアスタリスク** で挟みます。
    • AIへの効果: AIにその部分が特に重要であることを明確に伝えます。例えば、「ファイル操作には**FileSystemObject**を使用すること」と書けば、AIは一般的なファイル操作よりもFileSystemObjectを用いたコードを優先的に検討する可能性が高まります。
    • 使いどころ:
      • 特定のオブジェクト名、関数名、シート名、フォルダ名など、AIに正確に認識してほしい固有名詞
      • 必須条件や、特に注意してほしい重要な指示
  2. 箇条書き(構造化): * 項目 または 1. 項目
    • 記述方法: 複数の指示や要件を並べる際に、行の先頭に *(アスタリスクと半角スペース)または 1.(数字とピリオド、半角スペース)を置きます。
    • AIへの効果: 指示が複数の独立した項目から構成されていることをAIに伝えます。これにより、AIは指示の見落としを防ぎ、一つ一つの項目に対して網羅的に対応しようとします。また、プロンプトが長くなっても、内容が整理されAIが理解しやすくなります。
    • 使いどころ:
      • フォームに必要なコントロールの一覧。
      • 実装してほしい機能のリスト。
      • コードが満たすべき条件のリスト。

活用例:ユーザーフォームのプロンプトの場合
この後で紹介するユーザーフォームのプロンプトでも、**フォーム名** や **日付入力用**、**登録** といった部分を太字にしたり、機能のリストを箇条書きにしたりすることで、AIは各要素の重要性や指示の構造をより明確に把握し、より的確なVBAコードを生成してくれます。

このように、MarkdownはVBAの知識とは別に、AIとのコミュニケーションをさらにスムーズにするための有効なテクニックです。
難しい記号を覚える必要はありません。
重要な単語を**で囲んだり、複数の指示を箇条書きにしたりするだけでも、AIの回答の質と、あなたの“書かない自動化”の効率を大きく高めることができるでしょう。


ステップアップ!AIと挑戦するより高度な応用自動化事例

これまでの章で、あなたは単一のExcelシートや簡単な処理をAIに任せる方法を学びました。
ここからは、さらに一歩踏み込み、より複雑で実用的なシナリオにAIと共に挑戦してみましょう。

「AIにこんなことも頼めるのか!」

という驚きと、自動化の可能性がさらに広がっていくことを実感できるはずです。

ここでは、Excel業務でよく遭遇するけれど、手作業では手間のかかる、以下の4つの応用事例を紹介します。いずれも、AIに必要な情報を整理して適切なプロンプトを与えることで、高度な処理を行うコードでもAIが生成してくれます。そのコードで自動化を実現できることを体験してください。
  1. 複数のExcelファイルにまたがるデータ集計
  2. ユーザーフォームの作成と操作
  3. Excelデータを使ったWord文書の自動生成
  4. Web上の情報を取得する(簡単なスクレイピング)
これらの事例は、いずれも単なる繰り返し作業の自動化に留まらず、より高度なデータ処理や他アプリケーションとの連携、さらには外部情報との連携をAIと共に行う強力な一歩となるでしょう。

1. 複数のExcelファイルにまたがるデータ集計

多くの業務で、複数のExcelファイルに分散しているデータを集めて、ひとつのファイルやシートにまとめる作業は頻繁に発生します。

たとえば、次のようなケースでAIとVBAの出番です。
  • 部署ごとの月次売上ファイルをまとめて、全社売上集計表を作成する。
  • 各担当者が入力した日報ファイルを自動で集計し、週次報告用のデータを作成する。
  • プロジェクトごとの進捗ファイルを横断的に参照し、全体進捗サマリーを自動生成する。
  • 従業員一人ひとりの経費精算書や交通費精算書から、必要なデータを抽出して経理部門の集計表にまとめる。
  • 顧客アンケートの回答が個別のファイルになっている場合、すべての回答を一つに統合して分析基盤を作る。

これらをすべて手作業で行うと、ファイルを開いてはコピーし、別のファイルに貼り付けるという単純作業の繰り返しになり、時間もかかりますし、ミスの原因にもなります。しかし、AIとVBAを使えば、この手間のかかる作業をあっという間に終わらせることができます。

ここでは、複数店舗の売上データを集計する具体的なシナリオで自動化に挑戦しましょう。

シナリオ:複数店舗の売上データを集計する
あなたは複数の店舗を管理する部署にいます。各店舗からは毎日、日報として売上データが記載されたExcelファイルが送られてきます。
これらのファイルを、週次または月次で集計し、全体の売上を把握する必要があります。
  • 目的ファイル(集計先): 集計_売上データ.xlsm (このファイルにマクロを記述します)
  • 対象ファイル(集計元): 〇〇店_売上データ_20240501.xlsx、△△店_売上データ_20240501.xlsx のように、特定のフォルダ内に複数の店舗別売上ファイルがあると仮定します。
  • 集計する内容: 各店舗ファイルの特定のシート(例:日別売上シート)にある、特定範囲のデータ(例:A列の「日付」、B列の「商品名」からE列の「売上金額」まで)を、目的ファイルの全店集計シートにコピー&ペーストでまとめたい。その際、どの店舗のデータか分かるように、ファイル名から店舗名を抽出して新しい列として追加します。さらに、集計シートに同一店舗の同一日付のデータがすでに存在する場合は、既存のデータを削除してから新しいデータを追加することで、重複を避けます。

【店舗別売上ファイルの「日別売上」シートの例】
AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

日付 商品名 数量 単価 売上金額
2024/5/1 りんご 3 150 450
2024/5/1 みかん 2 100 200
2024/5/1 バナナ 5 120 600

【集計_売上データ.xlsm の「全店集計」シートのイメージ】
マクロ実行後、「全店集計」シートには、各店舗ファイルの「日別売上」シートからコピーされたデータに加え、ファイル名から抽出された店舗名が、以下のように追記されていきます。既存の同一店舗・同一日付のデータがあれば、新しいデータに置き換わります。

AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

日付 店舗名 商品名 数量 単価 売上金額
2024/5/1 A店 りんご 3 150 450
2024/5/1 A店 みかん 2 100 200
2024/5/1 A店 バナナ 5 120 600
2024/5/1 B店 りんご 2 150 300
2024/5/1 B店 みかん 1 100 100
2024/5/1 B店 バナナ 3 120 360

AIへのプロンプトの考え方と例
AIに効率よくコードを生成してもらうためには、以下の情報を具体的に伝えることが重要です。
  1. 何がしたいのか?: 複数のExcelファイルからデータを集計したい。
  2. どのファイルを対象にするのか?: 特定のフォルダにあるファイル。ファイル名の規則があれば伝える(例:〇〇店_売上データ_日付.xlsx)。
  3. どのシートのどの範囲のデータを集めるのか?: 各ファイルの日別売上シートのA列からE列まで。
  4. どこにまとめるのか?: マクロがあるファイルの全店集計シート。
  5. データはどのように貼り付けるのか?:
    • 各対象ファイルからデータを読み込むたびに、集計シート内で重複チェックとデータ追加を行う。
    • 読み込んだデータ各行について、日付と店舗名(ファイル名から抽出)の組み合わせを特定する。ファイル名が「〇〇店_売上データ_YYYYMMDD.xlsx」のような形式なので、「店」の前の部分を店舗名とする。
    • 集計シート内で、上記で特定した「日付」と「店舗名」の組み合わせと完全に一致する既存のすべての行を削除する。
    • その後、読み込んだデータ全体(各行に抽出した店舗名を追加したもの)を、「全店集計」シートの現在の最終行の次の行にまとめて貼り付ける。
  6. その他: 処理の開始と終了がわかるメッセージボックスを表示する。生成されるVBAコードではFileSystemObjectを使用してファイル操作を行い、各処理の内容をコメントで簡潔に解説してください。

    FileSystemObjectに関しては、Dir関数より汎用的なので筆者がこだわって追記しました。

これを踏まえて、AIに以下のようにプロンプトを作成してみましょう。

プロンプト例:
Excel VBAコードを作成してください。

目的:このマクロがあるExcelファイルと同じフォルダ内にある「店舗データ」フォルダ内の複数のExcelファイルからデータを集計し、このマクロがあるファイルのシートにまとめる。

### 手順:

1.  このマクロが保存されているExcelファイルと同じフォルダ内にある「**店舗データ**」フォルダ(このフォルダにはすでに集計対象のExcelファイルが格納されているものとする)を対象とする。
2.  「店舗データ」フォルダ内にある、ファイル名に「**店_売上データ**」という文字列が含まれ、拡張子が**.xlsx**のExcelファイルすべてを対象とする。ファイル操作には**FileSystemObject**を使用すること。
3.  対象となる各ファイルについて、以下の処理を繰り返す。
    a. 対象ファイルを開き、「**日別売上**」という名前のシートを選択する。
    b. そのシートの**A列からE列まで**のデータ(ただし、**タイトル行は含まない**で、データが入力されている範囲のみ)を読み込む。
    c. 読み込んだデータについて、各行から「日付」(読み込んだデータのA列)と、現在のファイル名から抽出した「店舗名」の組み合わせを特定する。ファイル名が「〇〇店_売上データ_YYYYMMDD.xlsx」の場合、「**店**」の前の部分(例:「〇〇店」)を店舗名とする。
    d. 「**全店集計**」シート内で、上記で特定した「日付」と「店舗名」の組み合わせと**完全に一致する既存のすべての行を削除**する。
    e. 読み込んだデータ全体(各行に抽出した店舗名を追加したもの)を、「**全店集計**」シートの現在の**最終行の次の行**にまとめて貼り付ける。
    f. 対象ファイルの処理が終わったら、そのファイルを閉じる(**保存はしない**)。

処理の開始と終了がわかるように**メッセージボックス**を表示してください。
生成されるVBAコードには、各処理の内容を**コメント**で簡潔に解説してください。
以下はMarkDownのプロンプトのプレビューです。

AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

AIが生成したVBAコードの例と解説
上記のプロンプトをAIに与えると、以下のようなVBAコードが生成されることが想定されます。
(これはあくまで一例であり、AIの回答によってコードの構造や詳細が異なる場合があります。)

Sub 全店売上データ集計()
  ' 画面更新と警告メッセージを一時的に無効化し、処理を高速化する
  Application.ScreenUpdating = False
  Application.DisplayAlerts = False

  Dim fso As Object ' FileSystemObjectのオブジェクト
  Dim targetFolderObj As Object ' 対象フォルダのオブジェクト
  Dim file As Object ' 処理中のファイルのオブジェクト

  Dim wbSource As Workbook
  Dim wsSource As Worksheet
  Dim wsTarget As Worksheet
  Dim lastRowTarget As Long
  Dim i As Long
  Dim storeName As String
  Dim dateToMatch As Date
  Dim targetRow As Long
  Dim tempArray() As Variant ' 読み込んだデータを一時的に格納する配列
  Dim rowCount As Long
  Dim currentFilePath As String ' 現在処理中のファイルのフルパス

  ' FileSystemObjectを生成(CreateObjectを使用するため、参照設定は不要)
  Set fso = CreateObject("Scripting.FileSystemObject")

  ' このマクロが保存されているExcelファイルと同じフォルダ内の「店舗データ」フォルダを指定
  Dim parentFolderPath As String
  parentFolderPath = ThisWorkbook.Path
  Dim dataFolderPath As String
  dataFolderPath = parentFolderPath & "\店舗データ\"

  ' 対象フォルダが存在するか確認し、オブジェクトとして設定
  If Not fso.FolderExists(dataFolderPath) Then
    MsgBox "「店舗データ」フォルダが見つかりません。パスを確認してください: " & dataFolderPath, vbCritical
    GoTo ExitSub
  End If
  Set targetFolderObj = fso.GetFolder(dataFolderPath)

  ' 「全店集計」シートを設定
  Set wsTarget = ThisWorkbook.Sheets("全店集計")

  ' 処理開始メッセージをユーザーに通知
  MsgBox "店舗売上データの集計を開始します。", vbInformation

  ' 指定フォルダ内のExcelファイルを順に処理
  For Each file In targetFolderObj.Files
    ' ファイル名に「店_売上データ」が含まれ、拡張子が.xlsxのファイルを対象とする
    If InStr(file.Name, "店_売上データ") > 0 And LCase(fso.GetExtensionName(file.Name)) = "xlsx" Then
      currentFilePath = file.Path ' 現在処理中のファイルのフルパスを取得

      ' 対象ファイルを開く
      Set wbSource = Workbooks.Open(currentFilePath)
      Set wsSource = wbSource.Sheets("日別売上")

      ' 店舗名をファイル名から抽出 (例: "A店_売上データ_20240501.xlsx" から "A店" を抽出)
      Dim baseFileName As String
      baseFileName = fso.GetBaseName(file.Name) ' 拡張子を除いたファイル名
      Dim nameParts() As String
      nameParts = Split(baseFileName, "_")
      storeName = nameParts(LBound(nameParts)) ' 例: "A店" が取得されることを想定

      ' ソースシートのA列からE列までのデータ範囲を取得(タイトル行を除く)
      ' データが1行もない場合はスキップ
      If wsSource.Cells(Rows.Count, "A").End(xlUp).Row < 2 Then
        ' データがないため、次のファイルへ
        wbSource.Close SaveChanges:=False
        GoTo NextFileInLoop
      End If

      ' データ範囲を配列に読み込む (A2セルから最終行のE列まで)
      rowCount = wsSource.Cells(Rows.Count, "A").End(xlUp).Row - 1 ' データ行数 (タイトル行を除く)
      tempArray = wsSource.Range("A2:E" & wsSource.Cells(Rows.Count, "A").End(xlUp).Row).Value

      ' 新しいデータを格納する一時的な二次元配列を準備
      ' (日付 + 店舗名 + 元の5列 = 6列)
      Dim processedData() As Variant
      ReDim processedData(1 To rowCount, 1 To 6)

      ' 読み込んだデータと店舗名を結合し、processedData配列に格納
      ' そして、集計シート内の重複行を削除
      For i = 1 To rowCount
        dateToMatch = tempArray(i, 1) ' 日付を取得
        
        ' 「全店集計」シート内の既存データをチェックし、重複する行があれば削除
        ' 同一日付・同一店舗のデータはすべて削除する
        Dim currentTargetLastRow As Long
        currentTargetLastRow = wsTarget.Cells(Rows.Count, "A").End(xlUp).Row

        ' 既存データ(2行目から最終行まで)をループして重複をチェック
        ' 下から上へループすることで、行削除による影響を避ける
        For targetRow = currentTargetLastRow To 2 Step -1
          ' 日付 (A列) と店舗名 (B列) が一致するかを確認
          If wsTarget.Cells(targetRow, "A").Value = dateToMatch And _
            wsTarget.Cells(targetRow, "B").Value = storeName Then
            wsTarget.Rows(targetRow).Delete Shift:=xlUp ' 重複行を削除
          End If
        Next targetRow
        
        ' 処理済みのデータとして一時配列に格納
        processedData(i, 1) = tempArray(i, 1) ' 日付
        processedData(i, 2) = storeName    ' 店舗名
        processedData(i, 3) = tempArray(i, 2) ' 商品名
        processedData(i, 4) = tempArray(i, 3) ' 数量
        processedData(i, 5) = tempArray(i, 4) ' 単価
        processedData(i, 6) = tempArray(i, 5) ' 売上金額
      Next i
      
      ' 全店集計シートの最終行の次の行に、新しいデータをまとめて貼り付け
      lastRowTarget = wsTarget.Cells(Rows.Count, "A").End(xlUp).Row
      wsTarget.Range("A" & lastRowTarget + 1).Resize(UBound(processedData, 1), UBound(processedData, 2)).Value = processedData

      ' ソースファイルを閉じる(保存しない)
      wbSource.Close SaveChanges:=False
    End If
NextFileInLoop:
  Next file

  ' 処理終了メッセージをユーザーに通知
  MsgBox "店舗売上データの集計が完了しました。", vbInformation

ExitSub:
  ' 画面更新と警告メッセージを有効に戻す
  Application.ScreenUpdating = True
  Application.DisplayAlerts = True
  
  ' オブジェクトの解放
  Set fso = Nothing
  Set targetFolderObj = Nothing
  Set file = Nothing
  Set wbSource = Nothing
  Set wsSource = Nothing
  Set wsTarget = Nothing

End Sub

コードの解説
  1. 変数宣言: 必要な変数を定義します。
    fso: FileSystemObject のオブジェクトを格納します。
    targetFolderObj: 対象フォルダのオブジェクトを格納します。
    file: 処理中のファイルのオブジェクトを格納します。
    wbSource, wsSource: 開いているソースファイルとシートのオブジェクトを格納します。
    wsTarget: 集計先となる「全店集計」シートのオブジェクトを格納します。
    lastRowTarget: 「全店集計」シートの最終行番号を格納します。
    i, targetRow: ループ処理で使用するカウンター変数です。
    storeName: ファイル名から抽出した店舗名を格納します。
    dateToMatch: 読み込んだデータの日付を格納します。
    tempArray: ソースシートから読み込んだ元のデータを一時的に格納する配列です。
    rowCount: tempArrayの行数(データ件数)を格納します。
    processedData: 店舗名を追加し、集計シートに貼り付ける形に整形されたデータを一時的に格納する配列です。
    currentFilePath: 現在処理中のファイルのフルパスを格納します。
  2. 処理開始メッセージ: マクロの開始をユーザーに知らせるメッセージボックスを表示します。
  3. FileSystemObjectの作成とパスの取得:
    Set fso = CreateObject("Scripting.FileSystemObject"): ファイルやフォルダを操作するためのFileSystemObjectを作成します。
    CreateObjectを使用する遅延バインディングの場合、VBAエディターでの参照設定は不要です。これにより、マクロの配布が容易になります。
    このマクロが保存されているExcelファイル (ThisWorkbook) のパスを取得し、それを使って対象の「店舗データ」フォルダのフルパスを構築します。
    fso.FolderExistsで対象フォルダの存在を確認し、存在しない場合はエラーメッセージを表示して処理を中断します。
    fso.GetFolderで対象フォルダのオブジェクトを設定します。
  4. 「全店集計」シートの設定:
    このマクロが動作しているブック内の「全店集計」という名前のシートを特定し、wsTargetとして設定します。
    このコードでは、シートの存在確認やヘッダー行の追加は行っていません。必要に応じて、事前にシートを作成し、ヘッダー行を設定しておく必要があります。
  5. ファイルループとデータ処理:
    • For Each file In targetFolderObj.Files で、targetFolderObj(「店舗データ」フォルダ)内の全てのファイルを一つずつループ処理します。
    • If InStr(file.Name, "店_売上データ") > 0 And LCase(fso.GetExtensionName(file.Name)) = "xlsx" Then で、ファイル名に「店_売上データ」が含まれ、かつ拡張子が「.xlsx」であるファイルのみを対象とします。
      • ファイルを開く: 条件に合致したExcelファイルを開き、その中の「日別売上」シートをwsSourceとして設定します。file.Pathでファイルのフルパスを取得します。
      • 店舗名の抽出: fso.GetBaseName(file.Name)で拡張子を除いたファイル名を取得し、それを_で分割して店舗名(例: A店)を抽出します。
        データ読み込み: 「日別売上」シートのA2セルからE列の最終行までのデータをtempArray配列に読み込みます。
      • 重複チェックと行削除:
        • 読み込んだtempArrayの各行について、その日付と抽出した店舗名を使って、「全店集計」シート内を検索します。
        • For targetRow = currentTargetLastRow To 2 Step -1 のループで、集計シートの最終行から上に向かって検索し、日付と店舗名が一致する行が見つかれば、その行を丸ごと削除します。これにより、該当する日付と店舗名のすべての行が削除されます。下から削除することで、行が削除されてもループの範囲に影響が出ないようにしています。
      • データの整形と準備: 読み込んだtempArrayのデータに抽出した店舗名を加えて、processedData配列に格納します。
      • データの一括貼り付け: 重複削除の処理が終わった後、processedData配列に格納された全てのデータを、「全店集計」シートの現在の最終行の次の行に、一括で書き込みます。
      • ファイルのクローズ: 処理が完了したソースファイルを保存せずに閉じ、次のファイルの処理に移ります。
  6. 処理終了メッセージ: 全てのファイルの処理が完了した後、完了をユーザーに知らせるメッセージボックスを表示します。
  7. 設定のリセットとオブジェクトの解放: 最後に、画面更新と警告メッセージの表示設定を元に戻し、使用したオブジェクトを解放してメモリをクリーンアップします。

事前準備
  • 作業フォルダの準備: マクロを記述するExcelファイル(例:集計_売上データ.xlsm)と同じ場所に、店舗データという名前のフォルダをあらかじめ作成します。
    その中に、集計対象となるいくつかの店舗別売上データファイル(例:A店_売上データ_20240501.xlsx、B店_売上データ_20240501.xlsx)を作成して入れておきましょう。各ファイルには日別売上シートを作り、A列からE列にダミーデータを入れておくとテストがしやすいです。
  • 集計用シートの準備: マクロを記述するExcelファイル(例:集計_売上データ.xlsm)内に、集計結果を書き込むための「全店集計」という名前のシートを作成しておきます。

使用方法
  1. 集計したいExcelファイル(このマクロを保存するファイル)を開きます。
  2. Alt + F11 を押してVBAエディタを開きます。
  3. VBAエディタの左側のプロジェクトエクスプローラーで、VBAProject(集計_売上データ.xlsm) を展開し、「標準モジュール」を右クリックします。
  4. 「挿入」→「標準モジュール」を選択します。
  5. 開いたモジュールに上記のVBAコードをコピー&ペーストします。
  6. VBAエディタを閉じます。
  7. Excelシートに戻り、Alt + F8 を押してマクロダイアログを開きます。
  8. 「全店売上データ集計」を選択し、「実行」をクリックします。


2. ユーザーフォームの作成と操作

Excelを使ったデータ入力や管理では、手入力によるミスや、入力規則を設けても破られてしまうといった課題がつきものです。より厳密なデータ管理や、直感的な操作を求められる場面では、ユーザーフォーム(UserForm)が非常に強力なツールとなります。

しかし、このユーザーフォームの作成は、VBA初心者にとってハードルが高い作業の一つです。部品の配置、プロパティの設定、そして各部品が連携するためのコード記述…これらをゼロから手作業で行うのは、多くの時間と労力を要します。

ここで、AIの真価が発揮されます。AIに「どんな入力フォームが欲しいか」「何を入力させたいか」「入力されたデータをどう処理したいか」を具体的に伝えるだけで、複雑なユーザーフォームの機能(入力チェック、シートへの転記など)に関するVBAコードまでを、AIが“書かない自動化”として生成してくれるのです。

「AIにこんなことも頼めるのか!」

と、あなたはきっと驚くことでしょう。ここでは、Excel業務でよくある「データ入力」のシナリオを想定し、AIと共にユーザーフォームの作成と操作に挑戦します。

シナリオ:日報入力フォームの作成
あなたはチームリーダーで、メンバーからの日報提出をExcelで行っています。しかし、メンバーごとに記入形式がバラバラだったり、必要な情報が漏れていたりして、集計作業に手間取っています。そこで、統一された入力形式を強制できるユーザーフォームを作成し、入力漏れや誤りを防ぎたいと考えています。
  • 目的ファイル(マクロ記述先): 日報管理.xlsm
  • 入力データ:
    • 日付(カレンダー形式で選択)
    • 氏名(ドロップダウンリストから選択)
    • 業務内容(複数行入力可能)
    • 作業時間(時間単位で数値入力、小数も可
    • 特記事項(任意入力)
  • フォームの機能:
    • 入力必須項目(日付、氏名、業務内容、作業時間)のチェック。未入力の場合は警告メッセージを表示。
    • 入力値の妥当性チェック(例:作業時間が負の値でないか、数値として正しいか)。
    • 「登録」ボタンで、入力されたデータをシートの最終行に追加。
    • 「クリア」ボタンで、入力フォームの各項目を初期化。
    • 「閉じる」ボタンでフォームを閉じる。
  • 転記先シート: 「日報データ」というシートのA列からF列までを想定。
    • A列: 連番
    • B列: 日付
    • C列: 氏名
    • D列: 業務内容
    • E列: 作業時間
    • F列: 特記事項

AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

AIへのプロンプトの考え方と例
AIに効率よくユーザーフォームのコードを生成してもらうには、以下の情報を具体的に伝えることが重要です。
  • 何がしたいのか?: ユーザーフォームを作成し、データ入力とシートへの転記を行いたい。
  • フォームのレイアウト: どのようなコントロール(テキストボックス、コンボボックス、コマンドボタンなど)を配置し、それぞれに何を表示させたいか。
  • 入力項目とその型: 日付、氏名、業務内容など、それぞれの項目がどのような形式(日付、文字列、数値など)で、どのような制約があるか。
  • 入力データの処理: 必須チェック、妥当性チェック、シートへの転記方法(どのシートのどの列に、どのように追加するか)。
  • ボタンの機能: 登録、クリア、閉じるボタンにそれぞれどのような機能を割り当てるか。
  • その他: エラーメッセージの表示方法、フォームを開くトリガー(例:ボタンクリック)。

これを踏まえて、AIに以下のようにプロンプトを作成してみましょう。

プロンプト例:
Excel VBAで、以下の仕様を持つユーザーフォームと、それに関連するVBAコードを作成してください。

### ユーザーフォームの仕様:

* **フォーム名**: `frmNippoInput`
* フォームに必要な以下のコントロールと、それに付随するラベルを作成してください:
    * `txtDate`: **日付入力用**のテキストボックス
    * `cmbMemberName`: **氏名選択用**のコンボボックス
    * `txtTaskDescription`: **業務内容入力用**の**複数行対応**テキストボックス
    * `txtWorkTime`: **作業時間入力用**のテキストボックス(時間単位で小数も可)
    * `txtRemarks`: **特記事項入力用**のテキストボックス
    * `cmdRegister`: ボタン「**登録**」
    * `cmdClear`: ボタン「**クリア**」
    * `cmdClose`: ボタン「**閉じる**」

### VBAコードの仕様:

1.  **フォーム表示用マクロ**:
    * `ShowNippoForm` という名前の**標準モジュール**に`Public Sub`を作成し、フォームを表示するようにしてください。

2.  **フォーム初期化時 (`UserForm_Initialize`)**:
    * `cmbMemberName` に初期値として「田中」「佐藤」「鈴木」を設定する。
    * 各テキストボックスとコンボボックスをクリアし、初期状態にする。

3.  **「登録」ボタンクリック時 (`cmdRegister_Click`)**:
    * **入力チェック**:
        * `txtDate`、`cmbMemberName`、`txtTaskDescription`、`txtWorkTime` が**未入力**の場合は、「日付、氏名、業務内容、作業時間は必須入力です。」という**メッセージボックス**を表示し、処理を中断する。
        * `txtDate` が**有効な日付形式でない**場合、「日付の入力形式が正しくありません。」と表示し、処理を中断する。
        * `txtWorkTime` が**数値として有効でない**場合、または**負の値**の場合、「作業時間は0以上の数値を入力してください。」と表示し、処理を中断する。
    * **シートへの転記**:
        * 「**日報データ**」という名前のシートにデータを転記する。もしシートが存在しない場合は**作成**し、ヘッダー行(連番, 日付, 氏名, 業務内容, 作業時間, 特記事項)を追加する。
        * シートの**最終行**に以下のデータを追加する:
            * A列: 連番(既存データの最終行の連番+1、初回は1)
            * B列: `txtDate` の値
            * C列: `cmbMemberName` の値
            * D列: `txtTaskDescription` の値
            * E列: `txtWorkTime` の値
            * F列: `txtRemarks` の値
        * データ転記後、「日報を登録しました。」という**メッセージボックス**を表示する。
        * 登録後、フォームの各項目を**クリア**する。

4.  **「クリア」ボタンクリック時 (`cmdClear_Click`)**:
    * すべての入力コントロール(テキストボックス、コンボボックス)の内容をクリアする。

5.  **「閉じる」ボタンクリック時 (`cmdClose_Click`)**:
    * フォームを閉じる。

生成されるVBAコードには、各処理の内容を**コメント**で簡潔に解説してください。
AIが生成したVBAコードの例と解説
上記のプロンプトをAIに与えると、以下のようなVBAコードが生成されることが想定されます。(これはあくまで一例であり、AIの回答によってコードの構造や詳細が異なる場合があります。)

VBAコードと配置場所
AIが生成するVBAコードは、機能によって記述する場所が異なります。以下の指示に従って、それぞれのコードを適切なモジュールにコピー&ペーストしてください。

1.標準モジュール (Module1など) に記述するコード
このコードは、Excelシート上に配置したボタンなどからユーザーフォームを呼び出すために使用します。

' --- 標準モジュール(例: Module1)に記述 ---

Sub ShowNippoForm()
  ' 日報入力フォームを表示する
  ' AIが生成したユーザーフォーム (frmNippoInput) を呼び出します。
  Load frmNippoInput ' フォームをメモリにロード
  frmNippoInput.Show ' フォームを表示 (モーダル表示: フォームを閉じるまで他の操作ができない)
End Sub

コードの解説:
  • Sub ShowNippoForm(): このプロシージャは、作成したユーザーフォーム frmNippoInput を表示するための入り口となります。
  • Load frmNippoInput: これはユーザーフォームをメモリに読み込むための命令です。
  • frmNippoInput.Show: ロードしたフォームを表示します。Show メソッドは通常、ユーザーがフォームを閉じるまで他のExcel操作をブロックする「モーダル」表示になります。

2.ユーザーフォームモジュール (frmNippoInput のコードウィンドウ) に記述するコード
これらのコードは、ユーザーフォームの内部的な動作(初期化、ボタンクリック時の処理など)を定義します。
VBEでfrmNippoInputをダブルクリックすると開くウィンドウに貼り付けてください。

' --- ユーザーフォームモジュール(frmNippoInput)に記述 ---

Private Sub UserForm_Initialize()
  ' フォームが初期化されるときに実行される(フォームが開かれる際に一度だけ実行)

  ' 氏名コンボボックスに初期値を設定
  With Me.cmbMemberName
    .AddItem "田中"
    .AddItem "佐藤"
    .AddItem "鈴木"
    .ListIndex = -1 ' 初期選択なし (何も選択されていない状態にする)
  End With

  ' 各コントロールをクリア(初期化)
  Call ClearFormControls
End Sub

Private Sub cmdRegister_Click()
  ' 登録ボタンがクリックされたときに実行される
  Dim ws As Worksheet      ' 転記先シートを格納する変数
  Dim lastRow As Long      ' 転記先シートの最終行を格納する変数
  Dim nextRenban As Long    ' 連番を格納する変数
  Dim workTimeValue As Double  ' 作業時間を数値として格納する変数

  ' --- 入力チェック ---
  ' 必須項目(日付、氏名、業務内容、作業時間)が入力されているかチェック
  If Trim(Me.txtDate.Value) = "" Or _
    Me.cmbMemberName.ListIndex = -1 Or _
    Trim(Me.txtTaskDescription.Value) = "" Or _
    Trim(Me.txtWorkTime.Value) = "" Then
    MsgBox "日付、氏名、業務内容、作業時間は必須入力です。", vbExclamation
    Exit Sub ' 処理を中断する
  End If

  ' 日付形式の有効性をチェック
  If Not IsDate(Me.txtDate.Value) Then
    MsgBox "日付の入力形式が正しくありません。例: 2024/05/01", vbExclamation
    Exit Sub
  End If

  ' 作業時間が数値として有効かチェック
  If Not IsNumeric(Me.txtWorkTime.Value) Then
    MsgBox "作業時間は数値を入力してください。", vbExclamation
    Exit Sub
  End If

  ' 数値に変換し、負の値でないかチェック
  workTimeValue = CDbl(Me.txtWorkTime.Value)
  If workTimeValue < 0 Then
    MsgBox "作業時間は0以上の数値を入力してください。", vbExclamation
    Exit Sub
  End If
  
  ' --- シート準備とデータ転記 ---
  ' 「日報データ」シートが存在するか確認し、存在しない場合は作成する
  On Error Resume Next ' エラーが発生しても処理を継続する
  Set ws = ThisWorkbook.Sheets("日報データ")
  On Error GoTo 0   ' エラーハンドリングを元に戻す

  If ws Is Nothing Then
    ' シートが存在しない場合、新しくシートを作成し名前を設定
    Set ws = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
    ws.Name = "日報データ"

    ' ヘッダー行を追加
    With ws
      .Cells(1, 1).Value = "連番"
      .Cells(1, 2).Value = "日付"
      .Cells(1, 3).Value = "氏名"
      .Cells(1, 4).Value = "業務内容"
      .Cells(1, 5).Value = "作業時間"
      .Cells(1, 6).Value = "特記事項"
      .Rows(1).Font.Bold = True ' ヘッダーを太字に設定
    End With
  End If

  ' データを転記する最終行を取得(A列の最終データ行)
  lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

  ' 連番の決定
  ' ヘッダー行のみの場合や、データが全くない場合は1から開始
  If lastRow = 1 And ws.Cells(1, 1).Value <> "連番" Then
    nextRenban = 1
  ElseIf lastRow = 1 And ws.Cells(1, 1).Value = "連番" Then
    nextRenban = 1
  Else ' 既存データがある場合は、最終行の連番に1を加算
    nextRenban = ws.Cells(lastRow, "A").Value + 1
  End If

  ' フォームからのデータをシートに転記
  With ws
    .Cells(lastRow + 1, 1).Value = nextRenban          ' 連番
    .Cells(lastRow + 1, 2).Value = CDate(Me.txtDate.Value)   ' 日付 (日付型に変換)
    .Cells(lastRow + 1, 3).Value = Me.cmbMemberName.Value    ' 氏名
    .Cells(lastRow + 1, 4).Value = Me.txtTaskDescription.Value ' 業務内容
    .Cells(lastRow + 1, 5).Value = workTimeValue        ' 作業時間 (数値型)
    .Cells(lastRow + 1, 6).Value = Me.txtRemarks.Value     ' 特記事項
  End With

  MsgBox "日報を登録しました。", vbInformation ' 登録完了メッセージ

  ' 登録後、フォームの各項目をクリアする
  Call ClearFormControls
End Sub

Private Sub cmdClear_Click()
  ' クリアボタンがクリックされたときに実行される
  Call ClearFormControls ' フォーム内のコントロールをクリアするサブルーチンを呼び出す
End Sub

Private Sub cmdClose_Click()
  ' 閉じるボタンがクリックされたときに実行される
  Unload Me ' フォームをメモリから解放し、閉じる
End Sub

' フォーム内のコントロールをクリアするサブルーチン
Private Sub ClearFormControls()
  Me.txtDate.Value = ""       ' 日付テキストボックスをクリア
  Me.cmbMemberName.ListIndex = -1  ' コンボボックスの選択を解除
  Me.txtTaskDescription.Value = "" ' 業務内容テキストボックスをクリア
  Me.txtWorkTime.Value = ""     ' 作業時間テキストボックスをクリア
  Me.txtRemarks.Value = ""     ' 特記事項テキストボックスをクリア
  Me.txtDate.SetFocus        ' 日付テキストボックスにカーソルを置く
End Sub

コードの解説:
  • UserForm_Initialize:フォームが表示される直前に実行され、コンボボックスの項目設定とフォームの初期化を行います。
  • cmdRegister_Click:
    • 1入力チェック:各入力フィールドが空でないか、日付や数値として正しい形式かを厳密にチェックします。
      ・特に「作業時間」については、IsNumeric関数で数値であることを確認後、CDblでDouble型に変換し、その値が負でないかをチェックすることで、型エラーを防ぎ、妥当な数値のみを受け付けるようにしました。
    • シート準備:日報データシートが存在しない場合、自動的に作成し、見出し行を設定します。
    • データ転記:シートの最終行を特定し、その次の行にフォームからの入力データを転記します。連番も自動で付与されます。
      転記後、完了メッセージを表示し、フォームの内容をクリアします。
  • cmdClear_Click:フォーム内のすべての入力フィールドをクリアし、初期状態に戻します。
  • cmdClose_Click:ユーザーフォームを閉じます。
  • ClearFormControls:入力フィールドをクリアする共通の処理として定義されており、UserForm_InitializeとcmdRegister_Clickから呼び出されます。これにより、コードの重複を避け、保守性を高めています。

ユーザーフォームの作成とコードの配置手順
AIがVBAコードを生成した後、それをExcelで動かすには、以下の手順でユーザーフォームの作成とコードの配置を行う必要があります。
  1. Excelファイルの準備:
    新しいExcelブックを作成し、名前を「日報管理.xlsm」として保存します。このブックには、「日報データ」という名前のシートを作成しておくことを推奨します。もしシートが存在しない場合でも、マクロが自動で作成するようにコードは記述されていますが、事前に準備しておくとスムーズです。
  2. VBAエディタを開く:
    「日報管理.xlsm」を開き、Alt + F11 キーを押してVBAエディタ(VBE)を開きます。
  3. ユーザーフォームの挿入と名前変更:
    • VBEの左側にあるプロジェクトエクスプローラーで、VBAProject(日報管理.xlsm) を右クリックします。
    • 「挿入」→「ユーザーフォーム」を選択します。新しいユーザーフォーム(通常はUserForm1という名前)が作成されます。
    • 作成されたフォームを選択した状態で、VBEの左下にあるプロパティウィンドウを探します。
    • プロパティウィンドウの(名前)という項目を、frmNippoInput に変更します。この名前はAIが生成するコードと連動しています。
  4. コントロールの配置とプロパティ設定:
    • VBEでfrmNippoInputをダブルクリックし、フォームのデザイン画面を表示します。
    • ツールボックス(通常はVBEの左側に表示)から必要なコントロール(ラベル、テキストボックス、コンボボックス、コマンドボタン)をドラッグ&ドロップでフォーム上に配置してください。
    • 配置した各コントロールを選択し、プロパティウィンドウで以下の設定を行います。
      • ラベル:
        Captionプロパティをそれぞれ「日付:」「氏名:」「業務内容:」「作業時間 (時間):」「特記事項:」に設定します。(「作業時間」には単位を追加しました)
      • テキストボックス:
        日付入力用: (名前)をtxtDateに設定
        業務内容入力用: (名前)をtxtTaskDescriptionに設定し、MultiLineプロパティをTrueに設定
        作業時間入力用: (名前)をtxtWorkTimeに設定
        特記事項入力用: (名前)をtxtRemarksに設定
      • コンボボックス:
        氏名選択用: (名前)をcmbMemberNameに設定
      • コマンドボタン:
        「登録」ボタン: (名前)をcmdRegisterに設定し、Captionプロパティを「登録」に設定
        「クリア」ボタン: (名前)をcmdClearに設定し、Captionプロパティを「クリア」に設定
        「閉じる」ボタン: (名前)をcmdCloseに設定し、Captionプロパティを「閉じる」に設定
  5. 標準モジュールの挿入:
    • VBEの左側にあるプロジェクトエクスプローラーで、VBAProject(日報管理.xlsm) を右クリックします。
    • 「挿入」→「標準モジュール」を選択します。新しいモジュール(通常はModule1という名前)が作成されます。
  6. コードのコピー&ペースト:
    AIが生成したVBAコードを、それぞれのモジュールに正確にコピー&ペーストします。
    • 上記の「1.標準モジュール (Module1など) に記述するコード」の内容を、作成した標準モジュール(例: Module1)のコードウィンドウに貼り付けます。
    • 上記の「2.ユーザーフォームモジュール (frmNippoInput のコードウィンドウ) に記述するコード」の内容を、作成したユーザーフォーム(frmNippoInput)をダブルクリックして開いたコードウィンドウに貼り付けます。
  7. フォームの実行:
    • Excelシートに戻り、適当な場所に図形やボタンを挿入します。
    • 挿入した図形やボタンを右クリックし、「マクロの登録」を選択します。
    • 表示されたダイアログで「ShowNippoForm」を選択し、「OK」をクリックします。
    • これで、図形やボタンをクリックすると、作成したユーザーフォームが表示されるはずです。フォームの各機能(入力、登録、クリア、閉じる)を試してみてください。

AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

ユーザーフォームの操作詳細については以下を参考にしてください。
Excelユーザーフォーム入門
エクセル(Excel)マクロ(VBA)をやっていればユーザーフォームの存在を知り、そしてユーザーフォームを使いたくなります。使いたくなるというより、使った方が良い場合が出てきます。しかし、ユーザーフォームは少々とっつきにくく、使い始めて使いこなすには、各種コントロールの特性を理解し、イベントについても深い知識が必要…
第1回.ユーザーフォームを挿入
・ユーザーフォームの挿入手順 ・ユーザーフォームの表示方法 ・プロパティの変更 ・ユーザーフォームを表示して確認
第2回.フォームのプロパティ
・フォームの全プロパティ ・フォームの主要なプロパティ ・ShowModalについて
第3回.コントロールの追加(コマンドボタン)
・ツールボックス ・コマンドボタンを配置 ・プロパティの変更 ・フォームを表示して動作確認
第4回.コントロールの位置・サイズ調整
・OKボタンの追加と移動 ・グリッドに合わせて移動&サイズ調整 ・プロパティで移動&サイズ調整
第5回.ラベルの追加
・ラベルの追加 ・ラベルのプロパティ設定 ・縦書き


3. Excelデータを使ったWord文書の自動生成

この事例では、Excelに並んだ顧客データなどを使って、案内状や証明書といったWord文書を自動で大量に作成する方法を学びます。定型文書作成の手間を大幅に削減できます。

シナリオ

Excelシートの顧客リスト情報(氏名、日付など)を使い、Wordのテンプレートファイルに用意されたプレースホルダー(##氏名####日付##)を自動で置き換え、個別のWord文書として保存します。

AIへのプロンプトの考え方と例:テンプレートと置き換えを明確に

Word文書の自動生成を依頼する際は、AIが以下の情報を明確に理解できるようプロンプトを構成します。

データ元: どのExcelファイル、どのシートから、どの列の情報を取得するか。
Wordテンプレート: 使用するWordテンプレートファイルのパスとファイル名、そしてテンプレート内に設定されたプレースホルダーの文字列(##氏名####日付##)。
出力先: 生成したWord文書をどこに、どのようなファイル名で保存するか。

プロンプト例

Excel VBAコードを作成してください。

目的:Excelデータを使ってWordテンプレートのプレースホルダーを置き換え、Word文書を自動生成する。

### 前提:

* マクロのあるExcelファイルと同じフォルダに以下が存在。
    * データ元Excelファイル: `顧客リスト.xlsx`
        * シート名: `名簿`、A列に氏名、B列に日付
    * Wordテンプレートファイル: `案内状テンプレート.docx`
        * テンプレート内のプレースホルダー: `##氏名##` と `##日付##`

### 手順:

1.  `顧客リスト.xlsx`の「名簿」シートから、氏名(A列)と日付(B列)を1行ずつ読み込む(1行目はタイトル行)。
2.  各行のデータで`案内状テンプレート.docx`を開き、`##氏名##`を読み込んだ氏名に、`##日付##`を読み込んだ日付に置き換える。
3.  置き換え後、Excelと同じフォルダ内の「**生成済み文書**」フォルダに「`氏名_案内状.docx`」として保存する(フォルダは存在しない場合作成)。
4.  Word文書の処理後、Wordを閉じる(保存不要)。

処理の開始と終了がわかるよう**メッセージボックス**を表示してください。
**参照設定が不要なコード**で作成してください。
生成されるVBAコードには、各処理の内容を**簡潔にコメント**してください。

AIが生成したVBAコードの例と解説

(※以下はAIが生成する可能性のあるコードの例です。AIの回答はプロンプトやモデルのバージョンにより変動します。)

' 標準モジュールに貼り付けて実行
Sub CreateWordDocsFromExcelNoRef()
  Dim wsData As Worksheet
  Dim objWord As Object, objDoc As Object
  Dim lastRow As Long, i As Long
  Dim customerName As String, docDate As String
  Dim saveFolderPath As String

  ' Word定数 (参照設定なしで使用するため)
  Const wdReplaceAll As Long = 2 ' 置換オプション: すべて置換

  ' 処理開始メッセージ
  MsgBox "Word文書の生成を開始します。", vbInformation

  ' 出力フォルダパスを設定し、なければ作成
  saveFolderPath = ThisWorkbook.Path & "\生成済み文書\"
  If Dir(saveFolderPath, vbDirectory) = "" Then MkDir saveFolderPath

  ' データシート設定
  Set wsData = ThisWorkbook.Worksheets("名簿") ' 顧客リスト.xlsxのシートを想定

  ' 最終行取得(A列基準)
  lastRow = wsData.Cells(Rows.Count, "A").End(xlUp).Row

  ' Wordアプリケーションを起動 (Late Binding)
  On Error GoTo ErrorHandler ' エラーハンドリング設定
  Set objWord = CreateObject("Word.Application")
  On Error GoTo 0 ' エラーハンドリング解除
  objWord.Visible = False ' Wordを非表示で実行

  ' 2行目から最終行までループ(1行目はタイトル行のため)
  For i = 2 To lastRow
    customerName = wsData.Cells(i, "A").Value ' 氏名取得
    docDate = Format(wsData.Cells(i, "B").Value, "yyyy年m月d日") ' 日付取得、形式指定

    ' Wordテンプレートを開く
    Set objDoc = objWord.Documents.Open(ThisWorkbook.Path & "\案内状テンプレート.docx")

    ' プレースホルダーを置き換え
    With objDoc.Content.Find
      .Text = "##氏名##": .Replacement.Text = customerName: .Execute Replace:=wdReplaceAll
      .Text = "##日付##": .Replacement.Text = docDate: .Execute Replace:=wdReplaceAll
    End With

    ' 文書を保存
    objDoc.SaveAs2 saveFolderPath & customerName & "_案内状.docx"

    ' 文書を閉じる
    objDoc.Close SaveChanges:=False
  Next i

  ' Wordアプリケーションを終了
  objWord.Quit
  Set objDoc = Nothing
  Set objWord = Nothing

  ' 処理終了メッセージ
  MsgBox "Word文書の生成が完了しました。", vbInformation

  Exit Sub

ErrorHandler:
  MsgBox "Wordアプリケーションの起動に失敗しました。" & vbCrLf & _
      "Wordがインストールされているか確認してください。", vbCritical
  If Not objWord Is Nothing Then objWord.Quit
  Set objDoc = Nothing
  Set objWord = Nothing
End Sub

コードの解説
  • CreateObject("Word.Application") を使うことで、参照設定なしでWordアプリケーションを操作できるようになります(Late Binding)。
  • wdReplaceAllのようなWord固有の定数は、Const wdReplaceAll As Long = 2 のように数値で直接定義することで、参照設定なしで利用可能になります。
  • Excelシートから氏名と日付を読み込み、指定されたWordテンプレートを開きます。
  • objDoc.Content.Find メソッドを使用して、テンプレート内の##氏名##や##日付##といったプレースホルダーをExcelから取得したデータで置き換えます。
  • objDoc.SaveAs2 で、指定したフォルダに新しいファイル名でWord文書を保存します。
  • 処理後、開いたWord文書とWordアプリケーションを閉じ、使用したオブジェクトを解放します。
  • Wordがインストールされていない場合などのエラーに対応するため、簡易的なエラーハンドリングを追加しています。

事前準備

  1. Excelデータファイル: マクロを保存するExcelファイルと同じフォルダ内に、「顧客リスト.xlsx」という名前のExcelファイルを作成し、中に「名簿」シートを準備します。A列に氏名、B列に日付を入力してください(1行目はタイトル行)。
    • 例:
      A列 B列
      氏名 日付
      山田太郎 2024/04/01
      鈴木花子 2024/04/05
  2. Wordテンプレートファイル: マクロを保存するExcelファイルと同じフォルダ内に、「案内状テンプレート.docx」という名前のWordファイルを作成します。このWordファイルの中に、置き換えたい箇所に##氏名####日付##といったプレースホルダーを入力しておきます。

使用方法

  1. 上記のVBAコードを、マクロを記述するExcelファイルの標準モジュールに貼り付けます。
  2. 「事前準備」で説明したExcelデータファイルとWordテンプレートファイルを準備し、適切に配置します。
  3. VBAエディタ(Alt + F11)からCreateWordDocsFromExcelNoRefマクロを実行します。
  4. マクロが完了すると、Excelファイルと同じフォルダ内に「生成済み文書」フォルダが作成され、中に個別のWord文書が保存されます。


4. Web上の情報を取得する(簡単なスクレイピング)

この応用事例では、Webサイトから特定の情報を取得する(スクレイピング)VBAコードをAIに作成させます。
Web上の公開データや、社内システムの情報を自動でExcelに取り込む際に役立ちます。

シナリオ
例えば、社内で定期的に参照する情報源がWebサイト上に表形式(HTMLの<table>タグ)で公開されているとします。これを手作業でExcelにコピー&ペーストしている場合、時間と手間がかかります。

このシナリオでは、具体的に以下のWebページを例とします。

例:Webページ内のMarkdown記法一覧表の取得
  • 対象URL: https://excel-ubara.com/GenerativeAI/GAI008.html
  • 取得したい情報: このWebページ内に記述されている「プロンプトでのMarkdown記法とサンプル」という見出しの直下にある、Markdown記法とその効果についてまとめられた表(HTMLの<table>タグ)のデータ。
  • 自動化の目的: この表の内容を自動的にExcelシートに抽出し、整理された形で出力することで、手作業によるコピー&ペーストの手間を削減し、常に最新の情報を効率的にExcelで管理できるようにします。

この自動化により、Webページの内容が更新された際も、マクロを実行するだけでExcelシートのデータが最新の状態に保たれ、業務の効率化と正確性の向上に貢献します。

AIへのプロンプトの考え方と例:目的の表を明確に
Webスクレイピングのプロンプトでは、AIがWebサイトにアクセスし、目的の表形式データを特定できるよう、以下の点を明確に伝えます。
  • 目的のURL: どのWebサイトから情報を取得したいか。
  • 取得したい情報: 表形式のデータ(<table>タグの内容)。
  • 情報の特定方法: Webページ上でその表がどこにあるかのヒント。今回は、特定の見出しのテキスト(<h4>タグのテキスト)を基準に、その後に続く最初の<table>タグを特定します。
  • 出力先: 取得した情報をExcelのどこに出力したいか(例:特定のシートのA1セルから)。

プロンプト例
Excel VBAコードを作成してください。

目的:指定したWebページの「プロンプトでのMarkdown記法とサンプル」という見出しの下にあるテーブル(tableタグ)の内容を、Excelシートに表として出力する。

### 手順:

1.  以下のURLにアクセスする。
    * `https://excel-ubara.com/GenerativeAI/GAI008.html`
2.  Webページ内で、**`h4`タグのテキストが「プロンプトでのMarkdown記法とサンプル」と完全に一致する見出し**を特定する。
3.  その見出しの**HTMLソースコード上での位置の直後にある最初の`table`タグ**の内容をすべて取得する。
4.  取得したテーブルのデータを、このマクロがあるExcelファイルの「**Markdown記法一覧**」という名前のシートの**A1セル**から表形式で貼り付ける。既存のデータはクリアする。
5.  処理の開始と終了がわかるように**メッセージボックス**を表示する。

**参照設定が不要なコード**で作成してください。
見出しを特定した後、その後のテーブルを確実に取得するロジックを実装してください。
生成されるVBAコードには、各処理の内容を**簡潔にコメント**してください。

AIが生成したVBAコードの例と解説
(※以下はAIが生成する可能性のあるコードの例です。AIの回答はプロンプトやモデルのバージョンにより変動します。)

' 標準モジュールに貼り付けて実行
Sub GetTableFromWebRobustFinal()
  Dim ie As Object ' Internet Explorer オブジェクト (Late Binding)
  Dim ws As Object ' 出力シート (Late Binding)
  Dim htmlDoc As Object ' HTMLDocument オブジェクト
  Dim h4Element As Object ' h4要素を格納
  Dim allTables As Object ' ページ内のすべてのテーブル
  Dim htmlTable As Object ' 目的のHTMLTable オブジェクト
  Dim htmlRow As Object ' HTMLTableRow オブジェクト
  Dim htmlCell As Object ' HTMLTableCell オブジェクト
  Dim rowNum As Long, colNum As Long
  Dim foundH4 As Boolean ' h4が見つかったかどうかのフラグ
  Dim foundTable As Boolean ' テーブルが見つかったかどうかのフラグ
  Dim h4Html As String ' h4要素のouterHTMLを格納

  ' 処理開始メッセージ
  MsgBox "Webからのテーブル情報取得を開始します。", vbInformation

  ' IEオブジェクトを作成
  On Error GoTo ErrorHandler ' エラーハンドリング設定
  Set ie = CreateObject("InternetExplorer.Application")
  On Error GoTo 0 ' エラーハンドリング解除
  ie.Visible = False ' IEを非表示で実行

  ' 指定のURLにアクセス
  ie.navigate "https://excel-ubara.com/GenerativeAI/GAI008.html"
  ' ページの読み込みが完了するまで待機
  Do While ie.Busy Or ie.readyState <> 4
    DoEvents
  Loop

  Set htmlDoc = ie.document

  ' 出力シートの準備
  On Error Resume Next ' エラーを無視して続行
  Set ws = ThisWorkbook.Sheets("Markdown記法一覧")
  If ws Is Nothing Then
    Set ws = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
    ws.Name = "Markdown記法一覧"
  End If
  On Error GoTo 0 ' エラー無視を解除
  ws.Cells.ClearContents ' 既存データをクリア

  rowNum = 1 ' Excelの開始行

  ' すべてのh4要素を検索し、目的の見出しを特定
  foundH4 = False
  For Each h4Element In htmlDoc.getElementsByTagName("h4")
    If h4Element.innerText = "プロンプトでのMarkdown記法とサンプル" Then
      foundH4 = True
      h4Html = h4Element.outerHTML ' h4のHTML文字列を取得
      Exit For ' 見つかったらループを抜ける
    End If
  Next h4Element

  If Not foundH4 Then
    MsgBox "指定の見出し「プロンプトでのMarkdown記法とサンプル」が見つかりませんでした。", vbExclamation
    ie.Quit
    Set ie = Nothing
    Exit Sub ' 処理を終了
  End If

  ' ページ全体のHTMLを取得し、h4要素以降の部分を抽出
  Dim pageHtml As String
  pageHtml = htmlDoc.body.innerHTML ' body内の全HTML

  ' h4要素のHTML文字列が見つかった位置を特定
  Dim h4Pos As Long
  h4Pos = InStr(pageHtml, h4Html)

  If h4Pos = 0 Then ' 万が一outerHTMLが特定できない場合(通常は発生しないはず)
    MsgBox "内部エラー:見出しのHTMLを特定できませんでした。", vbExclamation
    ie.Quit
    Set ie = Nothing
    Exit Sub
  End If

  ' h4要素の終了タグ以降の文字列を取得
  Dim afterH4Html As String
  afterH4Html = Mid(pageHtml, h4Pos + Len(h4Html))

  ' afterH4Htmlの中から最初のテーブルを見つける
  ' 新しいHTMLDocumentオブジェクトを作成し、h4以降のHTMLをロードすることで、
  ' その中からテーブルを検索する
  Dim tempDoc As Object
  Set tempDoc = CreateObject("HTMLFile")
  tempDoc.body.innerHTML = afterH4Html

  Set allTables = tempDoc.getElementsByTagName("table")
  If allTables.Length > 0 Then
    Set htmlTable = allTables(0) ' 最初のテーブルを取得
    foundTable = True
  Else
    foundTable = False
  End If

  If Not foundTable Then
    MsgBox "指定の見出しの後にテーブルが見つかりませんでした。", vbExclamation
    ie.Quit
    Set ie = Nothing
    Exit Sub ' 処理を終了
  End If

  ' テーブルの行をループ
  For Each htmlRow In htmlTable.getElementsByTagName("tr")
    colNum = 1 ' Excelの開始列

    ' ヘッダーセル(<th>)をループ
    For Each htmlCell In htmlRow.getElementsByTagName("th")
      ws.Cells(rowNum, colNum).Value = htmlCell.innerText
      colNum = colNum + 1
    Next htmlCell

    ' データセル(<td>)をループ
    For Each htmlCell In htmlRow.getElementsByTagName("td")
      ws.Cells(rowNum, colNum).Value = htmlCell.innerText
      colNum = colNum + 1
    Next htmlCell
    rowNum = rowNum + 1 ' 次のExcel行へ
  Next htmlRow

  ' IEを閉じる
  ie.Quit
  Set ie = Nothing
  Set tempDoc = Nothing ' 一時的なHTMLドキュメントも解放

  ' 処理終了メッセージ
  MsgBox "Webからのテーブル情報取得が完了しました。", vbInformation
  Exit Sub

ErrorHandler:
  MsgBox "エラーが発生しました。Webサイトの構造変更やInternet Explorerのセキュリティ設定を確認してください。" & vbCrLf & _
      "エラー内容: " & Err.Description, vbCritical
  If Not ie Is Nothing Then ie.Quit
  Set ie = Nothing
End Sub

コードの解説
  • htmlDoc.getElementsByTagName("h4") でページ内のすべての<h4>タグ要素を取得し、そのinnerText(表示テキスト)が "プロンプトでのMarkdown記法とサンプル" と完全に一致する見出しを探します。
  • 該当の<h4>タグが見つからなかった場合は、メッセージを表示して処理を終了します。
  • 修正点(重要):
    目的の<h4>タグが見つかったら、そのouterHTML(タグ自身を含むHTML文字列)を取得します。
    ページ全体のinnerHTMLから、h4タグのouterHTMLが見つかった位置を特定し、その直後から始まる部分のHTML文字列を抽出します。
    この抽出したHTML文字列を、新たに作成した一時的なHTMLFileオブジェクト(tempDoc)のbody.innerHTMLに読み込ませます。
    これにより、tempDocはh4タグ以降のHTML構造を持つため、そのtempDocの中からgetElementsByTagName("table")で最初の<table>要素を取得すれば、それが目的のテーブルとなります。この方法はNextSiblingのテキストノード問題やNull問題を回避し、より確実に対象テーブルを特定できます。
  • 目的のテーブルが見つからなかった場合も、同様にメッセージを表示して処理を終了します。
  • 特定したテーブル内の各行(<tr>)をループし、さらに各セル(<th>や<td>)のテキスト内容を読み込みます。
  • 取得したデータを、Excelシートの指定された位置(A1セルから)に表形式で貼り付けていきます。
  • 「Markdown記法一覧」シートが存在しない場合は自動で作成します。
  • 最後にIEを閉じ、使用したオブジェクト(ie と tempDoc)を解放します。
  • Webサイトへのアクセス失敗などに対応するため、エラーハンドリングを含んでいます。

事前準備
  1. Internet Explorerの有効化: Windowsの機能でInternet Explorerが有効になっている必要があります。通常は有効ですが、無効になっている場合は「Windowsの機能の有効化または無効化」から有効にしてください。
  2. Webサイトの確認: プロンプト例に記載のURL(https://excel-ubara.com/GenerativeAI/GAI008.html)にアクセスし、目的のテーブルがHTML上でどのように構成されているかを確認しておくと、万が一コードが動作しない場合の原因特定に役立ちます。

使用方法
  1. 上記のVBAコードを、マクロを記述するExcelファイルの標準モジュールに貼り付けます。
  2. VBAエディタ(Alt + F11)からGetTableFromWebRobustFinalマクロを実行します。
  3. マクロが完了すると、Excelファイル内に「Markdown記法一覧」シートが作成され、指定したWebページから取得したテーブルデータが貼り付けられます。

今回のVBAはなかなか完成しませんでした。
何回も何回もテスト確認とそれをAIに伝えてVBA修正を重ねた結果要約完成したものです。
以下は、この経緯についてAI自身に書かせたものです。(筆者はポイントだけ伝えて)
デバッグ経緯の追記
今回のWebスクレイピングのVBAコード開発では、WebページのHTML要素を辿るロジックにおいてデバッグが必要となりました。

共同デバッグの経緯と解決
当初、AIが提案したコードは、HTML要素の「次の兄弟」(NextSibling)を順に辿ることで目的の表を探すものでした。しかし、実行時に「実行時エラー '424': オブジェクトが必要です。」が発生。これは、NextSiblingが要素以外の「テキストノード」(改行など)や、予期せずNull値を返す場合があるため、VBAがそれを適切に扱えず発生するエラーでした。

ユーザーは、エラーが発生した箇所と「Nullになる」という具体的な情報を提供。AIは、その情報を元に、NextSiblingの返り値がNullNothingでないかのチェックを追加し、さらに要素ノードのみを処理するフィルタリングを試みました。

それでも問題が解決しないことから、最終的には「目的の見出し以降のHTML文字列を抽出し、それを一時的なHTMLドキュメントとして再解析する」という、より堅牢なアプローチをAIが提案しました。これにより、複雑な兄弟要素のナビゲーション問題を根本から回避し、無事に目的の表を取得できるようになりました。

このデバッグ過程は、ユーザーからの具体的なエラー情報と洞察(Nullになるという指摘)が、AIがより高度で安定した解決策を導き出すための重要な手がかりとなり、人とAIが共同で課題を乗り越えた好例となりました。

VBAとGemini API連携:AIコーディングアシスタントの構築

VBAの可能性は、Excel内だけに留まりません。外部のサービスやAIと連携することで、その能力は飛躍的に向上します。ここでは、VBAからAPI(Application Programming Interface)を介してGoogle Geminiなどの大規模言語モデルを直接呼び出し、あなたのVBAコーディングを強力にアシストしてもらう実践的な方法を学びます。

これまでは、AIにVBAコードのアイデアや具体的なスニペットを生成してもらう方法を見てきました。しかし、AIの真の力をExcel VBAに統合するには、外部API(Application Programming Interface)との連携が不可欠です。これにより、AIを単なるコーディングアシスタントとしてだけでなく、Excelの機能の一部として組み込み、より高度な自動化やデータ処理を実現できるようになります。

このセクションでは、Google Gemini APIを例にとり、VBAから直接AIのテキスト生成能力を利用する方法を具体的に解説します。
Google Gemini APIを利用するには、まずGoogle Cloud PlatformでAPIキーを取得し、Excel側でいくつかの初期設定を行う必要があります。APIキーは、あなたがGoogleのAIサービスを利用するための「鍵」のようなものです。この鍵を使って、AIに正しくアクセスできるようになります。

APIとは何か? VBAとAI連携の基本

API、つまりApplication Programming Interfaceは、ちょっと難しそうな言葉に聞こえるかもしれませんね。でも、その役割は、あなたが図書館で司書さんに本を探してもらうときの様子に似ています。

想像してみてください。あなたは図書館で、何か知りたいことや解決したい課題があります。でも、膨大な本の中から、どれが役に立つか、どこに置いてあるか分かりません。そこで、司書(API) に話しかけます。
  • あなたは司書に「〇〇について書かれた本を探しているんだけど」とか「△△のやり方がわかる本はないかな?」と、知りたいことややりたいこと(リクエスト) を伝えます。
  • 司書(API) は、あなたの言葉(リクエスト)を受け取ると、図書館の膨大な蔵書(様々な情報や機能の宝庫)の中から、あなたの知りたいことや解決したい課題にぴったりの「本(情報や機能)」を探し出してくれます。
  • そして、司書(API)は、見つけた本(必要な情報や機能の提供)をあなたの元に届けてくれます。
このように、APIは「異なるシステム(この場合は、あなたと図書館の蔵書)が、お互いに何を頼めるか、どう返事をもらえるかを決めたルール」であり、「そのルールに基づいて、システム同士がスムーズにやり取りするための窓口」だと考えてください。

この「あなた」の部分がExcelのVBA、図書館の蔵書の部分がAIに置き換わります。VBAでAIのAPIを利用できるようになると、Excelが自動的にAIと会話できるようになります。これにより、これまでは手動でコピー&ペーストしていたAIからのコードを、VBAが直接AIに注文して受け取り、Excelの業務に組み込むといった、より高度でシームレスな自動化が可能になります。

例えば、Excelの中で自動でできるようになります。
  • Excelのデータに基づいて、AIに商品の紹介文やキャッチコピーを自動で生成させ、別のセルに表示する。
  • 大量の顧客リストから特定の条件に合う顧客の情報をAIに要約させ、レポートにまとめる。
  • VBAコードでエラーが出たとき、そのエラーメッセージをAIに送って、その場で修正案を提案してもらう。

まさに、AIがあなたのVBA開発の「共同作業パートナー」として、リアルタイムにコード生成やデバッグを支援してくれるようになるのです。

Google Cloud Platform (GCP) アカウントの作成とAPIキーの取得

まず、Googleアカウントを持っていることを確認してください。もし持っていない場合は、無料で作成できます。
全体の手順フローは以下になります。
AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

  1. Google Cloud Platform (GCP) にアクセスする
    • ウェブブラウザで以下のURLにアクセスし、GCPコンソールを開きます。
      Google Cloud Console

    • Googleアカウントでログインします。初めてアクセスする場合は、利用規約への同意や、支払い情報の登録(無料枠でも必要となる場合がありますが、Gemini APIの無料利用枠の範囲であれば料金はかかりません)を求められることがあります。画面の指示に従って進めてください。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

  2. 新しいプロジェクトを作成する
    • GCPコンソールの左上にある、現在選択されているプロジェクト名(例:「My First Project」や「test」などの表示)をクリックします。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • クリックすると、「プロジェクトを選択」というダイアログが表示されます。このダイアログの右上に「新しいプロジェクト」というボタンまたはリンクがあります。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • 【「新しいプロジェクト」ボタンが見当たらない場合】
      • まれにUIの変更などで「新しいプロジェクト」ボタンの場所が異なる場合があります。その場合は、GCPコンソール画面上部にある大きな検索バーに「プロジェクトを作成」と入力し、検索結果から「プロジェクトを作成」または「新しいプロジェクトの作成」といった項目を選択しても、プロジェクト作成画面に直接移動します。

    • 「新しいプロジェクト」をクリックすると、「新しいプロジェクト」というタイトル(または同様の)の画面に切り替わります。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • この画面に「プロジェクト名」を入力するフィールドがあります。
    • ここに、あなたが付けたいプロジェクト名(例:「VBA-API」など、後から見て内容が分かりやすい名前)を入力してください。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • 「プロジェクト名」を入力すると、その下にある「プロジェクト ID」が自動的に提案されます。プロジェクトIDは一度作成すると変更できませんが、プロジェクト名は何回でも変更可能ですので、ここでは分かりやすい名前を設定しましょう。
    • 場所(組織やフォルダ)の選択が必要な場合は、適切なものを選択します。(個人の場合は、通常はデフォルトで問題ありません)
    • 最後に「作成」ボタンをクリックすれば、指定した名前で新しいプロジェクトが作成されます。
    • 作成が完了したら、再度プロジェクト選択プルダウンをクリックし、今作成したプロジェクトが選択されていることを確認します。

  3. Gemini API を有効にする
    • GCPコンソールの左側のナビゲーションメニューから、「APIとサービス」→「ライブラリ」を選択します。(メニューが見当たらない場合は、左上の三本線のアイコンをクリックして開いてください。)

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • 検索バーで「Gemini API」と入力し、検索します。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • 検索結果に表示される「Gemini API」をクリックします。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • Gemini APIのページで、「有効にする」ボタンをクリックします。これにより、あなたのプロジェクトでGemini APIが利用できるようになります。

  4. APIキーを作成する
    • 左側のナビゲーションメニューから、「APIとサービス」→「認証情報」を選択します。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • 画面上部にある「認証情報を作成」をクリックし、ドロップダウンメニューから「APIキー」を選択します。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • 新しいAPIキーが生成され、画面に表示されます。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

    • 重要: このAPIキーは非常に重要です!画面に表示されたAPIキーを必ずコピーし、安全な場所に保存してください。(例:メモ帳に一時的に貼り付ける、パスワード管理ツールに登録するなど。)
    • 警告: このAPIキーを直接Excelファイルに書き込んだり、GitHubなどの公開リポジトリにアップロードしたり、他者に安易に共有したりすることは絶対に避けてください。APIキーが漏洩すると、あなたのGCPアカウントが悪用され、意図しない課金が発生するなどのリスクがあります。
    • APIキーの確認後、「閉じる」をクリックします。
    • 【もしAPIキーを保存せずに閉めてしまっても大丈夫!】
      • 万が一、APIキーを控えるのを忘れて画面を閉めてしまっても心配ありません。
      • 再度「APIとサービス」→「認証情報」の画面に戻ると、作成済みのAPIキーのリストが表示されます。
      • 確認したいAPIキーの右側にある「鉛筆アイコン」をクリックして、そのAPIキーの編集画面を開いてください。
      • 編集画面の「詳細情報」セクションに「鍵を表示します。」というリンクがあります。これをクリックすると、伏せられていたAPIキーの文字列が一時的に表示されますので、そこでコピーして安全な場所に保存し直してください。
      • ただし、セキュリティ上の理由から、APIキーは一度しか表示されないよう設計されているサービスもあります(GCPは「鍵を表示します」で再表示可能ですが)。基本的には、生成された直後に必ずコピーして保存する習慣をつけることを強くお勧めします。
      • どうしても元のAPIキーを再確認できない、あるいはセキュリティ上の懸念がある場合は、同じ画面で「APIキーを削除」し、改めて「認証情報を作成」から新しいAPIキーを発行し直すことも可能です。無料枠の範囲であれば、この方法が最も確実で安全です。

Excel VBA側の初期設定

VBAからWeb上のAPIにアクセスするためには、外部の機能を利用するための準備が必要です。VBAでは、主に「参照設定」という方法で、外部ライブラリのオブジェクトを早期に認識させることができます。これにより、コードの記述時に候補が表示されたり、コンパイル時にエラーを検出したりできるメリットがあります。
  1. Excelを開き、Alt + F11 を押してVBAエディタ(VBE)を起動します。
  2. VBEのメニューバーから「ツール(T)」→「参照設定(R)...」を選択します。
  3. VBEのメニューバーから「ツール(T)」→「参照設定(R)...」を選択します。
  4. 参照設定ダイアログボックスが表示されます。スクロールして以下のライブラリを探し、チェックボックスをオンにします。
    • Microsoft XML, v6.0 (または Microsoft XML, v3.0 や Microsoft XML, v5.0 など、利用可能な最新バージョン)
    • このライブラリは、HTTPリクエストを送信し、Webサーバーと通信するためのオブジェクト (MSXML2.XMLHTTP60 など) を提供します。
  5. 「OK」ボタンをクリックしてダイアログボックスを閉じます。
【本章のVBAコードは「参照設定」不要で動く!】
しかし、参照設定を必要としない「レイトバインディング(事前バインディングなし)」という記述方法もあります。これは、VBAコードの実行時に初めてオブジェクトを認識させる方法で、特定の参照設定がなくても多くのPCでVBAコードがそのまま動くというメリットがあります。本書で紹介するAPI連携のVBAコードは、このレイトバインディングで記述するため、上記の「Microsoft XML」の参照設定は必須ではありません。

もし将来的に、VBEで記述時に候補が表示される「早期バインディング(参照設定あり)」で開発を進めたい場合は、上記の参照設定を行ってください。今回は、より多くの環境で動くことを優先し、参照設定なしで実装できるコードを中心に解説します。

これで、VBAからGemini APIを呼び出すための準備が整いました。次のステップでは、実際にAPIを呼び出すためのVBAコードを作成していきます。

VBAからAPIを呼び出す基本コードの作成(標準モジュール)

いよいよ、Excel VBAからGoogle Gemini APIを呼び出すためのVBAコードを作成します。ここでは、最も基本的なAPI連携の仕組みを学び、AIにテキスト生成を依頼する汎用的な関数を作成します。この関数を標準モジュールに記述することで、あなたのExcelブックのどこからでもAIの力を借りられるようになります。

まずは、以下のVBAコードを標準モジュールにコピー&ペーストしてください。
  1. ExcelのVBAエディタ(VBE)を開きます (Alt + F11)。
  2. VBEのメニューバーから「挿入(I)」→「標準モジュール(M)」を選択します。
  3. 新しく開いた真っ白なモジュールに、以下のコードをそのまま貼り付けてください。
Option Explicit

' ★ここにあなたのGemini APIキーを貼り付けてください★
Private Const GEMINI_API_KEY As String = "YOUR_GEMINI_API_KEY_HERE"

' Gemini APIのエンドポイントURL (モデル指定を含む)
' gemini-proではなく、より新しいモデルであるgemini-1.5-proを使用
Private Const GEMINI_API_URL As String = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key="

' ====================================================================
' 関数名: GetGeminiResponse
' 概要: Gemini APIを呼び出し、AIからの応答を取得する
' 引数:
'   promptText (String): AIに送信するプロンプト(指示文)
' 戻り値:
'   String: AIからの応答テキスト、またはエラーメッセージ
' ====================================================================
Public Function GetGeminiResponse(ByVal promptText As String) As String
    ' HTTP通信用のオブジェクトを宣言 (参照設定不要な「レイトバインディング」)
    Dim objHttp As Object ' MSXML2.XMLHTTP60
    Dim strURL As String
    Dim strRequestBody As String
    Dim strResponseText As String
    Dim lngStatusCode As Long
    Dim strErrorMessage As String
    Dim startPos As Long
    Dim endPos As Long
    Dim tempText As String

    On Error GoTo ErrorHandler

    ' HTTPオブジェクトの作成
    Set objHttp = CreateObject("MSXML2.XMLHTTP")

    ' APIの完全なURLを構築
    strURL = GEMINI_API_URL & GEMINI_API_KEY

    ' リクエストボディ(JSON形式)を構築
    ' JSON文字列を正しくエスケープする
    ' Chr(34)はダブルクォーテーション(")を表す
    ' Chr(92)はバックスラッシュ(\)を表す
    ' JSON内でダブルクォーテーションをエスケープするには \" と記述する
    strRequestBody = "{" & Chr(34) & "contents" & Chr(34) & ":" & _
                     "[" & _
                     "{" & Chr(34) & "parts" & Chr(34) & ":" & _
                     "[" & _
                     "{" & Chr(34) & "text" & Chr(34) & ":" & _
                     Chr(34) & Replace(promptText, Chr(34), Chr(92) & Chr(34)) & Chr(34) & _
                     "}" & _
                     "]}" & _
                     "]}"

    ' HTTPリクエストの準備
    objHttp.Open "POST", strURL, False ' False: 同期通信 (応答を待つ)
    objHttp.setRequestHeader "Content-Type", "application/json" ' JSON形式でデータを送信することを宣言

    ' HTTPリクエストの送信
    objHttp.send strRequestBody

    ' 応答のステータスコードを取得
    lngStatusCode = objHttp.Status

    ' 応答内容を取得
    strResponseText = objHttp.responseText

    ' ステータスコードが200 (OK) 以外の場合
    If lngStatusCode <> 200 Then
        strErrorMessage = "APIエラー (" & lngStatusCode . "): " & strResponseText
        Debug.Print strErrorMessage
        GetGeminiResponse = "エラー: " & strErrorMessage
        GoTo CleanUp
    End If

    ' JSON応答の解析
    ' "text": "応答内容" の部分を抽出する
    ' "text": (スペースの有無は問わない) の位置を見つける
    startPos = InStr(strResponseText, """text"":")
    
    If startPos > 0 Then
        ' "text":" の部分の長さをスキップし、その直後から最初のダブルクォーテーションを探す
        startPos = startPos + Len("""text"":")
        
        ' 実際のテキストが始まる最初のダブルクォーテーションを探す
        startPos = InStr(startPos, strResponseText, Chr(34))
        
        If startPos > 0 Then ' ダブルクォーテーションが見つかったら
            startPos = startPos + 1 ' ダブルクォーテーションの次からがテキスト開始
            
            ' テキストの終了を知らせる次のダブルクォーテーションを探す
            ' エスケープされたダブルクォーテーション \" を誤認識しないように注意
            endPos = startPos ' 検索開始位置を現在の開始位置に設定
            Do While endPos > 0
                endPos = InStr(endPos, strResponseText, Chr(34)) ' 次のダブルクォーテーションを探す
                If endPos > 0 Then
                    ' そのダブルクォーテーションの直前がバックスラッシュでなければ、それが終了位置
                    If Mid(strResponseText, endPos - 1, 1) <> Chr(92) Then
                        Exit Do ' 見つかったらループを抜ける
                    Else
                        endPos = endPos + 1 ' エスケープされていたら、次の検索開始位置を一つ進める
                    End If
                End If
            Loop
            
            If endPos > startPos Then
                tempText = Mid(strResponseText, startPos, endPos - startPos)
                ' JSON文字列に含まれる \" (エスケープされたダブルクォーテーション) を " に戻す
                GetGeminiResponse = Replace(tempText, Chr(92) & Chr(34), Chr(34))
                
                ' 改行コードのエスケープ(\n, \r)もあれば、適切な形式に変換
                GetGeminiResponse = Replace(GetGeminiResponse, Chr(92) & "n", vbCrLf)
                GetGeminiResponse = Replace(Chr(92) & "r", vbCr)
                ' タブ (\t) もよくエスケープされる
                GetGeminiResponse = Replace(GetGeminiResponse, Chr(92) & "t", vbTab)
                ' バックスラッシュ自体がエスケープされている場合 (\\) も元に戻す
                GetGeminiResponse = Replace(Chr(92) & Chr(92), Chr(92))

            Else
                GetGeminiResponse = "エラー: AI応答のテキスト部分の終了位置を解析できませんでした。応答: " & strResponseText
            End If
        Else
            GetGeminiResponse = "エラー: AI応答のテキスト開始ダブルクォーテーションが見つかりませんでした。応答: " & strResponseText
        End If
    Else
        GetGeminiResponse = "エラー: AI応答に 'text' フィールドが見つかりませんでした。応答: " & strResponseText
    End If
    
CleanUp:
    ' オブジェクトの解放
    Set objHttp = Nothing
    Exit Function

ErrorHandler:
    strErrorMessage = "予期せぬエラーが発生しました: " & Err.Description
    Debug.Print strErrorMessage
    GetGeminiResponse = "エラー: " & strErrorMessage
    Resume CleanUp ' エラーが発生してもCleanup処理に進む

End Function

コードの解説
上記のVBAコードは、GetGeminiResponse という名前の関数を定義しています。この関数が、あなたがAIに指示を送り、その応答を受け取るための「窓口」となります。
  • Option Explicit: VBAコードの先頭に記述するお勧めのステートメントです。変数をすべて明示的に宣言することを強制し、タイプミスなどによるエラーを防ぐのに役立ちます。
  • Private Const GEMINI_API_KEY As String = "YOUR_GEMINI_API_KEY_HERE":
    • ここに、先ほどGoogle Cloud Platformで取得したAPIキーを貼り付けます。「YOUR_GEMINI_API_KEY_HERE」の部分を、あなたのAPIキー文字列に置き換えてください。
    • Const は定数(値を変更できない変数)を宣言するキーワードです。APIキーは固定値なので、定数として定義するのが適切です。
    • 【重要】APIキーの扱い方については、この後も繰り返し注意喚起します。このコード例では直接記述していますが、実運用ではセルから読み込む、環境変数を使うなど、より安全な方法を検討すべきです。
  • Private Const GEMINI_API_URL As String:
    • これはGemini APIにアクセスするためのURLです。v1beta はAPIのバージョン、gemini-pro は利用するモデルの種類を示しています。現在のGeminiの主流モデルであるgemini-proを指定しています。
  • Public Function GetGeminiResponse(ByVal promptText As String) As String:
    • この行から関数が始まります。Public なので、Excelのシート上からでも、他のVBAプロシージャからでもこの関数を呼び出すことができます。
    • promptText As String は、AIに送りたい「質問文」や「指示文」を文字列として受け取るための引数です。
    • As String は、この関数がAIからの応答を文字列として返すことを意味します。
  • Dim objHttp As Object:
    • Web上のAPIと通信するために必要な XMLHTTP オブジェクトを宣言しています。
    • As Object と宣言することで、特定の参照設定(Microsoft XML, v6.0など)がなくても動くレイトバインディングを実現しています。これにより、このExcelファイルを使う人の環境に左右されにくくなります。
  • Set objHttp = CreateObject("MSXML2.XMLHTTP"):
    • CreateObject メソッドを使って、XMLHTTP オブジェクトのインスタンスを生成しています。これが、APIとの通信役を担います。
  • strURL = GEMINI_API_URL & GEMINI_API_KEY:
    • APIの基本URLと、あなたのAPIキーを結合し、AIにリクエストを送るための完全なURLを作成しています。
  • strRequestBody = "{""contents"":[{""parts"":[{""text"":""" & Replace(promptText, """", """""") & """]}]}}":
    • AIに送る指示(プロンプト)をJSON(JavaScript Object Notation)形式の文字列として構築しています。JSONは、Web APIでデータをやり取りする際によく使われる軽量なデータ形式です。
    • Replace(promptText, """", """""") は、プロンプトテキストの中にダブルクォーテーション(")が含まれていた場合に、JSONのルールに従ってエスケープ(\"のように変換)するための処理です。
  • objHttp.Open "POST", strURL, False:
    • APIにリクエストを送信するための準備をします。
    • "POST": データを送信するHTTPメソッドです。
    • strURL: リクエストを送るAPIのURLです。
    • False: 通信を同期的に行うことを意味します。つまり、AIからの応答があるまで、VBAコードは次の行に進まずに待ちます。簡易的なテストや短い処理には適していますが、長い処理ではExcelが固まってしまう可能性があるため、非同期通信(True)も選択肢になります(本書では同期通信で解説します)。
  • objHttp.setRequestHeader "Content-Type", "application/json":
    • 送信するデータがJSON形式であることをAPIに伝えています。これはAPIがデータを正しく解釈するために必要な設定です。
  • objHttp.send strRequestBody:
    • 実際にAPIにリクエスト(指示とデータ)を送信します。
  • lngStatusCode = objHttp.Status:
    • APIサーバーからの応答の状態を示す「ステータスコード」を取得します。200 は「成功」、400 や 500 番台は「エラー」を示します。
  • strResponseText = objHttp.responseText:
    • AIからの実際の応答内容(生成されたテキストなど)を文字列として取得します。この応答も通常はJSON形式です。
  • JSON応答の解析:
    • InStr や Mid 関数を使って、JSON応答の中から"text":"AIの応答内容"という部分を抽出し、AIが生成した純粋なテキストを取り出しています。より複雑なJSON構造を扱う場合は、専用のJSONパーサーライブラリ(VBA-JSONなど)を導入すると便利ですが、本書ではこの簡易的な方法で進めます。
  • ErrorHandler:
    • 予期せぬエラーが発生した場合に、VBAコードが停止せずにエラーメッセージを表示して処理を終了するためのエラーハンドリングです。
  • Set objHttp = Nothing:
    • 使用し終わったオブジェクトは、メモリを解放するために Nothing を設定します。これはVBAでの良い習慣です。

VBEイミディエイトウィンドウからのAPI呼び出し実践とデバッグ

VBAのGetGeminiResponse関数を作成したら、まずはExcelシートからではなく、VBE(VBAエディタ)のイミディエイトウィンドウを使って、その関数が正しく動作するかどうかをテストするのが最も効率的で、デバッグ作業には欠かせません。
イミディエイトウィンドウとは?
イミディエイトウィンドウは、VBAエディタ(VBE)の機能の一つで、VBAのコードを一行ずつ実行したり、変数の値を確認したり、関数やプロシージャを呼び出して即座に結果を表示したりするための便利なツールです。コードの動作確認やデバッグ作業において頻繁に利用されます。

1. イミディエイトウィンドウの表示
  • Excelを開き、Alt + F11 キーを押してVBEを起動します。
  • VBEのメニューバーから「表示(V)」「イミディエイト ウィンドウ(I)」を選択します。
  • または、Ctrl + G ショートカットキーでも表示できます。
  • VBEの下部、または任意の場所にイミディエイトウィンドウが表示されます。
2. GetGeminiResponse関数の呼び出しと基本的なテスト
イミディエイトウィンドウで関数を呼び出すには、関数が値を返す場合、その前に「?」(クエスチョンマーク)を付けます。
イミディエイトウィンドウの入力欄に、以下のように入力し、Enterキーを押します。

?GetGeminiResponse("APIとは")
  • ? は、GetGeminiResponse関数の戻り値をイミディエイトウィンドウに表示させるための指示です。
  • "APIとは" は、AIに送信する質問(プロンプト)です。
本来であれば、AIからの回答テキストがイミディエイトウィンドウに表示されるはずですが、初回はこのコードではエラーとなるはずです。

3. 発生したエラーとデバッグの実践
実際にこのコードをイミディエイトウィンドウで実行すると、以下のようなエラーに遭遇しました。

3-1. 最初のエラー:JSONペイロードの構造エラー
  • エラー内容:
    APIエラー (400): {"error": {"code": 400, "message": "Invalid JSON payload received. Expected , or } after key:value pair.\n[{\"text\":\"APIとは\"]}]}}\n ^", "status": "INVALID_ARGUMENT" }
    エラー: APIエラー (400): {"error": {"code": 400, "message": "Invalid JSON payload received. Expected , or } after key:value pair.\n[{\"text\":\"APIとは\"]}]}}\n ^", "status": "INVALID_ARGUMENT" }
  • AIを「リアルタイム・デバッガー」として活用:
    • このエラーメッセージは、APIが「Invalid JSON payload received(不正なJSONデータを受け取った)」と明確に教えてくれています。さらに、[{\"text\":\"APIとは\"]}]}}という部分が不正であり、どこが問題か(^で示される箇所)まで示してくれます。
    • これは、VBAで構築しているJSON文字列が、Gemini APIの要求する形式と異なっていることを示唆しています。特に、JSONではダブルクォーテーション(")を文字列内で使う場合、\"のようにバックスラッシュ(\)でエスケープする必要があります。しかし、VBAの文字列リテラルで"を表現する際に""と書くのと混同してしまい、不適切なエスケープ(例:"を""に置換していた)が行われていたことが原因でした。
3-2. 二番目のエラー:モデル名またはAPIエンドポイントの不一致
  • エラー内容:
    APIエラー (404): { "error": { "code": 404, "message": "models/gemini-pro is not found for API version v1beta, or is not supported for generateContent. Call ListModels to see the list of available models and their supported methods.", "status": "NOT_FOUND" } }
    エラー: APIエラー (404): { "error": { "code": 404, "message": "models/gemini-pro is not found for API version v1beta, or is not supported for generateContent. Call ListModels to see the list of available models and their supported methods.", "status": "NOT_FOUND" } }
  • AIを「リアルタイム・デバッガー」として活用:
    • このエラーメッセージは、「models/gemini-pro is not found」と、問題がモデル名にあることを非常に具体的に教えてくれます。さらに、「Call ListModels to see the list of available models」と、利用可能なモデルのリストを確認するよう促しています。
    • これは、gemini-proモデルが、現在のAPIバージョン(v1beta)では直接利用できないか、または別のモデル名に移行した可能性を示しています。APIの提供元は常にサービスを改善しており、モデル名や利用可能なエンドポイントは更新されることがあるため、適切なモデル(この場合はgemini-1.5-pro)への変更が必要でした。
3-3. 三番目のエラー:AI応答JSONの解析ロジックの問題
  • エラー内容:
    エラー: AI応答に 'text' フィールドが見つかりませんでした。応答: { "candidates": [ ... (大量のJSONレスポンス) ... ] }
  • AIを「リアルタイム・デバッガー」として活用:
    • このエラーが最も興味深い点でした。APIエラー (404)は解消され、VBA関数としてはエラーメッセージを返しているものの、その後に続く応答: { "candidates": [...] }の部分には、AIが生成した長文の回答が完璧なJSON形式で含まれていました。
    • これは、API通信自体は成功し、AIからの応答データは問題なく受け取れているにも関わらず、VBAコードがそのJSONデータの中から、実際に必要なAIの回答テキスト("text"フィールド)を正しく探し出せていないことを示しています。AIが返すJSONの整形("text": の後に半角スペースがあるかないかなど)や、テキスト内に含まれる特殊文字(\や"、改行コードなど)のエスケープ解除ロジックが、期待通りに機能していなかったためです。
    • AIからの「正しいJSON応答」というリアルタイムなフィードバックを基に、VBAのJSON解析ロジックを微調整することで、最終的なテキスト抽出に成功しました。

4. 教訓:地道な確認と修正が成功の鍵
今回のデバッグ過程は、API連携開発における以下の重要な教訓を与えてくれます。
  • APIの仕様は変化する: モデル名やエンドポイントは更新されるため、エラーメッセージを頼りに最新の情報を確認することが重要です。
  • エラーメッセージを丁寧に読む: エラーメッセージには、問題解決のための具体的なヒントが詰まっています。AIからの応答も、デバッグのための貴重な情報源となります。
  • JSONの構造とエスケープは厳密である: JSONは厳密な書式を持つため、手動で文字列を構築・解析する際には、エスケープルールや空白の有無に細心の注意が必要です。
  • 試行錯誤の繰り返し: 一度で完璧なコードが書けることは稀です。エラーが発生したら、焦らず、原因を一つずつ特定し、コードを少しずつ修正しては動作を確認する、という地道な作業の繰り返しが成功に繋がります。

完成したVBAコード

上記のデバッグ過程を経て、最終的に正しく動作するようになった GetGeminiResponse 関数の完成コードは以下の通りです。
このコードを標準モジュールに貼り付け、GEMINI_API_KEY をご自身のAPIキーに置き換えて使用してください。

Option Explicit

' ★ここにあなたのGemini APIキーを貼り付けてください★
Private Const GEMINI_API_KEY As String = "YOUR_GEMINI_API_KEY_HERE"

' Gemini APIのエンドポイントURL (モデル指定を含む)
' gemini-proではなく、より新しいモデルであるgemini-1.5-proを使用
Private Const GEMINI_API_URL As String = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key="

' ====================================================================
' 関数名: GetGeminiResponse
' 概要: Gemini APIを呼び出し、AIからの応答を取得する
' 引数:
'   promptText (String): AIに送信するプロンプト(指示文)
' 戻り値:
'   String: AIからの応答テキスト、またはエラーメッセージ
' ====================================================================
Public Function GetGeminiResponse(ByVal promptText As String) As String
    ' HTTP通信用のオブジェクトを宣言 (参照設定不要な「レイトバインディング」)
    Dim objHttp As Object ' MSXML2.XMLHTTP60
    Dim strURL As String
    Dim strRequestBody As String
    Dim strResponseText As String
    Dim lngStatusCode As Long
    Dim strErrorMessage As String
    Dim startPos As Long
    Dim endPos As Long
    Dim tempText As String

    On Error GoTo ErrorHandler

    ' HTTPオブジェクトの作成
    Set objHttp = CreateObject("MSXML2.XMLHTTP")

    ' APIの完全なURLを構築
    strURL = GEMINI_API_URL & GEMINI_API_KEY

    ' リクエストボディ(JSON形式)を構築
    ' JSON文字列を正しくエスケープする
    ' Chr(34)はダブルクォーテーション(")を表す
    ' Chr(92)はバックスラッシュ(\)を表す
    ' JSON内でダブルクォーテーションをエスケープするには \" と記述する
    strRequestBody = "{" & Chr(34) & "contents" & Chr(34) & ":" & _
                     "[" & _
                     "{" & Chr(34) & "parts" & Chr(34) & ":" & _
                     "[" & _
                     "{" & Chr(34) & "text" & Chr(34) & ":" & _
                     Chr(34) & Replace(promptText, Chr(34), Chr(92) & Chr(34)) & Chr(34) & _
                     "}" & _
                     "]}" & _
                     "]}"

    ' HTTPリクエストの準備
    objHttp.Open "POST", strURL, False ' False: 同期通信 (応答を待つ)
    objHttp.setRequestHeader "Content-Type", "application/json" ' JSON形式でデータを送信することを宣言

    ' HTTPリクエストの送信
    objHttp.send strRequestBody

    ' 応答のステータスコードを取得
    lngStatusCode = objHttp.Status

    ' 応答内容を取得
    strResponseText = objHttp.responseText

    ' ステータスコードが200 (OK) 以外の場合
    If lngStatusCode <> 200 Then
        strErrorMessage = "APIエラー (" & lngStatusCode & "): " & strResponseText
        Debug.Print strErrorMessage
        GetGeminiResponse = "エラー: " & strErrorMessage
        GoTo CleanUp
    End If

    ' JSON応答の解析
    ' "text": "応答内容" の部分を抽出する
    ' "text": (スペースの有無は問わない) の位置を見つける
    startPos = InStr(strResponseText, """text"":")
    
    If startPos > 0 Then
        ' "text":" の部分の長さをスキップし、その直後から最初のダブルクォーテーションを探す
        startPos = startPos + Len("""text"":")
        
        ' 実際のテキストが始まる最初のダブルクォーテーションを探す
        startPos = InStr(startPos, strResponseText, Chr(34))
        
        If startPos > 0 Then ' ダブルクォーテーションが見つかったら
            startPos = startPos + 1 ' ダブルクォーテーションの次からがテキスト開始
            
            ' テキストの終了を知らせる次のダブルクォーテーションを探す
            ' エスケープされたダブルクォーテーション \" を誤認識しないように注意
            endPos = startPos ' 検索開始位置を現在の開始位置に設定
            Do While endPos > 0
                endPos = InStr(endPos, strResponseText, Chr(34)) ' 次のダブルクォーテーションを探す
                If endPos > 0 Then
                    ' そのダブルクォーテーションの直前がバックスラッシュでなければ、それが終了位置
                    If Mid(strResponseText, endPos - 1, 1) <> Chr(92) Then
                        Exit Do ' 見つかったらループを抜ける
                    Else
                        endPos = endPos + 1 ' エスケープされていたら、次の検索開始位置を一つ進める
                    End If
                End If
            Loop
            
            If endPos > startPos Then
                tempText = Mid(strResponseText, startPos, endPos - startPos)
                ' JSON文字列に含まれる \" (エスケープされたダブルクォーテーション) を " に戻す
                GetGeminiResponse = Replace(tempText, Chr(92) & Chr(34), Chr(34))
                
                ' 改行コードのエスケープ(\n, \r)もあれば、適切な形式に変換
                GetGeminiResponse = Replace(GetGeminiResponse, Chr(92) & "n", vbCrLf)
                GetGeminiResponse = Replace(GetGeminiResponse, Chr(92) & "r", vbCr)
                ' タブ (\t) もよくエスケープされる
                GetGeminiResponse = Replace(GetGeminiResponse, Chr(92) & "t", vbTab)
                ' バックスラッシュ自体がエスケープされている場合 (\\) も元に戻す
                GetGeminiResponse = Replace(GetGeminiResponse, Chr(92) & Chr(92), Chr(92))

            Else
                GetGeminiResponse = "エラー: AI応答のテキスト部分の終了位置を解析できませんでした。応答: " & strResponseText
            End If
        Else
            GetGeminiResponse = "エラー: AI応答のテキスト開始ダブルクォーテーションが見つかりませんでした。応答: " & strResponseText
        End If
    Else
        GetGeminiResponse = "エラー: AI応答に 'text' フィールドが見つかりませんでした。応答: " & strResponseText
    End If
    
CleanUp:
    ' オブジェクトの解放
    Set objHttp = Nothing
    Exit Function

ErrorHandler:
    strErrorMessage = "予期せぬエラーが発生しました: " & Err.Description
    Debug.Print strErrorMessage
    GetGeminiResponse = "エラー: " & strErrorMessage
    Resume CleanUp ' エラーが発生してもCleanup処理に進む

End Function

AI時代のExcel革命:AI×VBAで“書かない自動化”超入門AI時代のExcel革命:AI×VBAで“書かない自動化”超入門


ExcelシートからAPI関数を利用してみる

GetGeminiResponse関数がイミディエイトウィンドウで正しく動作することを確認できたら、次は実際にExcelシートからこの関数を呼び出して、AIの応答をセルに表示させてみましょう。これは、ExcelでAI機能を活用する最も基本的な方法です。
  1. 質問を入力するセルを用意する
    Excelシートの任意のセル(例:A1セル)に、AIに質問したい内容を入力します。

  2. 例:A1セルに「日本の首都はどこですか?」と入力します。
    結果を表示するセルに数式を入力する

    AIの回答を表示させたいセル(例:B1セル)に、以下の数式を入力します。
    =GetGeminiResponse(A1)
    この数式は、「A1セルの内容をGetGeminiResponse関数の引数として渡し、その関数の戻り値(AIの回答)をB1セルに表示する」という意味です。

  3. Enterキーを押して結果を確認する
    • 数式を入力後、Enterキーを押すと、VBA関数が実行され、Google Gemini APIが呼び出されます。
    • しばらく待つと、B1セルにAIからの回答が表示されるはずです。
    • A1セルに質問「日本の首都はどこですか?」
    • B1セルに数式「=GetGeminiResponse(A1)」
    • B1セルにAIの回答「日本の首都は東京です。」と表示されるイメージです。

      AI時代のExcel革命:AI×VBAで“書かない自動化”超入門

このように、VBAで作成した関数は、Excelの標準関数と同じようにシート上の数式として利用できます。セルの値を変更すれば、その都度AIが新しい回答を生成してくれるため、リアルタイムに近い形でAIとの対話や情報取得が可能です。

【補足】汎用的なAI関数としての活用:個人用マクロブックとアドイン化
今回作成した GetGeminiResponse 関数は非常に汎用性が高く、様々なExcelブックで利用できる可能性があります。この関数を特定のExcelファイルだけでなく、常に利用可能にしておくには、以下の方法があります。
  • 個人用マクロブックへの登録:
    Excelには「PERSONAL.XLSB」という個人用マクロブックがあり、ここにマクロや関数を保存すると、どのExcelブックを開いてもそのマクロや関数が利用できるようになります。
    VBAエディタでGetGeminiResponse関数が記述されたモジュールをPERSONAL.XLSBプロジェクトにコピーすることで実現できます。
    個人用マクロブックに登録した関数は、イミディエイトウィンドウからも直接実行できます。
    個人用マクロブックの詳しい使い方や、コードの登録方法については、別途AIに質問して確認してください。
    これにより、=PERSONAL.XLSB!GetGeminiResponse(A1)のようにブック名を付加して呼び出すことが可能になります。
  • アドイン化 (.xlam):
    さらに高度な方法として、作成した関数を含むExcelファイルを「Excelアドイン (.xlam)」として保存し、Excelにインストールする方法があります。アドインとして登録することで、マクロ有効ブックを開く際にセキュリティ警告が表示されることなく、あたかもExcelの標準機能のように利用できるようになります。これは、複数のユーザーと機能を共有したり、配布したりする場合に特に便利です。

    アドイン作成の詳細については、以下のページをご参照ください。
    Excel VBA マクロをアドイン化する|VBA技術解説
    ・Excelアドインについて ・アドインファイルのフォルダ ・アドインの作り方 ・アドインの登録と有効化 ・ ・アドインで保存するVBA ・アドインを登録するVBA ・アドインを有効化するVBA ・登録されているアドインを確認するVBA ・アドインマネージャーを表示するVBA ・アドイン配布時に自動登録するVBA ・個人用マクロブックについて

API利用における注意点とセキュリティ

Google Gemini APIのような外部APIを利用する際、特に重要なのが「APIキーの管理」と「利用上の注意点」です。これらを怠ると、意図しない課金や情報漏洩などのリスクに繋がりかねません。

ここで解説する内容はGoogle Gemini APIに特化したものですが、APIキーの管理、利用制限(クォータ)、そして一般的な利用規約の遵守といった注意点は、他のほとんどのWeb APIにも共通する重要な考え方です。APIを使った開発を検討している方は、ぜひこのセクション全体に目を通しておくことを強くお勧めします。

APIキーの管理に関する具体的な対策
APIキーは、あなたのGoogle Cloudプロジェクトに紐付けられた認証情報であり、言わばあなたの「API利用のパスワード」です。これが第三者に漏洩すると、以下のような深刻な問題が発生する可能性があります。
  • 不正利用による課金: 悪意のある第三者があなたのAPIキーを使ってAPIを大量に呼び出し、その利用料があなたのGCPアカウントに請求されてしまう可能性があります。無料枠を超えた利用が発生した場合、高額な請求に繋がることもあります。
  • データへの不正アクセス: もしAPIキーが、機密情報へのアクセス権限を持つ他のAPI(例えば、Google Drive APIやCloud Storage APIなど)と関連付けられていた場合、不正なアクセスやデータ漏洩に繋がるリスクがあります。
  • サービスの停止: 悪意のある利用が検知された場合、GoogleによってAPIキーが無効化されたり、プロジェクトが停止されたりする可能性があります。

具体的な対策
  • コードへの直接記述を避ける: 今回のVBAコードでは学習目的のためにAPIキーを直接記述していますが、コード内に直接書くと、ファイル共有やバージョン管理時に意図せず漏洩するリスクがあるため、実運用では推奨されません。
    • より安全な方法の検討:
      • Excelシートから読み込む: シートの特定のセルにAPIキーを保存し、VBAコードでそのセルの値を読み込む方法。ただし、Excelファイルを共有する際には注意が必要です。
      • 環境変数として設定する: オペレーティングシステム(Windowsなど)の環境変数にAPIキーを設定し、VBAからそれを読み込む方法。これにより、APIキーがコードやファイル内に露出するのを防げます。
      • 外部設定ファイルを利用する: 暗号化された設定ファイルや、アクセス制限されたINIファイルなどにAPIキーを保存し、VBAで読み込む方法。
  • バージョン管理ツールでの管理: GitHubなどのバージョン管理システムを利用する場合、APIキーを直接コードに含めてコミットしないように細心の注意を払ってください。.gitignoreファイルなどを利用し、APIキーファイルや設定ファイルがリポジトリに含まれないように設定すべきです。
  • 必要最小限の権限設定: GCPの「APIとサービス」→「認証情報」画面でAPIキーを編集する際に、「APIの制限」を設定できます。ここでは、そのAPIキーがどのAPI(例えば、Gemini APIのみ)にのみアクセスを許可するかを制限できます。これにより、万一APIキーが漏洩しても、被害を最小限に抑えることができます。
  • 定期的なキーのローテーション: 定期的に新しいAPIキーを発行し、古いキーを無効化する(ローテーション)ことも、セキュリティを高める有効な手段です。
  • 不要なAPIキーの削除: 使用しなくなったAPIキーは速やかに削除してください。

レベル 方法 セキュリティ 実装難易度
初級 コード内直接記述 ★☆☆ ★☆☆
中級 Excelシートから読み込み ★★☆ ★★☆
上級 環境変数利用 ★★★ ★★★
プロ級 暗号化設定ファイル ★★★ ★★★

2. 利用制限(クォータ)と課金
Google Gemini APIには、不正利用や過度な利用を防ぐため、およびサービスの安定稼働のため、利用制限(クォータ)が設けられています。
  • 無料枠: 多くの場合、一定の範囲内であれば無料でAPIを利用できる「無料枠」が提供されています。しかし、この無料枠を超えて利用すると、課金が発生します。
  • クォータと無料枠の区別: クォータは、APIの利用量に対する技術的な上限を示すもので、無料枠の上限とは異なる場合があります。クォータ内でも、無料枠を超えると課金が発生することがあるため、両者を区別して管理することが重要です。
  • クォータの種類:
    • リクエスト数: 1分あたり、1日あたりのAPI呼び出し回数に制限がある場合があります。
    • トークン数: 送信するプロンプトや、AIが生成する応答の文字数(トークン数)に制限がある場合があります。
    • モデル固有の制限: 特定の高性能モデル(例: gemini-1.5-proなど)は、他のモデルよりもクォータが厳しかったり、課金レートが高かったりする場合があります。
  • 課金の確認: GCPコンソールの「課金」セクションで、現在のAPI利用状況とそれにかかる費用を確認できます。予期せぬ課金を防ぐため、定期的にこの画面を確認することをお勧めします。予算アラートを設定することも可能です。
  • クォータの確認と引き上げ申請: GCPコンソールの「APIとサービス」→「有効なAPIとサービス」から各APIを選択し、「クォータ」タブで現在の利用状況と制限を確認できます。もし、無料枠を超える、またはプロジェクトの要件として現在のクォータでは不足する場合は、この画面からクォータの引き上げ申請を行うことができます。ただし、引き上げが承認されるには審査があり、課金が発生する可能性が高まります。
3. その他の注意点
  • 利用規約の遵守: Google Gemini APIの利用規約を遵守することが必須です。特定の用途(例: 違法行為、誤情報の拡散など)での利用は禁じられています。
  • 応答時間の考慮: APIの応答には、ネットワーク状況やAIの処理負荷に応じて時間がかかることがあります。特に大量のデータを処理する場合や、UIに組み込む場合は、ユーザー体験を損なわないよう、非同期処理の検討やプログレスバーの表示などの工夫が必要です。
  • エラーハンドリングの強化: 今回のVBAコードにもエラーハンドリングを導入しましたが、実運用ではより詳細なエラーログの記録や、エラーの種類に応じた適切なメッセージ表示、リトライ処理などの堅牢なエラーハンドリングを実装することが重要です。

これらの注意点を理解し、適切に対応することで、安全かつ効率的にGoogle Gemini APIをExcel VBAで活用できるようになります。


まとめ:AIと共に進化する「書かない自動化」のその先へ

この第6章では、「AIとVBAを学び続ける!あなたの『超効率化』を止めないヒント」というテーマのもと、さらなる自動化の可能性を広げるための実践的な知識と応用例を探求してきました。プロンプト最適化から高度な応用事例、そして外部API連携によるAIのさらなる活用まで、あなたの「書かない自動化」を加速させるための多角的な視点を提供しました。

特にこの章では、以下の重要な学びがありました。
  • AIプロンプト最適化の深化: AIに意図が「伝わる」プロンプトの重要性を再認識し、より具体的で効果的な指示出しの技術を習得しました。これにより、AIが生成するVBAコードやアイデアの質を飛躍的に向上させることができます。
  • AIとの協調による応用自動化: 複雑なデータ集計、ユーザーインターフェースの構築(ユーザーフォーム)、異種アプリケーション連携(Word文書生成)、さらにはWebからの情報取得(スクレイピング)といった、多様な業務課題に対してAIをコーディングアシスタントとして活用する具体的なアプローチを学びました。
  • 外部連携とAPI活用の基礎: AIモデルそのものをVBAから直接操作するAPI連携の仕組みを理解し、APIキーの管理、利用制限(クォータ)、セキュリティといった実践的な注意点を把握しました。これにより、AIの能力をVBA環境に直接統合し、カスタマイズされた強力な自動化ツールを構築するための基盤を築きました。

これまでに学んだプロンプトの工夫、AIを巻き込んだ応用事例、そしてAPI連携の知識は、あなたの業務効率を飛躍的に向上させるための強力な武器となります。もはやあなたは、VBAコードを「ゼロから書く」必要はなく、AIと共に「創り出す」フェーズへと移行できるはずです。

AI×VBAは、決して「全自動化による思考停止」を意味するものではありません。
あなた自身の視点や判断力が、AIによる自動化の質と成果を大きく左右します。

本章で扱ったVBAによるAI連携は、数あるExcelの自動化機能の一つに過ぎません。第7章以降では、AI時代におけるExcelの役割がどのように変化し、VBAだけでなく、スピル・配列関数、LAMBDA関数、Python in Excel、Power Query、Power Pivotといった、Excelの様々な機能がどのようにAIと連携し、最適化された形で活用されていくのかを深掘りしていきます。


※本記事の作成にあたっては、生成AI(ChatGPT、Gemini、Claude)を活用し、文章および引用データの作成を行っています。最終的な内容は人間による確認・編集を経て掲載しています。





同じテーマ「AI×VBAで“書かない自動化”」の記事

AI時代のExcel革命:AI×VBAで“書かない自動化”超入門
第1章:AIって一体何?あなたのExcel作業をどう変える?(AI超基本)
第2章 VBAって怖くない!Excelを「言葉で動かす」(超入門)
第3章:AIを「自分だけのVBA先生」にする!質問・相談の超実践テクニック
第4章:【事例で学ぶ】AIとVBAでExcel作業を劇的に効率化する!
第5章:AI×VBAでつまづかない!トラブルシューティングとAIとの付き合い方
第6章:AIとVBAを学び続ける!あなたの「超効率化」を止めないヒント


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

第6章:AIとVBAを学び続ける!あなたの「超効率化」を止めないヒント|生成AI活用研究(2025-05-22)
第5章:AI×VBAでつまづかない!トラブルシューティングとAIとの付き合い方 |生成AI活用研究(2025-05-21)
第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日)


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

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」をお願いいたします。
本文下部へ