NavyDevilDoc commited on
Commit
2884750
Β·
verified Β·
1 Parent(s): b29d555

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +176 -22
src/streamlit_app.py CHANGED
@@ -30,40 +30,194 @@ def main():
30
  manual_interface()
31
 
32
  def excel_interface():
33
- """Handle Excel file upload and analysis."""
34
  st.header("πŸ“ Excel File Analysis")
35
 
 
 
 
36
  uploaded_file = st.file_uploader(
37
  "Upload Excel file with Config and Data sheets",
38
- type=['xlsx'],
39
- help="Excel file should have 'Config' sheet (category, maximize) and 'Data' sheet (name, category values)"
 
40
  )
41
 
42
  if uploaded_file is not None:
43
- try:
44
- # Load calculator from Excel
45
- calc = UtilityCalculator.from_excel(uploaded_file)
46
-
47
- st.success(f"βœ… Loaded {len(calc.products)} products with {len(calc.categories)} categories")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
- # Display configuration
50
- st.subheader("Configuration")
51
- config_df = pd.DataFrame({
52
- 'Category': calc.categories,
53
- 'Optimize': ['Maximize' if calc.maximize[cat] else 'Minimize' for cat in calc.categories],
54
- 'Weight': [calc.weights[cat] for cat in calc.categories]
55
  })
56
- st.dataframe(config_df, use_container_width=True)
57
 
58
- # Weight adjustment
59
- adjust_weights(calc)
 
 
 
 
60
 
61
- # Results
62
- display_results(calc)
63
 
64
- except Exception as e:
65
- st.error(f"❌ Error loading Excel file: {str(e)}")
66
- st.info("Make sure your Excel file has 'Config' and 'Data' sheets with the correct format.")
 
 
 
67
 
68
  def manual_interface():
69
  """Handle manual data entry interface."""
 
30
  manual_interface()
31
 
32
  def excel_interface():
33
+ """Handle Excel file upload with CSV conversion for HF Spaces compatibility."""
34
  st.header("πŸ“ Excel File Analysis")
35
 
36
+ # Add file upload instructions
37
+ st.info("πŸ’‘ Upload an Excel file with 'Config' and 'Data' sheets. The file will be converted to CSV format for processing.")
38
+
39
  uploaded_file = st.file_uploader(
40
  "Upload Excel file with Config and Data sheets",
41
+ type=['xlsx', 'xls'],
42
+ help="Excel file should have 'Config' sheet (category, maximize) and 'Data' sheet (name, category values)",
43
+ key="excel_uploader"
44
  )
45
 
46
  if uploaded_file is not None:
47
+ st.success(f"βœ… File uploaded: **{uploaded_file.name}**")
48
+
49
+ # Show file details
50
+ col1, col2, col3 = st.columns(3)
51
+ with col1:
52
+ st.metric("File Size", f"{uploaded_file.size:,} bytes")
53
+ with col2:
54
+ st.metric("File Type", uploaded_file.type)
55
+ with col3:
56
+ process_button = st.button("πŸš€ Process File", type="primary", use_container_width=True)
57
+
58
+ if process_button:
59
+ with st.spinner("πŸ”„ Processing Excel file via CSV conversion..."):
60
+ try:
61
+ # Method 1: HF Spaces compatible approach
62
+ # Read Excel file and convert to CSV in memory
63
+ uploaded_file.seek(0)
64
+
65
+ # Read both sheets from Excel
66
+ config_df = pd.read_excel(uploaded_file, sheet_name='Config')
67
+ data_df = pd.read_excel(uploaded_file, sheet_name='Data')
68
+
69
+ st.success("βœ… Successfully read Excel sheets")
70
+
71
+ # Show preview of what we read
72
+ with st.expander("πŸ“‹ File Contents Preview", expanded=True):
73
+ col1, col2 = st.columns(2)
74
+ with col1:
75
+ st.write("**Config Sheet:**")
76
+ st.dataframe(config_df, use_container_width=True)
77
+ with col2:
78
+ st.write("**Data Sheet:**")
79
+ st.dataframe(data_df.head(), use_container_width=True)
80
+
81
+ # Convert to CSV format (in memory) - this is the key part!
82
+ import io
83
+ config_csv = io.StringIO()
84
+ data_csv = io.StringIO()
85
+
86
+ config_df.to_csv(config_csv, index=False)
87
+ data_df.to_csv(data_csv, index=False)
88
+
89
+ # Reset StringIO positions
90
+ config_csv.seek(0)
91
+ data_csv.seek(0)
92
+
93
+ st.info("πŸ”„ Converted to CSV format for processing...")
94
+
95
+ # Now create the MCDA calculator from the CSV data
96
+ # Parse categories and maximize settings
97
+ categories = config_df['category'].tolist()
98
+ maximize_values = config_df['maximize'].tolist()
99
+ maximize = dict(zip(categories, maximize_values))
100
+
101
+ # Create calculator
102
+ calc = UtilityCalculator(categories, maximize)
103
+
104
+ # Add products from data
105
+ for _, row in data_df.iterrows():
106
+ product_name = row['name']
107
+ scores = {cat: row[cat] for cat in categories if cat in row}
108
+ calc.add_product(product_name, scores)
109
+
110
+ st.success(f"βœ… Successfully created calculator with {len(calc.products)} products and {len(calc.categories)} categories")
111
+
112
+ # Store in session state
113
+ st.session_state['excel_calculator'] = calc
114
+ st.session_state['excel_filename'] = uploaded_file.name
115
+
116
+ # Display configuration
117
+ st.subheader("πŸ“‹ Configuration")
118
+ config_display_df = pd.DataFrame({
119
+ 'Category': calc.categories,
120
+ 'Optimize': ['Maximize' if calc.maximize[cat] else 'Minimize' for cat in calc.categories],
121
+ 'Weight': [calc.weights[cat] for cat in calc.categories]
122
+ })
123
+ st.dataframe(config_display_df, use_container_width=True)
124
+
125
+ # Weight adjustment
126
+ adjust_weights(calc)
127
+
128
+ # Results
129
+ display_results(calc)
130
+
131
+ except Exception as e:
132
+ st.error(f"❌ Error processing Excel file: {str(e)}")
133
+
134
+ # Enhanced debugging
135
+ with st.expander("πŸ› Detailed Error Information"):
136
+ st.write("**Error Details:**")
137
+ st.write(f"- Error type: {type(e).__name__}")
138
+ st.write(f"- Error message: {str(e)}")
139
+
140
+ # Try to diagnose the issue
141
+ try:
142
+ uploaded_file.seek(0)
143
+ excel_file = pd.ExcelFile(uploaded_file)
144
+ st.write(f"- Available sheets: {excel_file.sheet_names}")
145
+
146
+ # Check if required sheets exist
147
+ if 'Config' not in excel_file.sheet_names:
148
+ st.error("❌ 'Config' sheet not found")
149
+ if 'Data' not in excel_file.sheet_names:
150
+ st.error("❌ 'Data' sheet not found")
151
+
152
+ except Exception as diag_error:
153
+ st.write(f"- Could not diagnose: {diag_error}")
154
+
155
+ import traceback
156
+ st.code(traceback.format_exc())
157
+
158
+ # Display results if calculator is in session state (from previous processing)
159
+ elif 'excel_calculator' in st.session_state:
160
+ calc = st.session_state['excel_calculator']
161
+ filename = st.session_state.get('excel_filename', 'Previous file')
162
+
163
+ st.info(f"πŸ“Š Currently analyzing: **{filename}**")
164
+
165
+ if st.button("πŸ”„ Clear and Upload New File"):
166
+ if 'excel_calculator' in st.session_state:
167
+ del st.session_state['excel_calculator']
168
+ if 'excel_filename' in st.session_state:
169
+ del st.session_state['excel_filename']
170
+ st.rerun()
171
+
172
+ # Display configuration
173
+ st.subheader("πŸ“‹ Configuration")
174
+ config_df = pd.DataFrame({
175
+ 'Category': calc.categories,
176
+ 'Optimize': ['Maximize' if calc.maximize[cat] else 'Minimize' for cat in calc.categories],
177
+ 'Weight': [calc.weights[cat] for cat in calc.categories]
178
+ })
179
+ st.dataframe(config_df, use_container_width=True)
180
+
181
+ # Weight adjustment
182
+ adjust_weights(calc)
183
+
184
+ # Results
185
+ display_results(calc)
186
+
187
+ else:
188
+ st.info("πŸ“€ Please upload an Excel file and click 'Process File' to begin analysis")
189
+
190
+ # Add sample download option
191
+ if st.button("πŸ“₯ Download Sample Excel Template"):
192
+ # Create sample data
193
+ sample_config = pd.DataFrame({
194
+ 'category': ['Performance', 'Cost', 'Quality', 'Reliability'],
195
+ 'maximize': [True, False, True, True]
196
+ })
197
 
198
+ sample_data = pd.DataFrame({
199
+ 'name': ['Product_A', 'Product_B', 'Product_C', 'Product_D'],
200
+ 'Performance': [85, 70, 90, 75],
201
+ 'Cost': [120, 100, 140, 110],
202
+ 'Quality': [90, 85, 95, 80],
203
+ 'Reliability': [88, 92, 85, 90]
204
  })
 
205
 
206
+ # Create Excel file in memory
207
+ import io
208
+ excel_buffer = io.BytesIO()
209
+ with pd.ExcelWriter(excel_buffer, engine='openpyxl') as writer:
210
+ sample_config.to_excel(writer, sheet_name='Config', index=False)
211
+ sample_data.to_excel(writer, sheet_name='Data', index=False)
212
 
213
+ excel_buffer.seek(0)
 
214
 
215
+ st.download_button(
216
+ label="πŸ“ Download Sample.xlsx",
217
+ data=excel_buffer.getvalue(),
218
+ file_name="MCDA_Sample_Template.xlsx",
219
+ mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
220
+ )
221
 
222
  def manual_interface():
223
  """Handle manual data entry interface."""