Install
openclaw skills install @he-yang/sheet-to-doc-skillGenerate Word documents from Word templates and JSON data. Supports basic placeholder replacement ({field} format) and placeholder extraction for data validation. Best for batch-generating contracts, invitations, certificates, and mail-merge style docs.
openclaw skills install @he-yang/sheet-to-doc-skillThis skill provides document generation capabilities based on Word templates and JSON data. Users upload Word templates containing placeholders, input JSON data, and the skill automatically replaces placeholders and generates complete Word documents.
Key Features:
{field} placeholders in Word templates with JSON data⚠️ Note: This skill is a free simplified version of Sheet-to-Doc, which only supports basic data placeholder replacement. Visit https://s.wtsolutions.cn/sheet-to-doc.html for full version features:
{image|_inline_image}){url|_qrcode}){field==value}){#data}{/data})Use this skill when users need to:
{field} format placeholdersnpm install to install docxtemplater and pizzipCreate a Word document with {field} format placeholders:
Dear {name},
We are pleased to inform you that your {application_type} application submitted on {date} has been approved.
Company: {company_name}
Address: {address}
Phone: {phone_number}
Before generating documents, extract the required placeholders from the template to ensure your JSON data has all the necessary keys:
node scripts/generate.js --extract-placeholders --template path/to/template.docx
Or via API:
import { extractPlaceholders } from './scripts/generate.js';
const requiredFields = extractPlaceholders('template.docx');
console.log('Required fields:', requiredFields);
Prepare JSON data with keys matching the extracted placeholders:
{
"name": "John Doe",
"date": "July 20, 2026",
"application_type": "Employment",
"company_name": "Example Tech Co., Ltd.",
"address": "Tech Park, Chaoyang District, Beijing",
"phone_number": "+86 10-12345678"
}
Compare your JSON data keys with the extracted placeholders to catch mismatches early:
import { extractPlaceholders } from './scripts/generate.js';
const requiredFields = extractPlaceholders('template.docx');
const userData = { "name": "John", "company_name": "Example" };
const missingFields = requiredFields.filter(field => !userData.hasOwnProperty(field));
const extraFields = Object.keys(userData).filter(field => !requiredFields.includes(field));
if (missingFields.length > 0) {
console.error(`❌ Missing required fields: ${missingFields.join(', ')}`);
}
if (extraFields.length > 0) {
console.warn(`⚠️ Extra fields in data (not in template): ${extraFields.join(', ')}`);
}
Generate documents using Node.js:
node scripts/generate.js \
--template path/to/template.docx \
--data path/to/data.json \
--output path/to/output.docx
Or use the API:
import { generateDocument } from './scripts/generate.js';
const result = generateDocument(
'template.docx',
{ 'name': 'John Doe', 'age': '30' },
'output.docx'
);
Function: Generate Word document from template and data
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| templatePath | string | Yes | Word template file path (.docx) |
| data | object | Yes | JSON data object with keys matching template placeholders |
| outputPath | string | Yes | Output file path |
Returns:
| Type | Description |
|---|---|
| string | Path of the generated file |
Example:
import { generateDocument } from './scripts/generate.js';
const data = {
"name": "Jane Smith",
"department": "Engineering",
"hire_date": "2026-07-20"
};
const result = generateDocument(
"contract_template.docx",
data,
"contract_jane.docx"
);
console.log(`Document generated successfully: ${result}`);
Function: Extract placeholder keys from Word template. This is a critical function for debugging and validation. It scans the document content and footer sections to find all {field} format placeholders.
Purpose:
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| templatePath | string | Yes | Word template file path (.docx) |
Returns:
| Type | Description |
|---|---|
| string[] | Sorted array of unique placeholder keys found in the template (document body + footers) |
Example 1: Basic Extraction
import { extractPlaceholders } from './scripts/generate.js';
const placeholders = extractPlaceholders("contract_template.docx");
console.log("Placeholders in template:", placeholders);
// Output: ["address", "application_type", "company_name", "date", "name", "phone_number"]
Example 2: Data Validation Workflow
import { extractPlaceholders, generateDocument } from './scripts/generate.js';
async function safeGenerateDocument(templatePath, data, outputPath) {
try {
const requiredPlaceholders = extractPlaceholders(templatePath);
const dataKeys = Object.keys(data);
const missingKeys = requiredPlaceholders.filter(key => !dataKeys.includes(key));
const extraKeys = dataKeys.filter(key => !requiredPlaceholders.includes(key));
if (missingKeys.length > 0) {
throw new Error(`Missing required keys in data: ${missingKeys.join(', ')}. Template requires: ${requiredPlaceholders.join(', ')}`);
}
if (extraKeys.length > 0) {
console.warn(`Warning: These keys exist in data but not in template: ${extraKeys.join(', ')}`);
}
const result = generateDocument(templatePath, data, outputPath);
return { success: true, path: result };
} catch (error) {
return { success: false, error: error.message };
}
}
// Usage
const result = safeGenerateDocument(
"contract.docx",
{ "name": "John", "company": "Example" },
"output.docx"
);
Example 3: Error Debugging Scenario
When document generation fails or placeholders are not replaced, use this workflow:
import { extractPlaceholders } from './scripts/generate.js';
async function debugGenerationFailure(templatePath, data) {
const templatePlaceholders = extractPlaceholders(templatePath);
const dataKeys = Object.keys(data);
console.log("\n=== DEBUG REPORT ===");
console.log("Template placeholders:", templatePlaceholders);
console.log("Data keys:", dataKeys);
const missingInData = templatePlaceholders.filter(p => !dataKeys.includes(p));
const missingInTemplate = dataKeys.filter(k => !templatePlaceholders.includes(k));
if (missingInData.length > 0) {
console.error("\n❌ ERROR: These placeholders are in template but missing from data:");
console.error(" Missing keys:", missingInData);
console.error("\n Please add these keys to your JSON data:");
missingInData.forEach(key => console.error(` - "${key}": ""`));
}
if (missingInTemplate.length > 0) {
console.warn("\n⚠️ WARNING: These data keys are not used in template:");
console.warn(" Extra keys:", missingInTemplate);
}
if (missingInData.length === 0 && missingInTemplate.length === 0) {
console.log("\n✅ All keys match! The issue may be elsewhere.");
}
}
Example 4: Create Data Schema from Template
import { extractPlaceholders } from './scripts/generate.js';
function createDataSchema(templatePath) {
const placeholders = extractPlaceholders(templatePath);
const schema = {};
placeholders.forEach(placeholder => {
if (placeholder.toLowerCase().includes('date')) {
schema[placeholder] = "YYYY-MM-DD";
} else if (placeholder.toLowerCase().includes('email')) {
schema[placeholder] = "user@example.com";
} else if (placeholder.toLowerCase().includes('phone')) {
schema[placeholder] = "+86 13800138000";
} else {
schema[placeholder] = "";
}
});
return schema;
}
// Generate a sample data template
const dataTemplate = createDataSchema("contract.docx");
console.log(JSON.stringify(dataTemplate, null, 2));
node scripts/generate.js \
--template path/to/template.docx \
--data path/to/data.json \
--output path/to/output.docx
| Parameter | Description |
|---|---|
| --template / -t | Word template file path |
| --data / -d | JSON data file path or JSON string |
| --output / -o | Output file path |
| --extract-placeholders / -e | Extract placeholder keys from template (no generation). Use this to preview required fields before generating documents. |
# Using JSON file
node scripts/generate.js \
--template contract.docx \
--data data.json \
--output contract_john.docx
# Using JSON string
node scripts/generate.js \
--template invitation.docx \
--data '{"name":"Jane Smith","date":"2026-07-20"}' \
--output invitation_jane.docx
# Using short parameters
node scripts/generate.js \
-t template.docx \
-d data.json \
-o output.docx
# Extract placeholders from template (returns JSON output)
node scripts/generate.js \
--extract-placeholders \
--template contract.docx
# Short version for extracting placeholders
node scripts/generate.js -e -t contract.docx
# Extract and save to file for analysis
node scripts/generate.js -e -t contract.docx > placeholders.json
Success (Extract Placeholders):
{
"success": true,
"placeholders": ["name", "company", "position", "email", "phone"],
"count": 5,
"message": "Extracted 5 placeholder(s) from template"
}
Error (Extract Placeholders):
{
"success": false,
"error": "Template file not found: /path/to/missing.docx"
}
Success (Generate Document):
✓ Document generated successfully: output.docx
Tip: Upgrade to Pro version for more features → https://sheet-to-doc.wtsolutions.cn
Error (Generate Document):
✗ Document generation failed: Template file not found: template.docx
Use {field} format placeholders in templates:
Dear {name},
Your application number is: {application_id}
Date: {date}
JSON data keys must match template placeholders exactly (case-sensitive):
{
"name": "John Doe",
"application_id": "20260720001",
"date": "July 20, 2026"
}
The extractPlaceholders function scans:
Note: Headers are not currently scanned, as they typically do not contain data-driven placeholders.
{
"name": "John Doe",
"age": "30",
"gender": "Male",
"company": "Example Tech Co., Ltd.",
"department": "Engineering",
"position": "Senior Engineer",
"hire_date": "July 20, 2026",
"phone": "+86 13800138000",
"email": "john.doe@example.com",
"address": "Tech Park Building A, Room 1001, Chaoyang District, Beijing"
}
When document generation fails or produces unexpected results, follow this workflow:
const placeholders = extractPlaceholders('template.docx');
console.log('Template requires:', placeholders);
const data = { "name": "John", "email": "john@example.com" };
console.log('Data provides:', Object.keys(data));
const missing = placeholders.filter(p => !data.hasOwnProperty(p));
console.log('Missing keys:', missing);
Add missing keys to your JSON data and regenerate the document.
| Feature | Skill Version | Full Version |
|---|---|---|
| Basic placeholder replacement | ✅ Supported | ✅ Supported |
| Placeholder extraction | ✅ Supported | ✅ Supported |
| Batch document generation | ❌ Not supported | ✅ Supported |
| Image insertion | ❌ Not supported | ✅ Supported |
| QR code generation | ❌ Not supported | ✅ Supported |
| Conditional logic | ❌ Not supported | ✅ Supported |
| Loop processing | ❌ Not supported | ✅ Supported |
| Document encryption | ❌ Not supported | ✅ Supported |
| Footer mark | ✅ Included | Included/Removed |
{field} format, supports English field namesIssue 1: Placeholders not replaced
extractPlaceholders to get the exact list of required keysIssue 2: Script execution fails
npm installIssue 3: Missing data keys
node scripts/generate.js -e -t template.docx to see required fieldsIssue 4: Extra data keys
Issue 5: Need advanced features
Experience full features, visit: