Skip to content

Commit

Permalink
Document and fix the Index variable in loops
Browse files Browse the repository at this point in the history
  • Loading branch information
Amberg committed Nov 7, 2024
1 parent 5e201e5 commit dac4e89
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 2 deletions.
3 changes: 2 additions & 1 deletion DocxTemplater.Test/DocxTemplater.Test.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>12.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
Expand Down
3 changes: 3 additions & 0 deletions DocxTemplater.Test/PatternMatcherTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ static IEnumerable TestPatternMatch_Cases()
yield return new TestCaseData("{{var}:format(a,b)}").Returns(new[] { PatternType.Variable }).SetName("Multiple Arguments");
yield return new TestCaseData("{{/}}").Returns(new[] { PatternType.ConditionEnd });
yield return new TestCaseData("{ { / } }").Returns(new[] { PatternType.ConditionEnd });
yield return new TestCaseData("{?{ds.QrBills.idx == 2}}").Returns(new[] { PatternType.Condition });
yield return new TestCaseData("{?{ds.QrBills._Idx == 2}}").Returns(new[] { PatternType.Condition }).SetName("underscore in variable name");
yield return new TestCaseData("{?{ds.QrBills._Idx % 2 == 0}}").Returns(new[] { PatternType.Condition }).SetName("modulo in condition");
yield return new TestCaseData(
"NumericValue is greater than 0 - {{ds.Items.InnerCollection.InnerValue}:toupper()}{{else}}" +
"I'm here if if this is not the case{{/}}{{/ds.Items.InnerCollection}}{{/Items}}")
Expand Down
68 changes: 68 additions & 0 deletions DocxTemplater.Test/SpecialCollectionVariableTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using System;

Check failure on line 4 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)

Check failure on line 4 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)

Check failure on line 4 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DocxTemplater.Test
{
internal class SpecialCollectionVariableTest
{
[Test]
public void TestIndexVariableInLoop()
{
var model = new[] {"Item1", "Item2", "Item3", "Item4"};

Check failure on line 17 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 17 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 17 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 17 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 17 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 17 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

Check failure on line 17 in DocxTemplater.Test/SpecialCollectionVariableTest.cs

View workflow job for this annotation

GitHub Actions / build

Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)
var template = "Items:{{#Items}}{{Items._Idx}}{{.}} {{/Items}}";

using var memStream = new MemoryStream();
using var wpDocument = WordprocessingDocument.Create(memStream, WordprocessingDocumentType.Document);
MainDocumentPart mainPart = wpDocument.AddMainDocumentPart();
mainPart.Document = new Document(new Body(new Paragraph(new Run(new Text(template)))));
wpDocument.Save();
memStream.Position = 0;
var docTemplate = new DocxTemplate(memStream);
docTemplate.BindModel("Items", model);
var result = docTemplate.Process();
result.Position = 0;
// compare body
result.Position = 0;
var document = WordprocessingDocument.Open(result, false);
var body = document.MainDocumentPart.Document.Body;
Assert.That(body.InnerXml, Is.EqualTo("<w:p xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">" +
"<w:r>" +
"<w:t xml:space=\"preserve\">Items:</w:t><w:t xml:space=\"preserve\">1</w:t><w:t xml:space=\"preserve\">Item1</w:t>" +
"<w:t xml:space=\"preserve\"> </w:t><w:t xml:space=\"preserve\">2</w:t><w:t xml:space=\"preserve\">Item2</w:t>" +
"<w:t xml:space=\"preserve\"> </w:t><w:t xml:space=\"preserve\">3</w:t><w:t xml:space=\"preserve\">Item3</w:t>" +
"<w:t xml:space=\"preserve\"> </w:t><w:t xml:space=\"preserve\">4</w:t><w:t xml:space=\"preserve\">Item4</w:t>" +
"<w:t xml:space=\"preserve\"> </w:t></w:r></w:p>"));
}

[Test]
public void TestConditionWithIndexVariableInLoop()
{
var model = new[] { "Item1", "Item2", "Item3", "Item4" };
var template = "Items:{{#Items}}{?{Items._Idx % 2 == 0}}{{.}}{{/}}{{/Items}}";

using var memStream = new MemoryStream();
using var wpDocument = WordprocessingDocument.Create(memStream, WordprocessingDocumentType.Document);
MainDocumentPart mainPart = wpDocument.AddMainDocumentPart();
mainPart.Document = new Document(new Body(new Paragraph(new Run(new Text(template)))));
wpDocument.Save();
memStream.Position = 0;
var docTemplate = new DocxTemplate(memStream);
docTemplate.BindModel("Items", model);
var result = docTemplate.Process();
result.Position = 0;
// compare body
result.Position = 0;
var document = WordprocessingDocument.Open(result, false);
var body = document.MainDocumentPart.Document.Body;
Assert.That(body.InnerXml, Is.EqualTo("<w:p xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:r><w:t xml:space=\"preserve\">Items:" +
"</w:t><w:t xml:space=\"preserve\">Item2</w:t>" +
"<w:t xml:space=\"preserve\">Item4</w:t></w:r></w:p>"));
}
}
}
2 changes: 1 addition & 1 deletion DocxTemplater/PatterMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal static class PatternMatcher
(?<separator>:\s*s\s*:) |
(?<else>(?:else)|:) |
(?(condMarker) # if condition marker is set, we expect a condition
(?<condition>[a-zA-Z0-9+\-*\/><=\s\.\!&\|]+)? #condition name (without brackets)
(?<condition>[a-zA-Z0-9+\-*\/><=\s\.\!&\|_%]+)? #condition expression (without brackets)
|
(?:
(?<prefix>[\/\#])?(?<varname>[a-zA-Z0-9\._]+)? #variable name
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ The syntax is case insensitive.
| `{{SomeDate}:F('MM/dd/yyyy')}` | Date variable with formatting - short syntax |
| `{{SomeBytes}:img()}` | Image Formatter for image data |
| `{{SomeHtmlString}:html()}` | Inserts HTML string into the word document |
| `{{#Items}}{?{Items._Idx % 2 == 0}}{{.}}{{/}}{{/Items}}` | Renders every second item in a list |
---
### Collections

Expand Down Expand Up @@ -113,6 +114,11 @@ Will render a table row for each item in the collection:
|-------|-----------|
| John | Developer |
| Alice | CEO |

#### Accessing the Index of the Current Item

To access the index of the current item, use the special variable `Items._Idx` In this example, the collection is called "Items".

---
### Separator

Expand Down

0 comments on commit dac4e89

Please sign in to comment.