1313
1414def excel_runner (
1515 xlsx_filepath ,
16- static_inputs : dict [str , list ],
16+ static_inputs : dict [str , list [ float | int | str ]] | list [ dict [ str , float | int | str ] ],
1717 dynamic_inputs : dict [str , dict [str , float ]],
1818 success_conditions : dict [str , callable ],
1919 static_identifier_keys : Optional [list [str ]] = None ,
2020 result_labels : Optional [dict [str , str ]] = None ,
21+ static_input_maps : Optional [dict [str , str ]] = None ,
2122 save_dir : Optional [str ] = None ,
2223 sheet_idx : int = 0 ,
2324) -> None :
@@ -29,13 +30,16 @@ def excel_runner(
2930 True for that iteration, then the workbook with that iteration's inputs is saved
3031 to disk.
3132
32- 'static_inputs': a dictionary keyed by either data labels or cell references. The
33- values are lists of values (like columns in a table). Each index of the values
34- represent the data used for one iteration. For keys containing cell references,
33+ 'static_inputs': a dictionary where each key is a cell reference and the values are a
34+ list of values to place in the cell OR a list of dictionaries, where each key is a
35+ cell reference and the value is the value to be placed.
36+ Each index in the list (whether the list is the inner or outer collection type)
37+ represents the data used for one iteration. For keys containing cell references,
3538 the cell reference is used as a static input value to the workbook. For keys
3639 that are not cell references, their values are accessible by 'static_identifier_keys',
3740 which will be used for creating the unique filename in the event that the
38- 'save_conditions' are satisfied.
41+ 'save_conditions' are satisfied. If the key is not in 'static_identifier_keys',
42+ it will be assumed to be a cell reference.
3943 'dynamic_inputs': a dictionary of dictionaries. The outer keys represent the unique
4044 label to describe the iteration, e.g. the name of the design element.
4145 The values are dictionaries keyed by cell references with single values which will
@@ -55,12 +59,17 @@ def excel_runner(
5559 the result_label dict might look like this: {"B6": "shear utilization ratio"}
5660 The result label will be used in the returned results. If None, then the cell references
5761 will be used instead.
62+ 'static_input_maps': A mapping of keys in 'static_inputs' to cell references. This is useful
63+ to provide when your data is keyed by some other process and you do not want to manually
64+ re-map your data to be keyed by cell referdences. By providing 'static_input_maps', this
65+ excel_runner will do that for you.
5866 'save_dir': The directory to store saved workbooks
5967 'sheet_idx': The sheet to modify within the workbook.
6068 """
61-
62- demand_cell_ids = list (static_inputs .keys ())
63- iterations = len (static_inputs [demand_cell_ids [0 ]])
69+ static_inputs = format_static_inputs (static_inputs )
70+ iterations = len (static_inputs )
71+ if static_input_maps is None :
72+ static_input_maps = dict ()
6473
6574 main_progress = Progress (
6675 TextColumn ("{task.description}" ),
@@ -83,18 +92,19 @@ def excel_runner(
8392 dynamic_results = {}
8493 with Live (panel ) as live :
8594 for iteration in range (iterations ):
95+ static_data = static_inputs [iteration ]
8696 demand_cells_to_change = {
87- cell_id : static_inputs [ cell_id ][ iteration ]
88- for cell_id in demand_cell_ids
89- if cell_id not in static_identifier_keys
97+ static_input_maps . get ( k , k ): v
98+ for k , v in static_data . items ()
99+ if k not in static_identifier_keys
90100 }
91101 identifier_values = {
92- cell_id : str (static_inputs [ cell_id ][ iteration ] )
93- for cell_id in demand_cell_ids
94- if cell_id in static_identifier_keys
102+ k : str (v )
103+ for k , v in static_data . items ()
104+ if k in static_identifier_keys
95105 }
96106 if identifier_values :
97- identifiers = "-" .join ([ static_inputs [ id_key ][ iteration ] for id_key in static_identifier_keys ] )
107+ identifiers = "-" .join (identifier_values . values () )
98108 else :
99109 identifiers = f"{ iteration } "
100110 variations_task = variations_progress .add_task ("Sheet variations" , total = len (dynamic_inputs .items ()))
@@ -275,4 +285,27 @@ def valid_excel_reference(cell: str) -> bool:
275285 if match is None :
276286 return False
277287 else :
278- return True
288+ return True
289+
290+
291+ def format_static_inputs (
292+ static_inputs : dict [str , list [float | int | str ]] | list [dict [str , float | int | str ]]
293+ ) -> list [dict [str , float | int | str ]]:
294+ """
295+ Transforms a dictionary of str keys and list values to a list of dictionaries.
296+
297+ All sub-lists must be the same size.
298+ """
299+ if isinstance (static_inputs , list ) and isinstance (static_inputs [0 ], dict ):
300+ return static_inputs
301+ else :
302+ column_data = [list_data for list_data in static_inputs .values ()]
303+ row_data = zip (* column_data )
304+ outer_acc = []
305+ for row in row_data :
306+ inner_acc = {}
307+ for idx , key in enumerate (static_inputs .keys ()):
308+ inner_acc .update ({key : row [idx ]})
309+ outer_acc .append (inner_acc )
310+ return outer_acc
311+
0 commit comments