Queries and Control Flow

Use filtering, sorting, grouping, projection, loops, and conditions to shape report output in Wordize templates.
What is this page about?

This page focuses on the expression patterns that turn raw data into readable report output.

It covers filtering, sorting, grouping, conditional regions, nested loops, and everyday formatting work with strings, numbers, dates, and null values.

The LINQ Reporting Engine evaluates C#-style expressions inside tags, which means you can shape collections close to the place where they are displayed.

Filter and Sort a Collection

Example template:

Confirmed segments
<<foreach [segment in booking.Segments.Where(s => s.IsConfirmed).OrderBy(s => s.DepartureUtc)]>>
- <<[segment.From]>> to <<[segment.To]>> on <<[segment.DepartureUtc]:"dd MMM HH:mm">>
<</foreach>>

Expected output:

Confirmed segments
- Seattle to Tokyo on 14 Jun 09:20
- Tokyo to Singapore on 18 Jun 13:05

Project a Simpler View

Projection is useful when the document only needs a small part of a larger object:

Visited cities:
<<foreach [city in booking.Segments.Select(s => s.To).Distinct()]>>- <<[city]>>
<</foreach>>

Expected output:

Visited cities:
- Tokyo
- Singapore
- Sydney

Group Repeated Content

Grouping is effective when the report should show headings with detail lines beneath each heading:

<<foreach [carrierGroup in booking.Segments.GroupBy(s => s.Carrier).OrderBy(g => g.Key)]>>
Carrier: <<[carrierGroup.Key]>>
<<foreach [segment in carrierGroup]>>- <<[segment.From]>> to <<[segment.To]>>
<</foreach>>
<</foreach>>

Expected output:

Carrier: Pacific Air
- Seattle to Tokyo
- Tokyo to Singapore
Carrier: Harbor Jet
- Singapore to Sydney

Switch Layouts With Conditions

Conditional blocks let the template describe multiple presentation paths for the same record:

<<if [booking.UpgradeOffer != null]>>
Upgrade offer: <<[booking.UpgradeOffer]>>
<<else>>
Upgrade offer: Not available for this fare.
<</if>>

This pattern is usually easier to maintain than scattering null checks into every output expression.

Nest Regions Carefully

Nested foreach blocks are common in itinerary, order, and scheduling reports:

<<foreach [traveler in booking.Travelers]>>
Traveler: <<[traveler.FullName]>>
<<foreach [segment in traveler.PersonalSegments]>>- <<[segment.From]>> to <<[segment.To]>>
<</foreach>>
<</foreach>>

If nesting becomes hard to follow, add tag headers and keep the inner blocks visually indented in the template document.

Strings, Numbers, Dates, and Nulls

Common formatting patterns:

Passenger count: <<[booking.Travelers.Count()]>>
Grand total: <<[booking.TotalAmount]:"0.00">> USD
Departure date: <<[booking.DepartureDate]:"dddd, dd MMM yyyy">>
<<foreach [traveler in booking.Travelers]>>
<<[traveler.FullName]>>: seat <<[traveler.Seat ?? "pending assignment"]>>
<</foreach>>

Expected output:

Passenger count: 2
Grand total: 1840.50 USD
Departure date: Sunday, 14 Jun 2026
Avery Chen: seat 12A
Noah Patel: seat pending assignment

These expressions keep light presentation logic in the template while leaving the underlying calculations in application code.

Collections and Dictionary Lookups

Collection queries and dictionary access can be mixed in a single expression when the model supports it:

Support language: <<[booking.Metadata["SupportLanguage"]]>>
Meal requests: <<[booking.Travelers.Count(t => t.MealPreference != null)]>>
Important to note:
Prefer readable expressions over dense one-liners. If an expression needs multiple branches, repeated grouping, or domain rules, precompute that value in your application model and bind the result instead.