Ootempl

Office Open XML document templating library for Elixir. Generate customized Word documents by replacing placeholders in templates with dynamic data.

Features

  • Simple Placeholder Replacement - Use {{variable}} syntax in Word templates
  • Nested Data Access - Access nested data with {{customer.name}} notation
  • Conditional Sections - Show/hide content with {{if condition}}...{{endif}}
  • Dynamic Tables - Auto-generate table rows from list data
  • Hierarchical Tables - Create nested table structures with {{#list}}...{{/list}} blocks
  • Image Replacement - Replace placeholder images with dynamic content
  • Case-Insensitive Matching - {{Name}}, {{name}}, and {{NAME}} all match the same data key
  • Formatting Preservation - Maintains Word formatting (bold, italic, fonts, colors, table borders)
  • Document Properties - Replace placeholders in title, author, company metadata
  • Headers & Footers - Process placeholders in headers, footers, footnotes, and endnotes
  • Comprehensive Validation - Reports all missing placeholders and errors for easy debugging

Quick Start

Create a Word template with placeholders:

Dear {{customer.name}},

Your order total is {{total}}.

Generate a document in Elixir:

data = %{
  "customer" => %{"name" => "John Doe"},
  "total" => "$99.99"
}

Ootempl.render("template.docx", data, "output.docx")
#=> :ok

Installation

If available in Hex, the package can be installed by adding ootempl to your list of dependencies in mix.exs:

def deps do
  [
    {:ootempl, "~> 0.1.0"}
  ]
end

Table Templates

Simple Tables

Table rows are automatically duplicated for list data:

data = %{
  "items" => [
    %{"name" => "Widget", "price" => "$10"},
    %{"name" => "Gadget", "price" => "$25"}
  ]
}

Template:

| Item           | Price           |
| {{items.name}} | {{items.price}} |

Output:

| Item   | Price |
| Widget | $10   |
| Gadget | $25   |

Hierarchical Tables

For nested data with parent-child relationships, use block markers in dedicated rows:

data = %{
  "categories" => [
    %{
      "name" => "Electronics",
      "subtotal" => "$300",
      "items" => [
        %{"desc" => "Phone", "price" => "$200"},
        %{"desc" => "Charger", "price" => "$100"}
      ]
    }
  ]
}

Template (marker rows are removed from output):

| {{#categories}} |           |         |  <- Marker row (removed)
| {{name}}        |           | {{subtotal}} |  <- Header row
| {{#items}}      |           |         |  <- Marker row (removed)
|                 | {{desc}}  | {{price}} |  <- Body row (repeated)
| {{/items}}      |           |         |  <- Marker row (removed)
| {{/categories}} |           |         |  <- Marker row (removed)

Output:

| Electronics |         | $300 |
|             | Phone   | $200 |
|             | Charger | $100 |

Block markers support:

  • Nested iteration - Parent/child data hierarchies
  • Data inheritance - Child rows access both parent and child fields
  • Empty handling - Empty lists produce no rows

Documentation

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/ootempl.