The Master Chef for Document Templates - Cook delicious documents with your data and templates.
DocuChef provides a unified interface for document generation across multiple formats. It supports Excel document generation using ClosedXML.Report.XLCustom, PowerPoint document generation using DollarSignEngine, and Word document generation with variable binding, table/paragraph repetition, and image insertion.
In the spirit of its culinary name, DocuChef offers both standard API methods and fun cooking-themed extension methods that make template processing feel like preparing a delicious dish!
- Excel Template Processing: Generate Excel documents from templates using ClosedXML.Report.XLCustom
- PowerPoint Template Processing: Generate PowerPoint presentations from templates with embedded variables and functions
- Flexible Variable Binding: Add variables, complex objects, collections to your templates
- Global Variables: Access system information and date/time within your templates
- Custom Function Support: Register custom functions for Excel cell processing and PowerPoint shape processing
- Error Handling: Clear error reporting with specialized exception types
- Culinary API Theme: Optional cooking-themed extension methods for a more enjoyable API experience
- Consistent Document Interface: All document types implement the
IDishinterface for unified handling - Word Template Processing: Generate Word documents from templates with variable binding, table/paragraph repetition, and image insertion
- Unresolved Variable Reporting:
IDish.UnresolvedVariableslists template expressions that failed to resolve during generation (PowerPoint and Word; always empty for Excel, a current limitation of the underlying ClosedXML.Report engine) - Configurable Logging:
RecipeOptions.LoggerFactoryroutes DocuChef's internal diagnostics through your ownMicrosoft.Extensions.Loggingpipeline instead of the console/debug output
- Additional built-in functions for Excel and PowerPoint templates
- Enhanced PowerPoint chart and table functionality
- Enhanced formatting options
- PowerPoint Template Syntax Guide — full
${...}binding syntax, control directives, and nested-context examples for PPT templates - Contributing — coding standards for this repository
Install-Package DocuChef
Or via .NET CLI:
dotnet add package DocuChef
// Create document processor
var chef = new Chef();
// Load your template (Excel or PowerPoint)
var recipe = chef.LoadTemplate("template.xlsx"); // or "template.pptx" or "template.docx"
// Add your data
recipe.AddVariable("Title", "Sales Report");
recipe.AddVariable("Products", productList);
recipe.AddVariable("Date", DateTime.Now);
// Generate and save the document
recipe.Cook("result.xlsx"); // or "result.pptx" or "result.docx"// Create document processor
var chef = new Chef();
// Load your recipe (template)
var recipe = chef.LoadRecipe("template.xlsx"); // or "template.pptx" or "template.docx"
// Add ingredients (variables)
recipe.AddIngredient("Title", "Sales Report");
recipe.AddIngredients(productData); // Add all properties from an object
// Cook the document and serve it
var dish = recipe.CookDish();
dish.Serve("result.xlsx"); // or "result.pptx" or "result.docx"
// Optionally, present the dish to the user
dish.Present(); // Opens in default application// Create document processor
var chef = new Chef();
// Prepare a dish directly from a template and data
chef.PrepareDish("template.xlsx", salesData, "result.xlsx");// Load Excel template
var recipe = chef.LoadTemplate("template.xlsx");
// Register custom functions for Excel processing
recipe.RegisterFunction("FormatCurrency", (cell, value, parameters) => {
if (value is decimal amount)
{
cell.Style.NumberFormat.Format = "$#,##0.00";
return amount;
}
return value;
});
// Or using the culinary API
recipe.RegisterTechnique("FormatCurrency", (cell, value, parameters) => {
// Same implementation
});
recipe.Cook("result.xlsx");To expand a list into one row per item, define a named range in the template that covers the
data row plus one extra column to its left and one extra row below it (a service column and a
service row — required by the underlying ClosedXML.Report engine). Name the range after the
variable you bind, and reference the current item with the fixed item keyword — not the
range name itself:
// Template: named range "Products" spanning A1:C2 (A = service column, row 2 = service row)
// B1: {{item.Name}} C1: {{item.Price}}
var recipe = chef.LoadTemplate("template.xlsx");
recipe.AddVariable("Products", productList); // one row is generated per item in productList
recipe.Cook("result.xlsx");// Load PowerPoint template
var recipe = chef.LoadTemplate("template.pptx");
var categories = new List<Category>();
recipe.AddVariable("Categories", categories);
// recipe.AddVariable(data);
// Generate the presentation
recipe.Cook("result.pptx");ParagraphRepeater and TableRepeater process only the outermost #foreach block. Nested blocks are silently skipped or produce incorrect output:
{{#foreach items}}
{{#foreach item.subItems}} ← NOT processed
{{subItem.Name}}
{{/foreach}}
{{/foreach}}
Workaround: Flatten the data before binding (pre-process nested collections into a flat list).
