/* global Word, Office */ /** * FR-17 / FR-18 — จุดเดียวที่คุยกับ document-level API ของ Word * (native save / อ่าน dirty / ปิดเอกสาร) แยกจาก versionFlow เพื่อให้ * autoSaveService กับปุ่ม [บันทึก] ใช้ร่วมได้โดยไม่ต้องพ่วง flow versioning * พอร์ตดิบจาก D:\word-addin-poc\addin\src\services\documentService.ts */ export enum DocumentCloseMode { /** บันทึกการแก้ไขก่อนปิด */ Save = "Save", /** ปิดโดยไม่บันทึก — ไว้ใช้ระดับ service เท่านั้น (UI ปัจจุบันไม่มีปุ่มไหนใช้) */ SkipSave = "SkipSave", } /** native save ตาม FR-2 ขั้นตอนที่ 4 — ใช้ร่วมทั้ง versionFlow และ autoSaveService * เรียกแบบไม่ส่ง saveBehavior: ปลอดภัยทุกรุ่น runtime — รุ่นเก่า (npm 1.1.110) ไม่มี * enum Word.SaveBehavior และรับ save() แบบไม่มี argument, รุ่นใหม่ param เป็น optional * ที่ default เดียวกัน (behavior = save เงียบ ๆ) */ export async function saveDocument(): Promise { await Word.run(async (context) => { context.document.save(); await context.sync(); }); } /** FR-3 — มีการแก้ไขที่ยังไม่ถูกบันทึกลงไฟล์ local หรือไม่ */ export async function isDocumentDirty(): Promise { return Word.run(async (context) => { context.document.load("saved"); await context.sync(); return !context.document.saved; }); } /** save แล้วเช็คว่า Word เห็นไฟล์สะอาดจริง — บางสถานะ (เช่น หลังเขียน custom properties / * custom XML part ของ flow versioning) Word ยังรายงาน saved=false แม้ save ผ่านแล้ว * จึง save ซ้ำแบบมีขอบเขต (รวมสูงสุด 3 รอบ) — ไม่งั้น periodic tick ของ auto-save * เห็น dirty ตอนไม่มีใครแก้อะไร แล้ว banner FR-3 ("มีการแก้ไขที่ยังไม่เป็น version") * โผล่ผิด ๆ หลังจบ flow */ export async function saveDocumentVerified(): Promise { await saveDocument(); for (let attempt = 0; attempt < 2; attempt += 1) { if (!(await isDocumentDirty())) return; await saveDocument(); } } /** * FR-18 — `document.close()` ต้องการ WordApi 1.5 **และใช้ไม่ได้บน Word on the web** * (requirement-set table ระบุรองรับ แต่หน้าเอกสารของ method เขียนไว้ว่า "isn't * supported in Word on the web") จึงต้องเช็ค platform คู่กันเสมอ — * UI ใช้ซ่อนปุ่ม close ทุกแบบ, service ใช้ guard ก่อนเรียกจริง * (เรียกนอก Word — เช่น SSR หรือ browser ธรรมดา — throw ถูก catch คืน false เสมอ) */ export function canCloseDocument(): boolean { try { return ( Office.context.requirements.isSetSupported("WordApi", "1.5") && Office.context.platform !== Office.PlatformType.OfficeOnline ); } catch { return false; } } /** FR-18 — ปิดเอกสารปัจจุบัน (task pane จะปิดตามเอกสาร) */ export async function closeDocument(mode: DocumentCloseMode = DocumentCloseMode.Save): Promise { if (!canCloseDocument()) { throw new Error( "เวอร์ชัน Word นี้ไม่รองรับการปิดเอกสารจาก add-in (รองรับเฉพาะ Word Desktop ที่ใช้ WordApi 1.5 ได้)" ); } await Word.run(async (context) => { // ส่งค่า underlying ของ enum เป็น string ตรง ๆ ไม่อ่าน Word.CloseBehavior.* — // runtime self-host อาจเป็นรุ่นเก่ากว่า @types (กรณี npm 1.1.110 เดิม: ไม่มี enum นี้เลย // อ่านแล้ว TypeError "reading 'save'"; ปัจจุบัน fetch ฉบับ CDN ล่าสุดมี enum แล้วแต่ค่า // string ทำงานเหมือนกันทุกรุ่น — cast กัน @types ที่พิมพ์ parameter เป็น enum object) context.document.close( (mode === DocumentCloseMode.Save ? "Save" : "SkipSave") as Word.CloseBehavior ); // ห้ามเรียก context.sync() หลัง close() — เอกสารปิดกลาง batch ทำให้ sync ถูก abort // (ตัวอย่างทางการของ Word เรียก close เฉยๆ แล้วพึ่ง implicit sync ตอน run() จบ) }); }