ยินดีต้อนรับจดหมายสำหรับลูกค้าใหม่สี่สิบคน, ใบรับรองสำหรับผู้เข้าร่วมทุกคน, ใบแจ้งหนี้ต่อคำสั่งซื้อหนึ่งรายการ: เอกสารเดียวกัน, แต่บันทึกที่แตกต่างกันในแต่ละครั้ง. ด้วย GroupDocs.Assembly.Mcp ที่ทำงานแบบโลคัล (dnx GroupDocs.Assembly.Mcp --yes), Claude Desktop, Cursor หรือ Copilot ทำได้ด้วยการเรียกเครื่องมือหนึ่งครั้ง, assemble_per_record, ซึ่งจะเติมเทมเพลต Word ของคุณหนึ่งครั้งต่อแต่ละองค์ประกอบของอาร์เรย์ JSON, บันทึกผลลัพธ์แต่ละไฟล์เป็น PDF ของตัวเองโดยตั้งชื่อจากฟิลด์ที่คุณเลือก, และรายงานบันทึกที่ล้มเหลวแทนที่จะหยุดที่บันทึกแรก:
สร้าง PDF จดหมายต้อนรับสำหรับลูกค้าทุกคนในไฟล์ customers.json โดยใช้ welcome-letter.docx, และตั้งชื่อแต่ละไฟล์ตามชื่อลูกค้า
เวอร์ชันขั้นตอนต่อขั้นตอนพร้อมการกำหนดค่าและการแก้ไขปัญหาอยู่ในเอกสาร: How to generate one document per record (mail merge) with an AI agent.
ทำไมไม่ให้เอเจนต์ทำลูป?
มันทำได้, และสำหรับห้าบันทึกก็พอใช้ได้. แต่ลูปของการเรียกเครื่องมือสี่สิบครั้งคือสี่สิบโอกาสที่เอเจนต์จะพลาดนับ, ข้ามบันทึกเมื่อบริบทยาว, หรือ “ช่วยเหลือ” โดยการเปลี่ยนคำจดหมายหนึ่งฉบับ. เครื่องมือต่อบันทึกจะย้ายลูปไปที่เซิร์ฟเวอร์: การเรียกหนึ่งครั้ง, เทมเพลตหนึ่งไฟล์, การวนผ่านอาร์เรย์หนึ่งครั้ง, และรายงานที่บอกจำนวนไฟล์ที่เขียนได้และบันทึกใดบ้างที่ไม่สำเร็จ. งานของเอเจนต์คือเลือกเทมเพลต, ไฟล์ข้อมูลและฟิลด์ตั้งชื่อ, แล้วอ่านรายงานกลับมาให้คุณ.
เอเจนต์ตรวจสอบอะไรเป็นอันดับแรก?
สองอย่าง: รูปแบบของข้อมูลและสิ่งที่เทมเพลตอ่านได้. ในการทดสอบของเรา, มีลูกค้าห้าคนใน customers.json และจดหมายต้อนรับหน้าเดียว:
-> get_document_info {"file":{"filePath":"customers.json"}}
<- { "dataKind": "json",
"data": { "root": "array", "length": 5, "keys": null } }
-> get_template_fields {"template":{"filePath":"welcome-letter.docx"}}
<- { "dataSourceNames": [ "customer" ],
"fields": [ "customer.Contact", "customer.Plan", "customer.Name",
"customer.Manager", "customer.FirstInvoice" ] }
เทมเพลตเรียกบันทึกหนึ่งว่า customer; เซิร์ฟเวอร์จะสรุปเอง, ดังนั้นเอเจนต์ไม่จำเป็นต้องส่ง dataSourceName.
การเรียกหนึ่งครั้ง, ห้าบันทึก, ความล้มเหลวหนึ่งรายการ
-> assemble_per_record {"template":{"filePath":"welcome-letter.docx"},
"data":{"filePath":"customers.json"},"fileNameField":"Name",
"format":"pdf"}
<- Assembled 4 of 5 document(s) from 'welcome-letter.docx' with
'customers.json', one per record (each record as 'customer'), as PDF.
Saved to:
.../Contoso Pharma.pdf
.../Fabrikam Logistics.pdf
.../Tailspin Toys.pdf
.../Litware Labs.pdf
1 record(s) failed:
record 4: InvalidOperationException: ... Can not get the value of
member 'FirstInvoice' on type 'System.Data.DataRow'. The template
reads 'FirstInvoice', which the data does not have. ...
บันทึกที่ 4, Wingtip Travel, ไม่มีวันที่ใบแจ้งหนี้แรกในข้อมูล. จดหมายสี่ฉบับที่เหลือถูกเขียน, แต่ละฉบับตั้งชื่อตามลูกค้า, และความล้มเหลวถูกส่งกลับพร้อมหมายเลขบันทึกและฟิลด์ที่หายไป. เอเจนต์จะรายงานว่า “จดหมายสี่ฉบับเสร็จ; Wingtip Travel ไม่มีวันที่ใบแจ้งหนี้แรก, คุณต้องการให้ปล่อยบรรทัดว่างหรือรอวันที่?” นั่นคือการสนทนาที่คุณต้องการ, แทนที่จะมีสี่สิบไฟล์โดยไม่รู้ว่าไฟล์ใดผิดพลาด.
วิธีการทำ fan‑out
customers.json [ {Name:"Contoso Pharma",...}, {Name:"Fabrikam ..."},
... 5 records ]
|
assemble_per_record {"template":{"filePath":"welcome-letter.docx"},
"data":{"filePath":"customers.json"},
"fileNameField":"Name","format":"pdf"}
|
+--> Contoso Pharma.pdf
+--> Fabrikam Logistics.pdf ... 2 more
'--> "4 of 5 ... 1 record(s) failed: record 4 ..."
สามพารามิเตอร์ทำหน้าที่นี้. fileNameField ตั้งชื่อผลลัพธ์แต่ละไฟล์จากฟิลด์ของบันทึก, เช่น customer.Name หรือหมายเลขใบแจ้งหนี้; หากไม่มี, ไฟล์จะได้รับหมายเลขลำดับ. recordsPath ชี้ไปที่อาร์เรย์เมื่อ JSON เป็นอ็อบเจ็กต์ที่บรรจุอาร์เรย์หนึ่ง, เช่น "customers" หรือ "batch.items". ส่วน maxDocuments คือเบรก.
สิ่งที่หยุด batch ที่วิ่งเกินขอบเขต?
maxDocuments, มีค่าเริ่มต้นเป็น 100 และสูงสุดได้ถึง 1000. ก่อนเขียนอะไรเซิร์ฟเวอร์จะนับบันทึก; หากจำนวนเกินขีดจำกัด, เซิร์ฟเวอร์จะปฏิเสธ. เราตั้งค่าเป็น 3 สำหรับลูกค้าห้าคนของเรา:
-> assemble_per_record {..., "maxDocuments":3}
<- Per-record assembly failed for 'welcome-letter.docx': there are 5
records, more than maxDocuments=3. Raise 'maxDocuments' (up to 1000)
or pass fewer records.
ไม่มีไฟล์ใดถูกเขียน. สำหรับการส่งจดหมายที่ต้องส่งถึงคนจริง, นี่คือค่าเริ่มต้นที่เหมาะสม: คำถามที่ชี้ไปที่การส่งออก CRM ทั้งหมดจะได้รับการตอบกลับเป็นคำถาม, ไม่ใช่ PDF หมื่นฉบับ.
ข้อมูลของฉันเป็นสเปรดชีต, ไม่ใช่ JSON
การสร้างต่อบันทึกอ่านเฉพาะ JSON: อาร์เรย์ของอ็อบเจ็กต์, หรืออ็อบเจ็กต์ที่บรรจุอาร์เรย์หนึ่ง. เมื่อรายการอยู่ใน CSV หรือแผ่นงาน, เอเจนต์จะเปลี่ยนแถวเป็น JSON ก่อน, ซึ่งเอเจนต์ทำได้ดี, แล้วเขียนไฟล์ลงในโฟลเดอร์ storage. หากคุณต้องการเอกสารหนึ่งฉบับที่แสดงทุกแถว, เช่น รายการราคา หรือทะเบียน, ให้ใช้ assemble_document พร้อม <<foreach>> ในเทมเพลต, ซึ่งจะอ่าน CSV และสเปรดชีตโดยตรง.
ข้อจำกัดที่ต้องระวัง
- การประกอบต่อบันทึกอ่านเฉพาะ JSON; ข้อมูล CSV และสเปรดชีตต้องแปลงเป็น JSON ก่อน.
- โหมดประเมินผล: ทุกไฟล์ที่สร้างจะเริ่มด้วย “Evaluation Only. Created with GroupDocs.Assembly 26.7…”, และเทมเพลตอีเมลจะเก็บเฉพาะข้อความตัวอักษรธรรมดา. ให้ทำการเปิดใช้งานไลเซนส์บนเซิร์ฟเวอร์ก่อนการส่งจดหมายจริง.
- ฟิลด์ที่หายไปจะทำให้บันทึกนั้นล้มเหลว.
allowMissingMembers: trueจะเขียนบันทึกโดยปล่อยบรรทัดว่างแทน; เลือกตามที่คุณต้องการ. - วันที่: เขียนเป็น
2026-12-01T00:00:00แล้วจัดรูปแบบในเทมเพลต, เช่นจดหมายของเราที่ใช้<<[customer.FirstInvoice]:"d MMMM yyyy">>. เราพบว่าข้อความวันที่ที่มีเฉพาะวันถูกเลื่อนหนึ่งวันบนเครื่องที่ตั้งค่า UTC+2 ในการทดสอบ. - เซิร์ฟเวอร์เขียนไฟล์; มันไม่ส่งไฟล์. การจัดส่งเป็นขั้นตอนแยกต่างหาก.
คำถามที่พบบ่อย
ฉันสามารถทำ mail merge ด้วย Claude โดยไม่ต้องอัปโหลดรายการลูกค้าได้หรือไม่?
ได้. เซิร์ฟเวอร์ทำงานแบบโลคัลและอ่าน customers.json จากโฟลเดอร์ storage ของคุณ; PDF ที่สร้างจะถูกเขียนลงที่นั่นเช่นกัน.
ไฟล์ผลลัพธ์ตั้งชื่ออย่างไร?
โดยฟิลด์บันทึกที่คุณส่งเป็น fileNameField, ในกรณีนี้คือชื่อลูกค้า, ดังนั้น Contoso Pharma.pdf. หากไม่ได้ตั้งค่า, จะใช้หมายเลขลำดับ.
แต่ละเอกสารสามารถเป็นอีเมลแทน PDF ได้หรือไม่?
ได้: ใช้เทมเพลต EML หรือ MSG, หรือส่ง format: "eml". ในโหมดประเมินผลเนื้อหา HTML ของอีเมลจะถูกแทนที่ด้วยบรรทัดประเมินผล, ดังนั้นให้ทดสอบการส่งอีเมลด้วยไลเซนส์.
ไปให้ลึกขึ้น
- เอกสาร, วิธีทำแบบมาตรฐาน: How to generate one document per record (mail merge) with an AI agent
- ศูนย์รวมเอกสาร: GroupDocs.Assembly MCP Server
- เริ่มต้นที่นี่: Let the model fill in the data, not write the document
- เกี่ยวข้อง: What does this template need? Ask it.
- เกี่ยวข้อง: The chart comes from the template, the numbers come from the data
- เกี่ยวข้อง: Your repo already has the data; let the agent make the PDF
- โมเดลการติดตั้งในองค์กรและความปลอดภัย: 3 architectures for AI document processing, and the one that keeps files inside your network
- คำถาม: GroupDocs Assembly forum
- แหล่งที่มา: GroupDocs.Assembly.Mcp on GitHub