Jak poslat kontakty z Excelu do Brevo pomocí VBA makra (a alternativa Office Scripts)

Funkční VBA makro, které posílá kontakty z Excel listu do API Brevo jedním kliknutím. Plus kdy použít Office Scripts + Power Automate a kompromisy oproti nastavení s Google Apps Script.

Featured image for article: Jak poslat kontakty z Excelu do Brevo pomocí VBA makra (a alternativa Office Scripts)

Máte kontakty v Excelu a chcete je v Brevo. Rychlá a špinavá odpověď je uložit soubor jako .csv a importovat ho, což je v pohodě jednou. Pro cokoli, co děláte opakovaně, týdenní předání obchodu, sešit, který váš tým denně aktualizuje, partnerský seznam, který se obnovuje, chcete tlačítko přímo v Excelu, které synchronizaci udělá.

Tato příručka pokrývá dvě cesty, které pro to skutečně dávají smysl:

  1. VBA makro vložené v sešitu. Bez licencí, bez cloudu, funguje offline, spustí se v okamžiku, kdy uživatel klikne na tlačítko. Správná odpověď pro asi 80 % případů „Excel do Brevo”.
  2. Office Scripts + Power Automate. TypeScript místo VBA, běží v cloudu, podporuje plánované triggery. Správná odpověď, pokud sešit žije v OneDrive/SharePoint a chcete bezobslužnou synchronizaci. Pozor ale na licencování Power Automate.

Pokud hledáte ekvivalent pro Google Sheets, podívejte se na doprovodný článek o Apps Script. A pokud chcete jen jednorázový CSV import ze skriptu na svém notebooku, příručka pro CSV import má verze v Pythonu, Node.js a cURL.

Co makro dělá

Když uživatel klikne na tlačítko „Sync to Brevo” na listu:

  1. Načte každý řádek z aktivního pracovního listu (nejprve hlavička, jeden kontakt na řádek).
  2. Sestaví JSON pole tvarované pro parametr jsonBody Brevo.
  3. POSTne ho na https://api.brevo.com/v3/contacts/import s API klíčem uloženým v sešitu.
  4. Zobrazí message box s výsledkem.

To je vše. Asi 120 řádků VBA. Níže je plný funkční modul.

Rozvržení listu, které makro očekává

emailfirstNamelastNamecompanycity
[email protected]JaneDoeAcmeBerlin
[email protected]JohnSmithGlobexParis

email je povinný. Každý další sloupec se stane atributem kontaktu Brevo, mapovaným podle hlavičky sloupce (uppercase) na název atributu. Takže firstNameFIRSTNAME, companyCOMPANY. Vlastní atributy (cokoli mimo standardní sadu) musí ve vašem Brevo účtu nejprve existovat. Definujte je pod Contacts → Settings → Contact attributes.

Krok 1: Otevřete VBA editor

V Excelu: stiskněte Alt + F11. Otevře se VBA editor. V panelu Project vlevo klikněte pravým tlačítkem na sešit a vyberte Insert → Module. Objeví se prázdný Module1.

Krok 2: Vložte plné makro

Nahraďte obsah Module1 tímto:

' ===========================================================================
' 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

Krok 3: Uložte sešit jako .xlsm

VBA makra přetrvávají pouze v sešitech s povolenými makry. Save As → vyberte Excel Macro-Enabled Workbook (.xlsm). Obyčejný formát .xlsx makra tiše odstraní. Mnoho lidí přijde o kód takto poprvé.

Krok 4: Nakonfigurujte svůj API klíč

Spusťte ConfigureApiKey jednou. Buď:

  • Ve VBA editoru klikněte kamkoli uvnitř subu ConfigureApiKey a stiskněte F5, nebo
  • V Excelu Developer → Macros, vyberte ConfigureApiKey, Run.

Vložte svůj xkeysib-... klíč. Makro ho ukládá jako vlastní vlastnost dokumentu uvnitř samotného sešitu, není ve zdrojovém kódu, není v registru a cestuje se souborem (takže pozor: pokud .xlsm pošlete e-mailem někomu jinému, API klíč jde s ním).

Pokud byste raději klíč uložili mimo sešit, přepněte úložiště na registry Windows:

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

SaveSetting/GetSetting zapisuje pod HKCU\Software\VB and VBA Program Settings\Brevo\Sync, na uživatele, ne na sešit. Použijte to, pokud má více sešitů sdílet jeden klíč nebo pokud nechcete klíč v souboru.

Krok 5: Přidejte tlačítko na list

Tohle z toho dělá zážitek na jedno kliknutí pro netechnické uživatele.

Insert → Shapes → Rectangle, hoďte jeden na list, popište ho „Sync to Brevo.” Pravý klik na tvar → Assign Macro → vyberte SyncSheetToBrevo. Hotovo.

Nebo, pro vyleštěnější UI, přidejte vlastní záložku na pásu karet přes Office Custom UI Editor. Ale pro většinu interních nástrojů je tvar jako tlačítko úplně dost.

Krok 6: Spusťte to

Klikněte na tlačítko. Makro načte řádky, dávkuje je, POSTne každou dávku do Brevo a zobrazí souhrnný message box. Import Brevo je asynchronní, takže zpráva o úspěchu znamená „Brevo dávku přijalo”. Samotné vytváření kontaktů se děje na serveru v dalších několika sekundách. Až skončí, dostanete od Brevo souhrnný e-mail (pokud nenastavíte disableNotification: true).

Časté nástrahy

Tlačítko nedělá nic a žádná chyba. Makra jsou zakázána. Podívejte se na žlutý bezpečnostní pruh v horní části listu a klikněte Enable Content. Pokud vaše organizace blokuje makra, podívejte se na cestu trust-center / code-signing níže.

Compile error: User-defined type not defined. Jste na Mac Excelu, který nemá MSXML2.XMLHTTP. Mac VBA neumí dělat HTTPS požadavky přímo, použijte místo toho cestu Office Scripts níže.

400 Bad Request od Brevo bez zjevné příčiny. Téměř vždy jedna z: (a) vlastní atribut ve vašem listu v Brevo zatím neexistuje, vytvořte ho nejdřív; (b) chyba v JSON escapování, uvozovky nebo zpětná lomítka v hodnotách buněk, které nebyly escapovány. Funkce EscapeJson v kódu řeší standardní případy. Pokud máte v datech zvláštní znaky, zalogujte payload do Immediate window (Debug.Print payload) a prohlédněte si to.

401 Unauthorized. Špatná hlavička. Je to api-key (malá písmena, pomlčka), ne Authorization. Makro používá tu správnou, ale pokud jste si zkopírovali snippet odjinud, zkontrolujte to znovu.

Excel zamrzá při velkých importech. Makro běží synchronně na UI vlákně. Pro 50 000+ řádků budete sledovat, jak Excel visí 10 až 30 sekund, zatímco staví JSON a čeká na Brevo. Buď to přijměte, nebo přepněte MSXML2.XMLHTTP na asynchronní variantu, ale v tomto měřítku jste lépe v Power Automate (další sekce).

Když VBA nestačí: Office Scripts + Power Automate

VBA neumí plánovanou cloudovou synchronizaci. Pokud potřebujete:

  • Sešit, který se synchronizuje s Brevo každou hodinu, aniž by ho někdo otevíral
  • Sešit v OneDrive/SharePoint, editovaný z webu
  • IT oddělení, které zakazuje desktopová makra

…pak chcete Office Scripts (cloudový ekvivalent Apps Script od Microsoftu) plus Power Automate (jejich vrstva pro plánování a HTTP).

Rozdělení: Office Scripts načte list a vrátí data kontaktů. Power Automate ta data vezme a POSTne je do Brevo na trigger.

Office Script (Excel pro 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 flow:

  1. Trigger: Recurrence (každou 1 hodinu), nebo ruční tlačítko, nebo „When a row is modified”, pokud chcete synchronizaci řízenou změnami.
  2. Action: Excel Online → Run script, namiřte na svůj sešit a skript výše. Uložte jeho návratovou hodnotu jako contacts.
  3. Action: HTTP (toto je Premium konektor, viz poznámka o licencování níže).
    • 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 → pokud status code ≠ 202, pošlete upozornění do Teams/e-mailem.

Realita licencování: akce HTTP je Premium konektor Power Automate. V plánech Microsoft 365 Business Basic/Standard dostáváte standardní konektory, ale ne Premium. Nejlevnější obchvat je doplněk Power Automate Premium (asi 15 USD/uživatel/měsíc v době psaní), nebo přesunout HTTP do malé Azure Function, kterou standardní flow může zavolat. Pokud už jste na E3/E5 s Premium v ceně, máte to.

Tohle je hlavní důvod, proč je příběh Apps Script čistší: UrlFetchApp v Apps Script je zdarma a neomezený, zatímco ekvivalent Microsoftu staví síťové volání za placený konektor.

VBA vs Office Scripts vs Apps Script: kdy co zvolit

PotřebaNejlepší volba
Tlačítko jedním kliknutím v sešitu, který váš tým denně otevíráVBA makro (tato příručka, horní polovina)
Sešit v OneDrive/SharePoint, hodinová auto-syncOffice Scripts + Power Automate (pro HTTP potřeba Premium)
Pouze Mac Excel, nemůžete VBAOffice Scripts + Power Automate
Data žijí v Google Sheets, ne v ExceluApps Script (zdarma, plánované triggery v ceně)
Jednorázový import, už nikdy ho nebudete potřebovatSave As → CSV a skript pro CSV import
Hromadný import ze souboru >10 MBCSV s fileUrl, viz příručka CSV

Proč to vyhrává nad Zapierem / no-code platformami

Pro opakovanou úlohu Excel do Brevo si automatizační nástroje třetích stran (Zapier, Make, n8n) účtují za úkol a staví třetí stranu mezi vaše data a Brevo. Přístup VBA má nulové průběžné náklady, žádný tok dat přes třetí stranu a žije uvnitř souboru. Když se sešit přesouvá, integrace se přesouvá s ním. Office Scripts + Power Automate je podobné, ale s Microsoftem jako třetí stranou (už ve vašem stacku, pokud jste na M365).

Celý smysl endpointu Brevo POST /v3/contacts/import je, že nepotřebujete lepicí platformu, vaše nástroje už umí dělat HTTP požadavky.

Další čtení

Frequently Asked Questions

Může VBA makro opravdu volat API Brevo z Excelu?
Ano. VBA umí dělat HTTP požadavky přes MSXML2.XMLHTTP, který je součástí každé moderní instalace Windows. Makro POSTuje JSON na api.brevo.com/v3/contacts/import, stejný endpoint, který by zasáhl Python nebo Node skript. Mac Excel to také zvládne přes Office Scripts + Power Automate, ale desktopové Mac VBA nemůže (chybí MSXML).
Mohu to spouštět podle plánu jako časové triggery v Apps Script?
Z VBA samotného ne. Excel musí být otevřený, aby se Application.OnTime spustilo. Pro bezobslužnou plánovanou synchronizaci máte dvě možnosti: (1) Plánovač úloh Windows, který otevře sešit a spustí makro, nebo (2) Office Scripts spouštěné plánovaným Power Automate flow (popsáno dále v této příručce).
Je VBA bezpečné? Naše firma blokuje makra.
VBA makra běží s přístupem k souborovému systému a registru, takže jejich blokování ve výchozím nastavení je rozumná politika. Dvě cesty kolem toho: (1) podepsat makro code-signing certifikátem a umístit sešit do Trusted Location, nebo (2) přeskočit VBA úplně a použít Office Scripts (TypeScript, sandbox, žádný přístup k souborovému systému). Office Scripts je moderní cesta posvěcená Microsoftem.
Jak se to srovnává s přístupem Google Apps Script?
Apps Script je blíž k „nastavit a zapomenout”. Běží v Google cloudu, plánované triggery jsou součástí, žádná licence Excelu/Power Automate. VBA vyhrává pro offline práci a ruční synchronizaci jedním kliknutím ze sešitu, který váš tým již má otevřený. Office Scripts + Power Automate je cloudový/plánovaný ekvivalent na straně Microsoftu, ale Power Automate často potřebuje placený premium konektor pro odchozí HTTP.
Začněte zdarma s Brevo