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.
@@ -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