ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

The value of the field in a field

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • The value of the field in a field

    I have a program that populates a data structure with various customer information and passes the DS to a print program. Right now this is all hard coded in the calling program. I want to externalize how the data structure is populated for each customer. Ideally, I want to have a file that contains the customer number and field names from an order file. This file will contain the from position and length within the data structure to place the value that is in the field. I am using the following code to populate data structure MRGDTA
    Code:
    Setll wkCust Reffile;
             Dou %Eof(Reffile);
               Reade wkCust Reffile;
               If not %Eof(Reffile);
               %Subst(Mrgdta:C1from:C1Leng) = %CHAR(C1field);
               Endif;
             Enddo;
    The problem is after each iteration of the loop, MRGDTA contains the value ?ORCUST? instead of the value contained in the field ORCUST specified in C1FIELD. In other words if C1FROM = 1 and C1LENG contains 10 and C1FIELD contains ?ORCUST? and ORCUST = ?SMITH?, I want to place ?SMITH? in posn 1 ? 10 of MRGDTA

    Can anyone think of a better/different way to do this

  • #2
    Basically this is not a thing that compiled languages like RPG can do. At least not in the way that you have tried to do it.

    If you could tell us what problem you are trying to solve by this approach we might be able to offer alternative suggestions.

    You can do this type of thing in RPG if you can constrain the problem space - these articles will show you what I mean by this. http://ibmsystemsmag.com/ibmi/develo...calculations-/ and the follow on http://ibmsystemsmag.com/ibmi/develo...-calculations/. That won't give you exactly what you want but the pointer based approach is an option.

    Other possible approaches would involve doing away with the DS and instead use a string containing (say) JSON/XML/name-values and then using XML-INTO or DATA-INTO to unpack into the final DS based on field names.

    As I say - knowing the problem you are trying to fix rather than suggesting ways of meeting your proposed approach would be more useful I think.

    Comment


    • #3
      Color me confused - according to the code above MRGDTA, from position specified in C1FORM for a length of C1Len will contain the character equivilent to the numeric field C1Field. C1Field being numeric will never have "ORCUST" as it's, well, not numeric.

      Comment


      • #4
        Originally posted by JonBoy View Post
        As I say - knowing the problem you are trying to fix rather than suggesting ways of meeting your proposed approach would be more useful I think.
        This is a concept cooked up by management. We have a print program that prints customer tags. I'm not sure it's even written in RPG. It's a proprietary product that I do not have access to. I am not even sure we have the source code. My manager sets up in using an interactive program how the data structure is formatted that is used in the print program, what information is expected in what positions. He wants to be able to set up in a control file on the iSeries, the positions the print program is expecting various pieces of information, e.g., customer#, invoice#, etc. to be in. As I mentioned in the original post, this is all currently hard coded in the program that calls the print program. He want's to be able to set this up in a file for new customers as needed so the program that calls the print program can check to see if the customer# being processed is in the set up file and if it is, format the data structure based on the specifications in the set up file. The tricky part is if the format of the DS changes (e.g. maybe another field to be printed on the tag). they want to be able to change it externally rather than modify the calling program to add more info to the DS before calling the print program.

        Hope this helps......thanks again

        Comment


        • #5
          Well the articles I referenced will show you one approach.

          Basically if I had to do this to work with an existing tool that I couldn't change (which seems to be what you're saying) then I would do something like this:

          Dcl-s data char(100) based(p_data); // where 100 is the size of the biggest field.

          Dcl-ds fieldNames;
          *n char(10) Inz('FIELD1');
          *n char(10) Inz('FIELD2');
          // etc. tc.
          name char(10) Dim(2) Pos(1);
          End-ds;

          Dcl-ds fieldPointers;
          *n pointer Inz(%Addr('FIELD1');
          *n pointer Inz(%Addr('FIELD2'));
          // etc. tc.
          namePointer pointer Dim(2) Pos(1);
          End-ds;

          Logic is basically

          Obtain field name from database or whatever.

          Lookup field name in name array.

          Use resulting index to set p_data to associated pointer from namePointer array

          Use %Subst(to set the value in the DS;

          e.g. %Subst( DS : startPos : length ) = data;

          The solution is not completely soft because the %Addr values have to be resolved at compile time. But the code only needs to change when a completely new field is introduced and you'd have to recompile at that point anyway.

          Another possibility is to retrieve the data via a dynamically built SQL statement and have it form the DS string. That may not fit for you though.

          There are other ways but ....

          Comment


          • #6
            Maybe taking this logic into a service program and pass the data to it via parms.

            Comment


            • #7
              If you're just looking to put data into particular positions of a buffer, the simplest way would be with %SUBST():

              Code:
              %subst(myBuf:fromPos:length) = 'VAL';
              Your biggest hurdle, imho, is the attempt to do things by a variable's name. That won't work because variable names don't exist at runtime. While the program is running, it's no longer using your source code, and its working by accessing memory addresses and offsets via pointer. It's not using the names of the variables, those cease to exist when the program is compiled. (That's why you have to add an extra 'debugging view' to debug a program -- well, its part of the reason, anyway)

              Stop thinking in terms of names. Instead, think in terms of where things are... such as starting/ending positions.

              If your fields are database columns (rather than just variables -- I know RPGers get these mixed up all the time because RPG variables can be automatically named the same as the DB columns, but they aren't really the same thing.) you can get them by name using dynamic SQL, or by using an API to find out where a field is found in a record buffer, together with %SUBST or pointer logic. I'd go with dynamic SQL because it'll be easier to read/maintain than the pointer logic would be.

              I'm really confused by the statement that you can't change this program -- but that the parameter list must be soft-coded. If it can't change, why are you doing this? It can't change.

              But, if it can be changed, I would strongly recommend re-thinking your approach. Instead of this weird soft-coded ds that you've invented, using a format like JSON (or XML if you want to go old school). This allows for much looser coupling (i.e. non-fixed parameters, easier to change one program without breaking the other, etc) and is a mainstream and well-understood way of doing things.

              Comment


              • #8
                If the data is always in the same position in the file - or can be determined where, you could define the file as program described file, define the record as a char and get the data from that.

                Comment

                Working...
                X