Green-screen Chart/Graph

From MidrangeWiki
Jump to: navigation, search

Green-screen Chart/Graph

Background

It is sometimes useful to display a graph of values on the AS400 green-screen. Although there are commercial products available for the AS400, these are often difficult to use and not available everywhere. This product was designed to allow for a simple text-based line-graph to be displayed on the screen. It will take a data-structure from another program, and build up the screen accordingly.

The program has been written to work correctly on either a wide screen (27x132) or a normal screen(24x80).

Screen Layout

GenChart - Overview.png

a. This is the header as passed to the program
b. This is the Y-label, as passed to the program
c. The Y-axis values will be build based on the chart type or the chart calc function
d. If the number of data points exceed the screen width, the program will create additional pages. Page Up/Down will show the rest of the entries. If you want to jump to the 1st page, press F17, or last page press F18.
e. If you position your cursor on any data item/column, and press F1, the program will display information about the data point

GenChart - Item Information.png

Objects

The following objects will be used by the program:

a. GENCHART#D - Display File
b. GENCHART#R – RPG Program


GenChart Program Parameters

The GENCHART#R program requires the following parameters:

a. Data structure (see point 4):
- The data structure will be passed from your program, to the GENCHART#R program, by using pointers. When you call the program, the variable has to use %ADDR(DSNAME).
b. Heading:
- Char (100).
- The heading you need for your chart
c. Y-Axis Label:
- Char(30)
- Here you can specify a label for the Y-Axis.
- Label will be affected by the Chart Type variable
d. Total Items:
- Int(10)
- Specify the number of values to be passed via the DataStructure
e. Max Value:
- Packed(31:2)
- Specify the Maximum value. This is needed to determine the sizing of the bars
f. Chart Type
- Char(10)
- Allows for two types of charts. Can be either
  • *PCT: Determine %, betwee max value and actual value
  • *NORMAL: Display the values on the screen as they are
g. Chart Calc:
- Char(10)
- If the values are too big, the program can scale them. Allowed values are:
  • *NONE – Keep the values as is
  • *TB – Scale the values in Terrabytes
  • *GB – Scale the values in Gigabytes
  • *KB – Scale the values in Megabytes
  • *KB – Scale the values in Kilobytes

RPG Program Usage

In order to use the GENCHART functionality inside your RPG program, the following is needed:

a. Data structure: A datastructure has to be passed onto the calling program. This data structure HAS to use the following definitions:
- The DataStructure must be limited to 9999 entries.
- Field 1 is a description field, 30 chars long. It will be used for the X-Axis
- Field 2 is a numeric field, packed 31:2.
    *====================================================================*    
      dcl-ds TestDS                       qualified dim(9999);                
          wDescription                    char(30);                           
          wDataItem                       packed(31:2);                       
      end-ds;                                                                 
    *====================================================================*    
b. GenChart Prototype: Add the prototype for the external program:


    *====================================================================*    
      dcl-pr GenChart                     extpgm('GENCHART#R');               
          p_InputDS                       pointer const;                      
          p_Heading                       char(100) const;                    
          p_Ylabel                        char(30) const;                     
          p_TotalItems                    like(TInt) const;                   
          p_MaxValue                      packed(31:2) const;                 
          p_ChartType                     char(10) const;                     
          p_YCalc                         char(10) const;                     
      End-pr;                                                                 
    *====================================================================*
c. Clear the data structure: You have to clear the data structure before you use it, to ensure it does not contain null values.
    *====================================================================*
      clear TestDS;
    *====================================================================*
d. Build up your SQL String:
- Limit your data to 9999 entries, either in the SQL String or in the fetch statement
- Use casting in SQL to ensure the data match the data structure
    *====================================================================*
      SQLString =                                                             
          'SELECT cast( ADATE as char(30)) as "WorkDate", cast(aspsizusd as '+
          'decimal(31,2)) as "Value" FROM aspinf#p order by aDate';           
    *====================================================================*
                                                                               
e. Prepare the SQL cursor now:
- Use SQL diagnostics to determine the number of records returned
    *====================================================================*
        exec sql Prepare SQLGET1 from :SqlString;                           
        exec sql declare IntCursor1 insensitive cursor for SQLGet1;         
        exec sql Open IntCursor1;                                           
        exec sql get diagnostics :wRecCount = DB2_NUMBER_ROWS;              
    *====================================================================*
f. Fetch the data:
    *====================================================================*
           exec sql fetch IntCursor1  for 9999 rows into :TestDs;              
           // Cose the Cursor                        
           exec sql close Intcursor1;                                          
    *====================================================================*
g. Determine the maximum size for the range:
    *====================================================================*
           exec sql select max(aspsiztot) into :wMaxValue from ASPINF#P;       
    *====================================================================*
h. Generate the chart now:
    *====================================================================*
           GenChart(%addr(TestDs):'ASP Information - % Usage':'% Storage':     
               wRecCount:wMaxValue:'*PCT':'*NONE');                            
           GenChart(%addr(TestDs):'ASP Information':'Size in GB':wRecCount:    
              wMaxValue:'*NORMAL':'*NONE');

Example program

THIS SOURCE CODE IS PROVIDED AS IS, USE IT AT YOUR OWN RISK!'

        CTL-OPT COPYRIGHT('Pieter Henrico')                           
                DATFMT(*ISO) TIMFMT(*HMS:)                            
                DFTACTGRP(*NO)                                        
                OPTIMIZE(*NONE)                                       
                OPTION(*NODEBUGIO)                                    
                USRPRF(*USER)                                         
                TEXT(*SRCMBRTXT)                                      
                CopyNest(128)                                         
                BndDir('QC2LE')                                       
                Thread(*Serialize);                                   
                                                                      
     *================================================================
     *    Declare files here                                          
     *================================================================
     // File Description here                                         0
     *================================================================
     *    Copy Programs                                               
     *================================================================
    *    Setup *Entry Parameters                                              
    *================================================================         
       dcl-pr TESTCHART#               extpgm('TESTCHART# ');                 
       end-pr;                                                                
       dcl-pi TESTCHART# ;                                                    
       end-pi;                                                                
    * ------------------------------------------------------------------------
      dcl-s wRecCount                     int(10) inz(0);                  
      dcl-s SqlString                     char(5000);                         
      dcl-s wCur                          int(10) inz(1);                  
      dcl-s wMaxValue                     packed(31:2) inz(0);                
    *====================================================================*    
      dcl-ds TestDS                       qualified dim(9999);                
          wDescription                    char(30);                           
          wDataItem                       packed(31:2);                       
      end-ds;                                                                 
    *====================================================================*    
      dcl-pr GenChart                     extpgm('GENCHART#R');               
          p_InputDS                       pointer const;                      
          p_Heading                       char(100) const;                    
          p_Ylabel                        char(30) const;                     
          p_TotalItems                    int(10) const;                   
          p_MaxValue                      packed(31:2) const;                 
          p_ChartType                     char(10) const;                     
          p_YCalc                         char(10) const;                     
      End-pr;                                                                 
                                                                              
    *====================================================================*    
    *  Mainline                                                          *    
    *====================================================================*    
    *================================================================         
    * Check if the data files are available                                   
    *================================================================         
                                                                              
      Clear TestDS;                                                           
     //  Build up the SQL String                                              
      Exec SQL Set Option DatFmt = *ISO;                                      
      SQLString =                                                             
          'SELECT cast( ADATE as char(30)) as "WorkDate", cast(aspsizusd as '+
          'decimal(31,2)) as "Value" FROM aspinf#p order by aDate';           
                                                                               
      // ================================================================      
      //  Prepare the SQL here                                                 
      // ================================================================      
           exec sql Prepare SQLGET1 from :SqlString;                           
           exec sql declare IntCursor1 insensitive cursor for SQLGet1;         
           exec sql Open IntCursor1;                                           
           exec sql get diagnostics :wRecCount = DB2_NUMBER_ROWS;              
                                                                               
      // ================================================================      
      //  Fill the datastructure                                               
      // ================================================================      
           exec sql fetch IntCursor1  for 9999 rows into :TestDs;              
           // Cose the Cursor, as it will be recreated                         
           exec sql close Intcursor1;                                          
           exec sql select max(aspsiztot) into :wMaxValue from ASPINF#P;       
           SndstsMsg('Loading Chart 1...');                                    
           GenChart(%addr(TestDs):'ASP Information - % Usage':'% Storage':     
               wRecCount:wMaxValue:'*PCT':'*NONE');                            
           GenChart(%addr(TestDs):'ASP Information':'Size in GB':wRecCount:    
              wMaxValue:'*NORMAL':'*NONE');                                   
                                                                              
                                                                              
     // ================================================================      
     //  Program ends here                                                    
     // ================================================================      
                                                                              
                                                                              
       *InLR = *On;                                                           
       return;                                                                
                                                                              


GENCHART#D - Source code

THIS SOURCE CODE IS PROVIDED AS IS, USE IT AT YOUR OWN RISK!

    A*%%TS  SD  20210608  135832  REKA        REL-V7R3M0  5770-WDS
    A*%%EC
    A                                      DSPSIZ(27 132 *DS4                 -
    A                                             24 80 *DS3)
    A                                      INDARA
    A          R MAIN
    A*%%TS  SD  20210607  181701  REKA        REL-V7R3M0  5770-WDS
    A                                      CF03(03 'Exit')
    A                                      PAGEDOWN(40 'PageDown')
    A                                      PAGEUP(41 'PageUP')
    A                                      CF01(01 'Info')
    A                                      CF18(18 'Last Page')
    A                                      CF17(17 'First Page')
    A                                      RTNCSRLOC(*RECNAME &CSRREC &CSRFLD)
    A                                      RTNCSRLOC(*MOUSE &CSRROW &CSRCOL)
    A                                      CSRLOC(ROWPOS     COLPOS)
    A                                      OVERLAY
    A                                      PRINT
    A            CSRFLD        10A  H
    A            CSRREC        10A  H
    A            COLPOS         3S 0H
    A            ROWPOS         3S 0H
    A            CSRROW         3S 0H
    A            CSRCOL         3S 0H
    A            HLINE        120   O  1  7DSPATR(HI)
    A            DLINE01      131A  O  3  1
    A            DLINE02      131A  O  4  1
    A            DLINE03      131A  O  5  1
    A            DLINE04      131A  O  6  1
    A            DLINE05      131A  O  7  1
    A            DLINE06      131A  O  8  1
    A            DLINE07      131A  O  9  1
    A            DLINE08      131A  O 10  1
    A            DLINE09      131A  O 11  1
    A            DLINE10      131A  O 12  1
    A            DLINE11      131A  O 13  1
    A            DLINE12      131A  O 14  1
    A            DLINE13      131A  O 15  1
    A            DLINE14      131A  O 16  1
    A            DLINE15      131A  O 17  1
    A            DLINE16      131A  O 18  1
    A            DLINE17      131A  O 19  1
    A            DLINE18      131A  O 20  1
    A            DLINE19      131A  O 21  1
    A            DLINE20      131A  O 22  1
    A            DLINE21      131A  O 23  1
    A            DLINE22      131A  O 24  1
    A            DLINE23      131A  O 25  1
    A            DLINE24      131A  O 26  1
    A            YDESC         40   O  2  1COLOR(BLU)
    A            FLINE1        50A  O 27 82DSPATR(HI)
    A                                 27  1'F1=Item Info'
    A                                      COLOR(BLU)
    A                                 27 16'F3=Exit'
    A                                      COLOR(BLU)
    A                                 27 26'F17=First Page'
    A                                      COLOR(BLU)
    A                                 27 43'F18=Last Page'
    A                                      COLOR(BLU)
    A          R INFO
    A*%%TS  SD  20210608  134900  REKA        REL-V7R3M0  5770-WDS
    A                                      CF03(03 'Exit')
    A  *DS4                                WINDOW(7 34 11 60 *NOMSGLIN)
    A  *DS3                                WINDOW(7 10 11 60 *NOMSGLIN)
    A                                  1 23'Item Information'
    A                                      DSPATR(HI)
    A                                  3  3'Page..............:'
    A                                  4  3'Values............:'
    A                                  5  5'-'
    A            WSDETAIL1     52A  O  5  7DSPATR(HI)
    A                                  6  5'-'
    A            WSDETAIL2     52A  O  6  7DSPATR(HI)
    A                                  7  5'-'
    A            WSDETAIL3     52A  O  7  7DSPATR(HI)
    A                                  8  5'-'
    A            WSDETAIL4     52A  O  8  7DSPATR(HI)
    A*                                 9  5'-'
    A*           WSDETAIL5     52A  O  9  7DSPATR(HI)
    A            WSPAGE        35A  O  3 24DSPATR(HI)
    A                                  9  5'-'
    A            WSDETAIL5     52A  O  9  7DSPATR(HI)
    A                                 11  4'F3=Exit'
    A                                      COLOR(BLU)
    A          R MAIN2
    A*%%TS  SD  20210608  093006  REKA        REL-V7R3M0  5770-WDS
    A                                      CF03(03 'Exit')
    A                                      PAGEDOWN(40 'PageDown')
    A                                      PAGEUP(41 'PageUP')
    A                                      CF01(01 'Info')
    A                                      CF18(18 'Last Page')
    A                                      CF17(17 'First Page')
    A                                      RTNCSRLOC(*RECNAME &CSRREC &CSRFLD)
    A                                      RTNCSRLOC(*MOUSE &CSRROW &CSRCOL)
    A                                      DSPMOD(*DS3)
    A                                      CSRLOC(ROWPOS     COLPOS)
    A                                      OVERLAY
    A                                      PRINT
    A            CSRFLD        10A  H
    A            CSRREC        10A  H
    A            COLPOS         3S 0H
    A            ROWPOS         3S 0H
    A            CSRROW         3S 0H
    A            CSRCOL         3S 0H
    A            H2LINE        70A  O  1  7DSPATR(HI)
    A            D2LINE01      78A  O  3  1
    A            D2LINE02      78A  O  4  1
    A            D2LINE03      78A  O  5  1
    A            D2LINE04      78A  O  6  1
    A            D2LINE05      78A  O  7  1
    A            D2LINE06      78A  O  8  1
    A            D2LINE07      78A  O  9  1
    A            D2LINE08      78A  O 10  1
    A            D2LINE09      78A  O 11  1
    A            D2LINE10      78A  O 12  1
    A            D2LINE11      78A  O 13  1
    A            D2LINE12      78A  O 14  1
    A            D2LINE13      78A  O 15  1
    A            D2LINE14      78A  O 16  1
    A            D2LINE15      78A  O 17  1
    A            D2LINE16      78A  O 18  1
    A            D2LINE17      78A  O 19  1
    A            D2LINE18      78A  O 20  1
    A            D2LINE19      78A  O 21  1
    A            D2LINE20      78A  O 22  1
    A            D2LINE21      78A  O 23  1
    A            Y2DESC        40A  O  2  1COLOR(BLU)
    A            F2LINE1       27A  O 24 52DSPATR(HI)
    A                                 24  1'F1=Item Info'
    A                                      COLOR(BLU)
    A                                 24 15'F3=Exit'
    A                                      COLOR(BLU)
    A                                 24 24'F17=1st Page'
    A                                      COLOR(BLU)
    A                                 24 38'F18=Last Page'
    A                                      COLOR(BLU)
    A          R ERRSCREEN
    A*%%TS  SD  20210608  135832  REKA        REL-V7R3M0  5770-WDS
    A                                      CF03(03 'Exit')
    A  *DS4                                WINDOW(10 46 4 40 *NOMSGLIN)
    A  *DS3                                WINDOW(10 20 5 40 *NOMSGLIN *NORSTC-
    A                                      SR)
    A                                  1 15'  ERROR!  '
    A                                      COLOR(RED)
    A                                      DSPATR(RI)
    A                                  3  4'  There is no data to display!  '
    A                                      DSPATR(HI)
    A                                      DSPATR(RI)

GENCHART#R - Source Code

     *================================================================
     *šProgram Name:‚GENCHART#R
     *šAuthor      :‚REKA       - Pieter Henrico
     *šDate        :‚2021-06-02
     *================================================================
     *šPurpose of program:‚
     *
     *  
     *
     * Before compile:
     *
     *THIS SOURCE CODE IS PROVIDED AS IS, USE IT AT YOUR OWN RISK!
     *
     *================================================================
     //==  A M E N D M E N T S                                              ==
     //=======================================================================
     //== DD.MM.YYYY   Name             Description
     //==
     //==
     //==
     //==
     *================================================================
        CTL-OPT COPYRIGHT('Pieter Henrico')
                DATFMT(*ISO) TIMFMT(*HMS:)
                DFTACTGRP(*NO)
                OPTIMIZE(*NONE)
                OPTION(*NODEBUGIO)
                USRPRF(*USER)
                TEXT(*SRCMBRTXT)
                ALWNULL(*USRCTL)
                CopyNest(128)
                Thread(*Serialize);
     *================================================================
     *š   Declare files here
     *================================================================
     // File Description here
      dcl-f  GENCHART#D      workstn indds(Indicators1);
     *================================================================
     *š   Copy Programs
     *================================================================
     *======================== *ENTRY ================================
     *š   Setup *Entry Parameters
     *================================================================
        dcl-pr GENCHART#R               extpgm('GENCHART#R ');
           p_InputDS                       pointer;
           p_Heading                       char(100);
           p_YLabel                        char(30);
           p_TotalItems                    int(10);
           p_MaxVal                        packed(31:2);
           p_ChartType                     char(10);
           p_YCalc                         char(10);
        end-pr;
        dcl-pi GENCHART#R ;
           p_InputDS                       pointer;
           p_Heading                       char(100);
           p_YLabel                        char(30);
           p_TotalItems                    int(10);
           p_MaxVal                        packed(31:2);
           p_ChartType                     char(10);
           p_YCalc                         char(10);
        end-pi;
     *================================================================
     *š   Declare data structures and variables here
     *================================================================
     * ------------------------------------------------------------------------
       /if not defined(#INDICATORS)
       /define #INDICATORS
       dcl-ds Indicators1;
           InfoRequest         ind pos(1) ;
           ExitPgm             ind pos(3) ;
           FirstPage           ind pos(17);
           LastPage            ind pos(18);
           PageDown            ind  pos(40) ;
           PageUp              ind  pos(41) ;
       end-ds ;
     /Endif
       dcl-s wDetailLine                   char(130) dim(24);
       dcl-s wLine                         int(10);
       dcl-s wTempLine                     char(130);
       dcl-s wColumn                       int(10);
       dcl-s wPage                         int(10);
       dcl-s wDetailX                      char(30) dim(140);
       dcl-s wDetailValue                  packed(15:2) dim(140);
       dcl-ds dsData    qualified based(wPointer) dim(9999);
           wXData                          char(30);
           wDataItem                       packed(31:2);
       end-ds;
       dcl-s wPointer                      pointer;
       dcl-s wMax                          packed(31:2);
       dcl-s wCount                        int(10) inz(0);
       dcl-s wStrCol                       int(10) inz(0);
       dcl-s wDeterminePages               ind inz('0');
       dcl-s wTotalPages                   int(10) inz(0);
       dcl-ds dsPage                       qualified dim(200);
           Start                           int(10);
           End                             int(10);
           Entries                         int(10);
       End-Ds;
       dcl-s wLineStr                      int(10) inz(0);
       dcl-s wLastCol                      int(10) inz(0);
       dcl-s wScreenLarge                  ind inz('0');
       dcl-c wCol_White                    const(X'22');
       //==============================================================
       Dcl-PR QsnQryModSup                 Int(10:0) extProc('QsnQryModSup');
          mode                             Char(1) const;
          modeAllowed                      Char(1) options(*OMIT);
          llhandle                         Int(10:0) const options(*OMIT);
          error                            Char(16) options(*varsize:*OMIT);
       End-PR;
       Dcl-C DS4_MODE                      '4';
       Dcl-C MODE_ALLOWED                  1;
     *====================================================================*
     *  Mainline                                                          *
     *====================================================================*
       wPointer = p_InputDS;
       wPage = 1;
       wMax = p_MaxVal;
       ROWPOS = 0;
       COLPOS = 0;
       wScreenLarge = ScreenSizeIs132();
       DoU ExitPgm = *On;
           Reset wDetailLine;
           Reset wDetailValue;
           Reset wDetailX;
           BuildScreen(wPage:wMax:p_TotalItems:p_YLabel:p_ChartType:p_YCalc);
           If wScreenLarge = *On;
               hLine = CenterText(%trim(p_Heading):%len(hLine));
               If p_TotalItems > 0;
                   exfmt main;
               Else;
                   write main;
                   exfmt ErrScreen;
                   ExitPgm = *On;
               EndIf;
           Else;
               h2Line = CenterText(%trim(p_Heading):%len(h2Line));
               If p_TotalItems > 0;
                   exfmt main2;
               Else;
                   write main2;
                   exfmt ErrScreen;
                   ExitPgm = *On;
               EndIf;
           EndIf;
           If ExitPgm = *Off;
               If wScreenLarge = *On;
                   wLastCol = wPage*(130-wLineStr);
               Else;
                   wLastCol = wPage*(78-wLineStr);
               EndIf;
               select;
               when PageUp = *On and wPage > 1;
                   wPage = wPage - 1;
               When PageDown = *On and wPage < wTotalPages;
                   wPage = wPage + 1;
               When FirstPage = *On;
                   wPage = 1;
                   FirstPage = *Off;
               When LastPage = *On;
                   wPage = wTotalPages;
                   LastPage = *Off;
               When InfoRequest = *On and CSRCOL >= wLineStr+1 and
                   CSRCol - wLineStr <= dsPage(wPage).Entries;
                   InfoRequest = *Off;
                   If wScreenLarge = *On;
                       wsPage = %trim(FLine1);
                   Else;
                       wsPage = %trim(F2Line1);
                   EndIf;
                   wsDetail1 = 'Heading:       ' + %trim(p_Heading);
                   wsDetail2 = 'X-Axis Label:  ' + %trim(wDetailX(csrcol):'1');
                   wsDetail3 = 'X-Value:       ' +
                       %trim(%editc(wDetailValue(csrcol)  :'1'));
                   wsDetail4 = 'Max Value:     ' +
                       %trim(%editc(wMax:'1'));
                   If wPage > 1;
                       wsDetail5 = 'Data point:    ' +
                           %trim(%editc(dsPage(wPage-1).End+
                           csrcol-wLineStr:'1'));
                   Else;
                       wsDetail5 = 'Data point:    ' +
                           %trim(%editc(csrcol-wLineStr:'1'));
                   EndIf;
                   exfmt info;
                   ROWPOS = CSRROW;
                   COLPOS = CSRCOL;
                   ExitPgm = *Off;
               EndSl;
           EndIf;
       EndDo;
      // ================================================================
      //  Program ends here
      // ================================================================
        *InLR = *On;
        return;
      // ================================================================
       dcl-proc BuildColumn;
       dcl-pi BuildColumn;
           pColumn                         int(10) value;
           pMaxValue                       int(20) value;
           pValue                          int(20) value;
           pXValue                         char(30) value;
       end-pi;
       dcl-s wLoopCount                    int(10) inz(0);
       dcl-s wChartValue                   int(10) inz(0);
       dcl-s wMaxRows                      int(10) inz(0);
       //
       If wScreenLarge = *On;
           wMaxRows = 23;
       Else;
           wMaxRows = 20;
       EndIf;
       wChartValue = %int((pValue/pMaxValue)*wMaxRows);
       wDetailValue(pColumn) = %dec(pValue:31:2);
       wDetailX(pColumn) = pXValue;
       If wChartValue > 0;
           For wLoopCount = wMaxRows downto (wMaxRows - wChartValue);
               If wLoopCount > 0;
                  %subst(wDetailLine(wLoopCount):pColumn:1) = '|';
               EndIf;
           EndFor;
           If wChartValue < wMaxRows;
              %Subst(wDetailLine(wMaxRows-wChartValue):pColumn:1) = '_';
           Else;
              %Subst(wDetailLine(1):pColumn:1) = '_';
           EndIf;
       EndIf;
       End-proc;
      // ================================================================
       dcl-proc BuildYLines;
       dcl-pi BuildYLines                  int(10);
           pMaxValue                       int(20) value;
           pYType                          char(10) value;
           pYLabel                         char(30) value;
           pYCalc                          char(10) value;
       end-pi;
       dcl-s wLoopCount                    int(10) inz(0);
       dcl-s wDivisor                      int(10) inz(0);
       dcl-s wTempValue                    packed(15:2) inz(0);
       dcl-s wUnderLine                    char(130) inz(*all'-');
       dcl-s wUnderLine2                   char(130) inz(*all'_');
       dcl-s wUnderLine3                   char(130) inz(*all'=');
       dcl-s wLength                       int(10) inz(0);
       dcl-s wEndOfDesc                    int(10) inz(0);
       //
       yDesc = pYLabel;
       y2Desc = pYLabel;
       Select;
       When pYType = '*PCT' and wScreenLarge = *On;  // Y-bar will be percentage
           wDetailLine(1)  = '100%  :' + wCol_White + %trim(wUnderLine);
           wDetailLine(6)  = ' 75%  :' + wCol_White + %trim(wUnderLine);
           wDetailLine(12) = ' 50%  :' + wCol_White + %trim(wUnderLine);
           wDetailLine(17) = ' 25%  :' + wCol_White + %trim(wUnderLine);
           wDetailLine(23) = '  0%  :' + wCol_White + %trim(wUnderLine2);
           wDetailLine(24) = '        ' +
               %trim(wUnderLine3);
           For wLine = 1 to 23;
               %subst(wDetailLine(wLine):7:2) = ':' + wCol_White;
           Endfor;
           wEndOfDesc = 8;
       When pYType = '*NORMAL' and wScreenLarge = *On;  // Determine Min/Max/25%/50%/75%
           select;         //1234567890123
           when pMaxValue >= 1000000000000 and pYCalc = '*TB';
               wDivisor = 1024*1024*1024*1024;
               yDesc = 'Size in TB';
           when pMaxValue >= 1000000000 and pYCalc = '*GB';
               wDivisor = 1024*1024*1024;
               yDesc = 'Size in GB';
           when pMaxValue >= 1000000 and pYCalc = '*MB';
               yDesc = 'Size in MB';
               wDivisor = 1024*1024;
           when pMaxValue >= 1000 and pYCalc = '*KB';
               yDesc = 'Size in KB';
               wDivisor = 1024;
           Other;
               wDivisor = 1;
           EndSl;
           wLength = %len(%trim(FormatNumber(%dec(pMaxValue/wDivisor:31:2))));
           wEndOfDesc = wLength + 4;
           wDetailLine(1) =
               %trim(FormatNumber(%dec(pMaxValue/wDivisor:31:2)));
           %subst(wDetailLine(1):wEndOfDesc+1:131-wEndOfDesc-1) =
               %trim(wUnderLine);
           wDetailLine(6) =
               %trim(FormatNumber(%dec(pMaxValue/wDivisor*0.75:31:2)));
           %subst(wDetailLine(6):wEndOfDesc+1:131-wEndOfDesc-1) =
               %trim(wUnderLine);
           wDetailLine(12) =
               %trim(FormatNumber(%dec(pMaxValue/wDivisor*0.50:31:2)));
           %subst(wDetailLine(12):wEndOfDesc+1:131-wEndOfDesc-1) =
               %trim(wUnderLine);
           wDetailLine(17) =
               %trim(FormatNumber(%dec(pMaxValue/wDivisor*0.25:31:2)));
           %subst(wDetailLine(17):wEndOfDesc+1:131-wEndOfDesc-1) =
               %trim(wUnderLine);
           wDetailLine(23) = '0';
           %subst(wDetailLine(23):wEndOfDesc+1:131-wEndOfDesc-1) =
               %trim(wUnderLine2);
           %Subst(wDetailLine(24):wEndOfDesc+1:131-wEndOfDesc-1)=
               %trim(wUnderLine3);
           For wLine = 1 to 23;
               %subst(wDetailLine(wLine):wEndOfDesc-1:2) = ':' +
                   wCol_White;
           Endfor;
       When pYType = '*PCT' and wScreenLarge = *Off;  // Y-bar will be percentage
           wDetailLine(1)  = '100%  : ' + %trim(wUnderLine);
           wDetailLine(5)  = ' 75%  : ' + %trim(wUnderLine);
           wDetailLine(10) = ' 50%  : ' + %trim(wUnderLine);
           wDetailLine(15) = ' 25%  : ' + %trim(wUnderLine);
           wDetailLine(20) = '  0%  : ' + %trim(wUnderLine2);
           wDetailLine(21) = '        ' +
               %trim(wUnderLine3);
           For wLine = 1 to 20;
               %subst(wDetailLine(wLine):7:2) = ':' + wCol_White;
           Endfor;
           wEndOfDesc = 8;
       When pYType = '*NORMAL' and wScreenLarge = *Off;  // Determine Min/Max/25%/50%/75%
           select;         //1234567890123
           when pMaxValue >= 1000000000000 and pYCalc = '*TB';
               wDivisor = 1024*1024*1024*1024;
               y2Desc = 'Size in TB';
           when pMaxValue >= 1000000000 and pYCalc = '*GB';
               wDivisor = 1024*1024*1024;
               y2Desc = 'Size in GB';
           when pMaxValue >= 1000000 and pYCalc = '*MB';
               y2Desc = 'Size in MB';
               wDivisor = 1024*1024;
           when pMaxValue >= 1000 and pYCalc = '*KB';
               y2Desc = 'Size in KB';
               wDivisor = 1024;
           Other;
               wDivisor = 1;
           EndSl;
           wLength = %len(%trim(FormatNumber(%dec(pMaxValue/wDivisor:31:2))));
           wEndOfDesc = wLength + 4;
           wDetailLine(1) =
               %trim(FormatNumber(%dec(pMaxValue/wDivisor:31:2)));
           %subst(wDetailLine(1):wEndOfDesc+1:79-wEndOfDesc-1) =
               %trim(wUnderLine);
           wDetailLine(5) =
               %trim(FormatNumber(%dec(pMaxValue/wDivisor*0.75:31:2)));
           %subst(wDetailLine(5):wEndOfDesc+1:79-wEndOfDesc-1) =
               %trim(wUnderLine);
            wDetailLine(10) =
               %trim(FormatNumber(%dec(pMaxValue/wDivisor*0.50:31:2)));
           %subst(wDetailLine(10):wEndOfDesc+1:79-wEndOfDesc-1) =
               %trim(wUnderLine);
           wDetailLine(15) =
               %trim(FormatNumber(%dec(pMaxValue/wDivisor*0.25:31:2)));
           %subst(wDetailLine(15):wEndOfDesc+1:79-wEndOfDesc-1) =
               %trim(wUnderLine);
           wDetailLine(20) = '0';
           %subst(wDetailLine(20):wEndOfDesc+1:79-wEndOfDesc-1) =
               %trim(wUnderLine2);
           %Subst(wDetailLine(21):wEndOfDesc+1:79-wEndOfDesc-1)=
               %trim(wUnderLine3);
           For wLine = 1 to 20;
               %subst(wDetailLine(wLine):wEndOfDesc-1:2) = ':' + wCol_White;
           Endfor;
       EndSl;
       Return wEndOfDesc;
       End-proc;
      // ================================================================
       dcl-proc FormatNumber;
       dcl-pi FormatNumber                 char(20);
           pInputValue                     packed(15:2) value;
       end-pi;
       dcl-s wTempValue                    char(20) inz(' ');
       //
       If pInputValue < 1 and pInputValue > 0;
           wTempValue = '0' + %trim(%editc(pInputValue:'J'));
       Else;
           wTempValue = %trim(%editC(pInputValue:'J'));
       EndIf;
       Return wTempValue;
       End-proc;
      // ================================================================
       dcl-proc BuildScreen;
       dcl-pi BuildScreen;
           pPage                           int(10) value;
           pMaxValue                       packed(31:2) value;
           pTotalItems                     int(10)  value;
           pYLabel                         char(30) value;
           pChartType                      char(10) value;
           pYCalc                          char(10) value;
       end-pi;
       dcl-s wLineCount                    int(10) inz(0);
       dcl-s wTotalColumns                 int(10) inz(0);
       dcl-s wPageCount                    int(10) inz(0);
       dcl-s wStrCol                       int(10) inz(0);
       dcl-s wEndCol                       int(10) inz(0);
       dcl-s wTempNum                      packed(31:2) inz(0);
       dcl-s wMaxCol                       int(10) inz(0);
           If wScreenLarge = *On;
               wMaxCol = 130;
           Else;
               wMaxCol = 78;
           EndIf;
           wLineStr = BuildyLines(pMaxValue:pChartType:pYLabel:pYCalc);
           If wDeterminePages = *Off;
               wDeterminePages = *On;
               wTotalColumns = wMaxCol - wLineStr;
               wTotalPages = %inth(pTotalItems/wTotalColumns);
               wStrCol = 1;
               If wTotalPages = 0;
                   wTotalPages = 1;
               EndIf;
               For wPageCount = 1 to wTotalPages;
                   dsPage(wPageCount).Start = wStrCol;
                   wEndCol = wStrCol + wTotalColumns - 1;
                   If wEndCol > pTotalItems;
                       wEndCol = pTotalItems;
                   EndIf;
                   dsPage(wPageCount).End = wEndCol;
                   dsPage(wPageCount).Entries = wEndCol - wStrCol + 1;
                   wStrCol = wEndCol + 1;
               EndFor;
           EndIf;
           wStrCol = dsPage(pPage).Start;
           wEndCol = dsPage(pPage).End;
           For wLineCount = 0 to (wMaxCol - wLineStr - 1);
               If dsData(wLineCount+wStrCol).wDataItem  < 0;
                   wTempNum = 0;
               Else;
                   wTempNum = dsData(wLineCount+wStrCol).wDataItem;
               EndIf;
               BuildColumn(wLineStr+wLineCount+1:pMaxValue:
                   wTempNum:
                   dsData(wLineCount+wStrCol).wxData);
           EndFor;
           BuildDLines();
           If wScreenLarge = *On;
               EvalR FLine1 = 'Page ' + %trim(%editc(wPage:'1')) + ' of ' +
               %trim(%editc(wTotalPages:'1')) + ' page(s)';
           Else;
               EvalR F2LIne1= 'Page ' + %trim(%editc(wPage:'1')) + ' of ' +
               %trim(%editc(wTotalPages:'1')) + ' page(s)';
           EndIf;
       End-proc;
      // ================================================================
      // ================================================================
       dcl-proc BuildDlines;
       If wScreenLarge = *On;
           dline01 = wDetailLine(1);
           dline02 = wDetailLine(2);
           dline03 = wDetailLine(3);
           dline04 = wDetailLine(4);
           dline05 = wDetailLine(5);
           dline06 = wDetailLine(6);
           dline07 = wDetailLine(7);
           dline08 = wDetailLine(8);
           dline09 = wDetailLine(9);
           dline10 = wDetailLine(10);
           dline11 = wDetailLine(11);
           dline12 = wDetailLine(12);
           dline13 = wDetailLine(13);
           dline14 = wDetailLine(14);
           dline15 = wDetailLine(15);
           dline16 = wDetailLine(16);
           dline17 = wDetailLine(17);
           dline18 = wDetailLine(18);
           dline19 = wDetailLine(19);
           dline20 = wDetailLine(20);
           dline21 = wDetailLine(21);
           dline22 = wDetailLine(22);
           dline23 = wDetailLine(23);
           dline24 = wDetailLine(24);
       Else;
           d2line01 = wDetailLine(1);
           d2line02 = wDetailLine(2);
           d2line03 = wDetailLine(3);
           d2line04 = wDetailLine(4);
           d2line05 = wDetailLine(5);
           d2line06 = wDetailLine(6);
           d2line07 = wDetailLine(7);
           d2line08 = wDetailLine(8);
           d2line09 = wDetailLine(9);
           d2line10 = wDetailLine(10);
           d2line11 = wDetailLine(11);
           d2line12 = wDetailLine(12);
           d2line13 = wDetailLine(13);
           d2line14 = wDetailLine(14);
           d2line15 = wDetailLine(15);
           d2line16 = wDetailLine(16);
           d2line17 = wDetailLine(17);
           d2line18 = wDetailLine(18);
           d2line19 = wDetailLine(19);
           d2line20 = wDetailLine(20);
           d2line21 = wDetailLine(21);
       EndIf;
       End-proc;
      // ====================================================================*
      //   Subroutine.... ScreenSizeIs132                                    *
      //   Description... Check if the screen is configured for 132 Chars    *
      //
      //   Parameters:
      //
      // ‚Example:
      //
      // šIf ScreenSizeIs132() = *Off;
      //      SndCompMsg('Screen is NOT configured for 132 chars');
      // šElse;
      //      SndCompMsg('Object is configured for 132 chars');
      // šEndIf;
      // ====================================================================*
       Dcl-Proc ScreenSizeIs132            export;
       Dcl-PI ScreenSizeIs132              ind;// Return Variable
       End-PI;
       // Check the screen size now
              If (QsnQryModSup(DS4_MODE:*OMIT:*OMIT:*OMIT) <> MODE_ALLOWED);
                 Return *Off;
              Else;
                 Return *On;
              EndIf;
       End-Proc;
     //********************************************************************
      //  ===================================================================================
      //   Center Text in a string
      //     Parm:    Input String varchar(32767)
      //              String Length (untrimmed)
      //     Returns: Output String varchar(32000)
      //  ===================================================================================
      //  EXAMPLE:
      //              wTestString = CenterText(wTestString):%len(wTestString));
      //
      //  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        dcl-proc CenterText              export;
           dcl-pi CenterText             char(32767);
              p_InputString              char(32767) const OPTIONS(*VARSIZE);
              p_Stringlength             int(10) value;
           end-pi;
      //
           dcl-s wStrPos                 int(10) inz(0);
           dcl-s wTempLen                int(10) inz(0);
           dcl-s wOutputString           char(32767) inz(' ');
              wTempLen = %len(%trim(%subst(p_InputString:1:p_StringLength)));
              wStrPos = ((p_StringLength - wTempLen)/2) + 1;
               %Subst(wOutputString:wStrPos:wTempLen) =
                   %trim(%subst(p_InputString:1:p_StringLength));
               Return wOutputString;
        end-proc;