View RSS Feed

Development Team Blog

Visual Report Writer and The Web (IX)

Rate this Entry
In this ninth blog about Visual Report Writer and the Web I want to take you to the next report that can be found at the Live Demo website (European Server, USA server) named FileList (RDS). If this is the first blog you read I encourage you to read the eight other blogs (1: The Solution, 2: Invoices Report, 3: The Cleanup, 4: The CustomerList, 5: The Orderlist, 6: The Credit and Balances Overview), 7: Inventory Stock Levels) and 8: Sick Leave). Meanwhile we have been able to release the Alpha II version of Visual Report Writer 3.0 and the 2.1+ Library only setup. The latter one is needed to make the web reporting using the 17.1 DataFlex Web Framework easy and look like at the demo website.

The Report
Sometimes you as programmer think that there are better ways to collect the data than a report writer or an SQL engine can come up with. Or faster ways. This is not always true but there are certainly moments that it is. For example if you have an OR construction in the data selection it might very well impossible for the report engine to use the most optimal way to collect the data. For these situations Visual Report Writer offers you the use of RDS as data source. RDS as abbreviation stands for Runtime Data Source and the developer collects the data in an array and passes this memory data to the report engine to be used as if it was a database. Next to "smarter" data collection there is another reason for using RDS; you can make a report on data that isn't really a database or very hard to access as a database. The report used for this ninth example is based on such a data-source; the famous filelist in DataFlex.

A RDS report starts with the row layout description. You define the columns of each row; the names, length and data-type of each row. For the filelist report this is "simple", there are 4 values known; table-number, root-name, display-name and logical-name. From documentation we can discover that the root-name is 40 characters, the display-name is 32 and the logical-name (since v17.0) is 31 characters in size.

The filelist report used in this example contains one function named Hidden. The function returns true if the first character of the display-name column starts with an '@' sign. This is a legacy feature of DataFlex. If the first character is an '@' sign the entry should not be shown to the user in a tool named DFQUERY (and later FlexQL and dbExplorer). You can use this feature for alias tables to reduce the number of tables to pick from in a report of program. As said it is a legacy option and modern tools (like Visual Report Writer) do not 'honor' this special feature itself. The report however does; If the function returns true the font italics setting is set to true.

Keep in mind that RDS reports require a programmer if other or more data is needed for the report where the other data-sources make it possible to teach/instruct an end-user in how to make/extend their reports using a standard edition (or later this year the enterprise edition) version of Visual Report Writer.

RDS reports can only be used succesfully if integrated with an application as their data needs to be placed in an array and passed to the report. If you don't do this the engine can only print test-data, not very interesting.

RDS integration is quite simple; you need to create an array and fill this with data. The array however is a bit strange if you look at array definitions. It has to be a jagged array (the 2nd dimension specified in the array definition cannot be fixed) but the 2nd dimension does need to be fixed in values and it needs to match the row layout in the report. In the filelist report 4 columns are defined which means you need to setup an array with 4 values in the 2nd dimension. If you don't do that the data-row will be skipped and the report looks untrustfull. Luckily the last value is the logical-name which needs to be an unique value in the filelist and therefore will 'never' be empty.

Variant[][] vData
The array contents needs to be passed to the report by using the TableData method.
The '0' in above statement is the table number used in the report. This is very often just 0 as it is very common to have only one table in an RDS report. However it is allowed to have multiple RDS tables and therefor you can pass a table number.

Let's take a look at the user interface. The report view consists of a tool-bar with buttons to generate the report and show the documentation about this report and integration. Below that there is a drop-down (cWebCombo) that allows you to select the ordering of the data. You can choose between table-number, root-name, display-name and logical-name.
Object oSortByCombo is a cWebCombo
    Set psLabel to "Sort by:"
    Set peLabelAlign to alignRight
    Set piColumnSpan to 5

    Procedure OnFill
        Send AddComboItem 1 'Table Number'
        Send AddComboItem 2 'Root Name'
        Send AddComboItem 3 'Display Name'
        Send AddComboItem 4 'Logical Name'
Each of them can be ascending or descending and the checkbox (cWebCheckbox class) determines this.
Object oDescendingCheckbox is a cWebCheckbox
    Set piColumnIndex to 6
    Set piColumnSpan to 2
    Set psCaption to "Descending"
The last user choice is a checkbox labeled "include hidden (protected) tables". This applies to the '@' sign rule explained above. If the checkbox is not selected any filelist entry starting (logical-name attribute) with an '@' sign is skipped.
Object oShowHiddenCheckbox is a cWebCheckbox
    Set piColumnSpan to 4
    Set piColumnIndex to 1
    Set psCaption to "Include Hidden (protected) Tables"
Like the Sick Leave Report this report is generated as an HTML string and displayed in a special control made for Visual Report Writer. You need to use version 3.0 or higher to use this control and feature. The report viewer class is connected to the report object and sends the message GenerateReportHTML to get the array of pages. This is coded as:
Function GenerateReportHTML Returns String[]
    String sReportId
    String[] sData
    Integer iArgSize

    Get OpenReport to sReportId
    If (sReportId <> "") Begin
        Send LoadData
        Send SetSortOrder

        Get_Argument_Size to iArgSize
        Get ComReportHTMLPreview sReportId (iArgSize - 10) to sData
        Send CloseReport sReportId

    Function_Return sData
The filelist information is collected in the method LoadData. This is not a standard routine although the name is used too when generating the interface from the integration wizard. In the LoadData method code is written to get the next filelist entry until no more entries are available.
Procedure LoadData
    Variant[][] vData
    Handle hTable
    Integer iRow
    Boolean bShowHidden
    String sDisplayName

    Get GetChecked of oShowHiddenCheckbox to bShowHidden

    Get_Attribute DF_FILE_NEXT_USED of hTable to hTable
    While (hTable <> 0)
        Get_Attribute DF_FILE_DISPLAY_NAME of hTable to sDisplayName
        If ((bShowHidden) or ((Left (sDisplayName, 1) <> '@') and (not (bShowHidden)))) Begin
            Move hTable to vData[iRow][0]
            Get_Attribute DF_FILE_ROOT_NAME of hTable to vData[iRow][1]
            Move sDisplayName to vData[iRow][2]
            Get_Attribute DF_FILE_LOGICAL_NAME of hTable to vData[iRow][3]
            Increment iRow
        Get_Attribute DF_FILE_NEXT_USED of hTable to hTable

    Send TableData C_USEMAINVRWREPORTID 0 vData
Finally the user requested sorting is passed to the Visual Report Writer engine in the method SetSortOrder.
Procedure SetSortOrder
    Integer iSortOrder iSortDirection
    Boolean bDescending

    Send RemoveAllRecordSortFields C_USEMAINVRWREPORTID

    WebGet psValue of oSortByCombo to iSortOrder
    Get GetChecked of oDescendingCheckbox to bDescending
    If (bDescending) Begin
        Move C_VRWDescending to iSortDirection
    Else Begin
        Move C_VRWAscending to iSortDirection

    Case Begin
        Case (iSortOrder = 1)
            Send AddRecordSortField C_USEMAINVRWREPORTID '{FileList.Number}' iSortDirection
            Case Break
        Case (iSortOrder = 2)
            Send AddRecordSortField C_USEMAINVRWREPORTID '{FileList.Rootname}' iSortDirection
            Case Break
        Case (iSortOrder = 3)
            Send AddRecordSortField C_USEMAINVRWREPORTID '{FileList.DisplayName}' iSortDirection
            Case Break
        Case (iSortOrder = 4)
            Send AddRecordSortField C_USEMAINVRWREPORTID '{FileList.LogicalName}' iSortDirection
            Case Break
    Case End
First all existing sort fields are removed from the definition read from disk. Then the iSortDirection is set to the chosen value for ascending or descending. Based on the drop-down value the sorting is done on table-number, root-name, display-name or logical-name.

This concludes the ninth blog about Visual Report Writer and the Web using the 17.1 Web Framework by Data Access Worldwide. We hope this helps you in making the decision how to do reporting now and in the future.
Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	2013-06-02_082810.jpg 
Views:	988 
Size:	56.1 KB 
ID:	6502