kreemyyyy commited on
Commit
6151f33
Β·
verified Β·
1 Parent(s): d52e72f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -91
app.py CHANGED
@@ -1,26 +1,20 @@
1
  import pandas as pd
2
- import openpyxl
3
  import gradio as gr
4
- import io
5
- import base64
6
- from datetime import datetime
7
 
8
  def convert_schedule(file_path, direction):
9
  if file_path is None:
10
- return pd.DataFrame({'Error': ['Please upload a file']}), None
11
 
12
  try:
13
- # 1. Load raw header rows to determine day labels
14
  raw = pd.read_excel(file_path, header=None)
15
  header1 = raw.iloc[0, 1:].astype(object)
16
  header2 = raw.iloc[1, 1:].astype(object)
17
 
18
- # Decide which header row to use: prefer second if fully populated
19
  if header2.notna().all() and not header2.str.startswith('Unnamed').any():
20
  days = header2.tolist()
21
  data_start = 2
22
  else:
23
- # Forward-fill merged first-row headers
24
  days = []
25
  last = None
26
  for val in header1:
@@ -31,7 +25,6 @@ def convert_schedule(file_path, direction):
31
  days.append(last)
32
  data_start = 1
33
 
34
- # 2. Load actual data using resolved day columns
35
  df = pd.read_excel(
36
  file_path,
37
  header=data_start,
@@ -39,14 +32,10 @@ def convert_schedule(file_path, direction):
39
  usecols=[0] + list(range(1, len(days) + 1))
40
  )
41
  df.columns = [str(day) for day in days]
42
-
43
- # 3. Retain original day column order
44
  day_cols = list(df.columns)
45
 
46
- # 4. Build assignment mapping via explicit iteration
47
  assignments = {}
48
  if direction == 'A to B':
49
- # Models in rows β†’ Texters as rows
50
  for model in df.index.astype(str):
51
  for day in day_cols:
52
  cell = df.at[model, day]
@@ -71,7 +60,6 @@ def convert_schedule(file_path, direction):
71
  models = days_map.get(day, [])
72
  result.at[texter, day] = ', '.join(models) if models else 'OFF'
73
  else:
74
- # Texters in rows β†’ Models as rows
75
  for texter in df.index.astype(str):
76
  for day in day_cols:
77
  cell = df.at[texter, day]
@@ -96,98 +84,44 @@ def convert_schedule(file_path, direction):
96
  texters = days_map.get(day, [])
97
  result.at[model, day] = ', '.join(texters) if texters else 'OFF'
98
 
99
- # 5. Cleanup axis names
100
  result.index.name = None
101
  result.columns.name = None
102
-
103
- # For display, include index as a column
104
  display_df = result.reset_index().rename(columns={'index': first_col_name})
105
-
106
- # 6. Create downloadable file using in-memory approach
107
- result_clean = result.copy().fillna('OFF')
108
 
109
- # Ensure all values are strings
110
- for col in result_clean.columns:
111
- result_clean[col] = result_clean[col].astype(str)
112
-
113
- # Create CSV file in memory (more reliable than Excel)
114
  download_df = result_clean.reset_index().rename(columns={'index': first_col_name})
 
115
 
116
- # Create CSV content
117
- csv_buffer = io.StringIO()
118
- download_df.to_csv(csv_buffer, index=False)
119
- csv_content = csv_buffer.getvalue()
120
-
121
- # Create filename with timestamp
122
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
123
- filename = f"converted_schedule_{timestamp}.csv"
124
-
125
- # Return the CSV content for download
126
- return display_df, (csv_content.encode('utf-8'), filename)
127
 
128
  except Exception as e:
129
- error_msg = f"Error processing file: {str(e)}"
130
- print(f"DEBUG: {error_msg}")
131
- error_df = pd.DataFrame({'Error': [error_msg]})
132
- return error_df, None
133
 
134
- # Wrapper function to handle the file download properly
135
- def process_and_download(file_path, direction):
136
- display_result, download_data = convert_schedule(file_path, direction)
137
-
138
- if download_data is None:
139
- return display_result, None
140
-
141
- # Create a temporary file that Gradio can serve
142
- import tempfile
143
- import os
144
-
145
- excel_content, filename = download_data
146
-
147
- # Save to a temporary file in the system temp directory
148
- temp_dir = tempfile.gettempdir()
149
- temp_path = os.path.join(temp_dir, filename)
150
-
151
- # Write CSV content
152
- with open(temp_path, 'w', encoding='utf-8') as f:
153
- f.write(excel_content.decode('utf-8'))
154
-
155
- return display_result, temp_path
156
-
157
- # Create the interface
158
  iface = gr.Interface(
159
- fn=process_and_download,
160
  inputs=[
161
- gr.File(
162
- label='Upload Weekly Schedule (.xlsx)',
163
- file_count='single',
164
- file_types=['.xlsx', '.xls']
165
- ),
166
- gr.Radio(
167
- ['A to B', 'B to A'],
168
- label='Convert Direction',
169
- value='A to B',
170
- info='A to B: Models→Texters, B to A: Texters→Models'
171
- )
172
  ],
173
  outputs=[
174
- gr.Dataframe(label='Converted Schedule (Preview)', wrap=True),
175
- gr.File(label='Download Converted Schedule (.csv)')
 
 
 
 
 
 
176
  ],
177
- title='πŸ”„ 7-Day Schedule Converter',
178
- description=(
179
- '**How to use:**\n'
180
- '1. Upload your Excel file with a 7-day schedule\n'
181
- '2. Choose conversion direction\n'
182
- '3. Preview the result and download the converted file\n\n'
183
- '*Supports merged headers and handles Models ↔ Texters conversion*'
184
- ),
185
  flagging_mode='never'
186
  )
187
 
188
  if __name__ == "__main__":
189
- iface.launch(
190
- server_name='0.0.0.0',
191
- server_port=7860,
192
- share=False
193
- )
 
1
  import pandas as pd
 
2
  import gradio as gr
 
 
 
3
 
4
  def convert_schedule(file_path, direction):
5
  if file_path is None:
6
+ return pd.DataFrame({'Message': ['Please upload a file']}), ""
7
 
8
  try:
9
+ # Same conversion logic as before
10
  raw = pd.read_excel(file_path, header=None)
11
  header1 = raw.iloc[0, 1:].astype(object)
12
  header2 = raw.iloc[1, 1:].astype(object)
13
 
 
14
  if header2.notna().all() and not header2.str.startswith('Unnamed').any():
15
  days = header2.tolist()
16
  data_start = 2
17
  else:
 
18
  days = []
19
  last = None
20
  for val in header1:
 
25
  days.append(last)
26
  data_start = 1
27
 
 
28
  df = pd.read_excel(
29
  file_path,
30
  header=data_start,
 
32
  usecols=[0] + list(range(1, len(days) + 1))
33
  )
34
  df.columns = [str(day) for day in days]
 
 
35
  day_cols = list(df.columns)
36
 
 
37
  assignments = {}
38
  if direction == 'A to B':
 
39
  for model in df.index.astype(str):
40
  for day in day_cols:
41
  cell = df.at[model, day]
 
60
  models = days_map.get(day, [])
61
  result.at[texter, day] = ', '.join(models) if models else 'OFF'
62
  else:
 
63
  for texter in df.index.astype(str):
64
  for day in day_cols:
65
  cell = df.at[texter, day]
 
84
  texters = days_map.get(day, [])
85
  result.at[model, day] = ', '.join(texters) if texters else 'OFF'
86
 
 
87
  result.index.name = None
88
  result.columns.name = None
89
+
90
+ # For display
91
  display_df = result.reset_index().rename(columns={'index': first_col_name})
 
 
 
92
 
93
+ # Create CSV text for copying
94
+ result_clean = result.copy().fillna('OFF')
 
 
 
95
  download_df = result_clean.reset_index().rename(columns={'index': first_col_name})
96
+ csv_text = download_df.to_csv(index=False)
97
 
98
+ return display_df, csv_text
 
 
 
 
 
 
 
 
 
 
99
 
100
  except Exception as e:
101
+ error_df = pd.DataFrame({'Error': [f"Error: {str(e)}"]})
102
+ return error_df, f"Error: {str(e)}"
 
 
103
 
104
+ # Interface with copy-paste text output
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  iface = gr.Interface(
106
+ fn=convert_schedule,
107
  inputs=[
108
+ gr.File(label='Upload Weekly Schedule (.xlsx)', file_types=['.xlsx', '.xls']),
109
+ gr.Radio(['A to B', 'B to A'], label='Convert Direction', value='A to B')
 
 
 
 
 
 
 
 
 
110
  ],
111
  outputs=[
112
+ gr.Dataframe(label='Converted Schedule (Preview)'),
113
+ gr.Textbox(
114
+ label='CSV Data (Copy This Text)',
115
+ lines=20,
116
+ max_lines=50,
117
+ show_copy_button=True,
118
+ info="Copy this text and paste it into Excel or save as .csv file"
119
+ )
120
  ],
121
+ title='πŸ”„ Schedule Converter - Copy/Paste Version',
122
+ description='Upload β†’ Convert β†’ Copy the CSV text β†’ Paste into Excel or save as .csv',
 
 
 
 
 
 
123
  flagging_mode='never'
124
  )
125
 
126
  if __name__ == "__main__":
127
+ iface.launch(server_name='0.0.0.0', server_port=7860)