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.
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
| Scenario | Consigliato? | Motivo |
|---|---|---|
| Prototipo veloce, pochi campi da più transazioni | Sì | Velocissimo da mettere in piedi, nessuna infrastruttura aggiuntiva |
| Report periodico per 100–500 righe | Sì, con cautela | Affidabile se ben scritto e stabile nel tempo |
| Estrazioni massive (migliaia di record) | No | Meglio BAPI/RFC, OData, BW/4HANA, Analysis for Office |
| Ambiente regolato con forte governance | Di solito no | Preferire 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 = TRUEdeve 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.
| Colonna | Contenuto | Esempio |
|---|---|---|
| A | Materiale (MATNR) | 10000001 |
| B | Descrizione (output) | (riempita dalla macro) |
| C (opz.) | Stato/Log | OK / Errore |
Abilitare SAP GUI Scripting
- Apri SAP Logon e connettiti a un sistema.
- Vai in Options ▸ Accessibility & Scripting ▸ Scripting.
- Spunta Enable scripting. Se è disabilitata forzatamente, chiedi al Basis di impostare
sapgui/user_scripting = TRUEsul 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
- Avvia SAP Logon e accedi al sistema.
- Apri Excel, salva il file come .xlsm.
- Inserisci un modulo standard (VBA) e incolla il codice qui sotto.
- Personalizza gli ID dei campi servendoti del Script Recording di SAP GUI (vedi sezione dedicata).
- 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:
- In SAP, attiva Customize Local Layout ▸ Script Recording and Playback.
- Premi Record, compi manualmente i passaggi (inserisci materiale, apri scheda, ecc.).
- Ferma la registrazione e apri il file generato: vedrai le chiamate
findById(...)con gli ID esatti. - Sostituisci nel codice gli ID di esempio con i tuoi descIds e l’ID del campo materiale se differente.
Esecuzione e verifica
- Apri SAP Logon e collegati al sistema corretto (stesso mandante in cui hai registrato gli ID).
- Compila colonna A con i codici materiale a partire da A2.
- Esegui ReadFromSAP (ALT+F8 → seleziona macro → Esegui).
- Osserva SAP mentre la macro esegue i passaggi; i risultati compariranno in colonna B.
- 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
WaitReadyo inserisci breviApplication.Waittra 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 GoToe 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
| Caratteristica | GUI Scripting (VBA) | OData / BAPI / BW |
|---|---|---|
| Tempo di avvio | Minuti/ore | Giorni/settimane (setup) |
| Robustezza | Media (sensibile a cambi GUI) | Alta (contratti stabili) |
| Prestazioni su grandi volumi | Basse | Alte |
| Sicurezza/Governance | Bassa–media | Alta |
| Flessibilità | Molto alta (qualsiasi transazione) | Media (entità esposte) |
Modello di progetto consigliato
- Allineamento IT: chiarisci policy scripting, mandanti abilitati e responsabilità.
- Prototipo rapido: implementa la macro con 2–3 campi chiave.
- Stabilizzazione: sostituisci gli ID “fragili”, aggiungi retry e logging.
- 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
- Attiva SAP GUI Scripting in SAP Logon; chiedi al Basis
sapgui/user_scripting = TRUEsul server. - Avvia SAP Logon e collegati al sistema.
- Prepara il foglio Excel (colonna A materiali; B risultati; C log).
- Incolla il codice, registra e sostituisci gli ID dei campi con quelli del tuo sistema.
- 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).
