VBAマクロでExcelの連絡先をBrevoにプッシュする方法(Office Scriptsという代替案も)

ExcelシートからBrevo APIへワンクリックで連絡先を投稿する動作する VBAマクロ。代わりにOffice Scripts + Power Automateを使うべき場合と、Google Apps Scriptセットアップとのトレードオフも解説します。

Featured image for article: VBAマクロでExcelの連絡先をBrevoにプッシュする方法(Office Scriptsという代替案も)

Excel に連絡先があり、それを Brevo に入れたい。手っ取り早い答えはファイルを .csv として保存してインポートすることで、1 回ならそれで構いません。繰り返し行うこと(週次のセールス引き継ぎ、チームが毎日更新するワークブック、定期的に更新されるパートナーリスト)には、Excel の中に同期を実行するボタンが欲しくなります。

このガイドでは、それに本当に意味のある 2 つのパスを取り上げます。

  1. ワークブックに埋め込まれた VBA マクロ。 ライセンスもクラウドもなく、オフラインで動作し、ユーザーがボタンをクリックした瞬間に実行されます。「Excel から Brevo」のケースの約 80 % にとっての正解です。
  2. Office Scripts + Power Automate。 VBA の代わりに TypeScript、クラウドで動作し、スケジュールトリガーをサポート。ワークブックが OneDrive/SharePoint にあり、無人同期を望む場合の正解ですが、Power Automate のライセンスに注意してください。

Google Sheets の同等品をお探しなら、Apps Script に関する関連記事を参照してください。ノート PC のスクリプトから一度きりの CSV インポートをしたいだけなら、CSV インポートガイドに Python、Node.js、cURL のバージョンがあります。

マクロが行うこと

ユーザーがシート上の「Sync to Brevo」ボタンをクリックしたとき。

  1. アクティブなワークシートのすべての行を読み取ります(最初にヘッダー行、1 行に 1 つの連絡先)。
  2. Brevo の jsonBody パラメータ用の JSON 配列を構築します。
  3. ワークブックに保存された API キーで https://api.brevo.com/v3/contacts/import に POST します。
  4. 結果を表示するメッセージボックスを表示します。

それだけです。約 120 行の VBA。以下が完全な動作するモジュールです。

マクロが期待するシートレイアウト

emailfirstNamelastNamecompanycity
[email protected]JaneDoeAcmeBerlin
[email protected]JohnSmithGlobexParis

email は必須です。それ以外のすべての列は Brevo の連絡先属性となり、列ヘッダー(大文字化)から属性名にマップされます。したがって firstNameFIRSTNAMEcompanyCOMPANY です。カスタム属性(標準セット以外のもの)は、Brevo アカウントに先に存在する必要があります。Contacts → Settings → Contact attributes で定義してください。

ステップ 1: VBA エディタを開く

Excel で Alt + F11 を押します。VBA エディタが開きます。左側の Project ペインで、ワークブックを右クリックして Insert → Module を選択します。空の Module1 が表示されます。

ステップ 2: 完全なマクロを貼り付ける

Module1 の内容を次のもので置き換えます。

' ===========================================================================
' Brevo contact sync for Excel
' Reads the active sheet's rows and POSTs them to Brevo's import API.
' ===========================================================================
Option Explicit
Private Const BREVO_API_BASE As String = "https://api.brevo.com/v3"
Private Const BREVO_LIST_ID As Long = 42 ' <- your Brevo list ID
Private Const BATCH_SIZE As Long = 1000
' --- Public entry points (the ones you assign to ribbon buttons) -----------
Public Sub SyncSheetToBrevo()
Dim apiKey As String
apiKey = GetApiKey()
If apiKey = "" Then
MsgBox "No API key configured. Run ConfigureApiKey first.", _
vbExclamation, "Brevo Sync"
Exit Sub
End If
Dim ws As Worksheet
Set ws = ActiveSheet
Dim emailCol As Long
emailCol = FindEmailColumn(ws)
If emailCol = 0 Then
MsgBox "Sheet must have an 'email' column in row 1.", _
vbExclamation, "Brevo Sync"
Exit Sub
End If
Dim lastRow As Long, lastCol As Long
lastRow = ws.Cells(ws.Rows.Count, emailCol).End(xlUp).Row
lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
If lastRow < 2 Then
MsgBox "No contact rows found.", vbInformation, "Brevo Sync"
Exit Sub
End If
Dim contacts As Collection
Set contacts = New Collection
Dim r As Long, c As Long
For r = 2 To lastRow
Dim email As String
email = LCase(Trim(CStr(ws.Cells(r, emailCol).Value)))
If email <> "" And InStr(email, "@") > 0 Then
Dim json As String
json = "{""email"":""" & EscapeJson(email) & """,""attributes"":{"
Dim attrFirst As Boolean
attrFirst = True
For c = 1 To lastCol
If c <> emailCol Then
Dim val As String
val = CStr(ws.Cells(r, c).Value)
If val <> "" Then
If Not attrFirst Then json = json & ","
Dim attrName As String
attrName = UCase(Trim(CStr(ws.Cells(1, c).Value)))
json = json & """" & attrName & """:""" & EscapeJson(val) & """"
attrFirst = False
End If
End If
Next c
json = json & "}}"
contacts.Add json
End If
Next r
If contacts.Count = 0 Then
MsgBox "No valid contact rows found.", vbInformation, "Brevo Sync"
Exit Sub
End If
Dim totalSent As Long
Dim batchNum As Long
Dim okCount As Long, failCount As Long
Dim batchStart As Long
For batchStart = 1 To contacts.Count Step BATCH_SIZE
batchNum = batchNum + 1
Dim batchEnd As Long
batchEnd = batchStart + BATCH_SIZE - 1
If batchEnd > contacts.Count Then batchEnd = contacts.Count
Dim payload As String
payload = "{""jsonBody"":["
Dim i As Long
For i = batchStart To batchEnd
If i > batchStart Then payload = payload & ","
payload = payload & contacts(i)
Next i
payload = payload & "],""listIds"":[" & BREVO_LIST_ID & _
"],""updateExistingContacts"":true,""emptyContactsAttributes"":false}"
Dim ok As Boolean
ok = PostToBrevo(apiKey, payload)
If ok Then
okCount = okCount + 1
totalSent = totalSent + (batchEnd - batchStart + 1)
Else
failCount = failCount + 1
End If
Next batchStart
MsgBox "Sent " & totalSent & " contact(s) in " & batchNum & " batch(es)." _
& vbCrLf & "Successful batches: " & okCount _
& vbCrLf & "Failed batches: " & failCount, _
vbInformation, "Brevo Sync"
End Sub
Public Sub ConfigureApiKey()
Dim key As String
key = InputBox("Paste your Brevo API key (xkeysib-...):", "Brevo API Key")
If key = "" Then Exit Sub
key = Trim(key)
If Left(key, 8) <> "xkeysib-" Then
MsgBox "That doesn't look like a Brevo API key (should start with xkeysib-).", _
vbExclamation, "Brevo API Key"
Exit Sub
End If
On Error Resume Next
ThisWorkbook.CustomDocumentProperties("BrevoApiKey").Delete
On Error GoTo 0
ThisWorkbook.CustomDocumentProperties.Add _
Name:="BrevoApiKey", _
LinkToContent:=False, _
Type:=msoPropertyTypeString, _
Value:=key
ThisWorkbook.Save
MsgBox "API key saved inside the workbook.", vbInformation, "Brevo API Key"
End Sub
' --- Private helpers --------------------------------------------------------
Private Function GetApiKey() As String
On Error Resume Next
GetApiKey = ThisWorkbook.CustomDocumentProperties("BrevoApiKey").Value
On Error GoTo 0
End Function
Private Function FindEmailColumn(ws As Worksheet) As Long
Dim lastCol As Long, c As Long
lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
For c = 1 To lastCol
If LCase(Trim(CStr(ws.Cells(1, c).Value))) = "email" Then
FindEmailColumn = c
Exit Function
End If
Next c
FindEmailColumn = 0
End Function
Private Function PostToBrevo(apiKey As String, payload As String) As Boolean
Dim http As Object
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "POST", BREVO_API_BASE & "/contacts/import", False
http.SetRequestHeader "api-key", apiKey
http.SetRequestHeader "Content-Type", "application/json"
http.SetRequestHeader "Accept", "application/json"
http.Send payload
PostToBrevo = (http.Status = 202)
If Not PostToBrevo Then
Debug.Print "Brevo error " & http.Status & ": " & http.responseText
End If
End Function
Private Function EscapeJson(s As String) As String
Dim r As String
r = Replace(s, "\", "\\")
r = Replace(r, """", "\""")
r = Replace(r, vbCrLf, "\n")
r = Replace(r, vbLf, "\n")
r = Replace(r, vbCr, "\n")
r = Replace(r, vbTab, "\t")
EscapeJson = r
End Function

ステップ 3: ワークブックを .xlsm として保存する

VBA マクロはマクロ有効ワークブックでのみ保持されます。Save As で Excel Macro-Enabled Workbook (.xlsm) を選択します。通常の .xlsx 形式はマクロを静かに削除します。多くの人が初めてこの方法でコードを失います。

ステップ 4: API キーを設定する

ConfigureApiKey を 1 回実行します。次のいずれか。

  • VBA エディタで ConfigureApiKey サブルーチン内のどこかをクリックして F5 を押す、または
  • Excel で Developer → MacrosConfigureApiKey を選んで Run する。

xkeysib-... キーを貼り付けます。マクロはこれをワークブック自体の中のカスタムドキュメントプロパティとして保存します。ソースコードにもレジストリにもなく、ファイルとともに移動します(つまり、.xlsm を誰かにメールすると API キーも一緒に行きます)。

キーをワークブックの外に置きたい場合は、保存先を Windows レジストリに切り替えます。

' Replace the body of ConfigureApiKey with:
SaveSetting "Brevo", "Sync", "ApiKey", key
' And GetApiKey with:
GetApiKey = GetSetting("Brevo", "Sync", "ApiKey", "")

SaveSetting/GetSettingHKCU\Software\VB and VBA Program Settings\Brevo\Sync の下に書き込みます。ユーザーごとであり、ワークブックごとではありません。複数のワークブックで 1 つのキーを共有したい場合や、キーをファイルに含めたくない場合に使います。

ステップ 5: シートにボタンを追加する

これが、技術者でないユーザー向けのワンクリック体験に変える要素です。

Insert → Shapes → Rectangle、シートに 1 つドロップして「Sync to Brevo」とラベル付けします。図形を右クリック → Assign MacroSyncSheetToBrevo を選択。完了です。

または、より洗練された UI を求めるなら、Office Custom UI Editor 経由でカスタムリボンタブを追加できますが、ほとんどの内部ツールでは図形をボタンとして使うので十分です。

ステップ 6: 実行する

ボタンをクリックします。マクロは行を読み取り、バッチ化し、各バッチを Brevo に POST し、サマリーメッセージボックスを表示します。Brevo のインポートは非同期なので、成功メッセージは「Brevo がバッチを受け付けた」ことを意味します。実際の連絡先作成はサーバーサイドで次の数秒の間に発生します。完了時には Brevo からメールサマリーが届きます(disableNotification: true を設定していない限り)。

よくある落とし穴

ボタンが何もせず、エラーもない。 マクロが無効化されています。シート上部の黄色いセキュリティバーを見て、Enable Content をクリックしてください。組織がマクロをブロックしている場合は、以下のトラストセンター/コード署名のパスを参照してください。

Compile error: User-defined type not defined Mac Excel を使っており、MSXML2.XMLHTTP がありません。Mac VBA は HTTPS リクエストを直接行えません。代わりに以下の Office Scripts のパスを使ってください。

Brevo からの 400 Bad Request で原因が明確でない。 ほとんどの場合、次のいずれかです。(a) シートのカスタム属性がまだ Brevo に存在しない、先に作成してください。(b) JSON エスケープのバグ、セル値内のクォートやバックスラッシュがエスケープされていない。コードの EscapeJson 関数は標準的なケースを処理します。データに変な文字がある場合は、payload を Immediate ウィンドウ(Debug.Print payload)にログ出力して検査してください。

401 Unauthorized ヘッダーが間違っています。Authorization ではなく api-key(小文字、ハイフン)です。マクロは正しいものを使っていますが、別の場所からスニペットをコピーした場合は再確認してください。

Excel が大きなインポートでフリーズする。 マクロは UI スレッド上で同期的に実行されます。50,000 行以上の場合、JSON を構築して Brevo を待つ間、Excel が 10 〜 30 秒ハングするのを見ることになります。それを受け入れるか、MSXML2.XMLHTTP を非同期バリアントに切り替えますが、その規模では Power Automate(次のセクション)のほうが良いです。

VBA では足りないとき: Office Scripts + Power Automate

VBA はスケジュールクラウド同期ができません。次のものが必要な場合。

  • 誰も開かなくても 1 時間ごとに Brevo に同期するワークブック
  • OneDrive/SharePoint にあり、Web から編集されるワークブック
  • デスクトップマクロを禁止する IT 部門

…そんな場合は Office Scripts(Microsoft の Apps Script のクラウド相当品)と Power Automate(スケジューリングと HTTP のレイヤー)が欲しくなります。

分担: Office Scripts はシートを読み取り、連絡先データを返します。Power Automate はそのデータを受け取り、トリガー時に Brevo に POST します。

Office Script(Excel for the web → Automate → New Script):

function main(workbook: ExcelScript.Workbook): {email: string, attributes: Record<string, string>}[] {
const sheet = workbook.getActiveWorksheet();
const range = sheet.getUsedRange();
if (!range) return [];
const values = range.getValues() as string[][];
if (values.length < 2) return [];
const headers = values[0].map(h => String(h).trim());
const emailIdx = headers.findIndex(h => h.toLowerCase() === "email");
if (emailIdx === -1) throw new Error("Sheet must have an 'email' column");
const contacts: {email: string, attributes: Record<string, string>}[] = [];
for (let r = 1; r < values.length; r++) {
const row = values[r];
const email = String(row[emailIdx] ?? "").trim().toLowerCase();
if (!email || !email.includes("@")) continue;
const attributes: Record<string, string> = {};
for (let c = 0; c < headers.length; c++) {
if (c === emailIdx) continue;
const v = row[c];
if (v === null || v === "") continue;
attributes[headers[c].toUpperCase()] = String(v);
}
contacts.push({ email, attributes });
}
return contacts;
}

Power Automate フロー:

  1. Trigger: Recurrence(1 時間ごと)、または手動ボタン、または変更駆動型同期が欲しいなら “When a row is modified”。
  2. Action: Excel Online → Run script、ワークブックと上記スクリプトを指定します。返り値を contacts として保存。
  3. Action: HTTP(これは Premium コネクタです、以下のライセンスノートを参照)。
    • Method: POST
    • URI: https://api.brevo.com/v3/contacts/import
    • Headers: api-key: xkeysib-...Content-Type: application/json
    • Body:
      {
      "jsonBody": @{outputs('Run_script')?['body/result']},
      "listIds": [42],
      "updateExistingContacts": true
      }
  4. Action: Condition → ステータスコードが 202 でなければ Teams/メールアラートを送信。

ライセンスの現実チェック: HTTP アクションは Power Automate Premium コネクタです。Microsoft 365 Business Basic/Standard プランでは、標準コネクタは得られますが Premium は得られません。最も安い回避策は Power Automate Premium アドオン(執筆時点で約 15 ドル/ユーザー/月)か、HTTP を標準フローから呼び出せる小さな Azure Function に移すことです。すでに E3/E5 に Premium が含まれているなら準備完了です。

これが Apps Script のストーリーがよりきれいである主な理由です。Apps Script の UrlFetchApp は無料で無制限ですが、Microsoft の同等品はネットワーク呼び出しを有料コネクタ層の背後に置きます。

VBA 対 Office Scripts 対 Apps Script: いつ何を選ぶか

ニーズベストオプション
チームが毎日すでに開いているワークブックでのワンクリックボタンVBA マクロ(このガイド、上半分)
OneDrive/SharePoint のワークブック、毎時の自動同期Office Scripts + Power Automate(HTTP には Premium が必要)
Mac Excel のみ、VBA を使えないOffice Scripts + Power Automate
データが Excel ではなく Google Sheets にあるApps Script(無料、スケジュールトリガー組み込み)
ワンショットインポート、二度と必要ないSave As → CSVCSV インポートスクリプトを使う
10MB を超えるファイルからの一括インポートfileUrl 付き CSVCSV ガイドを参照

なぜこれが Zapier / ノーコードプラットフォームに勝るのか

繰り返しの Excel から Brevo へのジョブでは、サードパーティの自動化ツール(Zapier、Make、n8n)はタスクごとに課金し、データと Brevo の間にサードパーティを挟みます。VBA アプローチには継続的なコストがゼロで、サードパーティのデータフローがなく、ファイル内に住みます。ワークブックが移動すれば、統合も一緒に移動します。Office Scripts + Power Automate は Microsoft をサードパーティとして同様ですが(M365 を使っているならすでにスタックにあります)。

Brevo の POST /v3/contacts/import エンドポイントの全体的なポイントは、グルー プラットフォームが必要ないことです。あなたのツールはすでに HTTP リクエストの作り方を知っています。

さらに読む

Frequently Asked Questions

VBAマクロは本当にExcel内からBrevo APIを呼び出せますか?
はい。VBAは現代的なWindowsインストールに付属するMSXML2.XMLHTTPを通じてHTTPリクエストを行えます。マクロはJSONをapi.brevo.com/v3/contacts/importにPOSTします。これはPythonやNodeスクリプトがアクセスするのと同じエンドポイントです。Mac ExcelもOffice Scripts + Power Automateを通じて行えますが、デスクトップMac VBAではできません(MSXMLがありません)。
Apps Scriptの時間トリガーのようにスケジュール実行できますか?
VBAだけでは無理です。Application.OnTimeを発火させるにはExcelが開いている必要があります。無人のスケジュール同期には2つの選択肢があります。(1) ワークブックを開いてマクロを実行するWindowsタスクスケジューラ、または (2) Power AutomateスケジュールフローによってトリガーされるOffice Scripts(このガイドの後半で取り上げます)。
VBAは安全ですか?私の会社はマクロをブロックしています。
VBAマクロはファイルシステムとレジストリへのアクセス権で動作するので、デフォルトでブロックすることは合理的なポリシーです。回避する2つのパス: (1) コード署名証明書でマクロに署名し、ワークブックをTrusted Locationに配置する、または (2) VBAを完全にスキップしてOffice Scripts(TypeScript、サンドボックス、ファイルシステムアクセスなし)を使う。Office ScriptsはMicrosoftが祝福する現代的なパスです。
これはGoogle Apps Scriptアプローチと比較してどうですか?
Apps Scriptはset-and-forgetに近いです。Googleのクラウドで動作し、スケジュールトリガーが組み込まれており、Excel/Power Automateライセンスは不要です。VBAはオフライン作業や、チームがすでに開いているワークブックからのワンクリック手動同期で勝ります。Office Scripts + Power AutomateはMicrosoft側のクラウド/スケジュール相当ですが、Power Automateは送信HTTPに有料のプレミアムコネクタを必要とすることが多いです。
Brevoで無料で始める