📤 Split & Send
IT EN

Macro VBA: dividere un foglio Excel in file separati per valore di colonna

Quasi tutte le macro che si trovano per questo scopo aggiungono un foglio per valore dentro lo stesso file. Se invece ti serve un .xlsx salvato per ogni regione, cliente o fornitore, qui trovi una routine che fa esattamente questo — e l'elenco onesto di ciò che ti lascia comunque da fare a mano.

La macro

Premi Alt+F11, poi Inserisci → Modulo, e incolla entrambe le procedure. Imposta splitCol sul numero della colonna con cui dividere: la colonna B è 2, la colonna D è 4.

Sub SplitToFilesByColumn()
    Dim wsData As Worksheet, wsNew As Worksheet, wbNew As Workbook
    Dim lastRow As Long, lastCol As Long, i As Long
    Dim splitCol As Long, savePath As String, n As Long
    Dim dict As Object, key As Variant

    splitCol = 2                                   ' <-- colonna di divisione
    Set wsData = ActiveSheet
    savePath = ThisWorkbook.Path & "\split\"

    lastRow = wsData.Cells(wsData.Rows.Count, splitCol).End(xlUp).Row
    lastCol = wsData.Cells(1, wsData.Columns.Count).End(xlToLeft).Column
    If lastRow < 2 Then MsgBox "Nessun dato trovato.": Exit Sub
    If Dir(savePath, vbDirectory) = "" Then MkDir savePath

    ' 1. raccoglie i valori unici della colonna
    Set dict = CreateObject("Scripting.Dictionary")
    For i = 2 To lastRow
        key = Trim(CStr(wsData.Cells(i, splitCol).Value))
        If Len(key) > 0 Then dict(key) = 1
    Next i

    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

    ' 2. una copia filtrata per valore, salvata come file a sé
    For Each key In dict.Keys
        Set wbNew = Workbooks.Add(xlWBATWorksheet)
        Set wsNew = wbNew.Worksheets(1)

        If wsData.AutoFilterMode Then wsData.AutoFilterMode = False
        wsData.Range(wsData.Cells(1, 1), wsData.Cells(lastRow, lastCol)) _
               .AutoFilter Field:=splitCol, Criteria1:=key

        wsData.Rows(1).Copy wsNew.Rows(1)
        On Error Resume Next
        wsData.Range(wsData.Cells(2, 1), wsData.Cells(lastRow, lastCol)) _
               .SpecialCells(xlCellTypeVisible).Copy wsNew.Cells(2, 1)
        On Error GoTo 0

        wbNew.SaveAs savePath & SafeFileName(CStr(key)) & ".xlsx", xlOpenXMLWorkbook
        wbNew.Close SaveChanges:=False
        n = n + 1
    Next key

    If wsData.AutoFilterMode Then wsData.AutoFilterMode = False
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    MsgBox n & " file salvati in " & savePath
End Sub

Function SafeFileName(s As String) As String
    Dim bad As Variant, ch As Variant
    bad = Array("\", "/", ":", "*", "?", """", "<", ">", "|")
    For Each ch In bad
        s = Replace(s, ch, "_")
    Next ch
    SafeFileName = Left(Trim(s), 100)
End Function
  1. Salva prima il file come .xlsm — un .xlsx normale non può contenere macro.
  2. Seleziona il foglio con i dati, con le intestazioni nella riga 1.
  3. Premi F5 dentro l'editor. I file compaiono nella sottocartella split accanto al tuo documento.

La prima volta eseguila su una copia. La macro attiva e disattiva i filtri sul foglio vero. Non cancella nulla, ma una prova su un duplicato costa poco.

Cosa la macro non risolve

La routine qui sopra è la metà facile. Tre cose restano sulle tue spalle, e sono il motivo per cui questo lavoro continua a portare via una mattinata.

LimiteCosa significa in pratica
Non invia nullaDevi comunque allegare venti file a venti messaggi quasi identici, ognuno a un indirizzo diverso. Aggiungere l'automazione di Outlook è un secondo progetto, per giunta fragile.
L'impaginazione si perde in parteLa formattazione delle celle viaggia con le righe copiate. Larghezze delle colonne, riquadri bloccati e formattazione condizionale no, a meno di scrivere codice apposta per ciascuno.
Le macro sono spesso bloccateMolte aziende bloccano le macro nei file ricevuti dall'esterno. Il collega a cui passi il documento potrebbe semplicemente non riuscire a eseguirla.

C'è poi la manutenzione: se qualcuno inserisce una colonna, splitCol = 2 punta in silenzio ai dati sbagliati, e la macro continua a girare senza protestare.

Quando il VBA è comunque la risposta giusta

Se la divisione gira senza presidio a orari stabiliti, vive dentro una macro più grande che già mantieni, o deve funzionare su una macchina senza accesso a internet, il VBA è lo strumento corretto e il codice qui sopra è un punto di partenza ragionevole.

Quando non lo è

Se stai scrivendo questa macro perché ogni settimana devi fare la stessa divisione e poi mandare ogni parte a una persona diversa, stai per costruire la metà facile e tenerti la metà noiosa. Split & Send fa entrambe in un colpo solo: scegli la colonna e ottieni un file formattato per ogni valore e una bozza email pronta per ciascuno — destinatario giusto, messaggio scritto una volta sola, file già allegato. Funziona nel browser, senza macro e senza installare nulla, e il tuo file non viene caricato da nessuna parte.

Non viene inviato nulla in automatico: le bozze finiscono nel tuo client di posta e le controlli prima che partano.

Provalo col tuo file — gratis, senza registrazione →

Domande frequenti

Perché la mia macro crea fogli invece di file?

Quasi tutti gli esempi online aggiungono un foglio per valore dentro lo stesso documento. Per ottenere file separati serve un nuovo oggetto Workbook per ogni valore e una chiamata a SaveAs, come nella routine qui sopra.

La macro mantiene la formattazione originale?

In parte. Copiando le righe la formattazione delle celle viene con loro, ma larghezze delle colonne, riquadri bloccati, formattazione condizionale e impostazione generale del foglio non vengono riprodotti se non li copi esplicitamente.

La macro può inviare ogni file a una persona diversa?

Da sola no. Dovresti aggiungere l'automazione di Outlook: un riferimento al modello a oggetti di Outlook e il codice che associa ogni valore a un indirizzo. Funziona, ma è un secondo progetto da scrivere e da mantenere.

E se in azienda le macro sono bloccate?

Succede spesso, e di solito viene fuori quando passi il file a un collega. Uno strumento nel browser non richiede alcuna macro, quindi non c'è niente da sbloccare.

Posso dividere per più di una colonna?

Con il VBA sì: costruisci la chiave del dizionario unendo i valori delle due celle con un separatore, e nel ciclo usa due criteri di filtro. È una modifica piccola al codice qui sopra.

Correlato: Dividere un Excel per colonna e inviare ogni parte · Stampa unione con un allegato diverso per ogni destinatario.