Πώς να στείλετε επαφές Excel στο Brevo με μακροεντολή VBA (και η εναλλακτική Office Scripts)
Μια λειτουργική μακροεντολή VBA που δημοσιεύει επαφές από φύλλο Excel στο API του Brevo με ένα κλικ. Συν, πότε να χρησιμοποιήσετε Office Scripts + Power Automate και τα συμβιβαστικά σημεία έναντι μιας ρύθμισης Google Apps Script.
Έχετε επαφές στο Excel και τις θέλετε στο Brevo. Η γρήγορη και πρόχειρη απάντηση είναι να αποθηκεύσετε το αρχείο ως .csv και να το εισάγετε, που είναι εντάξει μία φορά. Για οτιδήποτε κάνετε επαναλαμβανόμενα, εβδομαδιαία παράδοση πωλήσεων, workbook που η ομάδα σας ενημερώνει καθημερινά, λίστα συνεργατών που ανανεώνεται, θέλετε ένα κουμπί ακριβώς μέσα στο Excel που να κάνει τον συγχρονισμό.
Αυτός ο οδηγός καλύπτει τις δύο διαδρομές που πραγματικά έχουν νόημα γι’ αυτό:
- Μια μακροεντολή VBA ενσωματωμένη στο workbook. Χωρίς αδειοδότηση, χωρίς cloud, λειτουργεί offline, εκτελείται τη στιγμή που ένας χρήστης κάνει κλικ σε κουμπί. Η σωστή απάντηση για το ~80% των περιπτώσεων «Excel σε Brevo».
- Office Scripts + Power Automate. TypeScript αντί για VBA, τρέχει στο cloud, υποστηρίζει προγραμματισμένα triggers. Η σωστή απάντηση αν το workbook ζει σε OneDrive/SharePoint και θέλετε συγχρονισμό χωρίς επίβλεψη, αλλά να γνωρίζετε την αδειοδότηση του Power Automate.
Αν ψάχνετε το ισοδύναμο για Google Sheets, δείτε το συνοδευτικό άρθρο για το Apps Script. Και αν θέλετε απλά μια εφάπαξ εισαγωγή CSV από script στον φορητό σας, ο οδηγός εισαγωγής CSV έχει εκδόσεις σε Python, Node.js και cURL.
Τι κάνει η μακροεντολή
Όταν ο χρήστης κάνει κλικ σε ένα κουμπί «Sync to Brevo» στο φύλλο:
- Διαβάζει κάθε γραμμή από το ενεργό φύλλο εργασίας (πρώτα η γραμμή κεφαλίδων, μία επαφή ανά γραμμή).
- Κατασκευάζει έναν πίνακα JSON σχηματισμένο για την παράμετρο
jsonBodyτου Brevo. - Κάνει POST στο
https://api.brevo.com/v3/contacts/importμε το αποθηκευμένο API key του workbook. - Εμφανίζει ένα message box με το αποτέλεσμα.
Αυτό είναι. ~120 γραμμές VBA. Παρακάτω είναι η πλήρης, λειτουργική μονάδα.
Διάταξη φύλλου που αναμένει η μακροεντολή
| firstName | lastName | company | city | |
|---|---|---|---|---|
| [email protected] | Jane | Doe | Acme | Berlin |
| [email protected] | John | Smith | Globex | Paris |
Το email είναι υποχρεωτικό. Κάθε άλλη στήλη γίνεται attribute επαφής Brevo, αντιστοιχισμένο μέσω της κεφαλίδας στήλης (σε κεφαλαία) στο όνομα του attribute. Έτσι firstName → FIRSTNAME, company → COMPANY. Τα προσαρμοσμένα attributes (οτιδήποτε πέρα από το τυπικό σύνολο) πρέπει πρώτα να υπάρχουν στον λογαριασμό σας στο Brevo, ορίστε τα στο Contacts → Settings → Contact attributes.
Βήμα 1: Ανοίξτε τον VBA editor
Στο Excel: πατήστε Alt + F11. Ο VBA editor ανοίγει. Στο panel Project στα αριστερά, κάντε δεξί κλικ στο workbook σας και επιλέξτε 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 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 FunctionΒήμα 3: Αποθηκεύστε το workbook ως .xlsm
Οι μακροεντολές VBA διατηρούνται μόνο σε workbooks με ενεργοποιημένες μακροεντολές. Save As → επιλέξτε Excel Macro-Enabled Workbook (.xlsm). Η απλή μορφή .xlsx αφαιρεί τις μακροεντολές σιωπηλά, πολλοί άνθρωποι χάνουν κώδικα έτσι την πρώτη φορά.
Βήμα 4: Διαμορφώστε το API key σας
Εκτελέστε το ConfigureApiKey μία φορά. Είτε:
- Στον VBA editor, κάντε κλικ οπουδήποτε μέσα στο sub
ConfigureApiKeyκαι πατήστεF5, ή - Στο Excel, Developer → Macros, επιλέξτε
ConfigureApiKey, Run.
Επικολλήστε το κλειδί xkeysib-.... Η μακροεντολή το αποθηκεύει ως custom document property μέσα στο ίδιο το workbook, δεν είναι στον πηγαίο κώδικα, δεν είναι στο registry και ταξιδεύει με το αρχείο (οπότε προσοχή: αν στείλετε το .xlsm με email σε κάποιον, το API key πάει μαζί του).
Αν προτιμάτε να βάλετε το κλειδί κάπου εκτός του workbook, αλλάξτε την αποθήκευση στο registry των Windows:
' Replace the body of ConfigureApiKey with:SaveSetting "Brevo", "Sync", "ApiKey", key
' And GetApiKey with:GetApiKey = GetSetting("Brevo", "Sync", "ApiKey", "")Το SaveSetting/GetSetting γράφει κάτω από το HKCU\Software\VB and VBA Program Settings\Brevo\Sync, ανά χρήστη, όχι ανά workbook. Χρησιμοποιήστε το αν πολλά workbooks πρέπει να μοιράζονται ένα κλειδί, ή αν δεν θέλετε το κλειδί στο αρχείο.
Βήμα 5: Προσθέστε ένα κουμπί στο φύλλο
Αυτό είναι που το μετατρέπει σε εμπειρία ενός κλικ για μη-τεχνικούς χρήστες.
Insert → Shapes → Rectangle, ρίξτε ένα στο φύλλο, ονομάστε το «Sync to Brevo». Δεξί κλικ στο σχήμα → Assign Macro → επιλέξτε SyncSheetToBrevo. Έτοιμο.
Ή, για πιο γυαλισμένο UI, προσθέστε προσαρμοσμένη καρτέλα ribbon μέσω του Office Custom UI Editor, αλλά για τα περισσότερα εσωτερικά εργαλεία, το σχήμα-ως-κουμπί είναι αρκετό.
Βήμα 6: Εκτελέστε το
Κάντε κλικ στο κουμπί. Η μακροεντολή διαβάζει τις γραμμές, τις δημιουργεί σε batches, κάνει POST κάθε batch στο Brevo και εμφανίζει ένα συνοπτικό message box. Η εισαγωγή του Brevo είναι ασύγχρονη, οπότε το μήνυμα επιτυχίας σημαίνει «Το Brevo αποδέχθηκε το batch», η πραγματική δημιουργία επαφών συμβαίνει στην πλευρά του server τα επόμενα δευτερόλεπτα. Θα λάβετε email σύνοψης από το Brevo όταν τελειώσει (εκτός αν ορίσετε disableNotification: true).
Συνηθισμένες παγίδες
Το κουμπί δεν κάνει τίποτα και δεν υπάρχει σφάλμα. Οι μακροεντολές είναι απενεργοποιημένες. Δείτε την κίτρινη μπάρα ασφαλείας στην κορυφή του φύλλου, κάντε κλικ Enable Content. Αν ο οργανισμός σας μπλοκάρει μακροεντολές, δείτε τη διαδρομή trust-center / code-signing παρακάτω.
Compile error: User-defined type not defined. Είστε σε Mac Excel, που δεν έχει MSXML2.XMLHTTP. Το Mac VBA δεν μπορεί να κάνει HTTPS αιτήματα απευθείας, χρησιμοποιήστε τη διαδρομή Office Scripts παρακάτω.
400 Bad Request από το Brevo χωρίς προφανή αιτία. Σχεδόν πάντα ένα από: (α) ένα προσαρμοσμένο attribute στο φύλλο σας δεν υπάρχει ακόμα στο Brevo, δημιουργήστε το πρώτα; (β) bug JSON escaping, εισαγωγικά ή backslashes σε τιμές κελιών που δεν έγιναν escape. Η συνάρτηση EscapeJson στον κώδικα χειρίζεται τις τυπικές περιπτώσεις, αν τα δεδομένα σας έχουν περίεργους χαρακτήρες, καταγράψτε το payload στο Immediate window (Debug.Print payload) και ελέγξτε.
401 Unauthorized. Λάθος header. Είναι api-key (πεζά γράμματα, παύλα), όχι Authorization. Η μακροεντολή χρησιμοποιεί τη σωστή, αλλά αν αντιγράψατε snippet από αλλού, ξανατσεκάρετε.
Το Excel παγώνει σε μεγάλες εισαγωγές. Η μακροεντολή τρέχει σύγχρονα στο νήμα UI. Για 50.000+ γραμμές, θα δείτε το Excel να κρέμεται για 10 έως 30 δευτερόλεπτα ενώ χτίζει το JSON και περιμένει το Brevo. Είτε αποδεχτείτε το, είτε αλλάξτε το MSXML2.XMLHTTP στην ασύγχρονη παραλλαγή του, αλλά σε αυτή την κλίμακα είστε καλύτερα στο Power Automate (επόμενη ενότητα).
Όταν το VBA δεν είναι αρκετό: Office Scripts + Power Automate
Το VBA δεν μπορεί να κάνει προγραμματισμένο cloud συγχρονισμό. Αν χρειάζεστε:
- Το workbook να συγχρονίζεται με το Brevo κάθε ώρα χωρίς να το ανοίγει κανείς
- Το workbook σε OneDrive/SharePoint, επεξεργασμένο από web
- Τμήμα IT που απαγορεύει desktop μακροεντολές
…τότε θέλετε Office Scripts (το cloud ισοδύναμο της Microsoft για το Apps Script) συν Power Automate (το επίπεδο προγραμματισμού και HTTP τους).
Ο διαχωρισμός: το Office Scripts διαβάζει το φύλλο και επιστρέφει τα δεδομένα επαφών. Το Power Automate παίρνει αυτά τα δεδομένα και τα κάνει POST στο Brevo σε ένα trigger.
Το Office Script (Excel για το 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;}Το flow Power Automate:
- Trigger: Recurrence (κάθε 1 ώρα), ή χειροκίνητο κουμπί, ή «When a row is modified» αν θέλετε συγχρονισμό βασισμένο σε αλλαγές.
- Action: Excel Online → Run script, στρέψτε το στο workbook σας και το script παραπάνω. Αποθηκεύστε την επιστρεφόμενη τιμή ως
contacts. - Action: HTTP (αυτός είναι ο Premium connector, δείτε τη σημείωση αδειοδότησης παρακάτω).
- 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 → αν ο status code ≠ 202, στείλτε ειδοποίηση Teams/email.
Έλεγχος πραγματικότητας αδειοδότησης: η ενέργεια HTTP είναι Premium connector του Power Automate. Στα πλάνα Microsoft 365 Business Basic/Standard παίρνετε τους standard connectors αλλά όχι το Premium. Η φθηνότερη λύση είναι το πρόσθετο Power Automate Premium (~15 USD/χρήστη/μήνα τη στιγμή της συγγραφής), ή μετακινήστε το HTTP σε μια μικρή Azure Function που το standard flow μπορεί να καλέσει. Αν ήδη είστε σε E3/E5 με Premium συμπεριλαμβανόμενο, είστε έτοιμοι.
Αυτός είναι ο κύριος λόγος που η ιστορία του Apps Script είναι πιο καθαρή: το UrlFetchApp του Apps Script είναι δωρεάν και χωρίς περιορισμούς, ενώ το ισοδύναμο της Microsoft βάζει την κλήση δικτύου πίσω από επί πληρωμή connector tier.
VBA έναντι Office Scripts έναντι Apps Script: πότε επιλέγετε τι
| Ανάγκη | Καλύτερη επιλογή |
|---|---|
| Κουμπί ενός κλικ σε workbook που η ομάδα σας ήδη ανοίγει καθημερινά | Μακροεντολή VBA (αυτός ο οδηγός, πάνω μισό) |
| Workbook σε OneDrive/SharePoint, ωριαίος αυτόματος συγχρονισμός | Office Scripts + Power Automate (χρειάζεται Premium για HTTP) |
| Μόνο Mac Excel, δεν μπορείτε να χρησιμοποιήσετε VBA | Office Scripts + Power Automate |
| Τα δεδομένα ζουν στο Google Sheets, όχι στο Excel | Apps Script (δωρεάν, προγραμματισμένα triggers ενσωματωμένα) |
| Εφάπαξ εισαγωγή, δεν θα τη χρειαστείτε ξανά | Save As → CSV και χρησιμοποιήστε το script εισαγωγής CSV |
| Μαζική εισαγωγή από αρχείο >10 MB | CSV με fileUrl, δείτε τον οδηγό CSV |
Γιατί αυτό κερδίζει τα Zapier / no-code πλατφόρμες
Για επαναλαμβανόμενη εργασία Excel σε Brevo, εργαλεία αυτοματισμού τρίτων (Zapier, Make, n8n) χρεώνουν ανά task και βάζουν τρίτο μεταξύ των δεδομένων σας και του Brevo. Η προσέγγιση VBA έχει μηδενικό συνεχιζόμενο κόστος, χωρίς ροή δεδομένων τρίτων, και ζει μέσα στο αρχείο, όταν το workbook μετακινείται, η ενσωμάτωση μετακινείται μαζί. Το Office Scripts + Power Automate είναι παρόμοιο αλλά με τη Microsoft ως τρίτο (ήδη στο stack σας αν είστε σε M365).
Όλο το νόημα του endpoint POST /v3/contacts/import του Brevo είναι ότι δεν χρειάζεστε μια κολλητική πλατφόρμα, τα εργαλεία σας ήδη ξέρουν πώς να κάνουν HTTP αιτήματα.