Sap gui scripting
23 SAP development skills for Claude Code — ABAP, RAP, CAP, Fiori, BTP, HANA, S/4HANA, Integration Suite and more. Agent Skills Specification compatible.
npx -y skills add efeumutaslan/SAP-SKILLS --skill sap-gui-scriptingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
SAP GUI Scripting automation skill. Use when automating SAP GUI transactions with VBScript or Python, recording/replaying scripts, batch data entry, or screen scraping SAP screens. If the user mentions SAP GUI automation, GUI scripting, VBScript for SAP, transaction recording, or RPA with SAP GUI, use this skill.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
11.4 KB, as published. Nobody here has run it
SAP GUI Scripting & Automation
Related Skills
sap-build-process-automation— Desktop Agent uses GUI scripting under the hoodsap-testing-quality— Automated GUI testing with eCATT/CBTAsap-s4hana-extensibility— When to use API vs. GUI scripting
Quick Start
Prerequisites:
- Enable scripting on SAP server:
RZ11→ parametersapgui/user_scripting=TRUE - Enable on client: SAP GUI → Options → Accessibility & Scripting → Enable scripting
- Disable notification popups: uncheck "Notify when script attaches" and "Notify when script opens connection"
Record your first script:
- Open SAP GUI → transaction you want to automate
- Menu: Customize Local Layout (Alt+F12) → Script Recording and Playback
- Click Record, perform actions, click Stop
- Save as
.vbsfile — this is your starting template
Minimal VBScript — Run Transaction:
If Not IsObject(application) Then
Set SapGuiAuto = GetObject("SAPGUI")
Set application = SapGuiAuto.GetScriptingEngine
End If
Set connection = application.Children(0)
Set session = connection.Children(0)
session.findById("wnd[0]/tbar[0]/okcd").text = "/nMM03"
session.findById("wnd[0]").sendVKey 0
session.findById("wnd[0]/usr/ctxtRMMG1-MATNR").text = "MAT-001"
session.findById("wnd[0]").sendVKey 0
Core Concepts
Object Hierarchy
GuiApplication
└── GuiConnection (SAP system connection)
└── GuiSession (user session / window)
└── GuiFrameWindow (wnd[0], wnd[1]...)
├── GuiToolbar (tbar[0] = command, tbar[1] = app)
├── GuiUserArea (usr/)
│ ├── GuiTextField, GuiCTextField
│ ├── GuiComboBox, GuiCheckBox, GuiRadioButton
│ ├── GuiTableControl, GuiGridView (ALV)
│ ├── GuiTab, GuiTabStrip
│ └── GuiTree
├── GuiStatusbar (sbar/)
└── GuiTitlebar (titl/)
Element ID Pattern
Format: wnd[N]/area/type[row,col]
wnd[0]/tbar[0]/okcd— Command field (OKCode)wnd[0]/usr/ctxtFIELD-NAME— Context field (F4 help available)wnd[0]/usr/txtFIELD-NAME— Text input fieldwnd[0]/usr/chkFIELD-NAME— Checkboxwnd[0]/usr/radFIELD-NAME— Radio buttonwnd[0]/usr/btnBUTTON-NAME— Push buttonwnd[0]/usr/tblTABLE/ctxtFIELD[row,col]— Table cellwnd[0]/usr/cntlGRID/shellcont/shell— ALV Grid controlwnd[0]/sbar— Status bar (messages)
Virtual Keys (sendVKey)
| Key | Code | Description |
|---|---|---|
| Enter | 0 | Confirm/execute |
| F2 | 2 | Choose/display |
| F3 | 3 | Back |
| F5 | 5 | Refresh |
| F8 | 8 | Execute report |
| F12 | 12 | Cancel |
| Shift+F4 | 16 | Save as variant |
| Ctrl+S | 11 | Save |
| Ctrl+Shift+F3 | 43 | Delete |
Common Patterns
Pattern 1: Python Automation with win32com
import win32com.client
import time
def get_sap_session():
"""Connect to running SAP GUI session."""
sap_gui = win32com.client.GetObject("SAPGUI")
app = sap_gui.GetScriptingEngine
connection = app.Children(0)
session = connection.Children(0)
return session
def run_transaction(session, tcode):
"""Navigate to transaction."""
session.findById("wnd[0]/tbar[0]/okcd").text = f"/n{tcode}"
session.findById("wnd[0]").sendVKey(0)
def get_status_message(session):
"""Read status bar message."""
sbar = session.findById("wnd[0]/sbar")
return {
"type": sbar.MessageType, # S=Success, E=Error, W=Warning, I=Info
"text": sbar.Text
}
Pattern 2: Table Data Extraction
def extract_alv_grid(session, grid_id="wnd[0]/usr/cntlGRID/shellcont/shell"):
"""Extract all data from ALV grid."""
grid = session.findById(grid_id)
columns = grid.ColumnCount
rows = grid.RowCount
col_names = [grid.GetColumnTitles(i) for i in range(columns)]
data = []
for row in range(rows):
grid.SetCurrentCell(row, grid.GetColumnName(0))
record = {}
for col in range(columns):
col_name = grid.GetColumnName(col)
record[col_name] = grid.GetCellValue(row, col_name)
data.append(record)
return data
def extract_table_control(session, table_id):
"""Extract data from classic table control (scroll-aware)."""
table = session.findById(table_id)
all_rows = []
visible = table.VisibleRowCount
total = table.RowCount
for offset in range(0, total, visible):
table.VerticalScrollbar.Position = offset
for row in range(min(visible, total - offset)):
row_data = {}
for col in range(table.Columns.Count):
cell = table.GetCell(row, col)
row_data[table.Columns(col).Name] = cell.Text
all_rows.append(row_data)
return all_rows
Pattern 3: Batch Data Entry (e.g., Mass Material Change)
def mass_material_change(session, materials):
"""Change multiple materials via MM02."""
results = []
for mat in materials:
run_transaction(session, "MM02")
session.findById("wnd[0]/usr/ctxtRMMG1-MATNR").text = mat["matnr"]
session.findById("wnd[0]").sendVKey(0)
# Select views
for view in session.findById("wnd[0]/usr/tabsTABSPR1").Children:
if hasattr(view, "Selected"):
view.Selected = view.Text in mat.get("views", ["Basic Data 1"])
session.findById("wnd[0]").sendVKey(0)
# Update fields
for field_id, value in mat.get("fields", {}).items():
try:
session.findById(field_id).text = value
except Exception as e:
results.append({"matnr": mat["matnr"], "status": "ERROR", "msg": str(e)})
session.findById("wnd[0]").sendVKey(12) # Cancel
continue
session.findById("wnd[0]").sendVKey(11) # Ctrl+S
msg = get_status_message(session)
results.append({"matnr": mat["matnr"], "status": msg["type"], "msg": msg["text"]})
return results
Pattern 4: Handle Popups and Modal Dialogs
def handle_popup(session, action="confirm"):
"""Handle unexpected popup windows."""
try:
popup = session.findById("wnd[1]")
if action == "confirm":
popup.findById("wnd[1]/usr/btnBUTTON_1").press() # Yes/OK
elif action == "cancel":
popup.findById("wnd[1]/usr/btnBUTTON_2").press() # No/Cancel
elif action == "close":
popup.Close()
return True
except Exception:
return False # No popup present
def safe_action(session, action_func, max_popups=3):
"""Execute action and handle any resulting popups."""
action_func()
for _ in range(max_popups):
time.sleep(0.3)
if not handle_popup(session, "confirm"):
break
Pattern 5: Login Automation
def login_sap(system, client, user, password, language="EN"):
"""Open new SAP GUI connection and login."""
import subprocess
sap_logon = r"C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe"
subprocess.Popen([sap_logon])
time.sleep(3)
sap_gui = win32com.client.GetObject("SAPGUI")
app = sap_gui.GetScriptingEngine
connection = app.OpenConnection(system, True)
session = connection.Children(0)
session.findById("wnd[0]/usr/txtRSYST-MANDT").text = client
session.findById("wnd[0]/usr/txtRSYST-BNAME").text = user
session.findById("wnd[0]/usr/pwdRSYST-BCODE").text = password
session.findById("wnd[0]/usr/txtRSYST-LANGU").text = language
session.findById("wnd[0]").sendVKey(0)
# Handle multiple logon popup
handle_popup(session, "confirm")
return session
Pattern 6: Error-Resilient Script Template
import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
log = logging.getLogger("sap_script")
def run_with_retry(session, func, max_retries=3, *args, **kwargs):
"""Run GUI action with retry on transient errors."""
for attempt in range(max_retries):
try:
result = func(session, *args, **kwargs)
msg = get_status_message(session)
if msg["type"] == "E":
log.warning(f"Attempt {attempt+1}: SAP error: {msg['text']}")
if attempt < max_retries - 1:
session.findById("wnd[0]").sendVKey(3) # Back
continue
return result
except Exception as e:
log.error(f"Attempt {attempt+1}: Exception: {e}")
if attempt == max_retries - 1:
raise
return None
Error Catalog
| Error | Message | Root Cause | Fix |
|---|---|---|---|
Runtime error: -2147352567 | Object not found | Element ID wrong or screen changed | Use Script Recorder to get correct ID |
Scripting disabled | Server rejected script | sapgui/user_scripting = FALSE | Set via RZ11 or profile parameter |
No SAP GUI instance | GetObject failed | SAP GUI not running | Start SAP GUI before script |
Session busy | Cannot attach | Transaction is processing | Add time.sleep() before action |
Modal dialog open | Cannot access main window | Popup blocking | Handle wnd[1] before wnd[0] |
ALV: Invalid cell | GetCellValue error | Row index out of range | Check RowCount before access |
Multiple logon | Popup at login | User already logged in | Handle popup or close other session |
Authorization | No authorization for scripting | Missing S_SCR auth object | Assign auth via SU01/role |
Performance Tips
- Disable screen updates — Not natively supported; minimize visual impact by running in background session
- Batch via BDC/BAPI first — GUI scripting is last resort; prefer RFC/BAPI/OData for bulk operations
- Reuse sessions — Don't login/logout per record; reuse connection for batch processing
- Minimize findById calls — Cache element references:
field = session.findById(...)then reusefield - Handle scrolling — For table controls, read
VisibleRowCountand scroll incrementally - Parallel sessions — SAP allows up to 6 sessions per user; parallelize with
connection.Children(N) - Avoid hardcoded waits — Use status bar checks instead of fixed
time.sleep()where possible
Gotchas
- Screen variants: Same transaction can show different screens based on user settings — always verify screen number
- Language dependency: Element IDs can differ by logon language for some older transactions
- ALV vs. Table Control:
GuiGridView(ALV) andGuiTableControlhave completely different APIs - SAP GUI version: Scripting API changes between versions; test on target version
- Security policy: Many organizations disable scripting in production — always check policy
- 64-bit Python + 32-bit SAP GUI: COM interop may fail; use matching architecture