« Home | Delegators mount up! » | AMD Slashing Prices » | Weak Event Target References » | .NET Memory Leaks » | Shut the ding up » | Xwin32 MacroView Fonts » | ADSL2+ » | Task Bar Positioning » | Sysinternals to the rescue » | Cryptic IBM Filenames »

MVS Reports Script Tips

MacroView Studio is one of the software products developed and maintained by Torq Software. It includes the ability to edit MacroView graphic, metascript and report template files. This blog post relates to the reporting template functionality. The reporting functionality leverages the Active Reports developer product from Data Dynamics as its core reporting engine. As such this post also partially applies to other ActiveReports based applications in addition to MacroView Studio in particular. The reporting engine includes the ability to define a report class in script code. The report class methods will be called when particular report events occur and can be used to tailor reports in more ways than available using the standard GUI interface reporting engine functionality.

Here are the hints and tips:

  • MacroView Studio automatically adds all of the report sections and controls as fields to the report script class. This allows the script writer to easily get or set section and report control properties without a verbose syntax. The field name is take directly from the name given to the report section or control. The following report script sample illustrates the use of these automatically defined fields. Detail is a field that references the report Detail section whilst Rsh, Rsl, RshLabel, RslLabel, ScanFactor and ScanFactorLabel are all report controls whose property values and display state is modified by the script logic.

    public void Detail_BeforePrint()

    {

        string format = Format.Text;

        bool isImageFormat = false;

        bool needsRawScales = ( format != "INTEGER" && format != "FLOAT" );

     

        if ( format == "IMAGE" )

        {

            isImageFormat = true;

            Detail.BackColor = System.Drawing.Color.Bisque;

        }

        else if ( format == "INTEGER" )

            Detail.BackColor = System.Drawing.Color.SeaShell;

        else if ( format == "SCALE" )

            Detail.BackColor = System.Drawing.Color.LemonChiffon;

        else if ( format == "INTEGER" )

            Detail.BackColor = System.Drawing.Color.Honeydew;

        else if ( format == "DIGITAL" )

            Detail.BackColor = System.Drawing.Color.AliceBlue;

        else if ( format == "FLOAT" )

            Detail.BackColor = System.Drawing.Color.Khaki;

        else

            Detail.BackColor = System.Drawing.Color.White;

     

        Rsh.Visible = needsRawScales;

        Rsl.Visible = needsRawScales;

        RshLabel.Visible = needsRawScales;

        RslLabel.Visible = needsRawScales;

        ScanFactor.Visible = isImageFormat;

        ScanFactorLabel.Visible = isImageFormat;

    }       

  • There is currently no means of specifying a “using namespace;” statement within the report script. This is a limitation of the ActiveReports functionality. It means that arbitrary .NET class names or static members have to be referenced by their full name e.g. System.Drawing.Color.White.
  • MacroView Studio report script classes automatically have the Write and WriteLine methods defined. These take an object as an argument. The object is converted to a string via its ToString() method and the result is written to the report output log. The report output tab can be selected to view both server side metascript output and client side report script Write/WriteLine output. It provides a basic debug/tracing feature for MacroView reports.
  • The report field and control Value property provides access to the underlying value associated with the field or control. MacroView field values will be converted to string, decimal, DateTime or TimeSpan values in the reporting engine depending on the MacroView attribue value type. Decimal values can be cast to any of the numeric value types such as doubles for use in the report scripts.
  • The Format section event should be used to perform the majority of display format actions within a report section. The BeforePrint section event should only be used for control sizing actions as the section size has been fixed in the previous Format event processing. The AfterPrint section event is provided for ActiveReports backward compatibility and should not be used for MacroView reports.
  • Report scripts can easily get verbose and hence difficult to read and edit. Defining small report script functions to perform repetitive coding tasks can make your report script much more readable and maintainable. The following sample script functions provide examples of the types of repetitive tasks that can be done within a function rather than repetitively through your script code.

    // Gets a double precision numeric value for the specified field name.

    // Any data extraction exceptions are caught and a zero value returned.

    public double ToDouble( string fieldName )

    {

        try

        {

            Field field = rpt.Fields [fieldName];

            return (double) field.Value;

        }

        catch

        {

            return 0.0F;

        }

    }

     

    // Sets the value of the specified field.

    public void Set( string fieldName, object value )

    {

        Field field = rpt.Fields [fieldName];

        if ( field != null )

            field.Value = value;

        else

            WriteLine( "Failed to set field " + fieldName + " to " + value );

    }

     

    // Gets a double precision numeric value from the specified TextBox.

    private double ToDouble( TextBox textBox )

    {

        try

        {

            return (double) textBox.Value;

        }

        catch

        {

            return 0.0F;

        }

    }

  • It is often easiest to implement a report using calculated fields as a storage point for the results of script based calculations. To achieve this in the report script add the calculated fields within the DataInitialize event handler and  perform the calculations in the FetchData event handler.

    // Add any calculated fields not provided by the server query data in the DataInitialize

    // event handler function.

    public void ActiveReport_DataInitialize()

    {

        rpt.Fields.Add( "SourceType" );

    }

     

    // Perform the calculated field script logic in the FetchData event handler function.

    // Returning the eof parameter without modification at the end of this function

    // allows the server query result to be traversed as is whilst setting the

    // calculated field values.

    public bool ActiveReport_FetchData( bool eof )

    {

        string type = "PLC";

        if ( GetFieldString( "TYPE" ) == "IMAGE" )

            type = "IMAGE";

     

        SetFieldValue( "SourceType", type );

        return eof;

    }

     

    // Leverage small private functions to perform any repetive code actions and thus

    // keep the other code sections readable and maintainable.

    private string GetFieldString( string name )

    {

        Field field = rpt.Fields [name];

        if ( field != null )

            return field.Value.ToString();

        else

            return string.Empty;

    }

     

    private void SetFieldValue( string name, object value )

    {

        Field field = rpt.Fields [name];

        if ( field != null )

            field.Value = value;

        else

            WriteLine( "Field not defined: " + name );

    }

  • Field objects should only be referred to within the DataInitialize and FetchData event handlers to match the reporting model used by ActiveReports. Other event handlers can access the report control properties for use in script logic.
  • An alternative to using calculated fields on the client side is to create the calculated fields on the MacroView server side. Metascript table variables can be created in memory with the additional calculated fields which are then sent over to the client side for reporting. Scenario specific considerations affect whether a client side or server side approach should be taken e.g. metascript performance, report developers familiarity with C# and metascript, network throughput available between the server and client.

 

Links to this post

Create a Link