titipata commited on
Commit
356905a
·
verified ·
1 Parent(s): 6d0880e

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +260 -0
app.py ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ Excel Column Remover and Signature Adder
6
+ A simple Gradio app that removes first 2 columns and adds signature lines to Excel files.
7
+ """
8
+
9
+ import gradio as gr
10
+ import pandas as pd
11
+ import tempfile
12
+ import os
13
+ from datetime import datetime
14
+
15
+ def process_excel_file(input_file):
16
+ """
17
+ Process Excel file by removing first 2 columns and adding signature lines
18
+
19
+ Args:
20
+ input_file: Gradio file input object
21
+
22
+ Returns:
23
+ tuple: (output_file_path, success_message, preview_data)
24
+ """
25
+
26
+ try:
27
+ # Create output filename
28
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
29
+ output_filename = f"processed_report_{timestamp}.xlsx"
30
+ output_path = os.path.join(tempfile.gettempdir(), output_filename)
31
+
32
+ # Read Excel file
33
+ df = pd.read_excel(input_file.name, header=None)
34
+
35
+ print(f"Original shape: {df.shape}")
36
+
37
+ # Extract first 4 header rows and clean them (remove extra spaces)
38
+ header_rows = []
39
+ for i in range(min(4, len(df))):
40
+ row_data = df.iloc[i].dropna().astype(str).tolist()
41
+ if row_data:
42
+ # Take first non-empty cell and clean it
43
+ header_text = str(row_data[0]).strip()
44
+ header_rows.append([header_text])
45
+ else:
46
+ header_rows.append([''])
47
+
48
+ # Remove first 2 columns from all data (including headers)
49
+ df_processed = df.iloc[:, 2:] # Keep from column 2 onwards
50
+
51
+ print(f"After removing first 2 columns: {df_processed.shape}")
52
+
53
+ # Reset column indices
54
+ df_processed = df_processed.reset_index(drop=True)
55
+ df_processed.columns = range(len(df_processed.columns))
56
+
57
+ # Create the final structure:
58
+ # 1. First 4 header rows (cleaned)
59
+ # 2. Original data from column 3 onwards
60
+ # 3. Signature lines
61
+
62
+ final_data = []
63
+
64
+ # Add cleaned header rows
65
+ for header in header_rows:
66
+ final_data.append(header)
67
+
68
+ # Add empty separator row
69
+ final_data.append([])
70
+
71
+ # Add the rest of the data (starting from row 5 in original, which is row 0 after removing first 4)
72
+ data_start_row = 4 # Skip first 4 header rows we already added
73
+ for i in range(data_start_row, len(df_processed)):
74
+ row_data = df_processed.iloc[i].tolist()
75
+ final_data.append(row_data)
76
+
77
+ # Add signature lines at the end
78
+ signature_lines = [
79
+ [], # Empty row
80
+ [], # Empty row
81
+ [], # Empty row
82
+ ["กรรมการ", "", "กรรมการ", "", "กรรมการ"],
83
+ [], # Empty row
84
+ [], # Empty row
85
+ ["ผู้ได้รับมอบหมายให้รับเงินและเอกสารแทนตัวเงินตามรายละเอียดข้างต้น ไปแล้ว"],
86
+ [], # Empty row
87
+ [], # Empty row
88
+ [], # Empty row
89
+ ["ลงชื่อ.................................................(ผู้รับเงิน)"],
90
+ [], # Empty row
91
+ [], # Empty row
92
+ ["ลงชื่อ.................................................(หัวหน้าหน่วยงานย่อยผู้มอบหมาย)"]
93
+ ]
94
+
95
+ # Add signature lines
96
+ for signature_line in signature_lines:
97
+ final_data.append(signature_line)
98
+
99
+ # Create final dataframe
100
+ final_df = pd.DataFrame(final_data)
101
+
102
+ # Make sure all columns are filled
103
+ max_cols = max([len(row) for row in final_data if row])
104
+ final_df = final_df.reindex(columns=range(max_cols))
105
+
106
+ # Fill NaN values with empty strings
107
+ final_df = final_df.fillna('')
108
+
109
+ print(f"Final shape: {final_df.shape}")
110
+
111
+ # Save to Excel
112
+ final_df.to_excel(output_path, index=False, header=False, engine='openpyxl')
113
+
114
+ # Create preview (first 20 rows)
115
+ preview_df = final_df.head(20).copy()
116
+ # Add string column names for Gradio
117
+ preview_df.columns = [f'คอลัมน์_{i+1}' for i in range(len(preview_df.columns))]
118
+
119
+ # Convert to strings for display
120
+ for col in preview_df.columns:
121
+ preview_df[col] = preview_df[col].astype(str).replace('nan', '').replace('', '-')
122
+
123
+ success_message = f"""
124
+ ✅ **ประมวลผลเสร็จสิ้น!**
125
+
126
+ 📊 **สรุป:**
127
+ - รูปแบบต้นฉบับ: {df.shape[0]} แถว × {df.shape[1]} คอลัมน์
128
+ - หลังตัดคอลัมน์: {df_processed.shape[0]} แถว × {df_processed.shape[1]} คอลัมน์
129
+ - เพิ่มบรรทัดลงนาม: {len(signature_lines)} บรรทัด
130
+ - รูปแบบสุดท้าย: {final_df.shape[0]} แถว × {final_df.shape[1]} คอลัมน์
131
+
132
+ 📥 **ดาวน์โหลดไฟล์ที่ประมวลผลแล้ว**
133
+ """
134
+
135
+ return output_path, success_message, preview_df
136
+
137
+ except Exception as e:
138
+ error_message = f"""
139
+ ❌ **เกิดข้อผิดพลาด:**
140
+
141
+ {str(e)}
142
+
143
+ **กรุณาตรวจสอบ:**
144
+ - ไฟล์ Excel (.xls หรือ .xlsx) ที่ถูกต้อง
145
+ - มีข้อมูลในไฟล์
146
+ - ไฟล์ไม่เสียหาย
147
+ """
148
+ return None, error_message, pd.DataFrame({'ข้อผิดพลาด': ['ไม่สามารถประมวลผลไฟล์ได้']})
149
+
150
+ def create_gradio_interface():
151
+ """Create the Gradio interface"""
152
+
153
+ with gr.Blocks(title="Excel Column Processor", theme=gr.themes.Soft()) as iface:
154
+
155
+ gr.Markdown("""
156
+ # 📊 เครื่องมือประมวลผลไฟล์ Excel
157
+
158
+ ตัดคอลัมน์แรก 2 คอลัมน์ และเพิ่มบรรทัดลงนามท้ายไฟล์
159
+
160
+ **วิธีใช้:**
161
+ 1. อัปโหลดไฟล์ Excel
162
+ 2. กดปุ่ม "ประมวลผลไฟล์"
163
+ 3. ดาวน์โหลดไฟล์ผลลัพธ์
164
+ """)
165
+
166
+ with gr.Row():
167
+ with gr.Column():
168
+ gr.Markdown("""
169
+ **การทำงาน:**
170
+ - ตัดคอลัมน์ที่ 1 และ 2 ออก
171
+ - เลื่อนข้อมูลมาเริ่มที่คอลัมน์ A
172
+ - เพิ่มบรรทัดลงนาม (กรรมการ, ผู้รับเงิน, หัวหน้า)
173
+ - ส่งออกเป็น Excel ใหม่
174
+ """)
175
+
176
+ with gr.Row():
177
+ with gr.Column():
178
+ file_input = gr.File(
179
+ label="📁 อัปโหลดไฟล์ Excel",
180
+ file_types=[".xls", ".xlsx"],
181
+ file_count="single"
182
+ )
183
+
184
+ process_btn = gr.Button(
185
+ "🔄 ประมวลผลไฟล์",
186
+ variant="primary",
187
+ size="lg"
188
+ )
189
+
190
+ with gr.Row():
191
+ with gr.Column():
192
+ status_output = gr.Markdown(
193
+ label="📊 สถานะ",
194
+ value="👆 อัปโหลดไฟล์ Excel และกดประมวลผล"
195
+ )
196
+
197
+ with gr.Row():
198
+ with gr.Column():
199
+ file_output = gr.File(
200
+ label="💾 ดาวน์โหลดไฟล์ผลลัพธ์",
201
+ visible=False
202
+ )
203
+
204
+ with gr.Row():
205
+ with gr.Column():
206
+ preview_output = gr.Dataframe(
207
+ label="👀 ตัวอย่าง (20 แถวแรก)",
208
+ visible=False,
209
+ wrap=True
210
+ )
211
+
212
+ def handle_processing(file):
213
+ if file is None:
214
+ return (
215
+ gr.update(visible=False),
216
+ "⚠️ **กรุณาอัปโหลดไฟล์ Excel ก่อน**",
217
+ gr.update(visible=False)
218
+ )
219
+
220
+ result_file, message, preview = process_excel_file(file)
221
+
222
+ if result_file:
223
+ return (
224
+ gr.update(value=result_file, visible=True),
225
+ message,
226
+ gr.update(value=preview, visible=True)
227
+ )
228
+ else:
229
+ return (
230
+ gr.update(visible=False),
231
+ message,
232
+ gr.update(value=preview, visible=True)
233
+ )
234
+
235
+ process_btn.click(
236
+ fn=handle_processing,
237
+ inputs=[file_input],
238
+ outputs=[file_output, status_output, preview_output]
239
+ )
240
+
241
+ gr.Markdown("""
242
+ **รายละเอียด:**
243
+ - รองรับ Excel (.xls, .xlsx)
244
+ - ตัดคอลัมน์แรก 2 คอลัมน์อัตโนมัติ
245
+ - เพิ่มช่องลงนามสำหรับกรรมการ ผู้รับเงิน และหัวหน้า
246
+ - เหม���ะสำหรับรายงานการเงินและเอกสารทางการ
247
+
248
+ 💡 **เคล็ดลับ:** เครื่องมือนี้จะลบคอลัมน์ว่างด้านซ้ายและจัดรูปแบบให้พร้อมสำหรับการลงนาม
249
+ """)
250
+
251
+ return iface
252
+
253
+ # Create and launch the app
254
+ if __name__ == "__main__":
255
+ app = create_gradio_interface()
256
+ app.launch(
257
+ server_name="0.0.0.0",
258
+ server_port=7860,
259
+ share=False
260
+ )