Still wasn’t able to inline the images for this post, but I moved them to google photos, so at least now when you click you can actually see them in your browser, rather than having to download them as image.png
I’m generating documents using user-maintainable Word .dotx templates that get passed into Aspose LINQ ReportingEngine.BuildReport
.
One such document is a table of either two or three columns, in which most of the cells would be this same template statement:
<<[ItemIndex]>>. Item#<<[ItemCode]>> <<if [IsAbcd]>> ABCD<</if>><<if [IsEfgh]>> EFGH<</if>><<if [IsWxyz]>> (WXYZ)<</if>>
The original code that we’re now replacing also used Aspose.Words to do this, but used the classic Mail Merge approach, and did this whole concatenation in code beforehand. That means if they wanted to change how any of that is formatted, they would need developer intervention and a new version of the application.
With the LINQ reporting engine it’s much easier to do IFs right in the template, so I’m revisiting this.
In order to support two or three columns, the template had two sections, and the one with the wrong number of columns gets removed by the code. I think the new version will have to do the same.
The dataset schema looked something like this:
public class ExampleDataRow {
public string Concatenation1 { get; set; }
public string Concatenation2 { get; set; }
public string Concatenation3 { get; set; }
}
and the corresponding template in Word:
https://photos.app.goo.gl/wqkp7szomkkn6zxs5
old school mail merge template
Wanting to do this in the Word template instead, we can start by exposing more of the schema:
public class ExampleItem {
public int ItemIndex { get; set; }
public string ItemCode { get; set; }
public bool IsAbcd { get; set; }
public bool IsEfgh { get; set; }
public bool IsWxyz { get; set; }
}
public class ExampleDataRow {
public ExampleItem Item1 { get; set; }
public ExampleItem Item2 { get; set; }
public ExampleItem Item3 { get; set; }
}
The corresponding template in Word looks like this:
https://photos.app.goo.gl/7swejvk3wh7cqrkna
LINQ reporting template version 1
Even having adjusted the format on the non-printing markup, it’s hard to make sense of and even to tell that it’s the same thing maintained in 5 different places.
We can go a bit farther by nesting collections, which surprisingly lets us just use indexers:
public class ExampleDataTable
{
public List<List<ExampleItem>> ExampleDataRows { get; set; }
}
<<[[0].ItemIndex]>>. Item#<<[[0].ItemCode]>> <<if [[0].IsAbcd]>> ABCD<</if>><<if [[0].IsEfgh]>> EFGH<</if>><<if [[0].IsWxyz]>> (WXYZ)<</if>>
And further from that, we can use var:
<<var [i = [0]]>><<[i.ItemIndex]>>. Item#<<[i.ItemCode]>> <<if [i.IsAbcd]>> ABCD<</if>><<if [i.IsEfgh]>> EFGH<</if>><<if [i.IsWxyz]>> (WXYZ)<</if>>
Which results in a snippet that’s exactly the same for all of the cells we need it in…
but there’s nothing to do with that but still put it in 5 places, and so that still makes the template unreadable and unmaintainable. We haven’t really made any progress, other than making it a little less error-prone by not repeating Item1 Item2 Item3 several times:
https://photos.app.goo.gl/lwfucm6pkqnkmknp6
LINQ reporting template using nested lists and var
What I’d like to be able to do is define that snippet once and just reference in all of the places it applies.
I don’t know if there’s any existing way to do this, but I can’t seem to see one. (I even tried using Select
to project a string, but not only was that really messy, and would require the template maintainer to understand C# code which is unreasonable, but moreover you can really only get the text of the <<if>>
statements that way, not any formatting they might wish to apply.)
Some of the ways I’d think that could look:
-
Some kind of function syntax, which would be the easiest to understand and most flexible: <a href=
https://photos.app.goo.gl/wt2zmffyk12w4r1e7
>a function-like template -
A verbatim template include kind of syntax (which I’m guessing might be easier to implement, just a couple early passes on the document to find template tags and substitute them):
https://photos.app.goo.gl/c2ze7drcopz8mscn6
a verbatim early-include type of approach
Thoughts? Any existing way to do anything like this? Any roadmap for anything like this to exist in the future?
Thanks