Converting to CHAR with leading zeros

This is as much a reminder to myself as anything else because the %CHAR built in function has the unfortunate behaviour of stripping leading zeroes when converting a number to a character value. Sometimes I need to keep those leading zeroes, for example when handling elderly date fields.

Fortunately, there’s %EDITC.

This function returns a character result representing the numeric value edited according to the edit code.

The edit codes allow you to do pull all sorts of neat little tricks but, for my purposes, the most useful one is the X edit code which (obscurely) ensures a hexadecimal F sign for positive values. Handily, this means that leading blanks are converted into leading zeroes when converting from numeric to character.

Here’s an example:

      **Free

        // Converting to character with leading zeros
        ctl-opt dftactgrp(*no) actgrp(*new) main(Main);

        dcl-proc Main;
            dcl-pi *n end-pi;

            dcl-s numYear packed(4) inz(2016);
            dcl-s numMonth packed(2) inz(9);
            dcl-s numDay packed(2) inz(1);
            dcl-s charDate char(8) inz;
            dcl-c edit 'X';

            // This converts the numeric fields ino string '20160901'
            charDate = %editc(numYear: edit) +
                       %editc(numMonth: edit) +
                       %editc(numDay: edit);

            // And then I can convert the string into a date and display it
            dsply %date(charDate: *ISO);

            return;

        end-proc;

And if you need a reminder of what the other edit codes are, or what they do, you’re welcome

Using %TLOOKUP: An example

Firstly, a disclaimer. The CTDATA definition keyword indicates that an array or table should be loaded at compile time. This is a terrible idea for a whole host of reasons, not least of which is that the data is locked away in the program and that you need a programmer to change the data. It is far, far better to store any and all data outside of the program — physical files, SQL tables and data areas all exist for this purpose.

However, there are times when compile time tables cannot be avoided. These are times that I find myself looking at a really old program which is, inevitably, broken.

%TLOOKUP is weird. The function searches a table for an argument and returns either *ON or *OFF depending on whether or not a match was found. All pretty straightforward so far, if a little pointless. The oddities begin when you include the third, alt-table parameter.

Here’s an example:

        ctl-opt main(Main) dftactgrp(*no) actgrp(*new);

        //---------------------------------------------------------------------
        // Tables
        //---------------------------------------------------------------------
        dcl-s TABA char(3) dim(4) ctdata perrcd(1);
        dcl-s TABB char(2) dim(4) alt(TABA);

        //---------------------------------------------------------------------
        // Program main procedure
        //---------------------------------------------------------------------
        dcl-proc Main;
            dcl-pi *n end-pi;

            dcl-s check ind;


            check = %tlookup('129': TABA: TABB);
            dsply TABB;

            return;

        end-proc;
      * ---------------------------------------------------------------------- *
**  TABA - TABB
112G
113LU
129NL
150B

If I run this program, the tlookup searches table TABA for argument ‘129’. The third element of TABA matches this exactly, so the value of check is set to *ON.

And the value of TABB is set to ‘NL’, which is what we’re looking for.

But TABB is not a real field and cannot, for example, be used as an SQL host variable. For this, you would need to define another standalone field and populate it with TABB.

%TLOOKUP is an odd little function, and one that is very rarely needed. This post goes a very little way towards rectifying the fact that no-one else on the web wanted to provide an example of its use.