Skip to content

Commit 4ec0c4d

Browse files
authored
Merge pull request #12 from itk-dev-rpa/revert-11-develop
Revert "Develop"
2 parents 252772d + 0167a70 commit 4ec0c4d

File tree

14 files changed

+195
-529
lines changed

14 files changed

+195
-529
lines changed

.pylintrc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
[pylint.messages_control]
22
disable =
3+
C0303, # Trailing whitespace
4+
C0103, # Variable names
5+
C0305, # Trailing newlines
6+
C0304, # Missing final line
37
C0301, # Line too long
48
I1101, E1101, # C-modules members
5-
R0913, # Too many arguments
6-
R0914 # Too many local variables
9+
W0621, # Redefine outer name
10+
R0913 # Too many arguments
711

12+
[MASTER]
13+
ignore-paths = ^tests/ # Ignore the tests folder

ITK_dev_shared_components/SAP/gridview_util.py

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""This module provides static functions to perform common tasks with SAP GuiGridView COM objects."""
1+
"""This module provides static functions to peform common tasks with SAP GuiGridView COM objects."""
22

33
def scroll_entire_table(grid_view, return_to_top=False) -> None:
44
"""This function scrolls through the entire table to load all cells.
@@ -9,13 +9,11 @@ def scroll_entire_table(grid_view, return_to_top=False) -> None:
99
1010
Returns:
1111
_type_: _description_
12-
"""
13-
if grid_view.RowCount == 0 or grid_view.VisibleRowCount == 0:
14-
return
12+
"""
1513

1614
for i in range(0, grid_view.RowCount, grid_view.VisibleRowCount):
1715
grid_view.FirstVisibleRow = i
18-
16+
1917
if return_to_top:
2018
grid_view.FirstVisibleRow = 0
2119

@@ -30,7 +28,7 @@ def get_all_rows(grid_view, pre_load=True) -> tuple[tuple[str]]:
3028
3129
Returns:
3230
tuple[tuple[str]]: A 2D tuple of all cell values in the gridview.
33-
"""
31+
"""
3432

3533
if pre_load:
3634
scroll_entire_table(grid_view, True)
@@ -45,9 +43,9 @@ def get_all_rows(grid_view, pre_load=True) -> tuple[tuple[str]]:
4543
for c in columns:
4644
v = grid_view.GetCellValue(r, c)
4745
row_data.append(v)
48-
46+
4947
output.append(tuple(row_data))
50-
48+
5149
return tuple(output)
5250

5351

@@ -62,7 +60,7 @@ def get_row(grid_view, row:int, scroll_to_row=False) -> tuple[str]:
6260
6361
Returns:
6462
tuple[str]: A tuple of the row's data.
65-
"""
63+
"""
6664

6765
if scroll_to_row:
6866
grid_view.FirstVisibleRow = row
@@ -85,7 +83,7 @@ def iterate_rows(grid_view) -> tuple[str]:
8583
8684
Yields:
8785
tuple[str]: A tuple of the next row's data.
88-
"""
86+
"""
8987

9088
row = 0
9189
while row < grid_view.RowCount:
@@ -106,7 +104,7 @@ def get_column_titles(grid_view) -> tuple[str]:
106104
107105
Returns:
108106
tuple[str]: A tuple of the gridview's column titles.
109-
"""
107+
"""
110108

111109
return tuple(grid_view.GetColumnTitles(c)[0] for c in grid_view.ColumnOrder)
112110

@@ -125,7 +123,7 @@ def find_row_index_by_value(grid_view, column:str, value:str) -> int:
125123
126124
Returns:
127125
int: The index of the first row which column value matches the given value.
128-
"""
126+
"""
129127

130128
if column not in grid_view.ColumnOrder:
131129
raise ValueError(f"Column '{column}' not in grid_view")
@@ -134,14 +132,14 @@ def find_row_index_by_value(grid_view, column:str, value:str) -> int:
134132
# Only scroll when row isn't visible
135133
if not grid_view.FirstVisibleRow <= row <= grid_view.FirstVisibleRow + grid_view.VisibleRowCount-1:
136134
grid_view.FirstVisibleRow = row
137-
135+
138136
if grid_view.GetCellValue(row, column) == value:
139137
return row
140-
138+
141139
return -1
142140

143-
def find_all_row_indices_by_value(grid_view, column:str, value:str) -> list[int]:
144-
"""Find all indices of the rows where the given column's value
141+
def find_all_row_indecies_by_value(grid_view, column:str, value:str) -> list[int]:
142+
"""Find all indecies of the rows where the given column's value
145143
match the given value. Returns an empty list if no row is found.
146144
147145
Args:
@@ -153,8 +151,8 @@ def find_all_row_indices_by_value(grid_view, column:str, value:str) -> list[int]
153151
ValueError: If the column name doesn't exist in the grid view.
154152
155153
Returns:
156-
list[int]: A list of row indices where the value matches.
157-
"""
154+
list[int]: A list of row indecies where the value matches.
155+
"""
158156
if column not in grid_view.ColumnOrder:
159157
raise ValueError(f"Column '{column}' not in grid_view")
160158

@@ -164,8 +162,39 @@ def find_all_row_indices_by_value(grid_view, column:str, value:str) -> list[int]
164162
# Only scroll when row isn't visible
165163
if not grid_view.FirstVisibleRow <= row <= grid_view.FirstVisibleRow + grid_view.VisibleRowCount-1:
166164
grid_view.FirstVisibleRow = row
167-
165+
168166
if grid_view.GetCellValue(row, column) == value:
169167
rows.append(row)
170-
168+
171169
return rows
170+
171+
172+
173+
174+
if __name__=='__main__':
175+
import win32com.client
176+
177+
SAP = win32com.client.GetObject("SAPGUI")
178+
app = SAP.GetScriptingEngine
179+
connection = app.Connections(0)
180+
session = connection.Sessions(0)
181+
182+
table = session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell")
183+
184+
rows = find_all_row_indecies_by_value(table, "ZZ_PARTNER", '15879880')
185+
print(rows)
186+
table.setCurrentCell(rows[0], "ZZ_PARTNER")
187+
188+
# print(get_row(table, 1, True))
189+
190+
# scroll_entire_table(table)
191+
192+
# data = get_all_rows(table)
193+
# print(len(data), len(data[0]))
194+
195+
# for r in iterate_rows(table):
196+
# print(r)
197+
198+
# print(get_column_titles(table))
199+
200+
Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,33 @@
1-
"""This module provides static functions to handle multiple sessions of SAP.
1+
"""This module provides static function to handle multiple sessions of SAP.
22
Using this module you can spawn multiple sessions and automatically execute
33
a function in parallel on the sessions."""
44

55
import time
66
import threading
7-
import math
87
from typing import Callable
9-
108
import pythoncom
119
import win32com.client
1210
import win32gui
1311

1412
def run_with_session(session_index:int, func:Callable, args:tuple) -> None:
15-
"""Run a function in a specific session based on the sessions index.
16-
This function is meant to be run inside a separate thread.
13+
"""Run a function in a sepcific session based on the sessions index.
14+
This function is meant to be run inside a seperate thread.
1715
The function must take a session object as its first argument.
1816
Note that this function will not spawn the sessions before running,
1917
use spawn_sessions to do that.
2018
"""
2119

2220
pythoncom.CoInitialize()
2321

24-
sap = win32com.client.GetObject("SAPGUI")
25-
app = sap.GetScriptingEngine
22+
SAP = win32com.client.GetObject("SAPGUI")
23+
app = SAP.GetScriptingEngine
2624
connection = app.Connections(0)
2725
session = connection.Sessions(session_index)
2826

2927
func(session, *args)
3028

3129
pythoncom.CoUninitialize()
3230

33-
3431
def run_batch(func:Callable, args:tuple[tuple], num_sessions=6) -> None:
3532
"""Run a function in parallel sessions.
3633
The function will be run {num_sessions} times with args[i] as input.
@@ -43,7 +40,7 @@ def run_batch(func:Callable, args:tuple[tuple], num_sessions=6) -> None:
4340
for i in range(num_sessions):
4441
t = ExThread(target=run_with_session, args=(i, func, args[i]))
4542
threads.append(t)
46-
43+
4744
for t in threads:
4845
t.start()
4946
for t in threads:
@@ -52,7 +49,6 @@ def run_batch(func:Callable, args:tuple[tuple], num_sessions=6) -> None:
5249
if t.error:
5350
raise t.error
5451

55-
5652
def run_batches(func:Callable, args:tuple[tuple], num_sessions=6):
5753
"""Run a function in parallel batches.
5854
This function runs the input function for each set of arguments in args.
@@ -66,26 +62,16 @@ def run_batches(func:Callable, args:tuple[tuple], num_sessions=6):
6662
batch = args[b:b+num_sessions]
6763
run_batch(func, args, len(batch))
6864

69-
70-
def spawn_sessions(num_sessions=6) -> tuple:
65+
def spawn_sessions(num_sessions=6) -> list:
7166
"""A function to spawn multiple sessions of SAP.
7267
This function will attempt to spawn the desired number of sessions.
73-
If the current number of already open sessions exceeds the desired number of sessions
68+
If the current number of open sessions exceeds the desired number of sessions
7469
the already open sessions will not be closed to match the desired number.
7570
The number of sessions must be between 1 and 6.
76-
77-
Args:
78-
num_sessions: The number of sessions desired. Defaults to 6.
79-
80-
Raises:
81-
ValueError: If the number of sessions is not between 1 and 6.
82-
83-
Returns:
84-
tuple: A tuple of all currently open sessions.
71+
Returns a list of all open sessions.
8572
"""
86-
87-
sap = win32com.client.GetObject("SAPGUI")
88-
app = sap.GetScriptingEngine
73+
SAP = win32com.client.GetObject("SAPGUI")
74+
app = SAP.GetScriptingEngine
8975
connection = app.Connections(0)
9076
session = connection.Sessions(0)
9177

@@ -96,17 +82,25 @@ def spawn_sessions(num_sessions=6) -> tuple:
9682

9783
for _ in range(num_sessions - connection.Sessions.count):
9884
session.CreateSession()
99-
85+
10086
# Wait for the sessions to spawn
10187
while connection.Sessions.count < num_sessions:
10288
time.sleep(0.1)
10389

104-
sessions = tuple(connection.Sessions)
90+
sessions = list(connection.Sessions)
10591
num_sessions = len(sessions)
10692

107-
# Calculate number of columns and rows
108-
c = math.ceil(math.sqrt(num_sessions))
109-
r = math.ceil(num_sessions / c)
93+
if num_sessions == 1:
94+
c = 1
95+
elif num_sessions <= 4:
96+
c = 2
97+
elif num_sessions <= 6:
98+
c = 3
99+
100+
if num_sessions < 3:
101+
r = 1
102+
else:
103+
r = 2
110104

111105
w, h = 1920//c, 1040//r
112106

@@ -117,22 +111,20 @@ def spawn_sessions(num_sessions=6) -> tuple:
117111
x = i % c * w
118112
y = i // c * h
119113
win32gui.MoveWindow(hwnd, x, y, w, h, True)
120-
114+
121115
return sessions
122116

123-
124-
def get_all_SAP_sessions() -> tuple: # pylint: disable=invalid-name
117+
def get_all_SAP_sessions() -> tuple:
125118
"""Returns a tuple of all open SAP sessions (on connection index 0).
126119
127120
Returns:
128121
tuple: A tuple of SAP GuiSession objects.
129122
"""
130-
sap = win32com.client.GetObject("SAPGUI")
131-
app = sap.GetScriptingEngine
123+
SAP = win32com.client.GetObject("SAPGUI")
124+
app = SAP.GetScriptingEngine
132125
connection = app.Connections(0)
133126
return tuple(connection.Sessions)
134127

135-
136128
class ExThread(threading.Thread):
137129
"""A thread with a handle to get an exception raised inside the thread: ExThread.error"""
138130
def __init__(self, *args, **kwargs):
@@ -144,3 +136,5 @@ def run(self):
144136
self._target(*self._args, **self._kwargs)
145137
except Exception as e: # pylint: disable=broad-exception-caught
146138
self.error = e
139+
140+

ITK_dev_shared_components/SAP/opret_kundekontakt.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
"""This module provides a single function to conveniently peform the action 'opret-kundekontaker' in SAP."""
1+
"""This module provides a single function to conviniently peform the action 'opret-kundekontaker' in SAP."""
22

33
from typing import Literal
44
import win32clipboard
55
from ITK_dev_shared_components.SAP import tree_util
66

77

8-
def opret_kundekontakter(session, fp:str, aftaler:list[str] | None,
9-
art:Literal[' ', 'Automatisk', 'Fakturagrundlag', 'Fuldmagt ifm. værge', 'Konverteret', 'Myndighedshenvend.', 'Orientering', 'Returpost', 'Ringeaktivitet', 'Skriftlig henvend.', 'Telefonisk henvend.'],
8+
def opret_kundekontakter(session, fp:str, aftaler:list[str] | None,
9+
art:Literal[' ', 'Automatisk', 'Fakturagrundlag', 'Fuldmagt ifm. værge', 'Konverteret', 'Myndighedshenvend.', 'Orientering', 'Returpost', 'Ringeaktivitet', 'Skriftlig henvend.', 'Telefonisk henvend.'],
1010
notat:str, lock=None) -> None:
1111
"""Creates a kundekontakt on the given FP and aftaler.
1212
@@ -41,25 +41,33 @@ def opret_kundekontakter(session, fp:str, aftaler:list[str] | None,
4141

4242
# Go to editor and paste (lock if multithreaded)
4343
session.findById("wnd[0]/usr/subNOTICE:SAPLEENO:1002/btnEENO_TEXTE-EDITOR").press()
44-
if lock:
44+
if lock:
4545
lock.acquire()
46-
_set_clipboard(notat)
46+
_setClipboard(notat)
4747
session.findById("wnd[0]/tbar[1]/btn[9]").press()
48-
if lock:
48+
if lock:
4949
lock.release()
5050

5151
# Back and save
5252
session.findById("wnd[0]/tbar[0]/btn[3]").press()
5353
session.findById("wnd[0]/tbar[0]/btn[11]").press()
5454

5555

56-
def _set_clipboard(text:str) -> None:
57-
"""Private function to set text to the clipboard.
58-
59-
Args:
60-
text: Text to set to clipboard.
61-
"""
56+
def _setClipboard(text:str) -> None:
6257
win32clipboard.OpenClipboard()
6358
win32clipboard.EmptyClipboard()
6459
win32clipboard.SetClipboardText(text)
6560
win32clipboard.CloseClipboard()
61+
62+
63+
if __name__ == '__main__':
64+
from ITK_dev_shared_components.SAP import multi_session
65+
from datetime import datetime
66+
67+
session = multi_session.spawn_sessions(1)[0]
68+
fp = '25564617'
69+
aftaler = ['2291987', '2421562', '2311094']
70+
art = 'Orientering'
71+
notat = 'Test '+ str(datetime.now())
72+
73+
opret_kundekontakter(session, fp, aftaler, 'Automatisk', notat)

0 commit comments

Comments
 (0)