process-automation 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- process_automation-1.0.1/LICENSE +7 -0
- process_automation-1.0.1/PKG-INFO +133 -0
- process_automation-1.0.1/README.md +108 -0
- process_automation-1.0.1/functions/__init__.py +0 -0
- process_automation-1.0.1/functions/excel_macro.py +43 -0
- process_automation-1.0.1/functions/sap_connection.py +196 -0
- process_automation-1.0.1/functions/sap_extract.py +280 -0
- process_automation-1.0.1/functions/sharepoint_upload.py +180 -0
- process_automation-1.0.1/process_automation.egg-info/PKG-INFO +133 -0
- process_automation-1.0.1/process_automation.egg-info/SOURCES.txt +15 -0
- process_automation-1.0.1/process_automation.egg-info/dependency_links.txt +1 -0
- process_automation-1.0.1/process_automation.egg-info/requires.txt +8 -0
- process_automation-1.0.1/process_automation.egg-info/top_level.txt +3 -0
- process_automation-1.0.1/pyproject.toml +27 -0
- process_automation-1.0.1/setup.cfg +4 -0
- process_automation-1.0.1/tools/__init__.py +0 -0
- process_automation-1.0.1/tools/check_transactions.py +212 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright (c) 2026 Mircea Sava Ioan. All rights reserved.
|
|
2
|
+
|
|
3
|
+
This software is proprietary. No part of this software may be reproduced,
|
|
4
|
+
distributed, modified, or used in any form without prior written permission
|
|
5
|
+
from the copyright holder.
|
|
6
|
+
|
|
7
|
+
For licensing inquiries, contact the copyright holder.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: process-automation
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Automate SAP data extraction, SharePoint upload, and Excel macro execution
|
|
5
|
+
Author: Mircea Sava Ioan
|
|
6
|
+
License: Copyright (c) 2026 Mircea Sava Ioan. All rights reserved.
|
|
7
|
+
|
|
8
|
+
This software is proprietary. No part of this software may be reproduced,
|
|
9
|
+
distributed, modified, or used in any form without prior written permission
|
|
10
|
+
from the copyright holder.
|
|
11
|
+
|
|
12
|
+
For licensing inquiries, contact the copyright holder.
|
|
13
|
+
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: pandas
|
|
18
|
+
Requires-Dist: xlwings
|
|
19
|
+
Requires-Dist: pywin32
|
|
20
|
+
Requires-Dist: psutil
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: build; extra == "dev"
|
|
23
|
+
Requires-Dist: twine; extra == "dev"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# SAP Automation
|
|
27
|
+
|
|
28
|
+
## What is this?
|
|
29
|
+
|
|
30
|
+
We regularly need to pull data from SAP, format it as Excel, and upload it to SharePoint. Doing this manually is slow and repetitive. These scripts automate the entire process so you can run a single Python file and have the data extracted, saved, and uploaded automatically.
|
|
31
|
+
|
|
32
|
+
## Who is this for?
|
|
33
|
+
|
|
34
|
+
Anyone who needs to extract SAP reports on a recurring basis. You do not need to be a programmer. The templates are designed so you only need to:
|
|
35
|
+
|
|
36
|
+
1. Record your SAP steps (SAP has a built-in script recorder)
|
|
37
|
+
2. Paste the recording into the template
|
|
38
|
+
3. Fill in a few settings (transaction code, file paths)
|
|
39
|
+
4. Run the script
|
|
40
|
+
|
|
41
|
+
## How it works
|
|
42
|
+
|
|
43
|
+
The scripts follow this workflow:
|
|
44
|
+
|
|
45
|
+
1. Open SAP and connect to PR1
|
|
46
|
+
2. Run your recorded SAP transaction (fill in fields, execute report, click export)
|
|
47
|
+
3. Save the exported file locally
|
|
48
|
+
4. Read the file into memory
|
|
49
|
+
5. Copy a checked-in Excel template from SharePoint, write the data into it, and save it back to SharePoint
|
|
50
|
+
6. Clean up temporary files
|
|
51
|
+
|
|
52
|
+
The "checked-in file" is an `.xlsx` template that lives in a SharePoint folder. You specify the path to this template in your script. The scripts copy it, fill it with your data, and save the result as a new file in your destination folder. This ensures every upload has consistent formatting.
|
|
53
|
+
|
|
54
|
+
## Folder Structure
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
SAP_Automation/
|
|
58
|
+
├── functions/ Core modules that do the actual work (you don't edit these)
|
|
59
|
+
├── templates/ Starter scripts you copy and customize for each SAP transaction
|
|
60
|
+
└── tools/ Utilities like the transaction checker
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Templates
|
|
64
|
+
|
|
65
|
+
### SAP Pipeline (template_sap_pipeline.py)
|
|
66
|
+
|
|
67
|
+
The main template. Handles the full workflow: connect to SAP, run your transaction, export data, upload to SharePoint.
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
df = run_extract(sap_script,
|
|
71
|
+
transaction="ZSUPVENG",
|
|
72
|
+
export_format="xlsx",
|
|
73
|
+
template_folder=r"Z:\path\to\template_folder",
|
|
74
|
+
sharepoint_folder=r"Z:\path\to\your_sharepoint_folder",
|
|
75
|
+
)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**How to use:**
|
|
79
|
+
1. Copy this template and rename it (e.g. `ZSUPVENG.py`)
|
|
80
|
+
2. Paste your SAP recording into the `sap_script()` function
|
|
81
|
+
3. Set `transaction` to your transaction code
|
|
82
|
+
4. Set `template_folder` to the SharePoint folder containing your checked-in `.xlsx` template
|
|
83
|
+
5. Set `sharepoint_folder` to where you want the output file saved
|
|
84
|
+
6. Run the script
|
|
85
|
+
|
|
86
|
+
### SharePoint Upload (template_sharepoint_upload.py)
|
|
87
|
+
|
|
88
|
+
Uploads any data to SharePoint as a formatted Excel file. No SAP needed. Useful when you already have data in a file or DataFrame and just want to push it to SharePoint.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
result = save_excel_to_sharepoint(df,
|
|
92
|
+
template_folder=r"Z:\path\to\template_folder",
|
|
93
|
+
sharepoint_folder=r"Z:\path\to\your_sharepoint_folder",
|
|
94
|
+
output_filename_prefix="MyReport_2026-01-01",
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Excel Macros (template_excel_macro.py)
|
|
99
|
+
|
|
100
|
+
Opens an Excel workbook and runs VBA macros by name.
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
run_excel_macro(
|
|
104
|
+
file_path=r"Z:\path\to\your_workbook.xlsm",
|
|
105
|
+
macro_name="MyMacro",
|
|
106
|
+
module_name="Module1"
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Core Modules (functions/)
|
|
111
|
+
|
|
112
|
+
These are the building blocks. You don't need to edit these files.
|
|
113
|
+
|
|
114
|
+
| File | What it does |
|
|
115
|
+
|------|-------------|
|
|
116
|
+
| `sap_extract.py` | The main engine. Connects to SAP, runs your recording, handles the save dialog, reads the file, uploads to SharePoint |
|
|
117
|
+
| `sap_connection.py` | Opens SAP GUI, connects to PR1, handles popups like "Multiple Logon" |
|
|
118
|
+
| `sharepoint_upload.py` | Copies the checked-in template, writes your data into it, saves it to SharePoint |
|
|
119
|
+
| `excel_macro.py` | Opens an Excel file and runs a VBA macro |
|
|
120
|
+
|
|
121
|
+
## Export Formats
|
|
122
|
+
|
|
123
|
+
Your SAP recording should include the export menu clicks (right-click, select format, etc.). The `export_format` setting just tells the engine what file type to expect so it can handle the save dialog correctly.
|
|
124
|
+
|
|
125
|
+
| Format | What the engine does |
|
|
126
|
+
|--------|---------------------|
|
|
127
|
+
| `"txt"` | Fills in the save dialog, reads the tab-delimited text file |
|
|
128
|
+
| `"xlsx"` | Fills in the save dialog, waits for the file, closes the Excel window SAP opens |
|
|
129
|
+
| `"clipboard"` | No save dialog needed, reads directly from clipboard |
|
|
130
|
+
|
|
131
|
+
## Tools
|
|
132
|
+
|
|
133
|
+
**Transaction Checker** (`tools/check_transactions.py`): Scans all your scripts for SAP transaction codes, then connects to SAP and verifies each one opens successfully. Run it with `check_transactions.bat`.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# SAP Automation
|
|
2
|
+
|
|
3
|
+
## What is this?
|
|
4
|
+
|
|
5
|
+
We regularly need to pull data from SAP, format it as Excel, and upload it to SharePoint. Doing this manually is slow and repetitive. These scripts automate the entire process so you can run a single Python file and have the data extracted, saved, and uploaded automatically.
|
|
6
|
+
|
|
7
|
+
## Who is this for?
|
|
8
|
+
|
|
9
|
+
Anyone who needs to extract SAP reports on a recurring basis. You do not need to be a programmer. The templates are designed so you only need to:
|
|
10
|
+
|
|
11
|
+
1. Record your SAP steps (SAP has a built-in script recorder)
|
|
12
|
+
2. Paste the recording into the template
|
|
13
|
+
3. Fill in a few settings (transaction code, file paths)
|
|
14
|
+
4. Run the script
|
|
15
|
+
|
|
16
|
+
## How it works
|
|
17
|
+
|
|
18
|
+
The scripts follow this workflow:
|
|
19
|
+
|
|
20
|
+
1. Open SAP and connect to PR1
|
|
21
|
+
2. Run your recorded SAP transaction (fill in fields, execute report, click export)
|
|
22
|
+
3. Save the exported file locally
|
|
23
|
+
4. Read the file into memory
|
|
24
|
+
5. Copy a checked-in Excel template from SharePoint, write the data into it, and save it back to SharePoint
|
|
25
|
+
6. Clean up temporary files
|
|
26
|
+
|
|
27
|
+
The "checked-in file" is an `.xlsx` template that lives in a SharePoint folder. You specify the path to this template in your script. The scripts copy it, fill it with your data, and save the result as a new file in your destination folder. This ensures every upload has consistent formatting.
|
|
28
|
+
|
|
29
|
+
## Folder Structure
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
SAP_Automation/
|
|
33
|
+
├── functions/ Core modules that do the actual work (you don't edit these)
|
|
34
|
+
├── templates/ Starter scripts you copy and customize for each SAP transaction
|
|
35
|
+
└── tools/ Utilities like the transaction checker
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Templates
|
|
39
|
+
|
|
40
|
+
### SAP Pipeline (template_sap_pipeline.py)
|
|
41
|
+
|
|
42
|
+
The main template. Handles the full workflow: connect to SAP, run your transaction, export data, upload to SharePoint.
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
df = run_extract(sap_script,
|
|
46
|
+
transaction="ZSUPVENG",
|
|
47
|
+
export_format="xlsx",
|
|
48
|
+
template_folder=r"Z:\path\to\template_folder",
|
|
49
|
+
sharepoint_folder=r"Z:\path\to\your_sharepoint_folder",
|
|
50
|
+
)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**How to use:**
|
|
54
|
+
1. Copy this template and rename it (e.g. `ZSUPVENG.py`)
|
|
55
|
+
2. Paste your SAP recording into the `sap_script()` function
|
|
56
|
+
3. Set `transaction` to your transaction code
|
|
57
|
+
4. Set `template_folder` to the SharePoint folder containing your checked-in `.xlsx` template
|
|
58
|
+
5. Set `sharepoint_folder` to where you want the output file saved
|
|
59
|
+
6. Run the script
|
|
60
|
+
|
|
61
|
+
### SharePoint Upload (template_sharepoint_upload.py)
|
|
62
|
+
|
|
63
|
+
Uploads any data to SharePoint as a formatted Excel file. No SAP needed. Useful when you already have data in a file or DataFrame and just want to push it to SharePoint.
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
result = save_excel_to_sharepoint(df,
|
|
67
|
+
template_folder=r"Z:\path\to\template_folder",
|
|
68
|
+
sharepoint_folder=r"Z:\path\to\your_sharepoint_folder",
|
|
69
|
+
output_filename_prefix="MyReport_2026-01-01",
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Excel Macros (template_excel_macro.py)
|
|
74
|
+
|
|
75
|
+
Opens an Excel workbook and runs VBA macros by name.
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
run_excel_macro(
|
|
79
|
+
file_path=r"Z:\path\to\your_workbook.xlsm",
|
|
80
|
+
macro_name="MyMacro",
|
|
81
|
+
module_name="Module1"
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Core Modules (functions/)
|
|
86
|
+
|
|
87
|
+
These are the building blocks. You don't need to edit these files.
|
|
88
|
+
|
|
89
|
+
| File | What it does |
|
|
90
|
+
|------|-------------|
|
|
91
|
+
| `sap_extract.py` | The main engine. Connects to SAP, runs your recording, handles the save dialog, reads the file, uploads to SharePoint |
|
|
92
|
+
| `sap_connection.py` | Opens SAP GUI, connects to PR1, handles popups like "Multiple Logon" |
|
|
93
|
+
| `sharepoint_upload.py` | Copies the checked-in template, writes your data into it, saves it to SharePoint |
|
|
94
|
+
| `excel_macro.py` | Opens an Excel file and runs a VBA macro |
|
|
95
|
+
|
|
96
|
+
## Export Formats
|
|
97
|
+
|
|
98
|
+
Your SAP recording should include the export menu clicks (right-click, select format, etc.). The `export_format` setting just tells the engine what file type to expect so it can handle the save dialog correctly.
|
|
99
|
+
|
|
100
|
+
| Format | What the engine does |
|
|
101
|
+
|--------|---------------------|
|
|
102
|
+
| `"txt"` | Fills in the save dialog, reads the tab-delimited text file |
|
|
103
|
+
| `"xlsx"` | Fills in the save dialog, waits for the file, closes the Excel window SAP opens |
|
|
104
|
+
| `"clipboard"` | No save dialog needed, reads directly from clipboard |
|
|
105
|
+
|
|
106
|
+
## Tools
|
|
107
|
+
|
|
108
|
+
**Transaction Checker** (`tools/check_transactions.py`): Scans all your scripts for SAP transaction codes, then connects to SAP and verifies each one opens successfully. Run it with `check_transactions.bat`.
|
|
File without changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Excel Macro Runner
|
|
2
|
+
# ==================
|
|
3
|
+
# Opens an Excel file (even if already open) and runs a VBA macro by name.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# from excel_macro import run_excel_macro
|
|
7
|
+
#
|
|
8
|
+
# run_excel_macro(
|
|
9
|
+
# file_path=r"Z:\some_folder\my_workbook.xlsm",
|
|
10
|
+
# macro_name="MyMacroName",
|
|
11
|
+
# module_name="Module1" # optional — prefix with module name
|
|
12
|
+
# )
|
|
13
|
+
|
|
14
|
+
import win32com.client
|
|
15
|
+
import os
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_excel_macro(file_path: str, macro_name: str, module_name: str = None):
|
|
19
|
+
"""Open an Excel file (or attach to it if already open) and run a macro by name."""
|
|
20
|
+
file_path = os.path.abspath(file_path)
|
|
21
|
+
filename = os.path.basename(file_path)
|
|
22
|
+
|
|
23
|
+
excel = win32com.client.Dispatch("Excel.Application")
|
|
24
|
+
excel.Visible = True
|
|
25
|
+
|
|
26
|
+
# Check if the workbook is already open
|
|
27
|
+
wb = None
|
|
28
|
+
for i in range(excel.Workbooks.Count):
|
|
29
|
+
if excel.Workbooks(i + 1).Name.lower() == filename.lower():
|
|
30
|
+
wb = excel.Workbooks(i + 1)
|
|
31
|
+
break
|
|
32
|
+
|
|
33
|
+
if wb is None:
|
|
34
|
+
wb = excel.Workbooks.Open(file_path)
|
|
35
|
+
|
|
36
|
+
# Run the macro
|
|
37
|
+
if module_name:
|
|
38
|
+
macro_ref = f"'{wb.Name}'!{module_name}.{macro_name}"
|
|
39
|
+
else:
|
|
40
|
+
macro_ref = f"'{wb.Name}'!{macro_name}"
|
|
41
|
+
|
|
42
|
+
excel.Application.Run(macro_ref)
|
|
43
|
+
print(f"Macro '{macro_name}' executed successfully.")
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# SAP GUI Connection Manager
|
|
2
|
+
# ===========================
|
|
3
|
+
# Provides the SAPManager class to automate SAP GUI connections via COM scripting.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# sap = SAPManager()
|
|
7
|
+
# session = sap.get_session() # Opens SAP GUI, connects to PR1, returns a session
|
|
8
|
+
# ... (run your SAP script) ...
|
|
9
|
+
# sap.close_connection(session) # Logs off and closes the SAP window
|
|
10
|
+
#
|
|
11
|
+
# What get_session() does:
|
|
12
|
+
# 1. Connects to an existing SAP GUI instance, or launches a new one if none is running
|
|
13
|
+
# 2. Opens a NEW connection to the PR1 server (never reuses existing sessions)
|
|
14
|
+
# 3. Handles the "Multiple Logon" popup automatically
|
|
15
|
+
# 4. Handles the session manager screen if it appears instead of Easy Access
|
|
16
|
+
# 5. Returns the session object used to script SAP GUI actions (findById, press, etc.)
|
|
17
|
+
#
|
|
18
|
+
# Other methods:
|
|
19
|
+
# - return_to_main_menu(session) : sends /n and waits until Easy Access screen appears
|
|
20
|
+
# - close_connection(session) : sends /nex to log off (only closes this script's connection)
|
|
21
|
+
|
|
22
|
+
import subprocess
|
|
23
|
+
import os
|
|
24
|
+
import platform
|
|
25
|
+
import time
|
|
26
|
+
import win32com.client
|
|
27
|
+
|
|
28
|
+
class SAPManager:
|
|
29
|
+
def __init__(self, connection_name="-PR1 [PWC SAP ECC 6.0]", xml_name="PWC_SAPUILandscape.xml"):
|
|
30
|
+
self.connection_name = connection_name
|
|
31
|
+
self.xml_name = xml_name
|
|
32
|
+
self.session = None
|
|
33
|
+
self.connection = None
|
|
34
|
+
self.application = None
|
|
35
|
+
|
|
36
|
+
def _handle_session_manager_screen(self, session):
|
|
37
|
+
"""Navigate past the session manager screen if it appears.
|
|
38
|
+
|
|
39
|
+
Sometimes SAP opens to a screen titled just 'SAP' with a
|
|
40
|
+
'Start SAP Easy Access' button instead of going directly to the
|
|
41
|
+
main menu. Tries multiple approaches to click through.
|
|
42
|
+
"""
|
|
43
|
+
try:
|
|
44
|
+
title = session.findById("wnd[0]").text
|
|
45
|
+
if "Easy Access" in title:
|
|
46
|
+
return # Already on the main menu
|
|
47
|
+
print(f"Session manager screen detected (title: '{title}'). Clicking through...")
|
|
48
|
+
|
|
49
|
+
# Try to find and click the 'Start SAP Easy Access' button
|
|
50
|
+
# by scanning all children in the user area
|
|
51
|
+
try:
|
|
52
|
+
usr = session.findById("wnd[0]/usr")
|
|
53
|
+
for i in range(usr.Children.Count):
|
|
54
|
+
child = usr.Children(i)
|
|
55
|
+
try:
|
|
56
|
+
child_text = child.text if hasattr(child, 'text') else ""
|
|
57
|
+
if "Easy Access" in child_text or "Start" in child_text:
|
|
58
|
+
child.press()
|
|
59
|
+
time.sleep(2)
|
|
60
|
+
print(f"Clicked '{child_text}' button (id: {child.id}).")
|
|
61
|
+
return
|
|
62
|
+
except Exception:
|
|
63
|
+
continue
|
|
64
|
+
except Exception:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
# Fallback: press Enter which may activate the default button
|
|
68
|
+
try:
|
|
69
|
+
session.findById("wnd[0]").sendVKey(0)
|
|
70
|
+
time.sleep(2)
|
|
71
|
+
print("Pressed Enter to pass session manager screen.")
|
|
72
|
+
except Exception:
|
|
73
|
+
pass
|
|
74
|
+
except Exception as e:
|
|
75
|
+
print(f"Warning: Could not handle session manager screen: {e}")
|
|
76
|
+
|
|
77
|
+
def return_to_main_menu(self, session, timeout=5):
|
|
78
|
+
"""Navigate back to main menu and wait until it's confirmed.
|
|
79
|
+
|
|
80
|
+
Sends /n and polls until the SAP Easy Access main menu is detected
|
|
81
|
+
(title contains 'Easy Access'). This serves as a reliable signal
|
|
82
|
+
that the previous transaction has fully completed.
|
|
83
|
+
|
|
84
|
+
Returns True if main menu reached, False on timeout.
|
|
85
|
+
"""
|
|
86
|
+
try:
|
|
87
|
+
session.findById("wnd[0]/tbar[0]/okcd").text = "/n"
|
|
88
|
+
session.findById("wnd[0]").sendVKey(0)
|
|
89
|
+
except Exception as e:
|
|
90
|
+
print(f"Warning: Could not send /n command: {e}")
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
start = time.time()
|
|
94
|
+
while time.time() - start < timeout:
|
|
95
|
+
try:
|
|
96
|
+
title = session.findById("wnd[0]").text
|
|
97
|
+
if "Easy Access" in title:
|
|
98
|
+
print("Returned to SAP main menu.")
|
|
99
|
+
return True
|
|
100
|
+
except Exception:
|
|
101
|
+
pass
|
|
102
|
+
time.sleep(0.5)
|
|
103
|
+
|
|
104
|
+
print(f"Warning: Timed out waiting for main menu after {timeout}s.")
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
def close_connection(self, session):
|
|
108
|
+
"""Close the connection this script opened.
|
|
109
|
+
|
|
110
|
+
Sends /nex to log off and close the SAP window, then clears
|
|
111
|
+
internal references. Only affects this script's connection —
|
|
112
|
+
other connections remain untouched.
|
|
113
|
+
|
|
114
|
+
Returns True if closed successfully, False on error.
|
|
115
|
+
"""
|
|
116
|
+
try:
|
|
117
|
+
session.findById("wnd[0]/tbar[0]/okcd").text = "/nex"
|
|
118
|
+
session.findById("wnd[0]").sendVKey(0)
|
|
119
|
+
print(f"[{self.connection_name}] Connection closed.")
|
|
120
|
+
self.session = None
|
|
121
|
+
self.connection = None
|
|
122
|
+
return True
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print(f"Warning: Could not close connection: {e}")
|
|
125
|
+
return False
|
|
126
|
+
|
|
127
|
+
def _handle_multiple_logon_popup(self, session=None):
|
|
128
|
+
"""Internal helper to allow the multiple logon (continue with current session)."""
|
|
129
|
+
session = session or self.session
|
|
130
|
+
try:
|
|
131
|
+
popup = session.findById("wnd[1]", False)
|
|
132
|
+
if popup is not None:
|
|
133
|
+
if "License Information" in popup.text or "Multiple Logon" in popup.text:
|
|
134
|
+
session.findById("wnd[1]/usr/radMULTI_LOGON_OPT2").Select()
|
|
135
|
+
session.findById("wnd[1]/tbar[0]/btn[0]").press()
|
|
136
|
+
print(f"[{self.connection_name}] Allowed Multiple Logon - new session created.")
|
|
137
|
+
except Exception:
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
def get_session(self):
|
|
141
|
+
if platform.system() != "Windows":
|
|
142
|
+
raise RuntimeError("Windows OS is required for SAP GUI Scripting.")
|
|
143
|
+
|
|
144
|
+
# 1. Connect to existing SAP GUI or start new one
|
|
145
|
+
try:
|
|
146
|
+
try:
|
|
147
|
+
sap_gui_auto = win32com.client.GetObject("SAPGUI")
|
|
148
|
+
self.application = sap_gui_auto.GetScriptingEngine
|
|
149
|
+
print("Connected to existing SAP GUI instance.")
|
|
150
|
+
except Exception:
|
|
151
|
+
# No SAP GUI running — start it
|
|
152
|
+
exe_path = r"C:\Program Files\SAP\FrontEnd\SAPGUI\saplgpad.exe"
|
|
153
|
+
xml_full_path = os.path.expandvars(rf"%ProgramFiles%\SAP\PWCConfig\{self.xml_name}")
|
|
154
|
+
|
|
155
|
+
if not os.path.exists(exe_path):
|
|
156
|
+
raise FileNotFoundError(f"SAP Executable not found at {exe_path}")
|
|
157
|
+
|
|
158
|
+
subprocess.Popen(f'"{exe_path}" /LSXML_FILE="{xml_full_path}"', shell=True)
|
|
159
|
+
|
|
160
|
+
# Poll until SAP GUI is available instead of fixed sleep
|
|
161
|
+
for _ in range(15):
|
|
162
|
+
time.sleep(1)
|
|
163
|
+
try:
|
|
164
|
+
sap_gui_auto = win32com.client.GetObject("SAPGUI")
|
|
165
|
+
self.application = sap_gui_auto.GetScriptingEngine
|
|
166
|
+
break
|
|
167
|
+
except Exception:
|
|
168
|
+
continue
|
|
169
|
+
else:
|
|
170
|
+
raise RuntimeError("SAP GUI did not become available within 15 seconds")
|
|
171
|
+
print("Started new SAP GUI instance.")
|
|
172
|
+
except Exception as e:
|
|
173
|
+
raise RuntimeError(f"Failed to connect to SAP GUI: {e}")
|
|
174
|
+
|
|
175
|
+
# 2. Always open a new connection to avoid interfering with
|
|
176
|
+
# other scripts that may be using existing sessions
|
|
177
|
+
for attempt in range(2):
|
|
178
|
+
try:
|
|
179
|
+
print(f"[{self.connection_name}] Opening new connection...")
|
|
180
|
+
self.connection = self.application.OpenConnection(self.connection_name, True)
|
|
181
|
+
time.sleep(2)
|
|
182
|
+
self.session = self.connection.Children(0)
|
|
183
|
+
self._handle_multiple_logon_popup()
|
|
184
|
+
print(f"New connection opened with 1 session")
|
|
185
|
+
break
|
|
186
|
+
except Exception as e:
|
|
187
|
+
if attempt == 0:
|
|
188
|
+
print(f"Connection attempt failed, retrying: {e}")
|
|
189
|
+
time.sleep(3)
|
|
190
|
+
else:
|
|
191
|
+
raise ConnectionError(f"Could not open new connection to {self.connection_name}: {str(e)}")
|
|
192
|
+
|
|
193
|
+
# Handle session manager screen if it appears instead of Easy Access
|
|
194
|
+
self._handle_session_manager_screen(self.session)
|
|
195
|
+
|
|
196
|
+
return self.session
|