การถ่ายโอนข้อมูลขนาดใหญ่ระหว่างไฟล์ ODS โดยรักษา Macro ไว้: การสำรวจเครื่องมือและข้อจำกัด

Development Log · 2026-05-04


1. Title

การถ่ายโอนข้อมูลขนาดใหญ่ระหว่างไฟล์ ODS โดยรักษา Macro ไว้: การสำรวจเครื่องมือและข้อจำกัด


2. Date / Phase

วันที่เริ่มต้นสนทนา: 4 พฤษภาคม 2026 Phase: Data Migration & Tool Evaluation — Phase of Constraint Discovery


3. Background

ปัญหาที่จุดชนวนการสนทนาครั้งนี้คือความจำเป็นในการถ่ายโอนข้อมูลจำนวนมหาศาลจากเซลล์ช่วง A6–P950000 ในไฟล์ M5_RawDataFilter_for_IS1.ods ไปยังเซลล์ช่วง C17–R950000 ในไฟล์ M5_Exhaustive_HardFilter_for_IS1.ods โดยไม่ให้ข้อมูลในเซลล์อื่นของไฟล์ปลายทางสูญหาย

โจทย์นี้ดูเรียบง่ายในเชิงเทคนิค แต่เมื่อพิจารณาถึงขนาดข้อมูล (ประมาณ 15.2 ล้านเซลล์) และลักษณะของไฟล์ ODS ที่มีโครงสร้างซับซ้อน (เป็น ZIP archive ที่บรรจุ XML หลายไฟล์) จึงกลายเป็นการสำรวจที่ลึกซึ้งถึงขีดจำกัดของเครื่องมือแต่ละชนิด และนำไปสู่คำถามสำคัญเกี่ยวกับการรักษา Macro ซึ่งเป็นส่วนประกอบที่เปราะบางที่สุดของเอกสาร


4. Key Insights

Insight ที่ 1: เครื่องมือแต่ละชนิดมีจุดแลกเปลี่ยน (Trade-off) ที่แตกต่างกัน

เครื่องมือสามกลุ่มถูกนำมาพิจารณา ได้แก่ ezodf (ควบคุมระดับเซลล์ รักษารูปแบบได้ดี แต่ช้า), pandas (ประมวลผลเป็นชุด เร็วกว่ามาก แต่สูญเสียรูปแบบบางส่วน) และ LibreOffice UNO API (รักษาทุกอย่างได้ แต่ซับซ้อนและช้ากว่า)

เหตุผลที่ต้องเปรียบเทียบเช่นนี้ เพราะไม่มีเครื่องมือใดที่ "ดีที่สุด" ในทุกมิติ — การเลือกจึงขึ้นอยู่กับว่าอะไรคือสิ่งที่ยอมแลกได้ และอะไรคือสิ่งที่ห้ามสูญเสีย

Insight ที่ 2: ODS ไม่ใช่ "ไฟล์แผ่นงาน" แต่เป็น "คอนเทนเนอร์"

ความเข้าใจนี้เป็นจุดเปลี่ยนทางความคิด เพราะการมอง ODS เป็น ZIP ที่บรรจุ XML หลายไฟล์ทำให้เห็นว่า Macro ไม่ได้เป็นส่วนหนึ่งของ "ข้อมูล" ในเซลล์ แต่เป็นส่วนประกอบแยกที่ library ส่วนใหญ่ไม่รู้จักและไม่รักษาไว้ นี่คือรากของปัญหาทั้งหมด

Insight ที่ 3: UNO API คือทางเดียวที่รักษา Macro ได้อย่างสมบูรณ์

แต่มาพร้อมกับข้อกำหนดที่เข้มงวด คือ LibreOffice ต้องรันใน listening mode และเปิด connection ผ่าน socket ทุกครั้งที่ทำงาน แม้จะดูเป็นภาระ แต่ก็สามารถทำให้เป็นอัตโนมัติได้ด้วย subprocess และ atexit ซึ่งเปลี่ยนภาระให้กลายเป็นส่วนหนึ่งของ lifecycle ของสคริปต์

Insight ที่ 4: ขนาดข้อมูลมีนัยต่อเวลาและหน่วยความจำ

เครื่อง Ryzen 5 5600G พร้อม RAM 32GB เพียงพอต่อการประมวลผล แต่เวลาจะขึ้นอยู่กับวิธี: pandas ใช้เวลาเพียง 8–15 วินาที, ezodf 45–75 วินาที, UNO API 5–20 นาที ความต่างนี้สะท้อนหลักการว่า "ความสมบูรณ์ของข้อมูลและ metadata มีต้นทุนเสมอ"

Insight ที่ 5: ไฟล์ต้องถูกปิดก่อนรันสคริปต์

ข้อนี้ดูเหมือนรายละเอียดเล็กน้อย แต่เป็นข้อผิดพลาดที่พบบ่อยที่สุด — การที่ไฟล์ถูกเปิดอยู่ในโปรแกรมตารางจะทำให้เกิด lock และสคริปต์ไม่สามารถเขียนทับได้


5. Decisions

Decision ที่ 1: เลือกใช้ LibreOffice UNO API สำหรับงานที่ต้องรักษา Macro

หลังจากการประเมิน trade-off ระหว่างความเร็วและความสมบูรณ์ของ metadata การตัดสินใจคือยอมแลกความเร็วกับความสมบูรณ์ของเอกสาร เพราะ Macro เป็นสินทรัพย์ทางตรรกะที่สร้างขึ้นด้วยความตั้งใจ ไม่ควรสูญเสียไปเพียงเพื่อประหยัดเวลาไม่กี่นาที

Decision ที่ 2: ทำสคริปต์ให้เปิดและปิด LibreOffice อัตโนมัติ

แทนที่จะให้ผู้ใช้จัดการ LibreOffice listening mode ด้วยตนเองทุกครั้ง เราเลือกฝังการจัดการนี้เข้าไปในสคริปต์ผ่าน subprocess และ atexit เพื่อให้ lifecycle ของ LibreOffice ผูกกับ lifecycle ของสคริปต์

Decision ที่ 3: ทดสอบด้วยชุดข้อมูลขนาดเล็กก่อน

ก่อนรันกับข้อมูล 950,000 แถว ควรทดสอบกับ 100 แถวก่อน เพื่อยืนยันว่าเส้นทาง (path) ของไฟล์, การเชื่อมต่อ UNO และการแมปตำแหน่งเซลล์ถูกต้องทั้งหมด

Decision ที่ 4: แนะนำให้สำรองไฟล์ก่อนรันทุกครั้ง

เนื่องจากสคริปต์เขียนทับไฟล์ปลายทาง การสำรองจึงเป็นมาตรการป้องกันที่ไม่ควรละเลย โดยเฉพาะเมื่อไฟล์มี Macro ที่อาจสูญหายได้


6. Philosophy

บทสนทนานี้เผยให้เห็นหลักการเชิงปรัชญาที่สำคัญว่า "ข้อมูลไม่เท่ากับเอกสาร" — ข้อมูลคือเนื้อหา ส่วนเอกสารคือระบบนิเวศที่ประกอบด้วยเนื้อหา รูปแบบ และตรรกะ (Macro) การรักษาเฉพาะเนื้อหาแต่ทิ้งตรรกะ คือการรักษาร่างแต่ทิ้งวิญญาณ

อีกนัยหนึ่งคือ "ความเร็วไม่ใช่เป้าหมายสูงสุด แต่เป็นตัวแปรที่ต้องเจรจา" — เราไม่ควรเลือกวิธีที่เร็วที่สุดโดยอัตโนมัติ หากวิธีนั้นทำลายสิ่งที่เราให้คุณค่า การเลือกใช้ UNO API แม้จะช้ากว่า คือการยอมรับว่าคุณค่าบางอย่างมีราคาที่ต้องจ่าย

และสุดท้าย "ภาระที่ทำซ้ำได้ ควรถูกเปลี่ยนเป็นอัตโนมัติ" — การที่ต้องรัน LibreOffice ใน listening mode ทุกครั้งไม่ใช่ข้อจำกัดที่ต้องทน แต่เป็นโอกาสที่จะออกแบบ lifecycle ให้สคริปต์ดูแลตัวเอง


7. Future Work

สิ่งที่ควรทำต่อ:

  1. ทดสอบ UNO API กับข้อมูลจริงขนาด 950,000 แถว เพื่อวัดเวลาจริงและตรวจสอบว่าไม่มี memory leak
  2. ขยายสคริปต์ให้รองรับการเลือก sheet ปลายทาง (ปัจจุบัน hardcode เป็น sheet แรก)
  3. เพิ่ม logging แบบละเอียด เพื่อให้ตรวจสอบย้อนหลังได้หากเกิดข้อผิดพลาดกลางทาง
  4. พัฒนา rollback mechanism กรณีการถ่ายโอนล้มเหลวกลางทาง เพื่อไม่ให้ไฟล์ปลายทางอยู่ในสภาพครึ่ง ๆ กลาง ๆ
  5. สำรวจแนวทางใช้ XLSM แทน ODS หาก Macro เป็นปัจจัยสำคัญระยะยาว เพราะ ecosystem ของ Excel อาจมี library ที่รักษา Macro ได้ดีกว่า

8. Closing Note

การถ่ายโอนข้อมูลระหว่างไฟล์ ODS ที่ดูเหมือนเป็นเพียงงานเทคนิคเล็ก ๆ กลับกลายเป็นการเดินทางที่เผยให้เห็นชั้นของปัญหา และในแต่ละชั้นก็มีบทเรียนซ่อนอยู่ เราเริ่มต้นด้วยคำถามง่าย ๆ ว่า "จะย้ายข้อมูลอย่างไร" แต่เมื่อไล่ตามไป กลับพบว่าแท้จริงแล้วเรากำลังถามว่า "อะไรคือสิ่งที่เรายอมสูญเสีย" และ "อะไรคือสิ่งที่เราต้องรักษาไว้ไม่ว่าจะมีราคาเท่าใด"

การเลือกใช้ UNO API แม้จะช้ากว่า ไม่ได้เป็นเพียงเพราะความสมบูรณ์ของ Macro หากแต่เป็นการยอมรับว่าในงานข้อมูลบางประเภท ความเร็วไม่ใช่ตัวชี้วัดเดียวของความสำเร็จ และบางครั้ง การยอมช้าลงเพื่อรักษาสิ่งที่สำคัญกว่า คือการตัดสินใจที่ฉลาดที่สุด

การเดินทางครั้งนี้จึงไม่ใช่แค่การเขียนสคริปต์ แต่เป็นการเรียนรู้ที่จะคิดแบบวิศวกรที่ให้ความสำคัญกับ lifecycle ทั้งหมดของระบบ ไม่ใช่แค่ผลลัพธ์ปลายทาง


— บันทึกโดย KOOeda6, Phase of Constraint Discovery