| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import gradio as gr |
| import pandas as pd |
| import json |
| import io |
| import zipfile |
| from datetime import datetime |
| import traceback |
| import tempfile |
| import os |
| import sys |
| import subprocess |
|
|
| |
| try: |
| from PyPDF2 import PdfReader, PdfWriter |
| from reportlab.pdfgen import canvas |
| from reportlab.lib.pagesizes import letter |
| from reportlab.pdfbase import pdfmetrics |
| from reportlab.pdfbase.ttfonts import TTFont |
| print("Dependencies หลักถูกติดตั้งเรียบร้อยแล้ว") |
| except ImportError: |
| print("กำลังติดตั้ง dependencies ที่จำเป็น: PyPDF2, reportlab, pandas") |
| subprocess.check_call([sys.executable, "-m", "pip", "install", "PyPDF2", "reportlab", "pandas"]) |
| from PyPDF2 import PdfReader, PdfWriter |
| from reportlab.pdfgen import canvas |
| from reportlab.lib.pagesizes import letter |
|
|
| |
| try: |
| from PIL import Image |
| import numpy as np |
| import cv2 |
| import pytesseract |
| AI_OCR_ENABLED = True |
| print("Dependencies สำหรับ AI/OCR พร้อมใช้งาน") |
| except ImportError: |
| AI_OCR_ENABLED = False |
| print("คำเตือน: ไม่พบ Dependencies สำหรับ AI/OCR (Pillow, numpy, opencv-python, pytesseract)") |
| print("ฟังก์ชันที่เกี่ยวกับรูปภาพและ OCR จะไม่สามารถใช้งานได้") |
| print("ติดตั้งด้วย: pip install Pillow numpy opencv-python pytesseract และติดตั้ง Tesseract engine") |
|
|
| try: |
| from gradio_client import Client |
| SAMBANOVA_AI_ENABLED = True |
| print("Dependencies สำหรับ SambaNova AI พร้อมใช้งาน") |
| except ImportError: |
| SAMBANOVA_AI_ENABLED = False |
| print("คำเตือน: ไม่พบ Gradio Client (pip install 'gradio_client>=0.12.0')") |
| print("ฟังก์ชันที่ต้องใช้ AI Model จะไม่สามารถใช้งานได้") |
|
|
|
|
| |
| |
| |
|
|
| def analyze_pdf_fields(pdf_path): |
| """วิเคราะห์ฟิลด์ใน PDF และคืนค่าเป็น Dictionary""" |
| try: |
| reader = PdfReader(pdf_path) |
| all_fields = {} |
| |
| if reader.trailer.get("/Root") and reader.trailer["/Root"].get("/AcroForm"): |
| acro_form = reader.trailer["/Root"]["/AcroForm"] |
| if "/Fields" in acro_form: |
| for field in acro_form["/Fields"]: |
| field_obj = field.get_object() |
| if "/T" in field_obj: |
| field_name = str(field_obj["/T"]).strip("()") |
| field_type = str(field_obj.get("/FT", "Unknown")) |
| field_value = str(field_obj.get("/V", "")).strip("()") |
| all_fields[field_name] = { |
| 'type': field_type, |
| 'default_value': field_value, |
| 'method': 'AcroForm' |
| } |
| |
| for page_num, page in enumerate(reader.pages): |
| if "/Annots" in page: |
| for annotation in page["/Annots"]: |
| annot_obj = annotation.get_object() |
| if annot_obj.get("/Subtype") == "/Widget" and "/T" in annot_obj: |
| field_name = str(annot_obj["/T"]).strip("()") |
| if field_name not in all_fields: |
| field_type = str(annot_obj.get("/FT", "Widget")) |
| field_value = str(annot_obj.get("/V", "")).strip("()") |
| all_fields[field_name] = { |
| 'type': field_type, |
| 'default_value': field_value, |
| 'page': page_num + 1, |
| 'method': 'Annotation' |
| } |
| return all_fields |
| except Exception as e: |
| return {"error": str(e)} |
|
|
| def generate_csv_template(pdf_fields, num_rows=5): |
| """สร้าง CSV template จาก PDF fields""" |
| if not pdf_fields or "error" in pdf_fields: |
| return None, "ไม่สามารถสร้าง CSV template ได้" |
| template_data = {'id': list(range(1, num_rows + 1))} |
| for field_name in pdf_fields.keys(): |
| if field_name and field_name.strip(): |
| clean_name = field_name.strip() |
| sample_value = f"ข้อมูลสำหรับ {clean_name} {{}}" |
| template_data[clean_name] = [sample_value.format(i) for i in range(1, num_rows + 1)] |
| df = pd.DataFrame(template_data) |
| return df, "สร้าง CSV template สำเร็จ" |
|
|
| def generate_json_template(pdf_fields): |
| """สร้าง JSON template จาก PDF fields""" |
| if not pdf_fields or "error" in pdf_fields: |
| return None, "ไม่สามารถสร้าง JSON template ได้" |
| template = { |
| "pdf_info": {"total_fields": len(pdf_fields), "generation_time": datetime.now().isoformat()}, |
| "fields": {}, |
| "sample_data": [] |
| } |
| for field_name, field_info in pdf_fields.items(): |
| if field_name and field_name.strip(): |
| template["fields"][field_name.strip()] = field_info |
| for i in range(1, 4): |
| sample_record = {"id": i} |
| for field_name in template["fields"].keys(): |
| sample_record[field_name] = f"ข้อมูลตัวอย่าง {i}" |
| template["sample_data"].append(sample_record) |
| return template, "สร้าง JSON template สำเร็จ" |
|
|
| def create_template_files(pdf_file, num_rows, progress=gr.Progress()): |
| """สร้างไฟล์ template (CSV, JSON, README) และรวมเป็น ZIP""" |
| if pdf_file is None: |
| return None, "❌ กรุณาอัพโหลดไฟล์ PDF ก่อน" |
| |
| progress(0, desc="กำลังวิเคราะห์ PDF...") |
| try: |
| pdf_fields = analyze_pdf_fields(pdf_file.name) |
| if not pdf_fields or "error" in pdf_fields: |
| return None, "❌ ไม่พบ Form Fields ใน PDF หรือไฟล์เสียหาย" |
| |
| progress(0.3, desc="กำลังสร้าง CSV template...") |
| csv_df, _ = generate_csv_template(pdf_fields, num_rows) |
| |
| progress(0.6, desc="กำลังสร้าง JSON template...") |
| json_template, _ = generate_json_template(pdf_fields) |
| |
| if csv_df is None or json_template is None: |
| return None, "❌ ไม่สามารถสร้างไฟล์ template ได้" |
| |
| progress(0.8, desc="กำลังบีบอัดไฟล์เป็น ZIP...") |
| zip_buffer = io.BytesIO() |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_f: |
| csv_buffer = io.StringIO() |
| csv_df.to_csv(csv_buffer, index=False, encoding='utf-8-sig') |
| zip_f.writestr(f"template_{timestamp}.csv", csv_buffer.getvalue()) |
| |
| json_str = json.dumps(json_template, ensure_ascii=False, indent=2) |
| zip_f.writestr(f"template_{timestamp}.json", json_str) |
| |
| readme_content = f"""# PDF Form Template Files |
| Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} |
| PDF Fields Found: {len(pdf_fields)} |
| {chr(10).join([f"- {name}" for name in pdf_fields.keys()])} |
| """ |
| zip_f.writestr("README.txt", readme_content) |
| |
| zip_buffer.seek(0) |
| |
| |
| temp_dir = tempfile.gettempdir() |
| zip_filename = f"pdf_templates_{timestamp}.zip" |
| temp_zip_path = os.path.join(temp_dir, zip_filename) |
| with open(temp_zip_path, "wb") as f: |
| f.write(zip_buffer.getvalue()) |
| |
| progress(1, desc="สร้างไฟล์สำเร็จ!") |
| result_msg = f"✅ สร้าง template สำเร็จ!\n- พบ {len(pdf_fields)} fields\n- CSV มี {num_rows} แถวตัวอย่าง" |
| |
| return temp_zip_path, result_msg |
| |
| except Exception as e: |
| return None, f"❌ เกิดข้อผิดพลาด: {e}\n{traceback.format_exc()}" |
|
|
| def fill_pdf_form(pdf_path, field_data): |
| """เติมข้อมูลลงในฟอร์มของ PDF""" |
| reader = PdfReader(pdf_path) |
| writer = PdfWriter() |
| writer.append_pages_from_reader(reader) |
| |
| |
| for page in writer.pages: |
| try: |
| writer.update_page_form_field_values(page, field_data, auto_regenerate=False) |
| except Exception: |
| |
| pass |
| try: |
| writer.update_page_form_field_values(writer.pages[0], field_data) |
| except: |
| pass |
|
|
| output_buffer = io.BytesIO() |
| writer.write(output_buffer) |
| output_buffer.seek(0) |
| return output_buffer.getvalue() |
|
|
| def create_simple_pdf(data_row, filename): |
| """สร้าง PDF ใหม่แบบง่ายๆ กรณีที่ PDF ต้นฉบับไม่มีฟอร์ม""" |
| buffer = io.BytesIO() |
| |
| try: |
| pdfmetrics.registerFont(TTFont('THSarabunNew', 'THSarabunNew.ttf')) |
| font_name = 'THSarabunNew' |
| except: |
| font_name = 'Helvetica' |
|
|
| p = canvas.Canvas(buffer, pagesize=letter) |
| width, height = letter |
| |
| p.setFont(font_name, 16) |
| p.drawString(50, height - 50, f"เอกสาร: {filename.replace('.pdf', '')}") |
| p.line(50, height - 60, 550, height - 60) |
| |
| y_position = height - 90 |
| p.setFont(font_name, 12) |
| for column, value in data_row.items(): |
| if pd.notna(value) and str(value).strip(): |
| text = f"{str(column).strip()}: {str(value).strip()}" |
| try: |
| p.drawString(50, y_position, text) |
| except: |
| safe_text = text.encode('latin-1', 'replace').decode('latin-1') |
| p.drawString(50, y_position, safe_text) |
| y_position -= 20 |
| if y_position < 50: |
| p.showPage() |
| p.setFont(font_name, 12) |
| y_position = height - 50 |
| |
| p.save() |
| buffer.seek(0) |
| return buffer.getvalue() |
|
|
| def read_csv_safe(csv_file): |
| """อ่านไฟล์ CSV โดยลองหลาย encoding และ separator เพื่อความยืดหยุ่น""" |
| encodings = ['utf-8-sig', 'utf-8', 'cp874', 'tis-620'] |
| separators = [',', ';', '\t'] |
| |
| |
| filepath = csv_file.name |
|
|
| for encoding in encodings: |
| for sep in separators: |
| try: |
| df = pd.read_csv(filepath, encoding=encoding, sep=sep, engine='python') |
| if len(df.columns) > 1: |
| return df, None |
| except Exception: |
| continue |
| return None, "ไม่สามารถอ่านไฟล์ CSV ได้ ลองตรวจสอบ Encoding (ควรเป็น UTF-8) และ Separator (ควรเป็น ,)" |
|
|
| def process_pdf_csv(pdf_file, csv_file, filename_column, file_prefix, use_form_fields, progress=gr.Progress()): |
| """ฟังก์ชันหลักสำหรับประมวลผล PDF และ CSV""" |
| if not pdf_file or not csv_file: |
| return None, "❌ กรุณาอัพโหลดทั้งไฟล์ PDF และ CSV" |
|
|
| try: |
| df, csv_error = read_csv_safe(csv_file) |
| if df is None: |
| return None, f"❌ ไม่สามารถอ่าน CSV ได้: {csv_error}" |
|
|
| pdf_path = pdf_file.name |
| pdf_fields = analyze_pdf_fields(pdf_path) |
| has_form_fields = bool(pdf_fields and "error" not in pdf_fields) |
| |
| generated_pdfs = {} |
| log = [] |
| total_rows = len(df) |
|
|
| for index, row in df.iterrows(): |
| progress((index + 1) / total_rows, f"ประมวลผลแถวที่ {index + 1}/{total_rows}") |
| |
| |
| if filename_column and filename_column in df.columns and pd.notna(row[filename_column]): |
| safe_name = "".join(c for c in str(row[filename_column]) if c.isalnum() or c in (' ', '-', '_')).strip() |
| filename = f"{file_prefix}_{safe_name}.pdf" |
| else: |
| filename = f"{file_prefix}_{index + 1:03d}.pdf" |
| |
| row_data = row.to_dict() |
| |
| try: |
| if use_form_fields and has_form_fields: |
| |
| pdf_content = fill_pdf_form(pdf_path, row_data) |
| status = "เติมฟอร์มสำเร็จ" |
| else: |
| |
| pdf_content = create_simple_pdf(row_data, filename) |
| status = "สร้าง PDF ใหม่" if not has_form_fields else "สร้าง PDF ใหม่ (Fallback)" |
| |
| generated_pdfs[filename] = pdf_content |
| log.append(f"✅ {filename}: {status}") |
| except Exception as e: |
| log.append(f"❌ {filename}: เกิดข้อผิดพลาด - {e}") |
| |
| if not generated_pdfs: |
| return None, "❌ ไม่สามารถสร้าง PDF ได้เลย\n" + "\n".join(log) |
|
|
| |
| zip_buffer = io.BytesIO() |
| with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_f: |
| for filename, pdf_content in generated_pdfs.items(): |
| zip_f.writestr(filename, pdf_content) |
| zip_f.writestr("processing_log.txt", "\n".join(log)) |
| zip_buffer.seek(0) |
|
|
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| zip_filename = f"generated_pdfs_{timestamp}.zip" |
| temp_zip_path = os.path.join(tempfile.gettempdir(), zip_filename) |
| with open(temp_zip_path, 'wb') as f: |
| f.write(zip_buffer.getvalue()) |
| |
| result_message = f"✅ สร้าง PDF สำเร็จ {len(generated_pdfs)} ไฟล์!\nดูรายละเอียดใน processing_log.txt" |
| return temp_zip_path, result_message |
|
|
| except Exception as e: |
| return None, f"❌ เกิดข้อผิดพลาดร้ายแรง: {e}\n{traceback.format_exc()}" |
|
|
|
|
| |
| |
| |
|
|
| def init_sambanova_ai(): |
| """Initialize SambaNova AI model client.""" |
| if not SAMBANOVA_AI_ENABLED: |
| print("SambaNova AI is disabled.") |
| return None |
| try: |
| |
| client = Client("sambanova/Llama-3-8B-Instruct", hf_token="YOUR_HF_TOKEN") |
| print("SambaNova AI client initialized successfully.") |
| return client |
| except Exception as e: |
| print(f"Error initializing SambaNova AI: {e}") |
| return None |
|
|
| def extract_text_from_image(image_file): |
| """Extract text from an image file using Tesseract OCR.""" |
| if not AI_OCR_ENABLED or image_file is None: |
| return "", "OCR is not available or no image provided." |
| try: |
| image = Image.open(image_file.name) |
| |
| custom_config = r'--oem 3 --psm 6 -l tha+eng' |
| text = pytesseract.image_to_string(image, config=custom_config) |
| return text.strip(), "Text extracted successfully." |
| except Exception as e: |
| return "", f"OCR Error: {e}. ตรวจสอบว่าติดตั้ง Tesseract Engine ถูกต้อง" |
|
|
| def image_to_csv_with_ai(image_file, progress=gr.Progress()): |
| """Convert data from an image to a CSV file using OCR and AI for structuring.""" |
| if not AI_OCR_ENABLED: |
| return None, "❌ ฟังก์ชันนี้ต้องการ AI/OCR dependencies" |
| if image_file is None: |
| return None, "❌ กรุณาอัพโหลดรูปภาพ" |
| |
| progress(0.2, desc="กำลังอ่านข้อความจากรูปภาพ (OCR)...") |
| raw_text, ocr_status = extract_text_from_image(image_file) |
| if not raw_text: |
| return None, f"❌ ไม่พบข้อความในรูปภาพ: {ocr_status}" |
|
|
| progress(0.5, desc="กำลังใช้ AI จัดโครงสร้างข้อมูล...") |
| ai_client = init_sambanova_ai() |
| if not ai_client: |
| return None, "❌ ไม่สามารถเชื่อมต่อ AI Model ได้" |
|
|
| prompt = f""" |
| From the following text, extract key-value pairs. The output should be only the data in 'key: value' format, one per line. |
| Example: |
| Name: John Doe |
| Address: 123 Main St |
| Date: 2024-01-15 |
| |
| Text to process: |
| --- |
| {raw_text} |
| --- |
| """ |
| try: |
| |
| result = ai_client.predict(message=prompt, api_name="/chat") |
| |
| progress(0.8, desc="กำลังสร้างไฟล์ CSV...") |
| lines = result.strip().split('\n') |
| data = [line.split(':', 1) for line in lines if ':' in line] |
| |
| if not data: |
| return None, "AI ไม่สามารถจัดโครงสร้างข้อมูลได้" |
| |
| df = pd.DataFrame(data, columns=['Field', 'Value']).set_index('Field').T |
| |
| csv_buffer = io.StringIO() |
| df.to_csv(csv_buffer, index=False, encoding='utf-8-sig') |
| |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| temp_csv_path = os.path.join(tempfile.gettempdir(), f"extracted_data_{timestamp}.csv") |
| with open(temp_csv_path, 'w', encoding='utf-8-sig') as f: |
| f.write(csv_buffer.getvalue()) |
| |
| return temp_csv_path, "✅ แปลงรูปภาพเป็น CSV สำเร็จ" |
| except Exception as e: |
| return None, f"❌ เกิดข้อผิดพลาดระหว่างประมวลผลด้วย AI: {e}" |
|
|
|
|
| |
| |
| |
|
|
| def analyze_pdf_info(pdf_file): |
| """วิเคราะห์และแสดงข้อมูลสรุปของไฟล์ PDF บน UI""" |
| if pdf_file is None: |
| return "ยังไม่มีไฟล์ PDF" |
| try: |
| reader = PdfReader(pdf_file.name) |
| info = f"📄 **ข้อมูล PDF:**\n- จำนวนหน้า: {len(reader.pages)}\n" |
| pdf_fields = analyze_pdf_fields(pdf_file.name) |
| if pdf_fields and "error" not in pdf_fields: |
| info += f"- **พบ Form Fields: {len(pdf_fields)} ช่อง** (จะใช้วิธีเติมฟอร์ม)\n" |
| info += "\n🏷️ **ตัวอย่างชื่อ Fields:**\n" |
| for name in list(pdf_fields.keys())[:10]: |
| info += f" - `{name}`\n" |
| if len(pdf_fields) > 10: |
| info += f" - ... และอีก {len(pdf_fields) - 10} fields\n" |
| else: |
| info += "- **ไม่พบ Form Fields** (จะใช้วิธีสร้าง PDF ใหม่ทับลงบนกระดาษเปล่า)\n" |
| return info |
| except Exception as e: |
| return f"❌ ไม่สามารถวิเคราะห์ PDF: {e}" |
|
|
| def analyze_csv_info(csv_file): |
| """วิเคราะห์และแสดงข้อมูลสรุปของไฟล์ CSV และอัปเดต Dropdown""" |
| if csv_file is None: |
| return "ยังไม่มีไฟล์ CSV", gr.update(choices=[], value=None) |
| try: |
| df, error = read_csv_safe(csv_file) |
| if df is None: |
| return f"❌ ไม่สามารถอ่าน CSV: {error}", gr.update(choices=[], value=None) |
| |
| info = f"📋 **ข้อมูล CSV:**\n- จำนวนแถว: {len(df)}\n- จำนวนคอลัมน์: {len(df.columns)}\n" |
| info += "\n📝 **รายชื่อคอลัมน์:**\n" |
| for col in df.columns[:15]: |
| info += f" - `{col}`\n" |
| if len(df.columns) > 15: |
| info += f" - ... และอีก {len(df.columns) - 15} คอลัมน์\n" |
| |
| |
| return info, gr.update(choices=df.columns.tolist(), value=None) |
| except Exception as e: |
| return f"❌ ไม่สามารถวิเคราะห์ CSV: {e}", gr.update(choices=[], value=None) |
|
|
|
|
| |
| |
| |
|
|
| def create_interface(): |
| with gr.Blocks(title="PDF Form Filler & Template Generator", theme=gr.themes.Soft()) as app: |
| gr.Markdown("# 📄 เครื่องมือจัดการ PDF จากข้อมูล CSV") |
| gr.Markdown("รองรับการ **สร้าง Template** จาก PDF, **เติมข้อมูล** จาก CSV, และ **แปลงรูปภาพเป็น CSV** ด้วย AI") |
|
|
| with gr.Tabs(): |
| |
| with gr.TabItem("🔄 1. สร้าง Template"): |
| gr.Markdown("## สร้าง CSV/JSON Template จาก PDF ที่มี Form Fields") |
| with gr.Row(): |
| with gr.Column(scale=1): |
| template_pdf = gr.File(label="📄 อัพโหลด PDF ต้นฉบับ", file_types=[".pdf"]) |
| num_sample_rows = gr.Slider(label="จำนวนแถวตัวอย่างใน CSV", minimum=1, maximum=50, value=5, step=1) |
| generate_template_btn = gr.Button("🚀 สร้าง Template", variant="primary") |
| with gr.Column(scale=2): |
| template_pdf_info = gr.Markdown("อัพโหลด PDF เพื่อดูข้อมูล...") |
| template_result_file = gr.File(label="📦 ดาวน์โหลดไฟล์ Template (ZIP)", interactive=False) |
| template_result_message = gr.Markdown() |
|
|
| |
| with gr.TabItem("📝 2. เติมข้อมูล PDF"): |
| gr.Markdown("## เติมข้อมูลลงใน PDF จากไฟล์ CSV") |
| with gr.Row(): |
| with gr.Column(scale=1): |
| gr.Markdown("### 📂 1. อัพโหลดไฟล์") |
| pdf_file = gr.File(label="📄 PDF Form ต้นฉบับ", file_types=[".pdf"]) |
| csv_file = gr.File(label="📊 CSV ข้อมูล", file_types=[".csv"]) |
| |
| gr.Markdown("### ⚙️ 2. ตั้งค่า") |
| use_form_fields = gr.Checkbox(label="พยายามเติมข้อมูลลงใน Form Fields ที่มีอยู่", value=True) |
| file_prefix = gr.Textbox(label="คำนำหน้าชื่อไฟล์ (Prefix)", value="Document") |
| filename_column = gr.Dropdown(label="เลือกคอลัมน์ที่จะใช้เป็นชื่อไฟล์ (ถ้ามี)", interactive=True) |
| |
| fill_form_btn = gr.Button("🚀 เริ่มเติมข้อมูล", variant="primary") |
| |
| with gr.Column(scale=2): |
| pdf_info = gr.Markdown("อัพโหลด PDF เพื่อดูข้อมูล...") |
| csv_info = gr.Markdown("อัพโหลด CSV เพื่อดูข้อมูล...") |
| gr.Markdown("---") |
| filled_result_file = gr.File(label="📦 ดาวน์โหลด PDF ทั้งหมด (ZIP)", interactive=False) |
| filled_result_message = gr.Markdown() |
|
|
| |
| with gr.TabItem("🖼️ 3. แปลงรูปภาพเป็น CSV (AI)"): |
| gr.Markdown("## ใช้ OCR และ AI เพื่อดึงข้อมูลจากรูปภาพและสร้างเป็นไฟล์ CSV") |
| with gr.Row(): |
| with gr.Column(scale=1): |
| image_upload = gr.File(label="🖼️ อัพโหลดรูปภาพ (บิล, เอกสาร, ฯลฯ)", file_types=["image"]) |
| image_to_csv_btn = gr.Button("🤖 แปลงเป็น CSV", variant="primary", visible=AI_OCR_ENABLED) |
| if not AI_OCR_ENABLED: |
| gr.Markdown("⚠️ *ฟังก์ชันนี้ถูกปิดใช้งานเนื่องจากไม่พบ Library ที่จำเป็น (Pillow, OpenCV, Pytesseract)*") |
|
|
| with gr.Column(scale=2): |
| image_csv_output = gr.File(label="📄 ดาวน์โหลดไฟล์ CSV ที่ได้", interactive=False) |
| image_csv_message = gr.Markdown() |
|
|
| |
| template_pdf.change(fn=analyze_pdf_info, inputs=template_pdf, outputs=template_pdf_info) |
| generate_template_btn.click( |
| fn=create_template_files, |
| inputs=[template_pdf, num_sample_rows], |
| outputs=[template_result_file, template_result_message] |
| ) |
|
|
| pdf_file.change(fn=analyze_pdf_info, inputs=pdf_file, outputs=pdf_info) |
| csv_file.change(fn=analyze_csv_info, inputs=csv_file, outputs=[csv_info, filename_column]) |
| |
| fill_form_btn.click( |
| fn=process_pdf_csv, |
| inputs=[pdf_file, csv_file, filename_column, file_prefix, use_form_fields], |
| outputs=[filled_result_file, filled_result_message] |
| ) |
|
|
| if AI_OCR_ENABLED: |
| image_to_csv_btn.click( |
| fn=image_to_csv_with_ai, |
| inputs=[image_upload], |
| outputs=[image_csv_output, image_csv_message] |
| ) |
| |
| return app |
|
|
| |
| if __name__ == "__main__": |
| |
| try: |
| from reportlab.pdfbase import pdfmetrics |
| from reportlab.pdfbase.ttfonts import TTFont |
| |
| pdfmetrics.registerFont(TTFont('THSarabunNew', 'C:/Windows/Fonts/THSARI.TTF')) |
| print("ลงทะเบียน Font 'THSarabunNew' สำหรับ ReportLab สำเร็จ") |
| except: |
| print("คำเตือน: ไม่พบ Font 'THSarabunNew' ในระบบ อาจทำให้การสร้าง PDF ภาษาไทยมีปัญหา") |
| print("แนะนำให้ติดตั้งฟอนต์ TH SarabunPSK หรือปรับแก้ path ของฟอนต์ในโค้ด") |
|
|
| app = create_interface() |
| app.launch(debug=True) |