Excel e SAP: leggere dati da SAP con VBA (SAP GUI Scripting) – guida completa

Vuoi far aggiornare un foglio Excel leggendo automaticamente i dati da SAP? Non esiste una formula di cella per farlo, ma puoi ottenere il risultato in modo affidabile usando SAP GUI Scripting con una macro VBA. Qui trovi la guida completa, codice pronto e alternative più governate.

Indice

Perché non esiste un “comando di cella” per interrogare SAP da Excel

Excel non espone un connettore nativo che consenta a una cella di eseguire una transazione SAP e restituire un valore, come farebbe una formula con un database ODBC. SAP, a sua volta, non espone l’interfaccia delle transazioni SAP GUI come funzione chiamabile da Excel. Ecco perché non esiste una formula nativa (ad es. =SAP.LEGGI(…)) per leggere direttamente da SAP.

La via più veloce e controllabile è SAP GUI Scripting: una tecnologia ufficiale del client SAP GUI che consente di automatizzare le azioni dell’interfaccia (aprire una transazione, inserire valori, premere pulsanti, leggere campi) tramite VBA in Excel. È particolarmente utile per prototipi, estrazioni mirate e piccoli report.

Quando scegliere SAP GUI Scripting e quando no

ScenarioConsigliato?Motivo
Prototipo veloce, pochi campi da più transazioniVelocissimo da mettere in piedi, nessuna infrastruttura aggiuntiva
Report periodico per 100–500 righeSì, con cautelaAffidabile se ben scritto e stabile nel tempo
Estrazioni massive (migliaia di record)NoMeglio BAPI/RFC, OData, BW/4HANA, Analysis for Office
Ambiente regolato con forte governanceDi solito noPreferire integrazioni ufficiali e tracciate

Prerequisiti e sicurezza

  • Autorizzazioni: il tuo utente SAP deve poter accedere alle transazioni/valori richiesti.
  • Abilitazione client: in SAP Logon → Options ▸ Accessibility & Scripting ▸ Scripting attiva Enable Scripting.
  • Abilitazione server: il parametro di profilo sapgui/user_scripting = TRUE deve essere impostato dal team Basis.
  • Client SAP avviato: la macro si collega a una sessione già aperta. Se SAP Logon non è avviato e connesso, lo script fallisce.
  • Excel: macro abilitate (cartella .xlsm) e, se necessario, Trust access to the VBA project object model attivo nelle opzioni di sicurezza.
  • 32/64 bit: il codice qui proposto usa late binding ed è compatibile con Office 32/64 bit senza riferimenti COM aggiuntivi.

Struttura consigliata del foglio Excel

Per l’esempio, supponiamo di voler leggere la descrizione materiale dalla transazione MM03.

ColonnaContenutoEsempio
AMateriale (MATNR)10000001
BDescrizione (output)(riempita dalla macro)
C (opz.)Stato/LogOK / Errore

Abilitare SAP GUI Scripting

  1. Apri SAP Logon e connettiti a un sistema.
  2. Vai in Options ▸ Accessibility & Scripting ▸ Scripting.
  3. Spunta Enable scripting. Se è disabilitata forzatamente, chiedi al Basis di impostare sapgui/user_scripting = TRUE sul server di applicazione.

Nota sicurezza: molte aziende disattivano lo scripting per policy. Concorda con il team IT quando usarlo e su quali sistemi (dev/test vs prod).

Approccio passo–passo

  1. Avvia SAP Logon e accedi al sistema.
  2. Apri Excel, salva il file come .xlsm.
  3. Inserisci un modulo standard (VBA) e incolla il codice qui sotto.
  4. Personalizza gli ID dei campi servendoti del Script Recording di SAP GUI (vedi sezione dedicata).
  5. Esegui la macro principale: leggerà ogni materiale in colonna A e scriverà il risultato in colonna B.

Macro VBA completa (template pronto)

Il codice seguente implementa:

  • connessione alla sessione SAP già aperta (GetObject("SAPGUI"));
  • apertura MM03, inserimento del materiale, lettura della descrizione;
  • loop su tutte le righe valorizzate in colonna A;
  • gestione errori, attese, logging.
' ===== modSapRead.bas =====
Option Explicit

' Configurazione foglio e colonne
Private Const SHEETNAME As String = "SAPRead"
Private Const COL_INPUT As Long = 1     ' A: Materiale
Private Const COL_OUTPUT As Long = 2    ' B: Descrizione
Private Const COL_STATUS As Long = 3    ' C: Log/Stato (opzionale)

' --- Macro principale ---
Public Sub ReadFromSAP()
    On Error GoTo EH

    Dim ws As Worksheet
    Set ws = EnsureSheet(SHEET_NAME)

    Dim sess As Object
    Set sess = GetSapSession() ' richiede SAP GUI aperto

    Dim lastRow As Long
    lastRow = LastUsedRow(ws, COL_INPUT)
    If lastRow < 2 Then
        MsgBox "Nessun materiale trovato in colonna A.", vbInformation
        Exit Sub
    End If

    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual

    Dim i As Long, matnr As String, descText As String, ok As Boolean
    For i = 2 To lastRow
        matnr = Trim$(CStr(ws.Cells(i, COL_INPUT).Value))
        If Len(matnr) = 0 Then GoTo NextRow

        ws.Cells(i, COL_STATUS).Value = "In corso..."
        ok = False

        descText = FetchMaterialDescription(sess, matnr, ok)

        If ok Then
            ws.Cells(i, COL_OUTPUT).Value = descText
            ws.Cells(i, COL_STATUS).Value = "OK"
        Else
            ws.Cells(i, COL_STATUS).Value = "Errore"
        End If

NextRow:
        DoEvents
    Next i

    MsgBox "Lettura completata.", vbInformation

CleanExit:
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True
    Exit Sub

EH:
    MsgBox "Errore: " & Err.Number & " - " & Err.Description, vbExclamation, "ReadFromSAP"
    Resume CleanExit
End Sub

' --- Funzione: recupera la descrizione materiale da MM03 ---
Private Function FetchMaterialDescription(ByVal sess As Object, _
                                          ByVal matnr As String, _
                                          ByRef success As Boolean) As String
    On Error GoTo EH
    success = False

    ' Apre la transazione
    sess.StartTransaction "MM03"
    WaitReady sess

    ' Prova a valorizzare il campo Materiale (ID variabili tra sistemi)
    Dim idCandidates As Variant
    idCandidates = Array( _
        "wnd[0]/usr/ctxtRMMG1-MATNR", _
        "wnd[0]/usr/ctxtRM-MATNR", _
        "wnd[0]/usr/ctxtMARA-MATNR", _
        "wnd[0]/usr/ctxtSAPLMGMM:0010:RM-MATNR" _
    )
    If Not TrySetTextByIds(sess, idCandidates, matnr) Then
        Err.Raise vbObjectError + 100, , "Campo MATNR non trovato."
    End If

    ' Conferma / Esegui (di solito Enter basta; in alternativa il tasto Esegui)
    TryPressIfExists sess, Array("wnd[0]/tbar[1]/btn[8]") ' Esegui
    PressEnter sess

    WaitReady sess

    ' A questo punto sei nella schermata anagrafica del materiale.
    ' Leggi la descrizione (sostituisci l'ID con quello del tuo sistema).
    Dim descIds As Variant
    descIds = Array( _
        "wnd[0]/usr/ctxtMAKT-MAKTX", _
        "wnd[0]/usr/txtMAKT-MAKTX", _
        "wnd[0]/usr/subD0110SUB:SAPLMGMM:0110/txtMAKT-MAKTX" _
    )
    Dim val As String
    val = TryReadTextByIds(sess, descIds)

    ' In alternativa, leggi la barra di stato se la descrizione non è disponibile
    If Len(val) = 0 Then val = GetStatusBarText(sess)

    ' Torna indietro/chiudi
    TryPressIfExists sess, Array("wnd[0]/tbar[0]/btn[3]") ' Indietro
    WaitReady sess

    success = Len(val) > 0
    FetchMaterialDescription = val
    Exit Function

EH:
    FetchMaterialDescription = ""
End Function

' --- Helpers SAP ---

' Ottiene una sessione SAP esistente (prima connessione / prima sessione)
Public Function GetSapSession() As Object
    On Error GoTo EH

    Dim SapGuiAuto As Object, app As Object, conn As Object, sess As Object
    Set SapGuiAuto = GetObject("SAPGUI")
    Set app = SapGuiAuto.GetScriptingEngine

    If app.Children.Count = 0 Then Err.Raise vbObjectError + 101, , "Nessuna connessione SAP aperta."
    Set conn = app.Children(0)

    If conn.Children.Count = 0 Then Err.Raise vbObjectError + 102, , "Nessuna sessione attiva."
    Set sess = conn.Children(0)

    Set GetSapSession = sess
    Exit Function

EH:
    Err.Raise Err.Number, "GetSapSession", Err.Description & " - Avvia SAP Logon e connettiti."
End Function

Private Sub PressEnter(ByVal sess As Object)
    On Error Resume Next
    sess.SendVKey 0 ' Enter
End Sub

Private Sub WaitReady(ByVal sess As Object)
    On Error Resume Next
    Dim t As Single: t = Timer
    Do
        DoEvents
        If Timer - t > 15 Then Exit Do
        ' In alternativa, controlla proprietà Busy se disponibile:
        ' If sess.findById("wnd[0]").Busy = False Then Exit Do
    Loop
End Sub

Private Function GetStatusBarText(ByVal sess As Object) As String
    On Error Resume Next
    GetStatusBarText = sess.findById("wnd[0]/sbar").Text
End Function

Private Function TrySetTextByIds(ByVal sess As Object, ByVal ids As Variant, ByVal text As String) As Boolean
    On Error Resume Next
    Dim i As Long
    For i = LBound(ids) To UBound(ids)
        Err.Clear
        sess.findById(ids(i)).Text = text
        If Err.Number = 0 Then
            TrySetTextByIds = True
            Exit Function
        End If
    Next i
    TrySetTextByIds = False
End Function

Private Function TryReadTextByIds(ByVal sess As Object, ByVal ids As Variant) As String
    On Error Resume Next
    Dim i As Long, tmp As String
    For i = LBound(ids) To UBound(ids)
        Err.Clear
        tmp = CStr(sess.findById(ids(i)).Text)
        If Err.Number = 0 And Len(tmp) > 0 Then
            TryReadTextByIds = tmp
            Exit Function
        End If
    Next i
    TryReadTextByIds = ""
End Function

Private Sub TryPressIfExists(ByVal sess As Object, ByVal ids As Variant)
    On Error Resume Next
    Dim i As Long
    For i = LBound(ids) To UBound(ids)
        Err.Clear
        sess.findById(ids(i)).Press
        If Err.Number = 0 Then Exit Sub
    Next i
End Sub

' --- Helpers Excel ---

Private Function EnsureSheet(ByVal name As String) As Worksheet
    On Error Resume Next
    Set EnsureSheet = ThisWorkbook.Worksheets(name)
    On Error GoTo 0
    If EnsureSheet Is Nothing Then
        Set EnsureSheet = ThisWorkbook.Worksheets.Add
        EnsureSheet.Name = name
        With EnsureSheet
            .Range("A1").Value = "Materiale (MATNR)"
            .Range("B1").Value = "Descrizione"
            .Range("C1").Value = "Stato"
        End With
    End If
End Function

Private Function LastUsedRow(ByVal ws As Worksheet, ByVal col As Long) As Long
    LastUsedRow = ws.Cells(ws.Rows.Count, col).End(xlUp).Row
End Function

Come personalizzare gli ID dei campi

Gli identificatori GUI (wnd[0]/usr/...) possono variare per lingua, versione e customizing. Per ottenere i tuoi:

  1. In SAP, attiva Customize Local Layout ▸ Script Recording and Playback.
  2. Premi Record, compi manualmente i passaggi (inserisci materiale, apri scheda, ecc.).
  3. Ferma la registrazione e apri il file generato: vedrai le chiamate findById(...) con gli ID esatti.
  4. Sostituisci nel codice gli ID di esempio con i tuoi descIds e l’ID del campo materiale se differente.

Esecuzione e verifica

  1. Apri SAP Logon e collegati al sistema corretto (stesso mandante in cui hai registrato gli ID).
  2. Compila colonna A con i codici materiale a partire da A2.
  3. Esegui ReadFromSAP (ALT+F8 → seleziona macro → Esegui).
  4. Osserva SAP mentre la macro esegue i passaggi; i risultati compariranno in colonna B.
  5. In caso di errori, consulta la colonna C (stato) e la barra di stato SAP.

Errori comuni e soluzioni

  • “SAPGUI non è in esecuzione”: devi avviare SAP Logon e aprire una sessione prima di lanciare Excel.
  • Campo non trovato: sostituisci gli ID con quelli registrati sul tuo sistema; verifica anche la lingua del client.
  • Schermate dinamiche: alcune transazioni variano campi in base a ruolo/plant. Registrale e gestisci condizioni (if) nel codice.
  • Timeout/tempi di caricamento: aumenta l’attesa in WaitReady o inserisci brevi Application.Wait tra i passaggi più lenti.
  • Focus perso: evita di usare il PC durante l’esecuzione e disattiva notifiche che rubano il focus; in alternativa, esegui su una VM dedicata.

Best practice di robustezza

  • Late binding: evita riferimenti COM fissi → macro più portabile tra PC.
  • Gestione errori centralizzata: usa On Error GoTo e log in colonna C o su un file di testo.
  • Selettori multipli: usa array di ID candidati (come nell’esempio) per sopravvivere a piccole differenze di GUI.
  • Transazioni idempotenti: preferisci transazioni di sola lettura (MM03, MM60, ecc.) per minimizzare i rischi.
  • Non salvare credenziali nel codice: l’autenticazione resta interattiva via SAP Logon.
  • Lotti piccoli: spezza le elaborazioni in blocchi (ad es. 200 materiali per volta) e inserisci brevi pause per non saturare il server.

Estendere l’esempio: più campi e più transazioni

Per aggiungere altri campi (es. Gruppo merce, Unità base) registra gli ID e aggiungi ulteriori TryReadTextByIds. Per un flusso più articolato (es. prezzo condizionale) puoi aprire una seconda transazione (ME13) e leggere il valore da una griglia o un campo testo seguendo la stessa tecnica.

Esempio: loop ottimizzato su elenco materiali

Public Sub ReadManyMaterials()
    Dim ws As Worksheet: Set ws = EnsureSheet(SHEET_NAME)
    Dim sess As Object: Set sess = GetSapSession()

Dim arrIn As Variant, arrOut() As Variant, arrLog() As Variant
Dim lastRow As Long: lastRow = LastUsedRow(ws, COL_INPUT)
If lastRow < 2 Then Exit Sub

arrIn = ws.Range(ws.Cells(2, COL_INPUT), ws.Cells(lastRow, COL_INPUT)).Value
ReDim arrOut(1 To UBound(arrIn, 1), 1 To 1)
ReDim arrLog(1 To UBound(arrIn, 1), 1 To 1)

Dim r As Long, ok As Boolean, d As String
For r = 1 To UBound(arrIn, 1)
    If Len(Trim$(CStr(arrIn(r, 1)))) > 0 Then
        d = FetchMaterialDescription(sess, CStr(arrIn(r, 1)), ok)
        arrOut(r, 1) = d
        arrLog(r, 1) = IIf(ok, "OK", "Errore")
    Else
        arrOut(r, 1) = ""
        arrLog(r, 1) = ""
    End If
    DoEvents
Next r

ws.Range(ws.Cells(2, COL_OUTPUT), ws.Cells(lastRow, COL_OUTPUT)).Value = arrOut
ws.Range(ws.Cells(2, COL_STATUS), ws.Cells(lastRow, COL_STATUS)).Value = arrLog

End Sub 

Checklist “prima di premere Esegui”

  • SAP Logon è aperto, connesso al mandante giusto?
  • Scripting attivato lato client e lato server?
  • Gli ID dei campi nel codice corrispondono a quelli registrati nel tuo sistema?
  • Hai inserito i materiali a partire da A2 e salvato il file .xlsm?
  • Hai chiuso finestre pop-up che possono interferire (aggiornamenti, notifiche)?

Alternative più sicure e scalabili

Per esigenze enterprise o volumi elevati, valuta approcci data-centric che evitano l’automazione della GUI:

  • OData Services (SAP Gateway / S4): esponi entità (es. prodotto, anagrafica materiali) e consumale da Power Query (Dati → Recupera Dati → Da feed OData), con refresh pianificabile e tracciabilità.
  • RFC/BAPI: usa connettori ufficiali (ad es. .NET Connector) o soluzioni low-code per invocare funzioni applicative e caricare i dati in tabelle Excel o database intermedio.
  • SAP BW/4HANA & Analysis for Office: reportistica governata, gerarchie, key figure calcolate e refresh certificato in Excel.
  • SAP Analytics Cloud: per dashboard e storicizzazioni con controlli di sicurezza e scheduling.

Queste alternative richiedono più setup ma garantiscono robustezza, sicurezza e prestazioni per scenari produttivi.

Domande frequenti

Posso usare una formula di Excel per leggere SAP?
No. Non esiste un comando nativo di cella. Serve uno script (GUI Scripting/VBA) o un’integrazione dati (OData/BAPI/BW).

La macro può aprire SAP in automatico?
No in modo affidabile. La macro si collega a una sessione già aperta. È una scelta consapevole per sicurezza e stabilità.

È sicuro su produzione?
Dipende dalle policy. Molte aziende consentono lo scripting solo su sistemi non produttivi. In produzione preferire integrazioni governate.

Funziona con Office 64 bit?
Sì. Il codice proposto usa late binding e non richiede dichiarazioni API PtrSafe.

Come trovo gli ID giusti dei campi?
Usa il registratore di script di SAP GUI. Riproduci i passi manuali e copia nel codice gli ID findById(...) che ti servono.

Esempio rapido di registrazione (per sostituire gli ID)

' Estratto tipico dal registratore SAP (solo come esempio)
Session.StartTransaction "MM03"
Session.findById("wnd[0]/usr/ctxtRMMG1-MATNR").Text = "10000001"
Session.findById("wnd[0]/tbar[1]/btn[8]").Press
' ... navigazione schede ...
Dim desc As String
desc = Session.findById("wnd[0]/usr/txtMAKT-MAKTX").Text

Questo estratto ti indica esattamente quali ID usare nelle funzioni TrySetTextByIds e TryReadTextByIds.

Performance e affidabilità: suggerimenti pratici

  • Scrivi in Excel a blocchi: come nell’esempio, carica gli input in un array e scrivi gli output in un’unica assegnazione Range. Eviterai rallentamenti.
  • Gestisci gli imprevisti: finestre pop-up (ad es. selezione vista, warning) possono interrompere la macro. In caso, intercetta la barra di stato e prova percorsi alternativi.
  • Documenta: metti commenti nel codice con la versione SAP, mandante e percorso delle transazioni usati per la registrazione. Tornerà utile durante aggiornamenti.
  • Testa per ruolo: alcuni campi sono visibili solo con certi ruoli. Verifica con gli utenti finali.

Confronto sintetico: GUI Scripting vs integrazioni dati

CaratteristicaGUI Scripting (VBA)OData / BAPI / BW
Tempo di avvioMinuti/oreGiorni/settimane (setup)
RobustezzaMedia (sensibile a cambi GUI)Alta (contratti stabili)
Prestazioni su grandi volumiBasseAlte
Sicurezza/GovernanceBassa–mediaAlta
FlessibilitàMolto alta (qualsiasi transazione)Media (entità esposte)

Modello di progetto consigliato

  1. Allineamento IT: chiarisci policy scripting, mandanti abilitati e responsabilità.
  2. Prototipo rapido: implementa la macro con 2–3 campi chiave.
  3. Stabilizzazione: sostituisci gli ID “fragili”, aggiungi retry e logging.
  4. Valutazione: se la soluzione inizia a scalare (più campi, più utenti, più volumi), pianifica la migrazione a OData/BAPI/Analysis for Office.

Conclusioni

Non esiste un comando di cella in Excel per interrogare SAP. La soluzione più pragmatica è combinare SAP GUI Scripting con una macro VBA, come mostrato nel codice pronto all’uso: con pochi passaggi puoi leggere valori puntuali (es. descrizione materiale) direttamente in Excel. Tieni però presente i limiti fisiologici dell’automazione di interfaccia e, per esigenze produttive o su larga scala, considera alternative più robuste come OData, BAPI/RFC, SAP BW/4HANA o Analysis for Office.


Riepilogo operativo veloce

  1. Attiva SAP GUI Scripting in SAP Logon; chiedi al Basis sapgui/user_scripting = TRUE sul server.
  2. Avvia SAP Logon e collegati al sistema.
  3. Prepara il foglio Excel (colonna A materiali; B risultati; C log).
  4. Incolla il codice, registra e sostituisci gli ID dei campi con quelli del tuo sistema.
  5. Esegui ReadFromSAP e verifica gli output.

Con questa impostazione avrai una pipeline leggera ma efficace per leggere da SAP “direttamente” in Excel, mantenendo il controllo sul flusso e sui rischi.

In sintesi: non esiste un comando nativo per interrogare SAP da Excel; la via pratica è SAP GUI Scripting + VBA per prototipi e report snelli, mentre per ambienti produttivi valutare metodi più robusti e governati (OData/BAPI/BW/Analysis for Office).

Indice