File size: 4,298 Bytes
cdf2807 41a9969 cdf2807 bc36177 cdf2807 41a9969 aa3525b e22be08 41a9969 40ca158 a3de3da 41a9969 40ca158 41a9969 40ca158 cdf2807 41a9969 40ca158 41a9969 40ca158 41a9969 aa3525b cdf2807 41a9969 aa3525b 40ca158 aa3525b 40ca158 aa3525b 40ca158 41a9969 aa3525b 40ca158 aa3525b 40ca158 aa3525b 40ca158 aa3525b af26c90 41a9969 af26c90 bc36177 1fd5317 bc36177 1fd5317 41a9969 bc36177 af26c90 41a9969 aa3525b 40ca158 aa3525b bc36177 aa3525b 41a9969 aa3525b cdf2807 eb59eaa 1fd5317 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
import pandas as pd
import openpyxl # ensure XLSX engine is available
import gradio as gr
import uuid
import os
# 7-Day Schedule Converter with explicit iteration and header fill and download support
def convert_schedule(file_path, direction):
# 1. Load Excel sheet without header to inspect real headers
raw = pd.read_excel(file_path, header=None)
header1 = raw.iloc[0,1:].astype(object)
header2 = raw.iloc[1,1:].astype(object)
# Decide which header row to use: prefer fully populated second row
if header2.notna().all() and not header2.str.startswith('Unnamed').any():
days = header2.tolist()
data_start = 2
else:
# Forward-fill merged first-row headers
days = []
last = None
for val in header1:
if pd.isna(val) or str(val).startswith('Unnamed'):
days.append(last)
else:
last = str(val)
days.append(last)
data_start = 1
# 2. Load actual data with resolved day columns
df = pd.read_excel(
file_path,
header=data_start,
index_col=0,
usecols=[0] + list(range(1, len(days) + 1))
)
df.columns = [str(day) for day in days]
# 3. Retain exactly the original day columns
day_cols = list(df.columns)
# 4. Build assignment mapping via explicit iteration
assignments = {}
if direction == 'A to B':
for model in df.index.astype(str):
for day in day_cols:
cell = df.at[model, day]
for texter in str(cell).split(','):
texter = texter.strip()
if not texter or texter.lower() in ['nan', 'none']:
continue
assignments.setdefault(texter, {d: [] for d in day_cols})
assignments[texter][day].append(model)
# Create result DataFrame
index = sorted(assignments.keys())
result = pd.DataFrame(index=index, columns=day_cols)
for texter, days_map in assignments.items():
for day in day_cols:
models = days_map.get(day, [])
result.at[texter, day] = ', '.join(models) if models else 'OFF'
else:
for texter in df.index.astype(str):
for day in day_cols:
cell = df.at[texter, day]
for model in str(cell).split(','):
model = model.strip()
if not model or model.lower() in ['nan', 'none']:
continue
assignments.setdefault(model, {d: [] for d in day_cols})
assignments[model][day].append(texter)
index = sorted(assignments.keys())
result = pd.DataFrame(index=index, columns=day_cols)
for model, days_map in assignments.items():
for day in day_cols:
texters = days_map.get(day, [])
result.at[model, day] = ', '.join(texters) if texters else 'OFF'
# 5. Cleanup axis names
result.index.name = None
result.columns.name = None
# 6. Save to Excel for download, specifying engine
output_filename = f"converted_{uuid.uuid4().hex}.xlsx"
# Save under /mnt/data so HF Spaces can serve it
output_path = os.path.join('/mnt/data', output_filename)
result.to_excel(output_path, engine='openpyxl', index=True)
# Return both DataFrame and download path
return result, output_path
# Gradio UI definition
def main():
iface = gr.Interface(
fn=convert_schedule,
inputs=[
gr.File(label='Upload Weekly Schedule (.xlsx)', file_count='single', type='filepath'),
gr.Radio(['A to B', 'B to A'], label='Convert Direction')
],
outputs=[
gr.Dataframe(label='Converted Schedule'),
gr.File(label='Download Converted Excel')
],
title='7-Day Schedule Converter',
description=(
'Upload a 7-column weekly schedule (Models vs Days) with merged or single headers, '
'then flip between Models→Texters or Texters→Models. Download the result as .xlsx.'
),
allow_flagging='never'
)
iface.launch(server_name='0.0.0.0', server_port=7860)
if __name__ == '__main__':
main() |