Using IEnumerable with LINQ Reporting Engine

Hi,

I have successfully used the LINQ Reporting Engine to generate a Word document from a single object. However, when I pass in a collection object, an error is generated saying “An error has been encountered at the end of expression ‘FirstName]>’. Can not get the value of member ‘FirstName’ on type 'System.Collections.Generic.List`1”

I have checked the debugger and all the items have a FirstName value. The format I use in the Word document is <<[FirstName]>>, <<[LastName]>> which works fine with a single object.

Any ideas what I need to do to get a collection/IEnumerable to work with LINQ Reporting Engine?

Thanks

Tim

Hi Tim,

Thanks for your inquiry. To ensure a timely and accurate response, please attach the following resources here for testing:

  • Your input Word document.
  • Please create a standalone console application (source code without compilation errors) that helps us to reproduce your problem on our end and attach it here for testing.

As soon as you get these pieces of information ready, we’ll start investigation into your issue and provide you more information. Thanks for your cooperation.

PS: To attach these resources, please zip them and Click ‘Reply’ button that will bring you to the ‘reply page’ and there at the bottom you can include any attachments with that post by clicking the ‘Add/Update’ button.

Tahir,

Please find attached a console application showing the problem. The Word file I’ve used can be found in the root of the zip folder. You’ll see I’ve commented out some code showing a single Word merge using LINQ Reporting and this works fine but the IEnumerable one doesn’t.

Any questions, please let me know.

Thanks

Tim

Hi Tim,

Thanks for sharing the detail. We suggest you please check following documentation links. Please enclose the FirstName and LastName in foreach tag.

Outputting Sequential Data
In-Paragraph List Template

Please use following modified code with attached modified template document to get the desired output. Hope this helps you.

List<ReportGridContactsViewModel> reportContacts = new List<ReportGridContactsViewModel>();
reportContacts.Add(new ReportGridContactsViewModel { FirstName = "Tim", LastName = "Metcalfe" });
reportContacts.Add(new ReportGridContactsViewModel { FirstName = "Me", LastName = "Last" });
engine.BuildReport(doc, reportContacts, "clients");

Tahir,

Thank you for your response. That all makes sense but what I’m actually wanting to do is to create a new word document for each item in the collection, similar to a mail merge, Apologies for not mentioning that in my first post. How can I now achieve that with Linq Reporting and my sample document?

Thanks

Tim

Hi Tim,

Thanks for your inquiry. If you want to create new word document for each item in the collection, please use overloaded method of ReportingEngine.BuildReport (Document, Object).

List<ReportGridContactsViewModel> reportContacts = new List<ReportGridContactsViewModel>();
reportContacts.Add(new ReportGridContactsViewModel { FirstName = "Tim", LastName = "Metcalfe" });
reportContacts.Add(new ReportGridContactsViewModel { FirstName = "Me", LastName = "Last" });
int i = 1;
foreach (var item in reportContacts)
{
    engine.BuildReport(doc, item);
    doc.Save(@"Out" + i + ".docx");
    i++;
}```

Tahir,

Thanks for that. Sorry, i didn’t mean an individual Word document but multiple ones in the same file. For example, I have a Word document, a letter for example, and a collection with 100 records. I want to do a mail merge style process using Linq Reporting which will generate 100 letters within the same Word document.

Thanks

Tim

Hi Tim,

Thanks for your inquiry. In your case, we suggest you following two solutions. Hope these help you.

Solution 1 :
You can programmatically insert foreach tag before and after fields and then build report.

Aspose.Words.Document doc = new Aspose.Words.Document(@"AsposeLinqTemplate.docx");
ReportingEngine engine = new ReportingEngine();
List<ReportGridContactsViewModel> reportContacts = new List<ReportGridContactsViewModel>();
reportContacts.Add(new ReportGridContactsViewModel { FirstName = "Tim", LastName = "Metcalfe" });
reportContacts.Add(new ReportGridContactsViewModel { FirstName = "Me", LastName = "Last" });
Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);
builder.MoveToDocumentStart();
builder.Write("<<[FirstName]>>");
builder.MoveToDocumentEnd();
builder.Write("<<[LastName ]>>");
engine.BuildReport(doc, reportContacts, "clients");
doc.Save(@"Output.docx");

Solution 2 :
Create an empty document, iterate through the list, build the report, and then append the output document to empty document.

Aspose.Words.Document doc = new Aspose.Words.Document(@"AsposeLinqTemplate.docx");
ReportingEngine engine = new ReportingEngine();
List<ReportGridContactsViewModel> reportContacts = new List<ReportGridContactsViewModel>();
reportContacts.Add(new ReportGridContactsViewModel { FirstName = "Tim", LastName = "Metcalfe" });
reportContacts.Add(new ReportGridContactsViewModel { FirstName = "Me", LastName = "Last" });
Aspose.Words.Document FinalDoc = new Aspose.Words.Document();
FinalDoc.RemoveAllChildren();
int i = 1;
foreach (var item in reportContacts)
{
    Aspose.Words.Document cloneDoc = (Aspose.Words.Document)doc.Clone(true);
    engine.BuildReport(cloneDoc, item);
    FinalDoc.AppendDocument(cloneDoc, Aspose.Words.ImportFormatMode.KeepSourceFormatting);
    i++;
}
FinalDoc.Save(@"Output.docx");

Tahir,

Many thanks for your comprehensive responses. I will experiment with your last suggestions.

It maybe worthwhile updating your documentation for ‘mail merge’ type scenarios using Link Builder. That’s all I’ve really needed but, for me anyway, it wasn’t clear how best to achieve it.

Once again, many thanks.

Tim