#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Excel Column Remover and Signature Adder A simple Gradio app that removes first 2 columns and adds signature lines to Excel files. """ import gradio as gr import pandas as pd import tempfile import os from datetime import datetime def process_excel_file(input_file): """ Process Excel file by removing first 2 columns and adding signature lines Args: input_file: Gradio file input object Returns: tuple: (output_file_path, success_message, preview_data) """ try: # Create output filename timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") output_filename = f"processed_report_{timestamp}.xlsx" output_path = os.path.join(tempfile.gettempdir(), output_filename) # Read Excel file df = pd.read_excel(input_file.name, header=None) print(f"Original shape: {df.shape}") # Extract first 4 header rows and clean them (remove extra spaces) header_rows = [] for i in range(min(4, len(df))): row_data = df.iloc[i].dropna().astype(str).tolist() if row_data: # Take first non-empty cell and clean it header_text = str(row_data[0]).strip() header_rows.append([header_text]) else: header_rows.append(['']) # Remove first 2 columns from all data (including headers) df_processed = df.iloc[:, 2:] # Keep from column 2 onwards print(f"After removing first 2 columns: {df_processed.shape}") # Reset column indices df_processed = df_processed.reset_index(drop=True) df_processed.columns = range(len(df_processed.columns)) # Create the final structure: # 1. First 4 header rows (cleaned) # 2. Original data from column 3 onwards # 3. Signature lines final_data = [] # Add cleaned header rows for header in header_rows: final_data.append(header) # Add empty separator row final_data.append([]) # Add the rest of the data (starting from row 5 in original, which is row 0 after removing first 4) data_start_row = 4 # Skip first 4 header rows we already added for i in range(data_start_row, len(df_processed)): row_data = df_processed.iloc[i].tolist() final_data.append(row_data) # Add signature lines at the end signature_lines = [ [], # Empty row [], # Empty row [], # Empty row ["กรรมการ", "", "กรรมการ", "", "กรรมการ"], [], # Empty row [], # Empty row ["ผู้ได้รับมอบหมายให้รับเงินและเอกสารแทนตัวเงินตามรายละเอียดข้างต้น ไปแล้ว"], [], # Empty row [], # Empty row [], # Empty row ["ลงชื่อ.................................................(ผู้รับเงิน)"], [], # Empty row [], # Empty row ["ลงชื่อ.................................................(หัวหน้าหน่วยงานย่อยผู้มอบหมาย)"] ] # Add signature lines for signature_line in signature_lines: final_data.append(signature_line) # Create final dataframe final_df = pd.DataFrame(final_data) # Make sure all columns are filled max_cols = max([len(row) for row in final_data if row]) final_df = final_df.reindex(columns=range(max_cols)) # Fill NaN values with empty strings final_df = final_df.fillna('') print(f"Final shape: {final_df.shape}") # Save to Excel final_df.to_excel(output_path, index=False, header=False, engine='openpyxl') # Create preview (first 20 rows) preview_df = final_df.head(20).copy() # Add string column names for Gradio preview_df.columns = [f'คอลัมน์_{i+1}' for i in range(len(preview_df.columns))] # Convert to strings for display for col in preview_df.columns: preview_df[col] = preview_df[col].astype(str).replace('nan', '').replace('', '-') success_message = f""" ✅ **ประมวลผลเสร็จสิ้น!** 📊 **สรุป:** - รูปแบบต้นฉบับ: {df.shape[0]} แถว × {df.shape[1]} คอลัมน์ - หลังตัดคอลัมน์: {df_processed.shape[0]} แถว × {df_processed.shape[1]} คอลัมน์ - เพิ่มบรรทัดลงนาม: {len(signature_lines)} บรรทัด - รูปแบบสุดท้าย: {final_df.shape[0]} แถว × {final_df.shape[1]} คอลัมน์ 📥 **ดาวน์โหลดไฟล์ที่ประมวลผลแล้ว** """ return output_path, success_message, preview_df except Exception as e: error_message = f""" ❌ **เกิดข้อผิดพลาด:** {str(e)} **กรุณาตรวจสอบ:** - ไฟล์ Excel (.xls หรือ .xlsx) ที่ถูกต้อง - มีข้อมูลในไฟล์ - ไฟล์ไม่เสียหาย """ return None, error_message, pd.DataFrame({'ข้อผิดพลาด': ['ไม่สามารถประมวลผลไฟล์ได้']}) def create_gradio_interface(): """Create the Gradio interface""" with gr.Blocks(title="Excel Column Processor", theme=gr.themes.Soft()) as iface: gr.Markdown(""" # 📊 เครื่องมือประมวลผลไฟล์ Excel ตัดคอลัมน์แรก 2 คอลัมน์ และเพิ่มบรรทัดลงนามท้ายไฟล์ **วิธีใช้:** 1. อัปโหลดไฟล์ Excel 2. กดปุ่ม "ประมวลผลไฟล์" 3. ดาวน์โหลดไฟล์ผลลัพธ์ """) with gr.Row(): with gr.Column(): gr.Markdown(""" **การทำงาน:** - ตัดคอลัมน์ที่ 1 และ 2 ออก - เลื่อนข้อมูลมาเริ่มที่คอลัมน์ A - เพิ่มบรรทัดลงนาม (กรรมการ, ผู้รับเงิน, หัวหน้า) - ส่งออกเป็น Excel ใหม่ """) with gr.Row(): with gr.Column(): file_input = gr.File( label="📁 อัปโหลดไฟล์ Excel", file_types=[".xls", ".xlsx"], file_count="single" ) process_btn = gr.Button( "🔄 ประมวลผลไฟล์", variant="primary", size="lg" ) with gr.Row(): with gr.Column(): status_output = gr.Markdown( label="📊 สถานะ", value="👆 อัปโหลดไฟล์ Excel และกดประมวลผล" ) with gr.Row(): with gr.Column(): file_output = gr.File( label="💾 ดาวน์โหลดไฟล์ผลลัพธ์", visible=False ) with gr.Row(): with gr.Column(): preview_output = gr.Dataframe( label="👀 ตัวอย่าง (20 แถวแรก)", visible=False, wrap=True ) def handle_processing(file): if file is None: return ( gr.update(visible=False), "⚠️ **กรุณาอัปโหลดไฟล์ Excel ก่อน**", gr.update(visible=False) ) result_file, message, preview = process_excel_file(file) if result_file: return ( gr.update(value=result_file, visible=True), message, gr.update(value=preview, visible=True) ) else: return ( gr.update(visible=False), message, gr.update(value=preview, visible=True) ) process_btn.click( fn=handle_processing, inputs=[file_input], outputs=[file_output, status_output, preview_output] ) gr.Markdown(""" **รายละเอียด:** - รองรับ Excel (.xls, .xlsx) - ตัดคอลัมน์แรก 2 คอลัมน์อัตโนมัติ - เพิ่มช่องลงนามสำหรับกรรมการ ผู้รับเงิน และหัวหน้า - เหมาะสำหรับรายงานการเงินและเอกสารทางการ 💡 **เคล็ดลับ:** เครื่องมือนี้จะลบคอลัมน์ว่างด้านซ้ายและจัดรูปแบบให้พร้อมสำหรับการลงนาม """) return iface # Create and launch the app if __name__ == "__main__": app = create_gradio_interface() app.launch( server_name="0.0.0.0", server_port=7860, share=False )