Parsware
All articles

Parsware Platform

Reports from a query

A report prints what its saved query returns, so the query is where the work goes. A query that joins each invoice to its customer gives the Money owed report the customer's name and credit limit, and widening the query to overdue invoices changes the report without touching it.

The Money owed report: four invoices, each with its customer, the customer's credit limit and the amount, next to the title "Reports from a query"

A report prints what its saved query returns, nothing more. The drawing decides where things go on the page; the query decides which rows there are and what each row knows. So when a report needs something the table doesn't have, the answer is in the query.

This article makes Money owed: every invoice not yet paid, with the customer who owes it and that customer's credit limit. An invoice knows its customer, but not the customer's credit limit, so the query has to fetch it.

It uses the Invoices — Credit Check sample (business-rules-query-documents): an Invoice table, a Customer table, and invoices for Northwind Traders and Fabrikam. We built the query and the report in a solution of our own, Main, in the same environment.

1. A query that joins the customer

In Main, open Saved Queries and press New. We called it Invoices still owed, with their customer, with the logical name new_invoicesowed, and chose the Invoice table.

On the Advanced tab, Add related table lists the relationships Invoice already has. We chose Customer, one related record: each invoice has one customer. It is called customer in the query, and Keep rows with no match keeps an invoice that has no customer. Then we ticked five columns: the invoice's Reference, Status and Amount, and the customer's Name and Credit limit.

The query designer's Advanced tab: Customer joined as customer, keeping rows with no match, par_customerid to id; Returned columns lists Invoice Reference, Status and Amount, and Customer (customer) Name and Credit limit

Design a query covers the join in full. The filter asks for unpaid invoices, and the sort, which isn't shown, puts the largest amount first:

The Filter: Status Equals Unpaid

Save, then Preview. Three invoices, each with its customer beside it:

Results: 3 matching records, INV-1001 Northwind Traders with a credit limit of 20000, INV-1004 and INV-1005 Fabrikam with 3000

2. A report over it

Under Reports, press New. We called it Money owed and gave it one dataset: Name owed, and Saved query Invoices still owed, with their customer. Leave Record field empty. This report lists every invoice, so it isn't printed from one record (the id in the box is only a hint).

Edit report: Money owed, with one dataset named owed whose saved query is Invoices still owed, with their customer · par_invoice, and an empty Record field

Press Design, add a Report page from Insert, and point its Row (repeater) at owed, the same way as in article 137. We gave the row four cells and the band above it four headings.

3. Bind a joined column

Select the second cell, and open Binding on the Report tab. It lists what the query returns, and that includes the customer's columns, written as row.customer.par_name and row.customer.par_credit_limit:

The report designer with the Customer cell selected and the Binding picker open: Reference, Status, Amount, customer · Name (ticked, row.customer.par_name) and customer · Credit limit

customer is the name the query gave the join. Rename it in the query, and the binding has to follow it.

We bound the four cells to Reference, the customer's Name, their Credit limit and Amount, with Format number on the two amounts. Press Report to preview it:

The Money owed preview: Invoice, Customer, Credit limit and Amount; INV-1001 Northwind Traders 20,000.00 4,200.00, INV-1004 and INV-1005 Fabrikam 3,000.00, 1,200.00 and 640.00

Save the report.

4. Change the question, not the report

INV-1002 is missing. It belongs to Northwind Traders, and it's overdue, which is money owed too. The report is right; the question was too narrow.

Open the query again and change the filter's Equals to Is one of, with Unpaid and Overdue:

The Filter: Status Is one of Unpaid, Overdue

Save it, go back to the report and preview it. We didn't open its datasets or touch its drawing:

The Money owed preview with four invoices: INV-1001 and INV-1002 for Northwind Traders, 4,200.00 and 1,850.50, then INV-1004 and INV-1005 for Fabrikam

Every report, chart and script that names this query now asks the same, wider question. That's the reason to keep the question in a saved query rather than in each thing that uses it (article 048).

5. In the app

We put Money owed on the rail of the Billing app from article 145. In the Shell, the report runs on the server with the reader's own permissions:

The Billing app in the Shell with Money owed open: the four invoices with their customers and credit limits, Page 1 of 1, and Print

The customer table is checked in its own right. Somebody who may read invoices but not customers doesn't see the customers' names through the join.

A total over a joined column

The list functions take a joined column by the same name, in quotes: sum(owed, 'customer.par_credit_limit') adds up the credit limits, and pluck(owed, 'customer.par_name') gives a chart its labels.

What we fixed

Building this turned up two problems, now fixed:

  • A joined column printed blank. The binding picker offered row.customer.par_name, but the report received the column as one flat name, customer.par_name, so the binding found nothing and the cell was empty. The preview and the Shell draw a report with the same engine, so every report over a query with a related table was affected. The report now reads a joined column the way a script does, and the list functions accept the dotted name.
  • A new query's table button had no words on it. Before a table was chosen, the button showed only an icon. It now says Choose a table….

Try it

Import the Invoices — Credit Check sample, and make a report over a query that joins the customer. Then change the query, and preview the report again.

Next: a report in Persian.