Report Templates


What Is A Report?


In discussing queries we've discussed the input side of madsearch2. Queries are the tool with which we construct applications and manipulate the information stored with madsearch2 tables. Now we have to discuss the presentation of information.

By default, after executing a query, madsearch2 will display a table of results. This is allright as things go. The user will see answer results. However, the tabular form of data presentation doesn't fit in well with a well designed user interface. It also isn't always the most understandable format for users. In addition, we lose the ability to provide instructions, additional or supporting information, navigational features, as well as a look in keeping with surrounding site.

Report templates satisfy these needs. Reports allow you to present the data returned from a madsearch2 query as you would like it to be presented.

Reports are referred to a templates because within them we insert tags that will instruct madsearch2 to respond to various situations as well as insert our data. You can think of the template as being a structured presentation of your information -- a fill-in-the-blank sheet of sorts.


Report Structure: Sections


So what do reports look like? At heart, a report is simply a text file. It's internal supply the template for the query results output by madsearch2.

Reports files are divided into sections. Each section can be thought of as containing the contents of what would otherwise be an entire html document. Report sections represent decision points for madsearch2. Sections declare for madsearch2 what to output should a query return or not return answer records and to where.

What do we mean by where? Well, results can be output to the user's browser. This is pretty obvious and the expected behavior. However, results can additionally be output to a specified file. For example, this might be useful in the creation of log files for the acquisition of user data.

Let's now take a look at the four report sections that structure a madsearch2 report:


The Sections of A Report Template
ifRecords

The contents of an ifRecords section is output to the user's browser should there exist answer records for a query.

noRecords

The contents of a noRecords section is output to the user's browser should no answer records be returned for a query.

logIfRecords

The contents of a logIfRecords section is output to a specified file should there exist answer records for a query.

logNoRecords

The contents of a logNoRecords section is output to a specified file should no answer records be returned for a query.



Now that we know the names of the sections and when to use them, how do we specify them? Remember that we said report sections contain or encapsulate what would otherwise be considered a complete html document. Report section tags define a block within a report much as tags define a text area block within html.

Report sections are defined by an opening tag and an end tag. The opening tag is simply the name of the report section we wish to specify surrounded by curly brackets. The closing tag is simply the name of the report section preceeded by a forward slash character ("/") and surrounded by curly brackets. For example, say we wished to define an ifRecords section, we could simply place the following within our report template file:

{ ifRecords }

<html> <head> <title>sample report template</title> </head> <body> : : : </body> </html>
{ /ifRecords }

Note how the opening and closing section tags are encapsulating the contents of an html document in the above example. Ok, now for some nitty gritty detail: sections cannot be declared partially or entirely within another section. So, you cannot surround a noRecords section by and ifRecord section or something. When you stop and think about it, it wouldn't make much sense anyways.

Now we mentioned before, the the log related section tags output results or information to a specified file. How do we specify this file? Well between section declarations in our report template file we place a log file declaration. For example,

{ logFile | /wwws/data/myData/logfile }

would direct a logIfRecords or logNoRecords section to output its contents to the file "logfile" within the "/wwws/data/myData/" directory. Note that as we're dealing with the file system, the case of the directory path and filename are important.

What else can be inserted between section declarations? Comments. For example,

{ ifRecords }
:
:
{ /ifRecords }

this is a comment between two report sections
within a report template :)

{ noRecords }
:
:
{ /noRecords }

Any thing placed between section declarations aside from the logFile declaration is considered to be a comment. You may have guessed this, but comments are ignored by madsearch2.



It's all about the tags...


Ok, were getting to the data. Keep thy proverbial shirt on.

Now, we've mentioned that sections encapsulate what would otherwise be considered a complete html document. Now, interspersed within our html document, we're going to want madsearch2 to insert form input variables, answer record data, and other stuff. We're also going to want these formatted to our specifications. How do we do it?

MadSearch2 offers various tags that when placed within the html of a report section are interpreted as a command. Before we discuss how to insert answer records and fields from our answer records into report templates, let's get a feel for report tags by looking at the the msEnv, msVar, and msRead report tags.


msVar


Often times, we'd like to preserve state between madsearch2 transactions. For example, say someone supplied their name within a form on the input side of madsearch2. Perhaps we want to continue using their name in subsequent transactions. The msVar tag allows us carry over information from our input form to our report template. Thus, state is maintained.

How does it do this? The msVar tag allows us to specify the name of an input form variable. MadSearch2 then replaces the msVar tag with value of the form input variable provided.

We specify an msVar tag using the following syntax:

{ msVar | <form input variable name> }

msEnv


Whenever a query request is sent to madsearch2 to process, the web server software provides madsearch2 with information about the user making the request. On the web server side, this information is stored in what are known as enviornmental variables. You really don't need to know this, but for the fact the tag that accesses this information is named "msEnv" where the "env" stands for environment. Who knows? It might help you to remember them.

We specify an msEnv tag using the following syntax:

{ msEnv | <environmental variable name> | <formatting string> }

The formatting string may only be used with the date, time, and datetime environmental variables. But we get ahead of ourselves. What environmental variables are available to you? Funny you should ask. A table of them follows below:


Environmental Variables For Use With msEnv Tags
UserID
RemoteUser
Remote_User

displays the user id of the remote user if a user has been authenticated. otherwise, no insertion is made.

Date

displays the current date according to the format string of the msEnv tag. note that the format string is not optional.

Time

displays the current time according to the format string of the msEnv tag. note that the format string is not optional.

DateTime

displays the current date and time according to the format string of the msEnv tag. note that the format string is not optional.

RemoteHost
Remote_Host

displays the name of the remote host computer making the request to madsearch2. a blank is inserted if this information is unknown.

HTTP_Referer
HTTPReferer

displays url of form requesting a madsearch2 query

RemoteAddr
Remote_Addr

displays remote ip address of the remote host making the request to madsearch2. a blank is inserted if this information is unknown.

Now, oh pioneer, you may be asking what does a format string look like? Fear not, we will discuss date and time related formatting strings quite soon.


msRead

msRead tags are provided by MadSearch2 as a work around to the following problem: there's no such thing as a server side include when dealing with the output of a cgi-script (You do remember that MadSearch2 is a cgi-script. Don't you?).

Some of you are asking what a server side include would do for you. Actually they can do quite a few things. The one thing that we'll concentrate on is their ability to insert entire files within an html document. It's a handy feature to have when you have an element of a document that appears within every document or you need to repeat something multiple times within a document. Why type it in or cluter the structure of your document when you can simply say, "include this here file"?

But like we said, server side includes don't exist in cgi-output land. So let's take a look at the msRead tag. It will include the file for us! The syntax of an msRead tag is as follows:

{ msread | <fileName> | <fieldname> }

As you can see from above, the name of the file can be specified either through a hard-coded file name within the msRead tag or by specifying a field name from the fields within your answer table. Hmmm, that last one can be quite useful, no? Note that only one or the other option may be exercised.

Let's take a look at two examples of the msRead tag. In the first, we will see a filename specified. In the second, the file will be specified through a reference to a field within our answer table:

  • example one ::
    { msread | "/www/data/myMsReadFile" }
  • example two ::
    { msread | | myTableColumn }

Note in the second example, we must leave the second field empty between the two "|" characters.

Okay, so what are the issues in specifying filenames? There have to be issues. Right?

Indeed there are issues -- three of them. Firstly, the directory path and filename you specify are case sensitive. They must match precisely that which you would use to access the file on the underlying unix system. Secondly, the underlying file must be readable by group www or other and have a ".msread2" extension. msRead tags will not insert or work with files that do not have the ".msread2" extension. Thirdly, when you specify the filename, you are to omit this ".msread2" extension. MadSearch2 will automatically append this to the file you specify.

For the more technically prone: MadSearch2 attempts to cache the file so as to better performance by avoiding disk i/o in those cases where the contents of a file are to be inserted multiple times within a document. The caching of a file is dependent upon the size of the file and the availability of cache space.



As a final note to this discussion of the general purpose msEnv, msVar, and msRead tags, we should mention that these tags may be used anywhere within a declared section. (There is one exception: msRead tags which reference a field within the answer table may only be used within an msRecords section) We will next discuss the data related tags that we've all been waiting for...



It's About The Data
Or At Least, I Thought It Was...


So you say you want to display query results within your report? You've come to the right place. We can help you.

Remember how we defined report sections that encapsulated material? We're about to incorporate a similar concept. The first thing we have to do in order to display records is define a msRecords block.

A who? An msRecords block is defined by an opening tag ( {msRecords} ) and a closing tag ( {/msRecords} ) which surrounds an area that we wish to have repeatedly output for every answer record returned. For example, say our answer table contains 5 answer records. Let's define an msRecords block and place some content within it: (we'll pretend the block is within an ifRecords or logIfRecords section)


:
:

{ msRecords }
hello, answer record.
{ /msRecords }

:
:

This is quite a simple msRecords block. It's output would generate the following:


:
:

hello, answer record.
hello, answer record.
hello, answer record.
hello, answer record.
hello, answer record.

:
:

Why would it say the same thing five times? It's because we had five answer records. Remember?

Ok, that was cute, but not very helpful. What if we want to display the values of fields within our answer records? Simple. Within msRecords blocks, we can insert msData tags. msData tags not only specify the place of insertion for a field value from the current answer record, but sometimes also allow us to format the value inserted. The syntax of an msData tag is as follows:


{ msData | <field name> | <format string/options> }

The field name you specify must be one of those you "checked" within your query. Note that with queries of type insert, update, and delete all fields are returned for modified records within the answer table.

Okay. We're now ready to discuss format strings. Format strings can be specified for fields of type float, alphanumeric, date, time, and datetime. Each has different formatting descriptors or options. We discuss each in turn below. Note that format strings are only required for date, time, and datetime fields.

Float Fields

We often want to format floating point numbers to appear with a given precision. For example, when dealing with currency values $10.50 is probably more familiar to a user than $10.5000000. The formatting expression for a float field is simply this:

<minimum value width>.<number  of  digits  appearing after the decimal>

For example, to ensure that our $10.50 appears as such we might write our msData tag to look as follows:

{ msData | floatMoneyField | 10.2 }

Note that if our float field value has fewer characters than the field with specified, it will be padded with spaces on the left.


Date, Time, and DateTime Fields

The format strings for date, time, and datetime fields are made of formatting descriptors which specify which pieces of the field value are to be incorporated in the value presented. You can think of their format strings as a combination of surrounding text and descriptors where the surrounding text provides structure. You can also think of them as mini-templates.

Fields of type date and time do not share descriptors within one another. Therefore, we present them in separate tables. Fields to type datetime can mix and match the descriptors of both date and time fields within their format strings.

Date Field Format Descriptors

Field Descriptor Description
%a day of week, using abbreviated weekday names
%A day of week, using full weekday names
%b month, using abbreviated month names
%Bmonth, using full month names
%d day of month (1-31); single digits are preceeded by a blank
%Ddate as %m/%d/%y
%j day number of year (1-366)
%m month number (1-12)
%U week number of year (1-52); Sunday is the first day of the week
%w day of week; Sunday is day 0
%W week number of year (1-52); Monday is the first day of the week
%x date, using locale's date format
%y year within century (00-99)
%Y year, including century (for example, 1988)

Time Field Format Descriptors

Field Descriptor Description
%Hhour (00-23)
%Ihour (0-12)
%khour (0-23); single digits are preceeded by a blank
%lhour (1-12); single digits are preceeded by a blank
%Mminute (0-59)
%pAM/PM
%rtime as %I:%M:%S %p
%Rtime as %H:%M
%Sseconds (0-59)
%Ttime as %H:%M:%S
%Xtime, using locale's time format
%Ztime zone abbreviation

It is often times helpful to surround format strings in double quotes. MadSearch2 ignores quoted expressions. Let's take a look at an example. Say we have a datetime field named "lastUpdated" in which we store the date and time a record was last updated. Further suppose the value of this field for one of our records is 3/24/99 16:34:02, but we'd like to display this value to the user as "Wednesday, March 24, 1999 at 4:34pm". Our format string would look as follows:

{ msdata | lastUpdated | "%A, %B %d, %Y at %I:%M%p" }

AlphaNumeric Fields

We finally come to alphanumeric fields. The formatting options available for these fields are for the purpose of displaying alphanumeric data properly within the context of an html document. The table of format options below describes the currently available options:

Format Option Description
CRtoBR Converts carriage returns within the alphanumeric value to <br> html tags for the purpose of displaying text as originally entered. Html by default ignores carriage returns and white space within a document. This option is meant to deal with this behavior.
encodeQuotes

There are occasions in which we would like to insert a field value that contains quotes within an html tag. for example,

<input type="text" name="quotation" value="{msdata|quotation}">

In such a situation, should the quotation field contain a quotation mark, a user's browser will incorrectly (or correctly depending upon how you look at the matter) interpret the the field value's quotation mark to be the closing quotation mark of the value="" element of the input tag.

In order to avoid this, the encodeQuotes formatting option will substitute &quot; for every quotation mark that apears within the field value. This will allow the browser to correctly interpret the use of quotation marks.

multiSelect

When multiple options are selected within a Multiselect field within an html form, the value of the field is provided as a comma-delimitted list of values to MadSearch2. MadSearch2 stores this comma-delimitted list within an alphanumeric field.

This is all very well and good until we would like to repopulate a multiselect field with the previous selections made. The multiselect format option deals with this problem by parsing the comma-delimitted list and placing

<option value="something">something</option>
tags around the delimitted elements of the field value (the "something" in our example). You are responsible for the opening and closing tags which define the multiselect list. Really now, MadSearch2 can't do everything for you.

You should note that the multiselect option will only repopulate the list with those elements that were selected and stored within the MadSearch2 table queries. You are additionally responsible for ensuring that the list is populated with all other elements if this is desired.


Where Am I?

Sometimes it's nice to know where you are amongst the answer records? Are you looking at record 5 of 12 or 4 of 13?

To assist in this MadSearch2 offers three special identifiers that may be used within the msData tag in place of a field name. A table describing them follows:

Identifier Description
PreviousRecord Reports the previous record number. If the current record is 1 (the beginning record, nothing is printed.
CurrentRecord Reports the current record number. If there are no further records, nothing is printed. (We will see how this can occur later in discussing the use of the msNextRecord tag.)
NextRecord Reports the next record number. If there exists no next record, nothing is printed.

It should be noted that as with other msData tags, these special cases may only be used within the context of a msRecords block.


Conditional Tags

MadSearch2 provides to conreport tags are msDelEmpty and msDelExist which provide the ability to conditionally delete information contained within a block defined by an opening { msDelXXX } tag and closing { /msDel } tag. The msDelEmpty tag removes whatever is defined within the deletion block if the field it references is blank. The msDelExist tag removes whatever is defined with the deletion block if the field it references in not blank. Their syntax and usage is as follows:

{ msDelExist | <field name> } .... blah, blah .... { /msDel }
{ msDelEmpty | <field name> } .... blah, blah .... { /msDel }

Note that the closing tag for both the msDelExist and msDelEmpty deletion blocks is the { /msDel } tag. msDelXXXX tags may be nested within one another. It is important to ensure that for every { msDelXXXX } opening tag that there exists an { /msDel } closing tag.

If the condition of the msDelXXXX tag holds true, the entire contents of the particular msDelXXXX's deletion block are removed. Output resumes after the { /msDel } closing tag to which the msDelXXXX belongs. In the following example, if the address is not specified, the city, state, and zip are also not output. However, if the address is specified, but the city is not, all information but for the city is output:

{ msDelEmpty | address }

<td> <b> Address </td> <td> { msdata | address } <br>

{ msDelEmpty | city } { msdata | city }, { /msDel } { msdata | state } { msdata | zip }

</td>

{ /msDel }

It is important to choose the placement of msDelExist and msDelEmpty tags carefully. A misplaced msDelXXXX deltion block can cause unexpected results if not used properly. For example, if you are formatting your report through use of a table and the msDelExist tag removes a </table> closing tag, the table will not appear.


What's Next

Funny you should ask. Some of you may have guessed from the above scheme that the { msRecords } ... { /msRecords } repeat block and the formatting done within its contents, limits one to a vertical design.

Sometimes, one may wish to display multiple records horizontally as well as vertically. Or perhaps, someone's come up with another design that requires obtaining the next records prior to the end of the msRecords block. After all, the msRecord block will get the next record, but only allow for the repetition of the very same design.

Regardless, MadSearch2 provides the msNextRecord tag. Its syntax is as follows:

{ msNextRecord }

Now that was a waste of space. When MadSearch2 comes upon this tag within an msRecords block, it advances to the next record within the answer table. What happens if there is no next record? MadSearch2 will output all that is specifie by your template. However, in place of field values for msData tags, it will print a blank. The reason for this behavior is simple to understand. MadSearch2 doesn't know anything about how you've formatted your msRecords area. For it not to output anything at all at this point might be to destroy the formatting of your report.

Is there a way to avoid this? Yes. By using the msDelEmpty tag and referencing a field value, you can conditionally delete whatever you wish. When there are no further records to work with, MadSearch2 thinks all field values as being blank.

Note that msNextRecord tags may only be used within an msRecords block.


And Finally...

We haven't yet told you the one element of the puzzle that causes a report to be generated. In order for a report template to be used by MadSearch2, you must specify it using a form variable called "Report". For example, the following line within a form would declare a "report" or "reportName" variable and set it's value to refer to a report named "addressBook" within the "/www/data/cu/myReports/" directory.

<input type="hidden" name="report" value="/www/data/cu/myReports/address">

or 

<input type="hidden" name="reportName" value="/www/data/cu/myReports/address">

Easy, no? Now for the fine print:

  • The directory path and filename you specify are case sensitive. They must match precisely that which you would use to access the file on the underlying unix system.

  • The proper permissions must be set for MadSearch2 to be able to access the report. The underlying file must be readable by group www or other.

  • Report template files must have a ".msrpt2" extension. MadSearch2 will not work with any report template files that do not have the ".msrpt2" extension.

  • When you specify the filename within the report variable, you are to omit this ".msrpt2" extension. MadSearch2 will automatically append this to the file you specify. If you take a look at the example above, the report template's actual filename would be "address.msrpt2".