kreemyyyy commited on
Commit
89fb4b7
Β·
verified Β·
1 Parent(s): cab122b

Update schedule_converter.py

Browse files
Files changed (1) hide show
  1. schedule_converter.py +264 -0
schedule_converter.py CHANGED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import tempfile
4
+ import os
5
+ import requests
6
+ from openpyxl import load_workbook
7
+ from openpyxl.styles import Alignment
8
+
9
+ def auto_correct_names(series, threshold=90):
10
+ try:
11
+ from fuzzywuzzy import process, fuzz
12
+ except ImportError:
13
+ return series # Fallback if fuzzywuzzy is not installed
14
+ unique_names = series.dropna().unique()
15
+ name_mapping = {}
16
+ for name in unique_names:
17
+ matches = process.extractBests(
18
+ name, unique_names,
19
+ scorer=fuzz.token_sort_ratio,
20
+ score_cutoff=threshold
21
+ )
22
+ if matches:
23
+ best_match = max(matches, key=lambda x: (x[1], list(series).count(x[0])))
24
+ name_mapping[name] = best_match[0]
25
+ return series.replace(name_mapping)
26
+
27
+ def adjust_excel_formatting(file_path):
28
+ wb = load_workbook(file_path)
29
+ ws = wb.active
30
+ for col in ws.columns:
31
+ max_length = 0
32
+ col_letter = col[0].column_letter
33
+ for cell in col:
34
+ if cell.value:
35
+ max_length = max(max_length, len(str(cell.value)))
36
+ cell.alignment = Alignment(wrap_text=True)
37
+ ws.column_dimensions[col_letter].width = max_length + 2
38
+ wb.save(file_path)
39
+
40
+ def process_file_a_to_b(input_file, output_file):
41
+ try:
42
+ # Read the Excel file, skipping the first row (OVERNIGHT/MORNING header)
43
+ input_df = pd.read_excel(input_file, header=1)
44
+
45
+ # Get the date columns (all columns except the first one which contains model names)
46
+ date_columns = input_df.columns[1:].tolist()
47
+
48
+ # Melt the dataframe to long format
49
+ df_long = input_df.melt(
50
+ id_vars=[input_df.columns[0]], # First column (Model names)
51
+ var_name='DATE',
52
+ value_name='CHATTER'
53
+ )
54
+
55
+ # Clean up the data
56
+ df_long = df_long[df_long['CHATTER'].notna()] # Remove empty cells
57
+ df_long = df_long[df_long['CHATTER'] != ''] # Remove empty strings
58
+ df_long = df_long[df_long['CHATTER'] != 'OFF'] # Remove 'OFF' entries
59
+
60
+ # Group by chatter and date, collect all models
61
+ grouped = df_long.groupby(['CHATTER', 'DATE'])[input_df.columns[0]].apply(
62
+ lambda x: ', '.join(sorted(x))
63
+ ).reset_index()
64
+
65
+ # Pivot to get chatters as rows and dates as columns
66
+ pivoted = grouped.pivot(
67
+ index='CHATTER',
68
+ columns='DATE',
69
+ values=input_df.columns[0]
70
+ )
71
+
72
+ # Reorder columns to match original date order
73
+ pivoted = pivoted[date_columns]
74
+
75
+ # Define the expected order of chatters
76
+ expected_chatters = [
77
+ 'VELJKO2', 'VELJKO3', 'MARKO', 'GODDARD', 'ALEKSANDER', 'FEELIP',
78
+ 'DENIS', 'TOME', 'MILA', 'VELJKO', 'DAMJAN', 'DULE', 'CONRAD',
79
+ 'ALEXANDER', 'VEJKO3'
80
+ ]
81
+
82
+ # Reindex with expected order, keeping any additional chatters at the end
83
+ final_df = pivoted.reindex(expected_chatters + [x for x in pivoted.index if x not in expected_chatters])
84
+
85
+ # Fill empty cells with 'OFF'
86
+ final_df = final_df.fillna('OFF')
87
+
88
+ # Reset index and rename the index column to 'CHATTER'
89
+ final_df = final_df.reset_index()
90
+ final_df = final_df.rename(columns={'index': 'CHATTER'})
91
+
92
+ # Try to save to Excel, with error handling
93
+ try:
94
+ final_df.to_excel(output_file, index=False)
95
+ print(f"Saved Format B to {output_file}")
96
+ except PermissionError:
97
+ # If file is in use, try a different name
98
+ base, ext = os.path.splitext(output_file)
99
+ new_output = f"{base}_new{ext}"
100
+ final_df.to_excel(new_output, index=False)
101
+ print(f"Original file was in use. Saved Format B to {new_output}")
102
+ except Exception as e:
103
+ print(f"Error processing file: {str(e)}")
104
+ raise
105
+
106
+ def process_file_b_to_a(input_file, output_file):
107
+ try:
108
+ # Read the Excel file
109
+ input_df = pd.read_excel(input_file, header=0)
110
+
111
+ # Get the date columns (all columns except the first one which contains chatter names)
112
+ date_columns = input_df.columns[1:].tolist()
113
+
114
+ # Melt the dataframe to long format
115
+ df_long = input_df.melt(
116
+ id_vars=[input_df.columns[0]], # First column (Chatter names)
117
+ var_name='DATE',
118
+ value_name='MODEL'
119
+ )
120
+
121
+ # Clean up the data
122
+ df_long = df_long[df_long['MODEL'].notna()] # Remove empty cells
123
+ df_long = df_long[df_long['MODEL'] != ''] # Remove empty strings
124
+ df_long = df_long[df_long['MODEL'] != 'OFF'] # Remove 'OFF' entries
125
+
126
+ # Split comma-separated models into separate rows
127
+ df_long['MODEL'] = df_long['MODEL'].str.split(', ')
128
+ df_long = df_long.explode('MODEL')
129
+
130
+ # Group by model and date, collect all chatters
131
+ grouped = df_long.groupby(['MODEL', 'DATE'])[input_df.columns[0]].apply(
132
+ lambda x: ', '.join(sorted(x))
133
+ ).reset_index()
134
+
135
+ # Pivot to get models as rows and dates as columns
136
+ pivoted = grouped.pivot(
137
+ index='MODEL',
138
+ columns='DATE',
139
+ values=input_df.columns[0]
140
+ )
141
+
142
+ # Reorder columns to match original date order
143
+ pivoted = pivoted[date_columns]
144
+
145
+ # Sort models by frequency
146
+ model_order = grouped['MODEL'].value_counts().index.tolist()
147
+ final_df = pivoted.reindex(model_order)
148
+
149
+ # Fill empty cells with 'OFF'
150
+ final_df = final_df.fillna('OFF')
151
+
152
+ # Reset index to make MODEL a column
153
+ final_df = final_df.reset_index()
154
+
155
+ # Try to save to Excel, with error handling
156
+ try:
157
+ final_df.to_excel(output_file, index=False)
158
+ print(f"Saved Format A to {output_file}")
159
+ except PermissionError:
160
+ # If file is in use, try a different name
161
+ base, ext = os.path.splitext(output_file)
162
+ new_output = f"{base}_new{ext}"
163
+ final_df.to_excel(new_output, index=False)
164
+ print(f"Original file was in use. Saved Format A to {new_output}")
165
+ except Exception as e:
166
+ print(f"Error processing file: {str(e)}")
167
+ raise
168
+
169
+ def save_and_format_excel(df, original_filename):
170
+ name_part, ext_part = os.path.splitext(os.path.basename(original_filename))
171
+ processed_filename = f"{name_part}_processed{ext_part}"
172
+ temp_file_path = os.path.join(tempfile.gettempdir(), processed_filename)
173
+ df.to_excel(temp_file_path, index=False, sheet_name='Schedule')
174
+ adjust_excel_formatting(temp_file_path)
175
+ return temp_file_path
176
+
177
+ def get_local_file_from_path_or_url(path_or_url):
178
+ if path_or_url.startswith('http://') or path_or_url.startswith('https://'):
179
+ # Download the file
180
+ response = requests.get(path_or_url, stream=True)
181
+ response.raise_for_status()
182
+ suffix = os.path.splitext(path_or_url)[-1] or '.xlsx'
183
+ with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp_file:
184
+ for chunk in response.iter_content(chunk_size=8192):
185
+ tmp_file.write(chunk)
186
+ return tmp_file.name
187
+ else:
188
+ return path_or_url
189
+
190
+ def process_file(input_file, direction):
191
+ try:
192
+ if direction == "Format A β†’ Format B":
193
+ df = process_file_a_to_b(input_file, direction)
194
+ else:
195
+ df = process_file_b_to_a(input_file, direction)
196
+ temp_file_path = save_and_format_excel(df, input_file)
197
+ return df, temp_file_path
198
+ except Exception as e:
199
+ error_df = pd.DataFrame({"Error": [f"⚠️ {str(e)}"]})
200
+ return error_df, None
201
+
202
+ def download_file(out_path):
203
+ return out_path
204
+
205
+ with gr.Blocks(title="Schedule Converter") as demo:
206
+ gr.Markdown("# πŸ“… Schedule Converter")
207
+ gr.Markdown("Upload your schedule Excel file, select conversion direction, and download the result.")
208
+ with gr.Row():
209
+ input_file = gr.File(label="Upload Schedule File", type="filepath")
210
+ direction = gr.Dropdown([
211
+ "Format A β†’ Format B",
212
+ "Format B β†’ Format A"
213
+ ], value="Format A β†’ Format B", label="Conversion Direction")
214
+ with gr.Row():
215
+ process_btn = gr.Button("Process File", variant="primary")
216
+ reset_btn = gr.Button("Upload New File")
217
+ output_table = gr.Dataframe(label="Preview", wrap=True)
218
+ download_button = gr.Button("Download Processed File", visible=False)
219
+ temp_file_path = gr.State(value=None)
220
+ def reset_components():
221
+ return [None, pd.DataFrame(), None, gr.update(visible=False)]
222
+ def process_and_show(file, direction):
223
+ df, out_path = process_file(file, direction)
224
+ if out_path:
225
+ return df, out_path, gr.update(visible=True)
226
+ return df, None, gr.update(visible=False)
227
+ process_btn.click(
228
+ process_and_show,
229
+ inputs=[input_file, direction],
230
+ outputs=[output_table, temp_file_path, download_button]
231
+ )
232
+ reset_btn.click(
233
+ reset_components,
234
+ outputs=[input_file, output_table, temp_file_path, download_button]
235
+ )
236
+ download_button.click(
237
+ download_file,
238
+ inputs=temp_file_path,
239
+ outputs=gr.File(label="Processed Schedule")
240
+ )
241
+ if __name__ == "__main__":
242
+ print("Enter the path or URL to your Excel file:")
243
+ file_path_or_url = input().strip()
244
+ print("Enter output file path (e.g., D:/work/formatter/schedule_a.xlsx):")
245
+ output_path = input().strip()
246
+ print("Select conversion direction:")
247
+ print("1: Format A β†’ Format B")
248
+ print("2: Format B β†’ Format A")
249
+ direction_input = input().strip()
250
+ direction = "Format A β†’ Format B" if direction_input == "1" else "Format B β†’ Format A"
251
+
252
+ try:
253
+ local_file = get_local_file_from_path_or_url(file_path_or_url)
254
+ if direction == "Format A β†’ Format B":
255
+ process_file_a_to_b(local_file, output_path)
256
+ else:
257
+ process_file_b_to_a(local_file, output_path)
258
+ except Exception as e:
259
+ print(f"Error: {str(e)}")
260
+ print("Please make sure:")
261
+ print("1. The input file exists and is not open in Excel")
262
+ print("2. The output file is not open in Excel")
263
+ print("3. You have write permissions in the output directory")
264
+ demo.launch()