Så skickar du Excel-kontakter till Brevo med ett VBA-makro (och alternativet med Office Scripts)
Ett fungerande VBA-makro som postar kontakter från ett Excel-ark till Brevos API med ett klick. Plus när du i stället bör använda Office Scripts + Power Automate, och avvägningarna mot en lösning med Google Apps Script.
Du har kontakter i Excel och du vill ha in dem i Brevo. Det snabba och fula svaret är att spara filen som .csv och importera den, vilket går bra en gång. För allt du gör återkommande, veckovis säljöverlämning, en arbetsbok ditt team uppdaterar varje dag, en partnerlista som fräschas upp, vill du ha en knapp inuti Excel som gör synken.
Den här guiden går igenom de två vägar som faktiskt är vettiga för det:
- Ett VBA-makro inbäddat i arbetsboken. Ingen licens, inget moln, fungerar offline, körs i samma stund som en användare klickar på en knapp. Rätt svar för ungefär 80 % av “Excel till Brevo”-fallen.
- Office Scripts + Power Automate. TypeScript i stället för VBA, körs i molnet, stöder schemalagda triggers. Rätt svar om arbetsboken ligger i OneDrive/SharePoint och du vill ha synk utan tillsyn, men var medveten om Power Automate-licensieringen.
Om du letar efter Google Sheets-motsvarigheten, se följeartikeln om Apps Script. Och om du bara vill ha en engångs-CSV-import från ett skript på din laptop har CSV-importguiden versioner i Python, Node.js och cURL.
Vad makrot gör
När användaren klickar på en knapp “Sync to Brevo” på arket:
- Läs varje rad från det aktiva arbetsbladet (rubrikrad först, en kontakt per rad).
- Bygg en JSON-array i den form Brevos
jsonBody-parameter förväntar sig. - Posta till
https://api.brevo.com/v3/contacts/importmed arbetsbokens lagrade API-nyckel. - Visa en meddelanderuta med resultatet.
Det är allt. Cirka 120 rader VBA. Nedan följer hela den fungerande modulen.
Arklayout makrot förväntar sig
| firstName | lastName | company | city | |
|---|---|---|---|---|
| [email protected] | Jane | Doe | Acme | Berlin |
| [email protected] | John | Smith | Globex | Paris |
email är obligatorisk. Varje annan kolumn blir ett Brevo-kontaktattribut, mappat efter kolumnrubriken (versaler) till attributnamnet. Så firstName blir FIRSTNAME, company blir COMPANY. Anpassade attribut (allt utöver standarduppsättningen) måste finnas i ditt Brevo-konto först. Definiera dem under Contacts → Settings → Contact attributes.
Steg 1: öppna VBA-editorn
I Excel: tryck Alt + F11. VBA-editorn öppnas. I Project-panelen till vänster, högerklicka på din arbetsbok och välj Insert → Module. En tom Module1 dyker upp.
Steg 2: klistra in hela makrot
Ersätt innehållet i Module1 med detta:
' ===========================================================================' 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 IDPrivate 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 0End 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 = 0End 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 IfEnd 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 = rEnd FunctionSteg 3: spara arbetsboken som .xlsm
VBA-makron överlever bara i makroaktiverade arbetsböcker. Spara som, välj Excel Macro-Enabled Workbook (.xlsm). Det vanliga .xlsx-formatet rensar makron tyst. Många tappar kod på det sättet första gången.
Steg 4: konfigurera din API-nyckel
Kör ConfigureApiKey en gång. Antingen:
- I VBA-editorn, klicka var som helst inuti
ConfigureApiKey-sub:en och tryckF5, eller - I Excel, Developer → Macros, välj
ConfigureApiKey, Run.
Klistra in din xkeysib-...-nyckel. Makrot lagrar den som en custom document property inuti själva arbetsboken. Den är inte i källkoden, inte i registret, och följer med filen (så var medveten: om du mejlar .xlsm-filen till någon följer API-nyckeln med).
Om du hellre vill lägga nyckeln utanför arbetsboken byter du lagringen till Windows-registret:
' Replace the body of ConfigureApiKey with:SaveSetting "Brevo", "Sync", "ApiKey", key
' And GetApiKey with:GetApiKey = GetSetting("Brevo", "Sync", "ApiKey", "")SaveSetting/GetSetting skriver under HKCU\Software\VB and VBA Program Settings\Brevo\Sync, per användare, inte per arbetsbok. Använd det om flera arbetsböcker ska dela en nyckel, eller om du inte vill ha nyckeln i filen.
Steg 5: lägg till en knapp på arket
Det här är vad som gör det till en ett-klicks-upplevelse för icke-tekniska användare.
Insert → Shapes → Rectangle, släpp en på arket, märk den “Sync to Brevo.” Högerklicka på formen, Assign Macro, välj SyncSheetToBrevo. Klart.
Eller, för ett mer polerat gränssnitt, lägg till en anpassad menyflik via Office Custom UI Editor. Men för de flesta interna verktyg räcker en form-som-knapp gott.
Steg 6: kör det
Klicka på knappen. Makrot läser raderna, batchar dem, postar varje batch till Brevo och visar en sammanfattningsruta. Brevos import är asynkron, så meddelandet att det lyckats betyder “Brevo har tagit emot batchen”. Själva kontaktskapandet sker på serversidan inom de närmaste sekunderna. Du får en e-postsammanfattning från Brevo när det är klart (om du inte satt disableNotification: true).
Vanliga fallgropar
Knappen gör ingenting och inget felmeddelande visas. Makron är inaktiverade. Titta på den gula säkerhetsraden överst på arket, klicka Enable Content. Om din organisation blockerar makron, se vägen via trust center och kodsignering nedan.
Compile error: User-defined type not defined. Du sitter på Mac Excel, som inte har MSXML2.XMLHTTP. Mac VBA kan inte göra HTTPS-anrop direkt. Använd Office Scripts-vägen nedan i stället.
400 Bad Request från Brevo utan tydlig orsak. Nästan alltid en av: (a) ett anpassat attribut i ditt ark finns inte i Brevo ännu, skapa det först; (b) JSON-escapingbug, citattecken eller bakåtsnedstreck i cellvärden som inte blev escapade. Funktionen EscapeJson i koden hanterar standardfallen. Om din data har konstiga tecken, logga payload till Immediate-fönstret (Debug.Print payload) och inspektera.
401 Unauthorized. Fel header. Det är api-key (gemener, bindestreck), inte Authorization. Makrot använder rätt namn, men om du kopierat ett snippet någon annanstans ifrån, dubbelkolla.
Excel fryser vid stora importer. Makrot körs synkront på UI-tråden. För 50 000+ rader får du se Excel hänga i 10 till 30 sekunder medan det bygger JSON och väntar på Brevo. Antingen accepterar du det, eller så byter du MSXML2.XMLHTTP till dess asynkrona variant. Men i den skalan har du det bättre i Power Automate (nästa avsnitt).
När VBA inte räcker: Office Scripts + Power Automate
VBA kan inte göra schemalagd molnsynk. Om du behöver:
- Att arbetsboken synkar till Brevo varje timme utan att någon öppnar den
- Att arbetsboken ligger i OneDrive/SharePoint, redigeras från webben
- En IT-avdelning som förbjuder skrivbordsmakron
…då vill du ha Office Scripts (Microsofts molnmotsvarighet till Apps Script) plus Power Automate (deras schema- och HTTP-lager).
Uppdelningen: Office Scripts läser arket och returnerar kontaktdatan. Power Automate tar den datan och postar den till Brevo vid en trigger.
Office Script:et (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-flödet:
- Trigger: Recurrence (varje 1 timme), eller manuell knapp, eller “When a row is modified” om du vill ha förändringsdriven synk.
- Action: Excel Online → Run script. Peka på din arbetsbok och skriptet ovan. Spara dess returvärde som
contacts. - Action: HTTP (det här är Premium-konnektorn, se licensnoten nedan).
- 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}
- Method:
- Action: Condition. Om statuskod inte är 202, skicka en Teams- eller e-postvarning.
Verklighetscheck för licensiering: HTTP-actionen är en Power Automate Premium-konnektor. På planerna Microsoft 365 Business Basic/Standard får du standardkonnektorerna men inte Premium. Den billigaste vägen runt det är tillägget Power Automate Premium (cirka 15 USD/användare/månad i skrivande stund), eller att flytta HTTP till en liten Azure Function som det vanliga flödet kan anropa. Om du redan ligger på E3/E5 med Premium inkluderat är du klar.
Det är huvudskälet till att Apps Script-berättelsen är renare: Apps Scripts UrlFetchApp är gratis och utan begränsningar, medan Microsofts motsvarighet sätter nätverksanropet bakom en betald konnektornivå.
VBA mot Office Scripts mot Apps Script: när väljer du vad
| Behov | Bästa val |
|---|---|
| Ett-klicks-knapp i en arbetsbok ditt team redan öppnar varje dag | VBA-makro (den här guiden, övre halvan) |
| Arbetsbok i OneDrive/SharePoint, autosynk varje timme | Office Scripts + Power Automate (kräver Premium för HTTP) |
| Bara Mac Excel, kan inte använda VBA | Office Scripts + Power Automate |
| Datan ligger i Google Sheets, inte Excel | Apps Script (gratis, schemalagda triggers inbyggt) |
| Engångsimport, kommer aldrig behövas igen | Spara som CSV och använd CSV-importskriptet |
| Massimport från en fil >10 MB | CSV med fileUrl, se CSV-guiden |
Varför det här slår Zapier och no-code-plattformar
För ett återkommande Excel-till-Brevo-jobb tar tredjepartsverktyg för automatisering (Zapier, Make, n8n) betalt per task och sätter en tredje part mellan din data och Brevo. VBA-vägen har noll löpande kostnad, inget tredjepartsdataflöde, och bor inuti filen. När arbetsboken flyttar, flyttar integrationen med. Office Scripts + Power Automate är likadant fast med Microsoft som tredje part (redan i din stack om du ligger på M365).
Hela poängen med Brevos endpoint POST /v3/contacts/import är att du inte behöver en limplattform. Dina verktyg vet redan hur man gör HTTP-anrop.