2

I am writing a program that changes the colour of a field if is it a duplicate record. To do this I am using a nested perform to compare each item to each other. When it finds a duplicate I would like to MOVE DFHRED to that specific field for example CRS1AC. My issue is that I don't know how to reference the field I am trying to change the colour of once I've found that is it a duplicate, how do I do this? Here are the fields which are in the MAP file that I am trying to move the colour to if a duplicate exists...

 01     CRS1AC                PIC X.
 01     CRS1BC                PIC X.

 01     CRS2AC                PIC X.
 01     CRS2BC                PIC X.

 01     CRS3AC                PIC X.
 01     CRS3BC                PIC X.

 01     CRS4AC                PIC X.
 01     CRS4BC                PIC X.

 01     CRS5AC                PIC X.
 01     CRS5BC                PIC X.

here is my table setup...

     01  TABLES.
       05  TBL-CRS-ENTRIES        PIC S9(3) COMP-3  VALUE 5.
       05  TBL-CRS-VALUES         PIC X(4)  OCCURS 10 TIMES. 

       05  CRS-TBL REDEFINES TBL-CRS-VALUES  
                      PIC X(8)  OCCURS 5 TIMES.
       05  SUB-1          PIC S9(3) COMP-3 VALUE 1.
       05  SUB-2          PIC S9(3) COMP-3 VALUE 1.

& here is the code that checks for duplicates

   PERFORM VARYING SUB-1 FROM 1 BY 1 UNTIL SUB-1 > TBL-CRS-ENTRIES
     PERFORM VARYING SUB-2 FROM 1 BY 1 UNTIL SUB-2 > SUB-1 - 1
      IF CRS-TBL(SUB-1) = CRS-TBL(SUB-2)
  *if there is a match it should change the colour to red.
  * for example a match at CRS1AC & CRS1BC match CRS3AC & CRS3BC

  *this is my attempt at trying make the variable name.
        MOVE DFHRED TO CRS(SUB-1)AC
        MOVE DFHRED TO CRS(SUB-1)BC

        MOVE DFHRED TO CRS(SUB-2)AC
        MOVE DFHRED TO CRS(SUB-2)BC
        PERFORM 999-DUPLICATE-RECORD 
      END-IF
     END-PERFORM
   END-PERFORM.
   GOBACK.

So, if 'PSYC 1000' = 'PSYC 1000' & the name of those fields are.. 'CRS1AC+CRS1BC = CRS3AC+CRS3BC' <--- these are the fields I want to change the color of.

I've researched this heavily & still cannot find a solution. Hope this makes sense I know its all over the place, for further clarification please ask & if complete program code is required I can provide it.

Bill Woodger
  • 12,968
  • 4
  • 38
  • 47
Alexander.IV
  • 137
  • 1
  • 3
  • 9

1 Answers1

1

No, it is not possible to do what you want how you want.

COBOL is a compiled language. What is relevant about that is that you cannot make up the names of identifiers (variables) at run-time. Once a COBOL program is compiled, that is it, no more changes to the source for that executable version.

Where to go then?

You say this is part of your MAP.

 01     CRS1AC                PIC X.
 01     CRS1BC                PIC X.

 01     CRS2AC                PIC X.
 01     CRS2BC                PIC X.

 01     CRS3AC                PIC X.
 01     CRS3BC                PIC X.

 01     CRS4AC                PIC X.
 01     CRS4BC                PIC X.

 01     CRS5AC                PIC X.
 01     CRS5BC                PIC X.

But, because of those level-numbers of 01 those aren't part of anything, except the SECTION they belong to within the DATA DIVISION.

So you need to show your full, actual, MAP.

There is not an especially cute way, so what you have to do is REDEFINES the entire MAP, with an OCCURS which represents each screen-line for this portion of the screen (or entire screen, depends on the design) and define those attribute bytes within the OCCURS item.

What is really exciting about this is getting it all to line-up, by hand.

Now your program.

Your loops are wrong. You execute the inner-loop five times for each iteration of the outer-loop. Which means you are doing far more comparisons than necessary.

This is unwieldy:

SUB-2 > SUB-1 - 1

For that line of code, this would be better:

SUB-2 EQUAL TO SUB-1

The fifth outer-iteration is not required at all, because there are no values to compare to other than those which have already been compared (so the result will be the same, so why bother?).

Consider changing the definition of the identifiers (variables) you are using as subscripts and your total of entries to BINARY or COMP or COMP-4 (they all mean the same thing).

Consider giving them more meaningful names than SUB-1, SUB-2. It will make the code "read" better, which always helps.

Here's your data-defintion:

 01  TABLES.
   05  TBL-CRS-ENTRIES        PIC S9(3) COMP-3  VALUE 5.
   05  TBL-CRS-VALUES         PIC X(4)  OCCURS 10 TIMES. 

   05  CRS-TBL REDEFINES TBL-CRS-VALUES  
                  PIC X(8)  OCCURS 5 TIMES.
   05  SUB-1          PIC S9(3) COMP-3 VALUE 1.
   05  SUB-2          PIC S9(3) COMP-3 VALUE 1.

Some other things to make things easier for yourself:

Don't code identifiers (variables) after an OCCURS. It doesn't greatly matter in itself when there is no DEPENDING ON on the OCCURS, but since it does matter for that, why not be consistent (consistency is great, because when you are looking for a problem and you find inconsistency, it tells something about the writer of that particular bit of code).

Don't REDEFINES items which are defined with OCCURS. Even if you are using an old compiler (either you've put incorrect code here, or you are doing that) that gives you at least a Caution message. Try an experiment. Show that definition to a colleague, and ask them "what does this actually do?" Then show to another. And a third. If they all immediately reply, accurately, what it does, then you have a site with outstanding knowledge. You haven't, so don't do that.

Don't make identifiers signed, unless they can contain negative values. Then the reader can look at the definition and know it can't contain a negative value. Don't fall for "oh, we do it for performance". Name the compiler and show the compile options, and I'll show you what it is "gaining", or losing.

Don't use VALUE clauses for initial values of identifiers used as subscripts. Set them to their initial value before you use them. Unless you have tortuous code setting the value at the end of the current processing so it is ready for the next processing, all you are doing is confusing the human-reader. If there is a VALUE clause, it should be necessary.

Do give everything a good, descriptive, name, if it is being used. If something does not need a name, use FILLER to define it (often).

Your definition could be done like this:

 01  some-meaningful-name
     05  TBL-CRS-ENTRIES           BINARY PIC 9(4) VALUE 5.
     05  also-meaningful           BINARY PIC 9(4).
     05  meaningful-also           BINARY PIC 9(4).
     05  another-meaningful-name.
         10  FILLER OCCURS 10 TIMES.
             15  TBL-CRS-VALUES           PIC X(4). 

     05  FILLER REDEFINES another-meaningful-name.  
         10  FILLER OCCURS 5 TIMES.
             15  CRS-TBL                  PIC X(8).

Source code is for two things: for the compiler to convert into executable code; for the human reader to understand what has been coded. The compiler does not care about formatting the code. So format the code for the human reader. Even little things help:

  IF CRS-TBL(SUB-1) = CRS-TBL(SUB-2)

Vs

  IF CRS-TBL ( W-ORIGINAL-ITEM ) 
    EQUAL TO CRS-TBL ( W-NEW-ITEM )
Bill Woodger
  • 12,968
  • 4
  • 38
  • 47