Skip to content

Commit 5f34f41

Browse files
Merge pull request #4 from StructuralPython/releases/v0.2.0
Releases/v0.2.0
2 parents e133a2b + dba5d58 commit 5f34f41

File tree

5 files changed

+104
-11
lines changed

5 files changed

+104
-11
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,4 @@ cython_debug/
152152
#.idea/
153153
tests/test_data/stored_results.xlsx
154154
/tests/test_data/design
155+
tests/test_data/~$example_wb.xlsx

README.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,94 @@
11
# xl-engine
22
Use your existing Excel workbooks like they were Python programs: A utility built on XLWings to automate the input, execution, and data retrieval of your existing Excel Workbooks.
3+
4+
5+
## Installation
6+
7+
`pip install xl-engine`
8+
9+
## Basic Usage
10+
11+
### `execute_workbook`
12+
13+
Use `execute_workbook` when you want to execute a workbook once with known, provided parameters.
14+
15+
```python
16+
import xl_engine as xl
17+
18+
results = xl.execute_workbook(
19+
TEST_DATA_DIR / "example_wb.xlsx",
20+
cells_to_change = {"B1": 33, "B2": 66},
21+
cells_to_retrieve=['B4', 'B5'], # This can either be a list or a dict; see next example
22+
sheet_idx=1,
23+
new_filepath=TEST_DATA_DIR / "stored_results.xlsx"
24+
)
25+
26+
# results
27+
# {'B4': 22.0, 'B5': 11.0}
28+
```
29+
30+
You can also use a dictionary in `cells_to_retrieve` to meaningfully label the results:
31+
32+
```python
33+
results2 = xl.execute_workbook(
34+
TEST_DATA_DIR / "example_wb.xlsx",
35+
cells_to_change = {"B1": 33, "B2": 66},
36+
cells_to_retrieve={'B4': "label1", 'B5': "label2"}, # Now a dict
37+
sheet_idx=1,
38+
new_filepath=TEST_DATA_DIR / "stored_results.xlsx"
39+
)
40+
41+
# results2
42+
# {'label1': 44.0, 'label2': 39.599999999999994}
43+
```
44+
45+
### `excel_runner`
46+
47+
Use `excel_runner` when you want to execute a workbook multiple times (static inputs) with multiple options (dynamic inputs).
48+
49+
```python
50+
import xl_engine as xl
51+
52+
# Creates a callable with the following function signature: callable(x: float | int) -> bool:
53+
# When a value is a passed to dcr2, i.e. dcr2(some_value), it will return True if
54+
# the value is greater-than-or-equal-to 2
55+
dcr2 = xl.create_condition_check(2, "ge")
56+
57+
# static_inputs will be used to populate each workbook.
58+
# Within each set of static inputs, a second sub-iteration will occur
59+
# where the dynamic inputs will be input allowing you to test the
60+
# results for different "options" of dynamic inputs.
61+
# If the save conditions pass (return True for all keys), then a copy of the
62+
# workbook will be saved to disk with the successful inputs recorded.
63+
# A dictionary of all calculated results will be returned.
64+
results = xl.excel_runner(
65+
TEST_DATA_DIR / "example_wb.xlsx",
66+
static_inputs={"B1": [10, 20], "Labels": ["C01", "C02"]},
67+
dynamic_inputs={
68+
"OptA": {"B2": 22},
69+
"OptB": {"B2": 33},
70+
"OptC": {"B2": 55},
71+
},
72+
success_conditions={"B6": dcr2},
73+
static_identifier_keys=["Labels"],
74+
result_labels={"B6": "meaningful_value"},
75+
save_dir=TEST_DATA_DIR / "design"
76+
)
77+
```
78+
79+
Return value (for the "example_wb.xlsx" file included in the tests directory):
80+
81+
```python
82+
{
83+
'C01': {
84+
'successful_key': None, # None of the options were successful for this case
85+
'OptA': {'meaningful_value': 1.2121212121212122},
86+
'OptB': {'meaningful_value': 0.8080808080808081},
87+
'OptC': {'meaningful_value': 0.48484848484848486}
88+
},
89+
'C02': {
90+
'successful_key': 'OptA',
91+
'meaningful_value': 2.4242424242424243
92+
}
93+
}
94+
```

src/xl_engine/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
execute, and save Excel workbooks.
44
"""
55

6-
__version__ = "0.1.1"
6+
__version__ = "0.2.0"
77

88
from xl_engine.excel_engine import create_condition_check, execute_workbook, excel_runner

src/xl_engine/excel_engine.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def excel_runner(
1515
xlsx_filepath,
1616
static_inputs: dict[str, list],
1717
dynamic_inputs: dict[str, dict[str, float]],
18-
save_conditions: dict[str, callable],
18+
success_conditions: dict[str, callable],
1919
static_identifier_keys: Optional[list[str]] = None,
2020
result_labels: Optional[dict[str, str]] = None,
2121
save_dir: Optional[str] = None,
@@ -40,9 +40,9 @@ def excel_runner(
4040
label to describe the iteration, e.g. the name of the design element.
4141
The values are dictionaries keyed by cell references with single values which will
4242
populate the workbook for every static iteration.
43-
'save_conditions': a dictionary keyed by cell references whose values are unary callables
43+
'success_conditions': a dictionary keyed by cell references whose values are unary callables
4444
which return a bool when passed the value retrieved from the workbook at the cell
45-
reference during each iteration. If all callables in the 'save_conditions' dict
45+
reference during each iteration. If all callables in the 'success_conditions' dict
4646
return True, then that iteration of the workbook will be saved to disk. Use the
4747
create_condition_check() function in this module to quickly create such callables.
4848
'static_identifier_keys': The keys in 'static_inputs', which are not cell references,
@@ -105,7 +105,7 @@ def excel_runner(
105105
calculated_results = execute_workbook(
106106
xlsx_filepath,
107107
cells_to_change=cells_to_change,
108-
cells_to_retrieve=list(save_conditions.keys()),
108+
cells_to_retrieve=list(success_conditions.keys()),
109109
sheet_idx=sheet_idx
110110
)
111111
if isinstance(result_labels, dict):
@@ -116,7 +116,7 @@ def excel_runner(
116116
failed_results.update({design_tag: labeled_results})
117117

118118
save_condition_acc = []
119-
for result_cell_id, save_condition in save_conditions.items():
119+
for result_cell_id, save_condition in success_conditions.items():
120120
calculated_result = calculated_results[result_cell_id]
121121
save_condition_acc.append(save_condition(calculated_result))
122122
variations_progress.update(variations_task, advance=1)
@@ -133,7 +133,7 @@ def excel_runner(
133133
_ = execute_workbook(
134134
xlsx_filepath,
135135
cells_to_change=cells_to_change,
136-
cells_to_retrieve=list(save_conditions.keys()),
136+
cells_to_retrieve=list(success_conditions.keys()),
137137
new_filepath=f"{str(save_dir)}/{new_filename}",
138138
sheet_idx=sheet_idx,
139139
)

tests/test_excel_engine.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ def test_execute_workbook():
2828
results2 = xl.execute_workbook(
2929
TEST_DATA_DIR / "example_wb.xlsx",
3030
cells_to_change = {"B1": 33, "B2": 66},
31-
cells_to_retrieve=['B4', 'B5'],
31+
cells_to_retrieve={'B4': "label1", 'B5': "label2"},
3232
sheet_idx=1,
3333
new_filepath=TEST_DATA_DIR / "stored_results.xlsx"
3434
)
35-
assert results2['B4'] == 44
36-
assert math.isclose(results2['B5'], 39.6)
35+
assert results2['label1'] == 44
36+
assert math.isclose(results2['label2'], 39.6)
3737

3838
import xlwings as xw
3939
with xw.Book(TEST_DATA_DIR / "stored_results.xlsx") as wb:
@@ -51,7 +51,7 @@ def test_excel_runner():
5151
"OptB": {"B2": 33},
5252
"OptC": {"B2": 55},
5353
},
54-
save_conditions={"B6": dcr2},
54+
success_conditions={"B6": dcr2},
5555
static_identifier_keys=["Labels"],
5656
result_labels={"B6": "meaningful_value"},
5757
save_dir=TEST_DATA_DIR / "design"

0 commit comments

Comments
 (0)