@@ -17,6 +17,7 @@ def excel_runner(
1717 dynamic_inputs : dict [str , dict [str , float ]],
1818 save_conditions : dict [str , callable ],
1919 static_identifier_keys : Optional [list [str ]] = None ,
20+ result_labels : Optional [dict [str , str ]] = None ,
2021 save_dir : Optional [str ] = None ,
2122 sheet_idx : int = 0 ,
2223) -> None :
@@ -42,12 +43,18 @@ def excel_runner(
4243 'save_conditions': a dictionary keyed by cell references whose values are unary callables
4344 which return a bool when passed the value retrieved from the workbook at the cell
4445 reference during each iteration. If all callables in the 'save_conditions' dict
45- return True, then that iteration of the workbook will be saved to disk.
46+ return True, then that iteration of the workbook will be saved to disk. Use the
47+ create_condition_check() function in this module to quickly create such callables.
4648 'static_identifier_keys': The keys in 'static_inputs', which are not cell references,
4749 which will be used to create unique filenames whenever the save conditions are all
4850 True. e.g. if there is a key in 'static_inputs' called 'Label', then passing a list
4951 of ['Label'] as the static_identifier_keys will ensure that the data under the 'Label'
5052 key will be used as part of the unique filename.
53+ 'result_labels': A mapping of result cell references to what those cell references mean
54+ for a human. e.g. if the result cell B6 referred to a "shear utilization ratio" then
55+ the result_label dict might look like this: {"B6": "shear utilization ratio"}
56+ The result label will be used in the returned results. If None, then the cell references
57+ will be used instead.
5158 'save_dir': The directory to store saved workbooks
5259 'sheet_idx': The sheet to modify within the workbook.
5360 """
@@ -73,6 +80,7 @@ def excel_runner(
7380 panel = Panel (progress_group )
7481
7582 main_task = main_progress .add_task ("Primary Iterations" , total = iterations )
83+ dynamic_results = {}
7684 with Live (panel ) as live :
7785 for iteration in range (iterations ):
7886 demand_cells_to_change = {
@@ -85,8 +93,13 @@ def excel_runner(
8593 for cell_id in demand_cell_ids
8694 if not valid_excel_reference (cell_id )
8795 }
96+ if identifier_values :
97+ identifiers = "-" .join ([static_inputs [id_key ][iteration ] for id_key in static_identifier_keys ])
98+ else :
99+ identifiers = f"{ iteration } "
88100 variations_task = variations_progress .add_task ("Sheet variations" , total = len (dynamic_inputs .items ()))
89101 variations_progress .reset (variations_task )
102+ failed_results = {}
90103 for design_tag , design_cells_to_change in dynamic_inputs .items ():
91104 cells_to_change = demand_cells_to_change | design_cells_to_change
92105 calculated_results = execute_workbook (
@@ -95,7 +108,13 @@ def excel_runner(
95108 cells_to_retrieve = list (save_conditions .keys ()),
96109 sheet_idx = sheet_idx
97110 )
98-
111+ if isinstance (result_labels , dict ):
112+ labeled_results = {result_labels [k ]: v for k , v in calculated_results .items ()}
113+ else :
114+ labeled_results = calculated_results
115+
116+ failed_results .update ({design_tag : labeled_results })
117+
99118 save_condition_acc = []
100119 for result_cell_id , save_condition in save_conditions .items ():
101120 calculated_result = calculated_results [result_cell_id ]
@@ -106,28 +125,27 @@ def excel_runner(
106125 filepath = pathlib .Path (xlsx_filepath )
107126 name = filepath .stem
108127 suffix = filepath .suffix
109- if identifier_values :
110- identifiers = "-" .join ([static_identifier_keys [id_key ] for id_key in static_identifier_keys ])
111- else :
112- identifiers = f"{ iteration } "
113128
114129 new_filename = f"{ name } -{ identifiers } -{ design_tag } { suffix } "
115130 save_dir_path = pathlib .Path (save_dir )
116131 if not save_dir_path .exists ():
117132 save_dir_path .mkdir (parents = True )
118- calculated_results = execute_workbook (
133+ _ = execute_workbook (
119134 xlsx_filepath ,
120135 cells_to_change = cells_to_change ,
121136 cells_to_retrieve = list (save_conditions .keys ()),
122137 new_filepath = f"{ str (save_dir )} /{ new_filename } " ,
123138 sheet_idx = sheet_idx ,
124139 )
140+ dynamic_results .update ({identifiers : {"successful_key" : design_tag } | labeled_results })
125141 variations_progress .remove_task (variations_task )
126142 break
127143 else :
128144 variations_progress .remove_task (variations_task )
145+ dynamic_results .update ({identifiers : {"successful_key" : None } | failed_results })
129146 progress_group .renderables .append (Text (f"Variation: { iteration } did not meet the criteria" ))
130147 main_progress .update (main_task , advance = 1 )
148+ return dynamic_results
131149
132150
133151def execute_workbook (
@@ -158,6 +176,23 @@ def execute_workbook(
158176 locations. Can be a str or pathlib.Path. Directories on
159177 the path must already exist because this function will not create them if
160178 they do not.
179+
180+ ### Example:
181+
182+ dcr2 = xl.create_condition_check(2, "ge")
183+ results = xl.excel_runner(
184+ "example_wb.xlsx",
185+ static_inputs={"B1": [10, 20], "Labels": ["C01", "C02"]},
186+ dynamic_inputs={
187+ "OptA": {"B2": 22},
188+ "OptB": {"B2": 33},
189+ "OptC": {"B2": 55},
190+ },
191+ save_conditions={"B6": dcr2},
192+ static_identifier_keys=["Labels"],
193+ result_labels={"B6": "meaningful_value"},
194+ save_dir=TEST_DATA_DIR / "design"
195+ )
161196 """
162197 xlsx_filepath = pathlib .Path (xlsx_filepath )
163198 if not xlsx_filepath .exists ():
@@ -209,6 +244,12 @@ def create_condition_check(check_against_value: float, op: str) -> callable:
209244 'check_against_value' the value that will be encoded in the function
210245 to check against.
211246 'op': str, one of {"ge", "le", "gt", "lt", "eq", "ne"}
247+ - "ge" Greater-than-or-equal-to
248+ - "le" Less-than-or-equal-to
249+ - "gt" Greater-than
250+ - "lt" Less-than
251+ - "eq" Equal-to
252+ - "ne" Not-equal-to
212253 """
213254 operators = {
214255 "ge" : operator .ge ,
0 commit comments