I need to find how many policies are in each territory based on the territory code. So everytime I find the territory in the record, I need to increment the count for that territory in my table
then I would be able to move it to my output. I can't figure out how to count the policies in each territory based on the record below. I've tried a variety of things but nothing seems to work.
If you need more information, please let me know.
Below is the definition and an excerpt from the record (total of 57 records)
rec-94-type pic x(2)
rec-94-policy-number pic x(8)
filler pic x(5)
rec-94-parish-code pic x(3)
filler pic x(1)
rec-94-territory-code pic x(1)
94A 018517 080 1
94A 027721 090 1
94A 036470 250 6
94A 049137 010 1
......
My most recent attempt:
05 T2-TERRITORY-COUNT.
10 FILLER PIC X(4) VALUE '1 '.
10 FILLER PIC X(4) VALUE '2 '.
10 FILLER PIC X(4) VALUE '3 '.
10 FILLER PIC X(4) VALUE '4 '.
10 FILLER PIC X(4) VALUE '5 '.
10 FILLER PIC X(4) VALUE '6 '.
10 FILLER PIC X(4) VALUE '7 '.
10 FILLER PIC X(4) VALUE '8 '.
10 FILLER PIC X(4) VALUE '9 '.
05 T2-TERRITORY-TABLE REDEFINES T2-TERRITORY-COUNT.
10 T2-ENTRY OCCURS 9 TIMES
INDEXED BY T2-INDEX.
15 T2-TERRITORY-CODE PIC X.
15 T2-TERRITORY-COUNTER PIC 999.
A000-MAINLINE.
PERFORM B000-OPENING-PROCEDURE.
PERFORM B600-PRINT-HEADINGS.
PERFORM B200-READ-FILE.
PERFORM B300-MAIN-PROCEDURE
UNTIL END-OF-FILE-SW = 'YES'.
PERFORM B800-MOVE-TERRITORY-CODE
VARYING T2-INDEX FROM 1 BY 1
UNTIL T2-INDEX > 9.
PERFORM B110-MOVE-COUNTS
PERFORM B100-CLOSING-PROCEDURE.
STOP RUN.
B000-OPENING-PROCEDURE.
OPEN OUTPUT REPORT-FILE.
OPEN OUTPUT PRINT-FILE.
OPEN INPUT INPUT-FILE.
B100-CLOSING-PROCEDURE.
PERFORM B500-PRINT-TOTAL-LINE.
CLOSE REPORT-FILE.
CLOSE PRINT-FILE.
CLOSE INPUT-FILE.
B200-READ-FILE.
READ INPUT-FILE INTO RECORD-TYPE-94
AT END MOVE 'YES' TO END-OF-FILE-SW.
B300-MAIN-PROCEDURE.
IF REC-94-TYPE = "94"
PERFORM B400-SEARCH-TERRITORY
PERFORM B900-COUNT-POLICIES
ELSE
WRITE REPORT-RECORD FROM RECORD-TYPE-94
END-IF.
ADD 1 TO A-LINE-COUNT.
PERFORM B200-READ-FILE.
B400-SEARCH-TERRITORY.
SET T1-INDEX TO 1.
SEARCH T1-ENTRY
AT END
DISPLAY 'PARISH NOT FOUND IN TABLE'
CALL 'CEE3ABD' USING BY VALUE 12 BY VALUE 1
WHEN
REC-94-PARISH-CODE = T1-PARISH(T1-INDEX)
MOVE T1-TERRITORY(T1-INDEX) TO
REC-94-TERRITORY-CODE
ADD 1 TO A-DISK-COUNTER
PERFORM B700-MOVE-RECORDS
END-SEARCH.
B500-PRINT-TOTAL-LINE.
MOVE A-LINE-COUNT TO TOTAL-RECORDS.
MOVE A-DISK-COUNTER TO TOTAL-POLICIES.
WRITE PRINT-RECORD FROM TOTAL-LINE.
B600-PRINT-HEADINGS.
ADD 1 TO A-PAGE-COUNT.
MOVE A-PAGE-COUNT TO PRINT-PAGE-NUMBER.
WRITE PRINT-RECORD FROM HEADER.
WRITE PRINT-RECORD FROM HEADER-LINE-2.
WRITE PRINT-RECORD FROM COLUMN-LINE.
B700-MOVE-RECORDS.
MOVE REC-94-TYPE TO REC-94-TYPE-OUT
MOVE REC-94-POLICY-NUMBER TO REC-94-POLICY-NUMBER-OUT
MOVE REC-94-PARISH-CODE TO REC-94-PARISH-CODE-OUT
MOVE REC-94-TERRITORY-CODE TO REC-94-TERRITORY-CODE-OUT
WRITE REPORT-RECORD FROM TRNREC94-OUT.
B800-MOVE-TERRITORY-CODE.
MOVE T2-TERRITORY-CODE(T2-INDEX) TO DET-TERRITORY.
WRITE PRINT-RECORD FROM DETAIL-LINE.
B900-COUNT-POLICIES.
MOVE ZEROES TO T2-TERRITORY-COUNTER(T2-INDEX).
SET T2-INDEX TO 1.
SEARCH T2-ENTRY
AT END
DISPLAY 'NO POLICIES FOUND.'
WHEN
REC-94-TERRITORY-CODE =
T2-TERRITORY-CODE(T2-INDEX)
ADD 1 TO T2-TERRITORY-COUNTER(T2-INDEX)
END-SEARCH.
MOVE T2-TERRITORY-COUNTER(T2-INDEX) TO DET-NUMBER-POLICIES.
WRITE PRINT-RECORD FROM DETAIL-LINE.
I'd appreciate any pointers or just the correct direction to go in for this.. Thanks in advance!
My final code:
PERFORM B000-OPENING-PROCEDURE.
PERFORM B600-PRINT-HEADINGS.
PERFORM B200-READ-FILE.
PERFORM B300-MAIN-PROCEDURE
UNTIL END-OF-FILE-SW = 'YES'.
PERFORM C100-MOVE-COUNTS
VARYING T2-INDEX FROM 1 BY 1
UNTIL T2-INDEX > 9.
PERFORM B100-CLOSING-PROCEDURE.
STOP RUN.
B000-OPENING-PROCEDURE.
OPEN OUTPUT REPORT-FILE.
OPEN OUTPUT PRINT-FILE.
OPEN INPUT INPUT-FILE.
B100-CLOSING-PROCEDURE.
PERFORM B500-PRINT-TOTAL-LINE.
CLOSE REPORT-FILE.
CLOSE PRINT-FILE.
CLOSE INPUT-FILE.
B200-READ-FILE.
READ INPUT-FILE INTO RECORD-TYPE-94
AT END MOVE 'YES' TO END-OF-FILE-SW.
B300-MAIN-PROCEDURE.
IF REC-94-TYPE = "94"
PERFORM B400-SEARCH-TERRITORY
ELSE
WRITE REPORT-RECORD FROM RECORD-TYPE-94
END-IF.
ADD 1 TO A-LINE-COUNT.
PERFORM B200-READ-FILE.
B400-SEARCH-TERRITORY.
SET T1-INDEX TO 1.
SEARCH T1-ENTRY
AT END
DISPLAY 'PARISH NOT FOUND IN TABLE'
CALL 'CEE3ABD' USING BY VALUE 12 BY VALUE 1
WHEN
REC-94-PARISH-CODE = T1-PARISH(T1-INDEX)
MOVE T1-TERRITORY(T1-INDEX) TO
REC-94-TERRITORY-CODE
ADD 1 TO A-DISK-COUNTER
PERFORM B700-MOVE-RECORDS
PERFORM B900-COUNT-POLICIES
END-SEARCH.
B500-PRINT-TOTAL-LINE.
MOVE A-LINE-COUNT TO TOTAL-RECORDS.
MOVE A-DISK-COUNTER TO TOTAL-POLICIES.
WRITE PRINT-RECORD FROM TOTAL-LINE.
B600-PRINT-HEADINGS.
ADD 1 TO A-PAGE-COUNT.
MOVE A-PAGE-COUNT TO PRINT-PAGE-NUMBER.
WRITE PRINT-RECORD FROM HEADER.
WRITE PRINT-RECORD FROM HEADER-LINE-2.
WRITE PRINT-RECORD FROM COLUMN-LINE.
B700-MOVE-RECORDS.
MOVE REC-94-TYPE TO REC-94-TYPE-OUT
MOVE REC-94-POLICY-NUMBER TO REC-94-POLICY-NUMBER-OUT
MOVE REC-94-PARISH-CODE TO REC-94-PARISH-CODE-OUT
MOVE REC-94-TERRITORY-CODE TO REC-94-TERRITORY-CODE-OUT
WRITE REPORT-RECORD FROM TRNREC94-OUT.
B900-COUNT-POLICIES.
SET T2-INDEX TO 1.
SEARCH T2-ENTRY
AT END
DISPLAY 'NO POLICIES FOUND.'
WHEN
REC-94-TERRITORY-CODE = T2-TERRITORY-CODE(T2-INDEX)
DD 1 TO T2-TERRITORY-COUNTER(T2-INDEX)
END-SEARCH.
C100-MOVE-COUNTS.
MOVE T2-TERRITORY-CODE(T2-INDEX) TO DET-TERRITORY.
MOVE T2-TERRITORY-COUNTER(T2-INDEX) TO DET-NUMBER-POLICIES.
WRITE PRINT-RECORD FROM DETAIL-LINE.
The version of B900 with the search statement should work, but B900 is called, and only called once, from A000. Move the PERFORM B900 statement to B300 and you should collect a count for each record read.
Also, T2-TERRITORY-COUNTER is initialized with spaces. Please initialize it with zeros. Depending on your compiler, it might not make a difference, but it is easier to understand the intent of the variable if it starts from zero.
* update *
Your updated code still has spaces for T2-TERRITORY-COUNTER.
Perhaps the following will help. It is based on your code, but some parts were removed to make the relevant parts easier to see. The code below works for GNU Cobol (formerly OpenCobol - see sourceforge.net).
IDENTIFICATION DIVISION.
PROGRAM-ID. COUNT-TERRITORY.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT POLICY-FILE ASSIGN TO 'POLICY.DAT'
FILE STATUS IS POLICY-FILE-STATUS
ORGANIZATION IS LINE SEQUENTIAL.
SELECT REPORT-FILE ASSIGN TO 'POLICY.RPT'
FILE STATUS IS REPORT-FILE-STATUS
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD POLICY-FILE.
01 POLICY-RECORD PIC X(20).
FD REPORT-FILE.
01 REPORT-RECORD PIC X(132).
WORKING-STORAGE SECTION.
01 IS-POLICY-FILE-AT-END PIC XXX VALUE 'NO '.
88 POLICY-FILE-AT-END VALUE 'YES'.
01 POLICY-FILE-STATUS PIC 9(2).
88 POLICY-FILE-OK VALUES 0 10.
* VALUE 00 = SUCCESS
* VALUE 10 = END OF FILE
01 REPORT-FILE-STATUS PIC 9(2).
88 REPORT-FILE-OK VALUES 0 10.
* VALUE 00 = SUCCESS
* VALUE 10 = END OF FILE
01 RECORD-TYPE-94.
05 REC-94-TYPE PIC X(2).
88 INCLUDED-RECORD-TYPE VALUE '94'.
05 REC-94-POLICY-NUMBER PIC X(8).
05 FILLER PIC X(5).
05 REC-94-PARISH-CODE PIC X(3).
05 FILLER PIC X(1).
05 REC-94-TERRITORY-CODE PIC X(1).
01 T2-TERRITORY-COUNT.
05 FILLER PIC X(4) VALUE '1000'.
05 FILLER PIC X(4) VALUE '2000'.
05 FILLER PIC X(4) VALUE '3000'.
05 FILLER PIC X(4) VALUE '4000'.
05 FILLER PIC X(4) VALUE '5000'.
05 FILLER PIC X(4) VALUE '6000'.
05 FILLER PIC X(4) VALUE '7000'.
05 FILLER PIC X(4) VALUE '8000'.
05 FILLER PIC X(4) VALUE '9000'.
01 T2-TERRITORY-TABLE REDEFINES T2-TERRITORY-COUNT.
05 T2-ENTRY OCCURS 9 TIMES
INDEXED BY T2-INDEX.
10 T2-TERRITORY-CODE PIC X.
10 T2-TERRITORY-COUNTER PIC 999.
PROCEDURE DIVISION.
A000-MAINLINE.
PERFORM B000-OPENING-PROCEDURE
PERFORM B200-READ-FILE
PERFORM B300-MAIN-PROCEDURE
UNTIL POLICY-FILE-AT-END
PERFORM C100-WRITE-TERRITORY-COUNTS
PERFORM B100-CLOSING-PROCEDURE
STOP RUN
.
B000-OPENING-PROCEDURE.
OPEN INPUT POLICY-FILE
OPEN OUTPUT REPORT-FILE
.
B100-CLOSING-PROCEDURE.
CLOSE POLICY-FILE
CLOSE REPORT-FILE
.
B200-READ-FILE.
READ POLICY-FILE INTO RECORD-TYPE-94
AT END SET POLICY-FILE-AT-END TO TRUE
PERFORM D100-CHECK-POLICY-FILE-STATUS
.
B300-MAIN-PROCEDURE.
IF INCLUDED-RECORD-TYPE
PERFORM B900-COUNT-POLICIES
ELSE
WRITE REPORT-RECORD FROM RECORD-TYPE-94
PERFORM D200-CHECK-REPORT-FILE-STATUS
END-IF
PERFORM B200-READ-FILE
.
B900-COUNT-POLICIES.
SET T2-INDEX TO 1
SEARCH T2-ENTRY
AT END
DISPLAY 'TERRITORY ' REC-94-TERRITORY-CODE
' UNKNOWN'
WHEN REC-94-TERRITORY-CODE = T2-TERRITORY-CODE (T2-INDEX)
ADD 1 TO T2-TERRITORY-COUNTER (T2-INDEX)
END-SEARCH
.
C100-WRITE-TERRITORY-COUNTS.
MOVE SPACES TO REPORT-RECORD
WRITE REPORT-RECORD
PERFORM D200-CHECK-REPORT-FILE-STATUS
PERFORM VARYING T2-INDEX FROM 1 BY 1
UNTIL T2-INDEX > 9
STRING 'POLICY COUNT FOR TERRITORY '
T2-TERRITORY-CODE (T2-INDEX)
': '
T2-TERRITORY-COUNTER (T2-INDEX)
INTO REPORT-RECORD
WRITE REPORT-RECORD
PERFORM D200-CHECK-REPORT-FILE-STATUS
END-PERFORM
.
D100-CHECK-POLICY-FILE-STATUS.
IF NOT POLICY-FILE-OK
DISPLAY 'ERROR CODE READING POLICY FILE: '
POLICY-FILE-STATUS
END-IF
.
D200-CHECK-REPORT-FILE-STATUS.
IF NOT REPORT-FILE-OK
DISPLAY 'ERROR CODE WRITING REPORT FILE: '
POLICY-FILE-STATUS
END-IF
.
You PERFORM B900-COUNT-POLICIES only once, after the end-of-file is already reached.
B900- also just uses whatever value T2-INDEX last had.
You have two main choices: either a loop to do it; or, assuming that your territory is zero to less-than-or-equal-to nine - in which case you can use the value of the territory to set the value for your index and just add. SEARCH is possible (the reason it didn't work for you was still the execution of the paragraph only after end-of-file, not with each record), but in my experience it is not a method that is chosen for this type of task.
If you want to use the territory to get the value for the index to use for the ADD, use SET:
SET T2-INDEX TO rec-94-territory-code
Except you can't. rec-94-territory-code is an alpha-numeric (a PIC X field. This is good for anything not used in a calculation). It is unproblematic to define a new numeric field in your WORKING-STORAGE and first
MOVE rec-94-territory-code TO new-numeric-field
then
SET T2-INDEX TO new-numeric-field
For the loop, I think you can already get there.
However, before you do any adding either way, it would be a good idea if your per-territory counts started off at zero. Yours state off at space. Even if that "works", it is not good practice.
So you need to start those from zero - a loop is good for now.
In the light of your code changes, your next problem is how you've attempted to set initial values to your table of counts.
For now, add a paragraph after your OPEN paragraph and PERFORM that new paragraph. In that paragraph, make a loop to set the values in your table to zero, starting from the first and ending with the ninth.
Related
EDIT: Figured it out. I needed to call the read again at the end of A420-COUNT-MARKS
Edit: Working on a z/OS mainframe that I'm accessing via Vista TN3270. The program is submitted using JCL which was provided by the teacher.
I'm in school for programming and I have a COBOL assignment where my program reads a file full of subject names and codes and a file full of student marks and an associated subject code. It must use this info to create a report that lists all the subjects and count the number of students that received grades of A , B, C, D or F for each subject. It then totals up the amount of each grade at the bottom.
Report example:
01 ABC COLLEGE TESTING CENTER
02 TEST RESULTS SUMMARY DATE: yyyy/mm/dd
03
04 SUBJECT NAME A B C D F
05
06 xxxxxxxxxxxxxxxxxxxx 9,999 9,999 9,999 9,999 9,999
07 xxxxxxxxx 9,999 9,999 9,999 9,999 9,999
19
20 TOTAL 99,999 99,999 99,999 99,999 99,999
The problem is that my program is only outputting the header rows, but won't output the detail rows or the grand total row. I've written functions to perform these things but they're not getting any errors so I have no idea what's going wrong.
Here's my file control and file section:
FILE-CONTROL.
SELECT F01-SUBJ-FILE ASSIGN TO F01SUBJ.
SELECT F02-MARK-FILE ASSIGN TO F02MARK.
SELECT F03-REPT-FILE ASSIGN TO F03REPT.
FILE SECTION.
FD F01-SUBJ-FILE
RECORDING MODE IS F
RECORD CONTAINS 80 CHARACTERS
DATA RECORD IS F01-SUBJ-RECORD.
01 F01-SUBJ-RECORD.
05 F01-SUBJ-CODE PIC X(6).
05 F01-SUBJ-NAME PIC X(20).
05 PIC X(54).
FD F02-MARK-FILE
RECORDING MODE IS F
RECORD CONTAINS 80 CHARACTERS
DATA RECORD IS F02-MARK-RECORD
01 F02-MARK-RECORD.
05 F02-STUD-NAME PIC X(20).
05 F02-SUBJ-CODE PIC X(6).
05 PIC X.
05 F02-DATE-TEST PIC X(8).
05 F02-STUD-MARK PIC 9(3).
05 PIC X(42).
FD F03-REPT-FILE
RECORDING MODE IS F
RECORD CONTAINS 120 CHARACTERS
DATA RECORD IS F03-REPT-RECORD.
01 F03-REPT-RECORD.
05 PIC X(120).
Here's working storage:
WORKING-STORAGE SECTION.
01 W01-EOF-SWITCH.
05 W01-MARK-EOF PIC X VALUE 'N'.
05 W01-SUBJ-EOF PIC X VALUE 'N'.
01 W02-TEST-TABLE.
05 W02-SUBJ-COUNT PIC 99 VALUE 0.
05 W02-SUBJ-MAX PIC 99 VALUE 50.
05 W02-TEST-ROW OCCURS 1 TO 50
DEPENDING ON W02-SUBJ-COUNT
ASCENDING KEY IS W02-SUBJ-CODE
INDEXED BY W02-IDX.
10 W02-SUBJ-CODE PIC X(6) VALUE SPACES.
10 W02-SUBJ-NAME PIC X(20) VALUE SPACES.
10 W02-A-CTR PIC 9999 VALUE 0.
10 W02-B-CTR PIC 9999 VALUE 0.
10 W02-C-CTR PIC 9999 VALUE 0.
10 W02-D-CTR PIC 9999 VALUE 0.
10 W02-F-CTR PIC 9999 VALUE 0.
01 W03-REPT.
05 W03-HEADER-ROW1.
10 PIC X(9) VALUE SPACES.
10 PIC X(3) VALUE 'ABC'.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'COLLEGE'.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'TESTING'.
10 PIC X VALUE SPACES.
10 PIC X(6) VALUE 'CENTER'.
10 PIC X(85) VALUE SPACES.
05 W03-HEADER-ROW2.
10 PIC X(9) VALUE SPACES.
10 PIC X(4) VALUE 'TEST'.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'RESULTS'.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'SUMMARY'.
10 PIC X(11) VALUE SPACES.
10 PIC X(5) VALUE 'DATE:'.
10 PIC X VALUE SPACES.
10 W03-YEAR PIC 9999.
10 PIC X VALUE '/'.
10 W03-MONTH PIC 99.
10 PIC X VALUE '/'.
10 W03-DAY PIC 99.
10 PIC X(64) VALUE SPACES.
05 W03-HEADER-ROW3.
10 PIC X VALUE SPACES.
10 PIC X(7) VALUE 'SUBJECT'.
10 PIC X VALUE SPACES.
10 PIC X(4) VALUE 'NAME'.
10 PIC X(15) VALUE SPACES.
10 PIC X VALUE 'A'.
10 PIC X(7) VALUE SPACES.
10 PIC X VALUE 'B'.
10 PIC X(7) VALUE SPACES.
10 PIC X VALUE 'C'.
10 PIC X(7) VALUE SPACES.
10 PIC X VALUE 'D'.
10 PIC X(7) VALUE SPACES.
10 PIC X VALUE 'F'.
10 PIC X(59) VALUE SPACES.
05 W03-DETAIL-ROW.
10 PIC X VALUE SPACES.
10 W03-SUBJ-NAME PIC X(20).
10 PIC XXX VALUE SPACES.
10 W03-A-CTR PIC Z,ZZ9.
10 PIC XXX VALUE SPACES.
10 W03-B-CTR PIC Z,ZZ9.
10 PIC XXX VALUE SPACES.
10 W03-C-CTR PIC Z,ZZ9.
10 PIC XXX VALUE SPACES.
10 W03-D-CTR PIC Z,ZZ9.
10 PIC XXX VALUE SPACES.
10 W03-F-CTR PIC Z,ZZ9.
10 PIC X(59) VALUE SPACES.
01 W04-SYS-DATE.
05 W04-YEAR PIC 9999.
05 W04-MONTH PIC 99.
05 W04-DAY PIC 99.
01 W05-TOTALS.
05 W05-TOTAL-A PIC 99999 VALUE 0.
05 W05-TOTAL-B PIC 99999 VALUE 0.
05 W05-TOTAL-C PIC 99999 VALUE 0.
05 W05-TOTAL-D PIC 99999 VALUE 0.
05 W05-TOTAL-F PIC 99999 VALUE 0.
Here's procedure division
PROCEDURE DIVISION.
PERFORM A100-OPEN-FILES
PERFORM A200-WRITE-HEADINGS
PERFORM A300-PROCESS-SUBJECTS
PERFORM A400-PROCESS-MARKS
PERFORM A500-WRITE-TOTALS
PERFORM A600-CLOSE-FILES
STOP RUN
.
A100-OPEN-FILES.
* OPENS FILES
OPEN INPUT F01-SUBJ-FILE
F02-MARK-FILE
OPEN OUTPUT F03-REPT-FILE
.
A200-WRITE-HEADINGS.
* WRITES HEADERS TO THE REPORT FILE
MOVE W03-HEADER-ROW1 TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
MOVE FUNCTION CURRENT-DATE (1:8) TO W04-SYS-DATE
MOVE W04-YEAR TO W03-YEAR
MOVE W04-MONTH TO W03-MONTH
MOVE W04-DAY TO W03-DAY
MOVE W03-HEADER-ROW2 TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
MOVE W03-HEADER-ROW3 TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
.
A300-PROCESS-SUBJECTS.
* MOVES SUBJECT NAMES AND CODES INTO W02-TEST-TABLE
PERFORM A310-READ-RECORD
PERFORM UNTIL W01-SUBJ-EOF = 'Y'
IF W02-SUBJ-COUNT < W02-SUBJ-MAX
ADD 1 TO W02-SUBJ-COUNT
SET W02-IDX TO W02-SUBJ-COUNT
MOVE F01-SUBJ-CODE TO W02-SUBJ-CODE(W02-IDX)
MOVE F01-SUBJ-NAME TO W02-SUBJ-NAME(W02-IDX)
ELSE
DISPLAY "ERROR - SUBJECT FILE EXCEEDS MAX OF "
W02-SUBJ-MAX " RECORDS, RECORD IGNORED"
END-IF
PERFORM A310-READ-RECORD
END-PERFORM
.
A310-READ-RECORD.
* READS FROM THE SUBJECT FILE INTO THE SUBJECT RECORD
READ F01-SUBJ-FILE
AT END MOVE 'Y' TO W01-SUBJ-EOF
END-READ
.
A400-PROCESS-MARKS.
PERFORM A410-READ-RECORD
PERFORM A420-COUNT-MARKS
UNTIL W01-MARK-EOF = 'Y'
.
A410-READ-RECORD.
* READS FROM THE MARK FILE INTO THE MARK RECORD
READ F02-MARK-FILE
AT END MOVE 'Y' TO W01-MARK-EOF
END-READ
.
A420-COUNT-MARKS.
* COUNTS GRADE TOTALS
SET W02-IDX TO 1
SEARCH ALL W02-TEST-ROW
AT END DISPLAY 'INVALID INPUT RECORD: ' F02-MARK-RECORD
WHEN W02-SUBJ-CODE(W02-IDX) = F02-SUBJ-CODE
EVALUATE F02-STUD-MARK
WHEN "80" THRU "100"
ADD 1 TO W05-TOTAL-A
ADD 1 TO W02-A-CTR(W02-IDX)
WHEN "70" THRU "79"
ADD 1 TO W05-TOTAL-B
ADD 1 TO W02-B-CTR(W02-IDX)
WHEN "60" THRU "69"
ADD 1 TO W05-TOTAL-C
ADD 1 TO W02-C-CTR(W02-IDX)
WHEN "50" THRU "59"
ADD 1 TO W05-TOTAL-D
ADD 1 TO W02-D-CTR(W02-IDX)
WHEN OTHER
ADD 1 TO W05-TOTAL-F
ADD 1 TO W02-F-CTR(W02-IDX)
END-EVALUATE
END-SEARCH
.
A500-WRITE-TOTALS.
PERFORM A510-WRITE-SUBJ-GRADE-TOTALS
PERFORM A520-WRITE-GRADE-GRAND-TOTALS
.
A510-WRITE-SUBJ-GRADE-TOTALS.
PERFORM VARYING W02-IDX FROM 1 BY 1
UNTIL W02-IDX > W02-SUBJ-COUNT
MOVE W02-SUBJ-NAME(W02-IDX) TO W03-SUBJ-NAME
MOVE W02-A-CTR(W02-IDX) TO W03-A-CTR
MOVE W02-B-CTR(W02-IDX) TO W03-B-CTR
MOVE W02-C-CTR(W02-IDX) TO W03-C-CTR
MOVE W02-D-CTR(W02-IDX) TO W03-D-CTR
MOVE W02-F-CTR(W02-IDX) TO W03-F-CTR
MOVE W03-DETAIL-ROW TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
END-PERFORM
.
A520-WRITE-GRADE-GRAND-TOTALS.
* WRITES THE GRADE GRAND TOTALS TO THE REPORT FILE
* AFTER INSERTING A BLANK ROW
MOVE SPACES TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
MOVE W05-TOTAL-A TO W03-TOTAL-A
MOVE W05-TOTAL-B TO W03-TOTAL-B
MOVE W05-TOTAL-C TO W03-TOTAL-C
MOVE W05-TOTAL-D TO W03-TOTAL-D
MOVE W05-TOTAL-F TO W03-TOTAL-F
MOVE W03-TOTAL-ROW TO F03-REPT-RECORD
WRITE F03-REPT-RECORD
.
A600-CLOSE-FILES.
* CLOSES THE FILES
CLOSE F01-SUBJ-FILE
F02-MARK-FILE
F03-REPT-FILE
.
I'm glad you figured it out, Tom.
I hope you're not turned off and will explore further. FYI, while ISPF, TSO/E, and other classic user interfaces still work (and some people still like them, and they'll continue to work "forever"), nowadays developers often use and prefer graphical user interfaces. There are some free ones, for example IBM Explorer for z/OS and its Remote System Explorer (RSE):
https://developer.ibm.com/mainframe/products/zosexplorer/
That works just fine on its own on a Mac or PC (Linux or Windows), as you prefer (with the RSE part on z/OS). All free. Or, if you wish, you can add a more "COBOL aware" editor (among several other features) if you add the IBM Z Open Development plug-ins:
https://developer.ibm.com/mainframe/products/ibm-z-open-development/
And that works too, free for 90 days. At the end of the 90 days you can either pay the going price to keep those plug-ins or uninstall them and just use the base/free Explorer for z/OS functions.
Maybe this'd be good feedback to your instructor/professor? Yes, your first experience with any programming language can be (for example) via emacs and a terminal emulator. Yes, you can write Apple Swift code (for example) with emacs, ISPF, or vi. However, these classic user interfaces aren't everybody's favorite firsts. Again, if you like a particular UI, and it works for you, no problem! But from a pedagogical perspective it's probably best to start with something more familiar to the audience.
On edit: As another example, if you happen to prefer Microsoft Visual Studio Code, then you can add IBM Z Open Editor free of charge to that IDE.
I figured out what was wrong with my program by placing a DISPLAY at the start of each function which output what function was running. I saw that it was in an infinite loop in A420-COUNT-MARKS and that I forgot to add a PERFORM A410-READ-RECORD at the end of it.
OK so I'm doing assignment but then I found that I was asked to add page numbers and change pages for each 4 records. Since it's an online course and I don't think there is anything about page numbers in lecture videos. So the main problems are
To add a heading that contains date and page number,
Print 4 records per page, which means page needs to be changed after printing 4 records.
I really have no idea how to do this.
Here is the code I have finished:
ENVIRONMENT DIVISION.
FILE-CONTROL. SELECT STOCK-IN ASSIGN TO 'F:/CS201S13/PROJECT2.TXT'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT STOCK-OUT ASSIGN TO 'F:/CS201S13/PROJECT2OUTPUT.TXT'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD STOCK-IN.
01 STOCK-RECORD.
05 ST-TRANSACTION-INFORMATION.
10 ST-TRANSACTION-SHARES PIC 9(3).
10 ST-TRANSACTION-STOCK PIC X(14).
05 ST-PURCHASE-INFORMATION.
10 ST-PURCHASE-PRICE PIC 9(5)V99.
10 ST-PURCHASE-DATE.
15 ST-PURCHASE-YEAR PIC 99.
15 ST-PURCHASE-MONTH PIC 99.
15 ST-PURCHASE-DAY PIC 99.
05 ST-SALE-INFORMATION.
10 ST-SALE-PRICE PIC 9(5)V99.
10 ST-SALE-DATE.
15 ST-SALE-YEAR PIC 99.
15 ST-SALE-MONTH PIC 99.
15 ST-SALE-DAY PIC 99.
FD STOCK-OUT.
01 STOCK-RECORD-OUT.
05 ST-TRANSACTION-INFORMATION-OUT.
10 ST-TRANSACTION-SHARES-OUT PIC 9(3).
10 ST-TRANSACTION-STOCK-OUT PIC X(14).
05 TOTAL-PURCHASE PIC 9(8)V99.
05 PIC X(4).
05 TOTAL-SALE PIC 9(8)V99.
05 PIC X(4).
05 TOTAL-PROFIT PIC 9(8)V99.
05 PIC X(4).
05 ST-PURCHASE-DATE-OUT.
10 ST-PURCHASE-YEAR-OUT PIC 99.
10 PIC X VALUE '/'.
10 ST-PURCHASE-MONTH-OUT PIC 99.
10 PIC X VALUE '/'.
10 ST-PURCHASE-DAY-OUT PIC 99.
05 PIC X(4).
05 ST-SALE-DATE-OUT.
10 ST-SALE-YEAR-OUT PIC 99.
10 PIC X VALUE '/'.
10 ST-SALE-MONTH-OUT PIC 99.
10 PIC X VALUE '/'.
10 ST-SALE-DAY-OUT PIC 99.
05 PIC X(4).
05 RECORD-OUT PIC 9 VALUE 0.
05 PAGE-OUT PIC 9.
WORKING-STORAGE SECTION.
01 ARE-THERE-MORE-RECORDS PIC XXX VALUE 'YES'.
01 IS-THIS-PAGE-FULL PIC XXX VALUE 'NO '.
PROCEDURE DIVISION.
100-MAIN-PROCESS.
OPEN INPUT STOCK-IN
OUTPUT STOCK-OUT
MOVE ST-TRANSACTION-INFORMATION TO ST-TRANSACTION-INFORMATION-OUT
PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ STOCK-IN
AT END
MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 200-PROCEDURE-RTN
ADD 1 TO RECORD-OUT
END-READ
END-PERFORM
CLOSE STOCK-IN
STOCK-OUT
STOP RUN.
200-PROCEDURE-RTN.
IF RECORD-OUT = 4
MOVE 'YES' TO IS-THIS-PAGE-FULL
MOVE 0 TO RECORD-OUT
MOVE 'NO ' TO IS-THIS-PAGE-FULL
ADD 1 TO PAGE-OUT
END-IF
MULTIPLY ST-PURCHASE-PRICE BY ST-TRANSACTION-SHARES GIVING TOTAL-PURCHASE
MULTIPLY ST-SALE-PRICE BY ST-TRANSACTION-SHARES GIVING TOTAL-SALE
SUBTRACT TOTAL-PURCHASE FROM TOTAL-SALE GIVING TOTAL-PROFIT
WRITE STOCK-RECORD-OUT.
You are both close, and far away.
"Close" because you need a little bit of code in between setting IS-THIS-PAGE-FULL to YES and NO.
"Far away" as you have quite a lot to do rather than just "patch up" what you have.
Is the program writing an output file (STOCK-OUT) and a report, or is STOCK-OUT the report? If it is a report, change the names so that it is clear that it is a report, not an output file.
Don't worry if this seems a lot. You should be learning how to Program in Cobol, as well as learning Cobol. Doesn't happen overnight.
In no particular order:
Include FILE-STATUS checking for all IO operations on all files, always. At the moment, if your input fails to open and the system does not fail the program (even if yours does, you are presumably learning Cobol to be able to work with any system, not just the one you have) then no records will be read, your "end of file test" will never be YES and you'll have a BFL (Big Fat Loop). With the FILE-STATUS checking, produce useful messages, including key/reference/record number as appropriate for failed READ or WRITE.
You may feel that this is a lot of work. However, put together some "template" files with all the stuff in, and then paste (or even COPY) those into your program each time.
You have VALUE clause in the FD. These will not do what you think.
You have single digit for your page count, which is unlikely to have general application.
Why use YES and NO as literals? Look at the SET verb, in relation to "condition names", use 88's for tests and "flags/switches".
You have "MOVE ST-TRANSACTION-INFORMATION" after the input is opened but before a record is read, and only have one reference to it in the program. This is not going to work.
For reading files, have a look at the "priming read" approach.
read input
loop until end-of-file (88 on file-status)
process data
read input
end-loop
This avoids the AT END/NOT AT END, allows processing of headers (if present) and "empty files" without clogging-up the main logic. The code "expands" with headers/trailers (including the correct number of them), sequence-checking of keys, etc, but you only need to code it once then "template" it.
According to your VALUE clauses in your FD, you expect RECORD-OUT to be zero, so the test for 4 will actually get you five on the first page, and four thereafter.
You always assume there will be a "profit" (a positive amount), which is not realistic, yet you don't allow a signed value for the "profit".
Now, for the report.
For your report FD, just make it a simple thing, length of your print line.
In WORKING-STORAGE, define data for the headings and titles that you need. Define data for a print line. Since you're in the WORKING-STORAGE, put VALUEs for everything which will not have data MOVEd to it in the PROCEDURE DIVISION.
When you have written four items (or when your program tells you this) and you have a fifth, write the headings and titles, remembering to update the page number.
I say "or when your program tells you this" because you can set your original value of "records written" to 4. Comment it, so that it is clear that it is what you want, and why you want it. The reason is, you don't have to then deal with "first time" headings and othe things. For first time, or on a "contol break" (I guess you'll get to those soon) set the " done on a page already" to the maximum for a page, and the headings will pop out when you want.
Format the print line. PERFORM a para to print it (which is where the "page full" test will be).
Note: You can use VALUEs for your "/"s in the dates, or you can use the "/" editing character in the PICture, like this:
05 an-input-date PIC X(8) (can be other definitions).
...
05 date-to-print PIC X(4)/XX/XX.
...
MOVE an-input-date TO date-to-print
I like to see that you are using "minimal full-stops/periods". You can go a little further.
MOVE an-input-date TO date-to-print
.
Then you get your final full-stop/period in a paragraph, without having it "attached" to any particular line of code, which makes "tossing code around" easier, as you don't have to think "do I need/not need that full-stop/period there".
You could also look through some of the Cobol questions here, and get a handle on some general tips and advice.
This may or may not help, if LINAGE is not supported you'll have to do some explicit counting.
*****************************************************************
* Example of LINAGE File Descriptor
* Author: Brian Tiffin
* Date: 10-July-2008
* Tectonics: $ cobc -x linage.cob
* $ ./linage <filename ["linage.cob"]>
* $ cat -n mini-report
*****************************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. linage-demo.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
select optional data-file assign to file-name
organization is line sequential
file status is data-file-status.
select mini-report assign to "mini-report".
DATA DIVISION.
FILE SECTION.
FD data-file.
01 data-record.
88 endofdata value high-values.
02 data-line pic x(80).
FD mini-report
linage is 16 lines
with footing at 15
lines at top 2
lines at bottom 2.
01 report-line pic x(80).
WORKING-STORAGE SECTION.
01 command-arguments pic x(1024).
01 file-name pic x(160).
01 data-file-status pic 99.
01 lc pic 99.
01 report-line-blank.
02 filler pic x(18) value all "*".
02 filler pic x(05) value spaces.
02 filler pic x(34)
VALUE "THIS PAGE INTENTIONALLY LEFT BLANK".
02 filler pic x(05) value spaces.
02 filler pic x(18) value all "*".
01 report-line-data.
02 body-tag pic 9(6).
02 line-3 pic x(74).
01 report-line-header.
02 filler pic x(6) VALUE "PAGE: ".
02 page-no pic 9999.
02 filler pic x(24).
02 filler pic x(5) VALUE " LC: ".
02 header-tag pic 9(6).
02 filler pic x(23).
02 filler pic x(6) VALUE "DATE: ".
02 page-date pic x(6).
01 page-count pic 9999.
PROCEDURE DIVISION.
accept command-arguments from command-line end-accept.
string
command-arguments delimited by space
into file-name
end-string.
if file-name equal spaces
move "linage.cob" to file-name
end-if.
open input data-file.
read data-file
at end
display
"File: " function trim(file-name)
" open error or empty"
end-display
go to early-exit
end-read.
open output mini-report.
write report-line
from report-line-blank
end-write.
move 1 to page-count.
accept page-date from date end-accept.
move page-count to page-no.
write report-line
from report-line-header
after advancing page
end-write.
perform readwrite-loop until endofdata.
display
"Normal termination, file name: "
function trim(file-name)
" ending status: "
data-file-status
end-display.
close mini-report.
* Goto considered harmful? Bah! :)
early-exit.
close data-file.
exit program.
stop run.
****************************************************************
readwrite-loop.
move data-record to report-line-data
move linage-counter to body-tag
write report-line from report-line-data
end-of-page
add 1 to page-count end-add
move page-count to page-no
move linage-counter to header-tag
write report-line from report-line-header
after advancing page
end-write
end-write
read data-file
at end set endofdata to true
end-read
.
*****************************************************************
* Commentary
* LINAGE is set at a 20 line logical page
* 16 body lines
* 2 top lines
* A footer line at 15 (inside the body count)
* 2 bottom lines
* Build with:
* $ cobc -x -Wall -Wtruncate linage.cob
* Evaluate with:
* $ ./linage
* This will read in linage.cob and produce a useless mini-report
* $ cat -n mini-report
*****************************************************************
END PROGRAM linage-demo.
I am trying to finish a program that I have started but am confused as to what I need to do and how to do the last step. The instructions are to:
At the end of report:
A. Print the number of personnel records processed.
B. The number of records where there was an unsuccessful search of the Dept Table.
C. The number of records where there was an unsuccessful search of the Title Table.
I have completed all of the program except this last step. Can someone please help me finish this program?
enter code here ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT PERSONNEL-FILE
ASSIGN TO 'CH12PPPF.DAT'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT DEPT-TABLE-FILE
ASSIGN TO 'CH12PPDT.DAT'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT TITLE-TABLE-FILE
ASSIGN TO 'CH12PPTT.DAT'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT PRINT-FILE
ASSIGN TO 'THORNTONCA4.RPT'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD PERSONNEL-FILE.
01 PERSONNEL-REC.
05 SSNO-IN PIC 9(9).
05 NAME-IN PIC X(20).
05 SALARY-IN PIC 9(6).
05 CAMPUS-CODE-IN PIC 9.
05 DEPT-CODE-IN PIC 99.
05 TITLE-CODE-IN PIC 999.
FD DEPT-TABLE-FILE.
01 DEPT-REC.
05 T-DEPT-NO PIC 99.
05 T-DEPT-NAME PIC X(10).
FD TITLE-TABLE-FILE.
01 TITLE-REC.
05 T-TITLE-CODE PIC 999.
05 T-TITLE-NAME PIC X(10).
FD PRINT-FILE.
01 PRINT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 STORED-AREAS.
05 MORE-RECS PIC X(3) VALUE 'YES'.
05 WS-DATE.
10 WS-YEAR PIC 9999.
10 WS-MONTH PIC 99.
10 WS-DAY PIC 99.
05 WS-PAGE-CT PIC 99
VALUE ZERO.
05 WS-LINE-CT PIC 99
VALUE ZERO.
01 HDR1-OUT.
05 PIC X(25)
VALUE SPACES.
05 PIC X(20)
VALUE 'FINAL REPORT'.
05 DATE-OUT.
10 MONTH-OUT PIC 99.
10 PIC X
VALUE '/'.
10 DAY-OUT PIC 99.
10 PIC X
VALUE '/'.
10 YEAR-OUT PIC 9999.
05 PIC X(2)
VALUE SPACES.
05 PIC X(5)
VALUE 'PAGE'.
05 PAGE-OUT PIC Z9.
*****************************************************************
* The Campus Table consists of 5 10-position names and will be *
* accessed as a direct-referenced table. EACH_CAMPUS *
* subscriped by the CAMPUS_CODE_IN will provide the name. *
*****************************************************************
01 CAMPUTS-TABLE
VALUE 'UPSTATE DOWNSTATE CITY MELVILLE HUNTINGTON'.
05 EACH-CAMPUS
OCCURS 5 TIMES PIC X(10).
*****************************************************************
* The Dept Table will be accessed by a SEARCH. Even if the *
* table is entered in Dept No sequence, there would be no *
* real benefit to using a SEARCH ALL since there are only *
* 25 entries. *
*****************************************************************
01 DEPT-TABLE.
05 DEPT-ENTRIES OCCURS 25 TIMES INDEXED BY X1.
10 DEPT-NO PIC 99.
10 DEPT-NAME PIC X(10).
*****************************************************************
* The Title Talbe will be accessed by a SEARCH ALL. To use a *
* binary seach the entries must be in sequence by a key *
* field and the table should be relatively large. *
*****************************************************************
01 TITLE-TABLE.
05 TITLE-ENTRIES OCCURS 50 TIMES
ASCENDING KEY IS TITLE-NO INDEXED BY X2.
10 TITLE-NO PIC 999.
10 TITLE-NAME PIC X(10).
01 DETAIL-REC.
05 PIC X(1) VALUE SPACES.
05 SSNO-OUT PIC 999B99B9999.
05 PIC X(1) VALUE SPACES.
05 NAME-OUT PIC X(20).
05 PIC X(1) VALUE SPACES.
05 SALARY-OUT PIC $ZZZ,ZZZ.
05 PIC X(1) VALUE SPACES.
05 CAMPUS-OUT PIC X(10).
05 PIC X(1) VALUE SPACES.
05 DEPT-OUT PIC X(10).
05 PIC X(1) VALUE SPACES.
05 TITLE-OUT PIC X(10).
PROCEDURE DIVISION.
100-MAIN-MODULE.
OPEN INPUT PERSONNEL-FILE
DEPT-TABLE-FILE
TITLE-TABLE-FILE
OUTPUT PRINT-FILE
MOVE FUNCTION CURRENT-DATE TO WS-DATE
MOVE WS-MONTH TO MONTH-OUT
MOVE WS-DAY TO DAY-OUT
MOVE WS-YEAR TO YEAR-OUT
PERFORM 500-HDG-RTN.
PERFORM 200-LOAD-DEPT-TABLE
PERFORM 300-LOAD-TITLE-TABLE
PERFORM UNTIL MORE-RECS = 'NO '
READ PERSONNEL-FILE
AT END
MOVE 'NO ' TO MORE-RECS
NOT AT END
PERFORM 400-CALC-RTN
END-READ
END-PERFORM
CLOSE PERSONNEL-FILE
DEPT-TABLE-FILE
TITLE-TABLE-FILE
PRINT-FILE
STOP RUN.
200-LOAD-DEPT-TABLE.
PERFORM VARYING X1 FROM 1 BY 1
UNTIL X1 > 25
READ DEPT-TABLE-FILE
AT END DISPLAY 'NOT ENOUGH DEPT TABLE RECORDS'
STOP RUN
END-READ
MOVE DEPT-REC TO DEPT-ENTRIES (X1)
END-PERFORM.
300-LOAD-TITLE-TABLE.
PERFORM VARYING X2 FROM 1 BY 1
UNTIL X2 > 50
READ TITLE-TABLE-FILE
AT END DISPLAY 'NOT ENOUH TITLE TABLE RECORDS'
STOP RUN
END-READ
MOVE TITLE-REC TO TITLE-ENTRIES (X2)
IF X2 > 1 THEN
IF TITLE-NO (X2) <= TITLE-NO (X2 - 1)
DISPLAY 'TITLE RECORDS ARE NOT IN SEQUENCE'
STOP RUN
END-IF
END-IF
END-PERFORM.
400-CALC-RTN.
MOVE SPACES TO DETAIL-REC
MOVE SSNO-IN TO SSNO-OUT
MOVE NAME-IN TO NAME-OUT
MOVE SALARY-IN TO SALARY-OUT
IF CAMPUS-CODE-IN >= 1 AND <= 5
MOVE EACH-CAMPUS (CAMPUS-CODE-IN) TO CAMPUS-OUT
END-IF
SET X1 TO 1
SEARCH DEPT-ENTRIES
AT END MOVE 'XXXXXXXXXX' TO DEPT-OUT
WHEN DEPT-CODE-IN = DEPT-NO (X1)
MOVE DEPT-NAME (X1) TO DEPT-OUT
END-SEARCH
SEARCH ALL TITLE-ENTRIES
AT END MOVE 'XXXXXXXXXX' TO TITLE-OUT
WHEN TITLE-NO (X2) = TITLE-CODE-IN
MOVE TITLE-NAME (X2) TO TITLE-OUT
END-SEARCH
WRITE PRINT-REC FROM DETAIL-REC
AFTER ADVANCING 2 LINES.
500-HDG-RTN.
ADD 1 TO WS-PAGE-CT
MOVE WS-PAGE-CT TO PAGE-OUT
WRITE PRINT-REC FROM HDR1-OUT
AFTER ADVANCING PAGE
MOVE ZEROS TO WS-LINE-CT.
You need to:
Produce code to accumulate all the values you need to print at the end
Produce definition(s) of the final part of the report
Produce the final part of report once the main input file has been processed, ie after your first PERFORM and before the CLOSE
You should get into the habit of checking all file statuses after each IO operation, using FILE-STATUS, and accurately report when something unexpected happens.
You'll find it worthwhile to give good names even to indexes, and use 88s wherever possible for IF or EVALUATE and avoid using things like this "IF CAMPUS-CODE-IN >= 1 AND <= 5".
How I can read a .dat file with struct like that: ( A = ALPHANUMERIC && N = NUMERIC )
0AAAAAAAANNNN (233 BLANK SPACES ) 999999 ( SEQUENTIAL NUMBER ONE BY ONE )
1NNNNNNNNNNNNAAAAAAAAAAAAAAAAAAA (194 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA (194 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
1NNNNNNNNNNNNAAAAAAAAAAAAAAAAAAA (194 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA (194 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
1NNNNNNNNNNNNAAAAAAAAAAAAAAAAAAA (194 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA (194 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
1NNNNNNNNNNNNAAAAAAAAAAAAAAAAAAA (194 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA (194 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
9 (245 BLANK SPACES) 999999 (SEQUENTIAL NUMBER ONE BY ONE)
So, I know, how I can make a program to read this in C/C++ or in C#, but, I try to make in Cobol, just for study....
But, I don't know what the command I need to use to open the file with this style ( I just know the:
ORGANIZATION IS LINE SEQUENTIAL.
I think, exist a another command to open with custon instructions... i don't know...
So, btw, how I can open the file and read the informations ??
( i just need to read the line 1 on time, and, I need to read the line 2 and 3 always paried ... 4 and 5 && 6 and 7 && 8 and 9 ... )
and, I whant to show that information with DISPLAY ( just for study )
Thanks :)
Something like this below your FD:
01 INPUT-RECORD.
05 IR-RECORD-TYPE PIC X.
88 INPUT-RECORD-IS-HEADER VALUE '0'.
88 INPUT-RECORD-IS-DATA1 VALUE '1'.
88 INPUT-RECORD-IS-DATA2 VALUE '2'.
88 INPUT-RECORD-IS-TRAILER VALUE '9'.
05 FILLER PIC X(whatever).
You may need a "trailing" byte for a record-delimiter, I don't know, and you'll have to sort out the lengths, as they seem to vary.
These in Working-Storage:
01 INPUT-RECORD-HEADER.
05 IRH-RECORD-TYPE PIC X.
05 IRH-ITEM1 PIC X(8).
05 IRH-ITEM2 PIC 9(4).
05 FILLER PIC X(233).
05 IRH-SEQUENCE PIC X(6)
01 INPUT-RECORD-DATA1.
05 IRD1-RECORD-TYPE PIC X.
05 IRD1-ITEM1 PIC 9(14).
05 IRD1-ITEM1 PIC X(19).
05 FILLER PIC X(194).
05 IRD1-SEQUENCE PIC X(6)
01 INPUT-RECORD-DATA2.
05 IRD2-RECORD-TYPE PIC X.
05 IRD2-ITEM1 PIC X(33).
05 FILLER PIC X(194).
05 IRD2-SEQUENCE PIC X(6)
01 INPUT-RECORD-TRAILER.
05 IRT-RECORD-TYPE PIC X.
05 FILLER PIC X(245).
05 IRT-SEQUENCE PIC X(6).
You have to read each record, one at a time. Identify it. Put it in the correct W-S definition. When you read a "2" you can process the "1" you have stored along with the "2".
My datanames aren't very good, as I don't know what your data is. Also I have not "formatted" the definitions, which will make them more readable when you do it.
For OpenCOBOL, here is a sample standard in/standard out filter program:
>>SOURCE FORMAT IS FIXED
*> ***************************************************************
*><* ===========
*><* filter
*><* ===========
*><* :Author: Brian Tiffin
*><* :Date: 20090207
*><* :Purpose: Standard IO filters
*><* :Tectonics: cobc -x filter.cob
*> ***************************************************************
identification division.
program-id. filter.
environment division.
configuration section.
input-output section.
file-control.
select standard-input assign to keyboard.
select standard-output assign to display.
data division.
file section.
fd standard-input.
01 stdin-record pic x(32768).
fd standard-output.
01 stdout-record pic x(32768).
working-storage section.
01 file-status pic x value space.
88 end-of-file value high-value
when set to false is low-value.
*> ***************************************************************
procedure division.
main section.
00-main.
perform 01-open
perform 01-read
perform
until end-of-file
perform 01-transform
perform 01-write
perform 01-read
end-perform
.
00-leave.
perform 01-close
.
goback.
*> end main
support section.
01-open.
open input standard-input
open output standard-output
.
01-read.
read standard-input
at end set end-of-file to true
end-read
.
*> All changes here
01-transform.
move stdin-record to stdout-record
.
*>
01-write.
write stdout-record end-write
.
01-close.
close standard-input
close standard-output
.
end program filter.
*><*
*><* Last Update: dd-Mmm-yyyy
and here is a demonstration of using LINAGE that just happens to read in a text file.
*****************************************************************
* Example of LINAGE File Descriptor
* Author: Brian Tiffin
* Date: 10-July-2008
* Tectonics: $ cocb -x linage-demo.cob
* $ ./linage-demo <filename ["linage-demo.cob"]>
* $ cat -n mini-report
*****************************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. linage-demo.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
select optional data-file assign to file-name
organization is line sequential
file status is data-file-status.
select mini-report assign to "mini-report".
DATA DIVISION.
FILE SECTION.
FD data-file.
01 data-record.
88 endofdata value high-values.
02 data-line pic x(80).
FD mini-report
linage is 16 lines
with footing at 15
lines at top 2
lines at bottom 2.
01 report-line pic x(80).
WORKING-STORAGE SECTION.
01 command-arguments pic x(1024).
01 file-name pic x(160).
01 data-file-status pic 99.
01 lc pic 99.
01 report-line-blank.
02 filler pic x(18) value all "*".
02 filler pic x(05) value spaces.
02 filler pic x(34)
VALUE "THIS PAGE INTENTIONALLY LEFT BLANK".
02 filler pic x(05) value spaces.
02 filler pic x(18) value all "*".
01 report-line-data.
02 body-tag pic 9(6).
02 line-3 pic x(74).
01 report-line-header.
02 filler pic x(6) VALUE "PAGE: ".
02 page-no pic 9999.
02 filler pic x(24).
02 filler pic x(5) VALUE " LC: ".
02 header-tag pic 9(6).
02 filler pic x(23).
02 filler pic x(6) VALUE "DATE: ".
02 page-date pic x(6).
01 page-count pic 9999.
PROCEDURE DIVISION.
accept command-arguments from command-line end-accept.
string
command-arguments delimited by space
into file-name
end-string.
if file-name equal spaces
move "linage-demo.cob" to file-name
end-if.
open input data-file.
read data-file
at end
display
"File: " function trim(file-name) " open error"
end-display
go to early-exit
end-read.
open output mini-report.
write report-line
from report-line-blank
end-write.
move 1 to page-count.
accept page-date from date end-accept.
move page-count to page-no.
write report-line
from report-line-header
after advancing page
end-write.
perform readwrite-loop until endofdata.
display
"Normal termination, file name: "
function trim(file-name)
" ending status: "
data-file-status
end-display.
close mini-report.
* Goto considered harmful? Bah! :)
early-exit.
close data-file.
exit program.
stop run.
****************************************************************
readwrite-loop.
move data-record to report-line-data
move linage-counter to body-tag
write report-line from report-line-data
end-of-page
add 1 to page-count end-add
move page-count to page-no
move linage-counter to header-tag
write report-line from report-line-header
after advancing page
end-write
end-write
read data-file
at end set endofdata to true
end-read
.
*****************************************************************
* Commentary
* LINAGE is set at a 20 line logical page
* 16 body lines
* 2 top lines
* A footer line at 15 (inside the body count)
* 2 bottom lines
* Build with:
* $ cobc -x -Wall -Wtruncate linage-demo.cob
* Evaluate with:
* $ ./linage-demo
* This will read in linage-demo.cob and produce mini-report
* $ cat -n mini-report
*****************************************************************
END PROGRAM linage-demo.
With those samples, along with Gilbert's answer, you should have enough to tackle your problem, with the caveat that these examples are shy on proper error handling, so be careful is this is homework or a paid assignment. For an example of standard input/output or by filename depending on command line arguments (or lack thereof), see the ocdoc.cob program in the OpenCOBOL FAQ.
Offtopic: Output of an ocdoc pass over ocdoc.cob itself can be seen at http://opencobol.add1tocobol.com/ocdoc.html (Why mention it? The COBOL lexicon highlighter for Pygments has just been accepted into main. Any Pygments pulled after version 1.6 will allow for COBOL (context free) lexical highlighting.)
You write an ordinary Cobol program that reads a file.
The first byte (character) of the record is either 0, 1, 2, or 9.
Define a Working-Storage area (01 level) for each of the 4 record types. Then, after you read the record, you move it from the input area to the appropriate Working-Storage area for the record.
Then you process the record how you wish from one of the 4 Working-Storage areas.
Hey all, got one mountain of a problem here. I have completed a program I had to do for college homework, but when I run it the output shows almost nothing it is suppose to. This only happens when I RUN it though. If I hold F11 to STEP through the whole thing it shows the results as it is suppose to be. Normally I would not ask about something this big but I am stumped. Here is my code:
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT SALESAMT-FILE-IN
ASSIGN TO 'SALESAMT.SEQ'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT SALESMAN-FILE-IN
ASSIGN TO 'SALESMAN.SEQ'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT SALESQTR-FILE-IN
ASSIGN TO 'SALESQTR.SEQ'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT SALESAMT-FILE-OUT
ASSIGN TO 'SALESAMT.RPT'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD SALESMAN-FILE-IN.
01 SALESMAN-RECORD-IN.
05 SM-NUMBER-IN PIC 99.
05 SM-NAME-IN PIC X(20).
FD SALESQTR-FILE-IN.
01 SALESQTR-RECORD-IN.
05 QUARTER-YEAR PIC X.
FD SALESAMT-FILE-IN.
01 SALESAMT-RECORD-IN.
05 SM-NUMBER PIC 99.
05 PIC X.
05 MONTH-NUMBER PIC 9.
05 PIC X.
05 SALES-AMOUNT PIC 9(5).
FD SALESAMT-FILE-OUT.
01 SALESAMT-RECORD-OUT PIC X(80).
WORKING-STORAGE SECTION.
01 ARE-THERE-MORE-RECORDS PIC X(3) VALUE 'YES'.
01 REPORT-START PIC X VALUE 'Y'.
01 LINE-COUNT PIC 99 VALUE ZEROS.
01 LINE-JUMP PIC X VALUE 'Y'.
01 PAGE-NUMBER PIC 99 VALUE ZEROS.
01 QUARTER-CHECK PIC X.
01 ROUTINE-CHECK PIC 99 VALUE ZEROS.
01 SALESMAN-MATH PIC 9(5) VALUE ZEROS.
01 SALESMAN-TOTAL PIC 9(6) VALUE ZEROS.
01 FINAL-M-TOTAL-1 PIC 9(7) VALUE ZEROS.
01 FINAL-M-TOTAL-3 PIC 9(7) VALUE ZEROS.
01 FINAL-M-TOTAL-2 PIC 9(7) VALUE ZEROS.
01 FINAL-TOTAL PIC 9(7) VALUE ZEROS.
01 SM-NUM-M PIC 99 VALUE ZEROS.
01 MORE-TABLE-RECS PIC X VALUE 'Y'.
01 SPACE-LINE PIC X VALUE SPACE.
01 MONTH-NAMES
VALUE 'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.
05 MONTH-TITLES OCCURS 12 TIMES PIC X(3).
01 MONTH-ARRAY.
05 THREE-MONTHS OCCURS 3 TIMES.
10 MONTH-TOTAL OCCURS 99 TIMES PIC 9(7) VALUE ZEROS.
01 SALESMAN-TABLE.
05 TABLE-ENTRIES OCCURS 99 TIMES
INDEXED BY IND-TABLE-ENTRIES.
10 SALESMAN-NUMBER PIC 99 VALUE ZEROS.
10 SALESMAN-NAME PIC X(20) VALUE SPACES.
01 SALESMAN-COUNT PIC 9(3) VALUE ZEROS.
01 WS-DATE.
05 RUN-YEAR PIC XX.
05 RUN-MONTH PIC XX.
05 RUN-DAY PIC XX.
01 HEADING-LINE-1.
05 PIC X(17) VALUE SPACES.
05 PIC X(35)
VALUE 'SALES AMOUNTS BY SALESMAN AND MONTH'.
05 PIC X(10) VALUE SPACES.
05 HL-1-DATE.
10 MONTH-2 PIC XX.
10 PIC X VALUE '/'.
10 DAY-2 PIC XX.
10 PIC X VALUE '/'.
10 YEAR-2 PIC XX.
05 PIC X(3) VALUE SPACES.
05 PAGE-1 PIC X(4) VALUE 'PAGE'.
05 PIC X(1) VALUE SPACES.
05 NUMBER-PAGE PIC Z9.
01 HEADING-LINE-2.
05 HL-NUM PIC X(3) VALUE 'NUM'.
05 HL-BLANK-A PIC XX VALUE SPACES.
05 HL-NAME PIC X(4) VALUE 'NAME'.
05 HL-BLANK-B PIC X(20) VALUE SPACES.
05 HL-MONTH-1 PIC X(3) VALUE SPACES.
05 HL-BLANK-C PIC X(8) VALUE SPACES.
05 HL-MONTH-2 PIC X(3) VALUE SPACES.
05 HL-BLANK-D PIC X(8) VALUE SPACES.
05 HL-MONTH-3 PIC X(3) VALUE SPACES.
05 HL-BLANK-E PIC X(10) VALUE SPACES.
05 HL-TOTAL PIC X(5) VALUE 'TOTAL'.
01 DETAIL-LINE.
05 DL-BLANK-A PIC X VALUE SPACES.
05 DL-NUM-COLUMN PIC 99.
05 DL-BLANK-B PIC XX VALUE SPACES.
05 DL-NAME-COLUMN PIC X(17).
05 DL-BLANK-C PIC X(4) VALUE SPACES.
05 DL-MONTH-1 PIC ZZ,Z(3).
05 DL-BLANK-D PIC X(5) VALUE SPACES.
05 DL-MONTH-2 PIC ZZ,Z(3).
05 DL-BLANK-E PIC X(5) VALUE SPACES.
05 DL-MONTH-3 PIC ZZ,Z(3).
05 DL-BLANK-F PIC X(8) VALUE SPACES.
05 DL-TOTAL PIC Z(3),Z(3).
01 TOTALS-LINE.
05 TL-WORDS PIC X(12)
VALUE 'Final Totals'.
05 TL-BLANK-A PIC X(12) VALUE SPACES.
05 MONTH-1-TOTAL PIC Z,Z(3),Z(3).
05 TL-BLANK-A PIC X(2) VALUE SPACES.
05 MONTH-2-TOTAL PIC Z,Z(3),Z(3).
05 TL-BLANK-A PIC X(2) VALUE SPACES.
05 MONTH-3-TOTAL PIC Z,Z(3),Z(3).
05 TL-BLANK-A PIC X(5) VALUE SPACES.
05 MONTH-FINAL-TOTAL PIC Z,Z(3),Z(3).
PROCEDURE DIVISION.
100-MAIN.
OPEN INPUT SALESAMT-FILE-IN, SALESMAN-FILE-IN,
SALESQTR-FILE-IN
OPEN OUTPUT SALESAMT-FILE-OUT
ACCEPT WS-DATE FROM DATE
MOVE RUN-MONTH TO MONTH-2
MOVE RUN-DAY TO DAY-2
MOVE RUN-YEAR TO YEAR-2
PERFORM 200-NEXT-PAGE
PERFORM 300-SALES-ARRAY
PERFORM 400-SALESMAN-NAME
PERFORM 500-PROCESS-FILE
PERFORM 600-FINAL-TOTALS
CLOSE SALESAMT-FILE-IN, SALESMAN-FILE-IN, SALESQTR-FILE-IN
CLOSE SALESAMT-FILE-OUT
STOP RUN.
200-NEXT-PAGE.
ADD 1 TO PAGE-NUMBER
MOVE PAGE-NUMBER TO NUMBER-PAGE
MOVE HEADING-LINE-1 TO SALESAMT-RECORD-OUT
IF REPORT-START = 'N'
WRITE SALESAMT-RECORD-OUT
AFTER ADVANCING PAGE
ELSE
MOVE 'N' TO REPORT-START
WRITE SALESAMT-RECORD-OUT
AFTER ADVANCING 1 LINE
PERFORM 210-MONTH-CHECK
END-IF.
MOVE HEADING-LINE-2 TO SALESAMT-RECORD-OUT
WRITE SALESAMT-RECORD-OUT
AFTER ADVANCING 2 LINES
MOVE ZEROS TO LINE-COUNT.
210-MONTH-CHECK.
READ SALESQTR-FILE-IN
AT END
CONTINUE
NOT AT END
PERFORM 220-MONTH-NAME
END-READ.
220-MONTH-NAME.
EVALUATE QUARTER-YEAR
WHEN = 1 MOVE MONTH-TITLES(1) TO HL-MONTH-1
MOVE MONTH-TITLES(2) TO HL-MONTH-2
MOVE MONTH-TITLES(3) TO HL-MONTH-3
WHEN = 2 MOVE MONTH-TITLES(4) TO HL-MONTH-1
MOVE MONTH-TITLES(5) TO HL-MONTH-2
MOVE MONTH-TITLES(6) TO HL-MONTH-3
WHEN = 3 MOVE MONTH-TITLES(7) TO HL-MONTH-1
MOVE MONTH-TITLES(8) TO HL-MONTH-2
MOVE MONTH-TITLES(9) TO HL-MONTH-3
WHEN = 4 MOVE MONTH-TITLES(10) TO HL-MONTH-1
MOVE MONTH-TITLES(11) TO HL-MONTH-2
MOVE MONTH-TITLES(12) TO HL-MONTH-3
END-EVALUATE.
300-SALES-ARRAY.
PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ SALESAMT-FILE-IN
AT END
MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 310-STORE-DATA
END-READ
END-PERFORM.
310-STORE-DATA.
MOVE SM-NUMBER TO SM-NUM-M
EVALUATE MONTH-NUMBER
WHEN 1 PERFORM 320-FIRST-MONTH
WHEN 2 PERFORM 330-SECOND-MONTH
WHEN 3 PERFORM 340-THIRD-MONTH
END-EVALUATE.
320-FIRST-MONTH.
ADD SALES-AMOUNT TO
MONTH-TOTAL OF MONTH-ARRAY (1, SM-NUM-M).
330-SECOND-MONTH.
ADD SALES-AMOUNT TO
MONTH-TOTAL OF MONTH-ARRAY (2, SM-NUM-M).
340-THIRD-MONTH.
ADD SALES-AMOUNT TO
MONTH-TOTAL OF MONTH-ARRAY (3, SM-NUM-M).
400-SALESMAN-NAME.
PERFORM UNTIL MORE-TABLE-RECS = 'N'
READ SALESMAN-FILE-IN
AT END
MOVE 'N' TO MORE-TABLE-RECS
NOT AT END
PERFORM 450-TABLE-LOAD
END-READ
END-PERFORM.
450-TABLE-LOAD.
MOVE SM-NUMBER-IN TO SALESMAN-COUNT
MOVE SM-NUMBER-IN TO SALESMAN-NUMBER (SALESMAN-COUNT)
MOVE SM-NAME-IN TO SALESMAN-NAME (SALESMAN-COUNT).
500-PROCESS-FILE.
PERFORM UNTIL ROUTINE-CHECK = 99
ADD 1 TO ROUTINE-CHECK
PERFORM 510-TABLE-SEARCH
END-PERFORM.
510-TABLE-SEARCH.
SEARCH TABLE-ENTRIES
WHEN SALESMAN-NUMBER (ROUTINE-CHECK) = ROUTINE-CHECK
PERFORM 520-WRITE-FILE
WHEN SALESMAN-NUMBER (ROUTINE-CHECK) = 0
CONTINUE
END-SEARCH.
520-WRITE-FILE.
MOVE SALESMAN-NAME (ROUTINE-CHECK) TO DL-NAME-COLUMN
IF DL-NAME-COLUMN = SPACES
MOVE '*** Not Found ***' TO DL-NAME-COLUMN
END-IF
MOVE ROUTINE-CHECK TO DL-NUM-COLUMN
MOVE ROUTINE-CHECK TO SM-NUM-M
MOVE MONTH-TOTAL (1, SM-NUM-M) TO DL-MONTH-1
MOVE DL-MONTH-1 TO SALESMAN-MATH
ADD SALESMAN-MATH TO SALESMAN-TOTAL
ADD SALESMAN-MATH TO FINAL-M-TOTAL-1
ADD SALESMAN-MATH TO FINAL-TOTAL
MOVE MONTH-TOTAL (2, SM-NUM-M) TO DL-MONTH-2
MOVE DL-MONTH-2 TO SALESMAN-MATH
ADD SALESMAN-MATH TO SALESMAN-TOTAL
ADD SALESMAN-MATH TO FINAL-M-TOTAL-2
ADD SALESMAN-MATH TO FINAL-TOTAL
MOVE MONTH-TOTAL (3, SM-NUM-M) TO DL-MONTH-3
MOVE DL-MONTH-3 TO SALESMAN-MATH
ADD SALESMAN-MATH TO SALESMAN-TOTAL
ADD SALESMAN-MATH TO FINAL-M-TOTAL-3
ADD SALESMAN-MATH TO FINAL-TOTAL
IF SALESMAN-TOTAL > 0
MOVE SALESMAN-TOTAL TO DL-TOTAL
MOVE DETAIL-LINE TO SALESAMT-RECORD-OUT
WRITE SALESAMT-RECORD-OUT
AFTER ADVANCING 2 LINES
END-IF
MOVE ZEROS TO SALESMAN-TOTAL.
600-FINAL-TOTALS.
MOVE FINAL-M-TOTAL-1 TO MONTH-1-TOTAL
MOVE FINAL-M-TOTAL-2 TO MONTH-2-TOTAL
MOVE FINAL-M-TOTAL-3 TO MONTH-3-TOTAL
MOVE FINAL-TOTAL TO MONTH-FINAL-TOTAL
MOVE TOTALS-LINE TO SALESAMT-RECORD-OUT
WRITE SALESAMT-RECORD-OUT
AFTER ADVANCING 3 LINES.
To me it seems that the logic is right as it does work, but for some reason it (in my mind when i see the results) jumps completely over 520-WRITE-FILE when it runs. With this I do leave a few notes.
I know 510-TABLE-SEARCH makes little sense and I intend to change it later, but I need to fix this first and it works for the moment. Unless it is the main problem please don't harass me over it.
I will be willing to add the data in the SEQ files if someone asks me for it.
My code might be a bit complex and I admit to that, but I am doing the best I can with the teacher I have (I mostly have to learn this stuff on my own).
I appreciate any help I receive and thank anyone who tries to help in advance.
edit: I am using a compiler called Micro Focus, Net Express 5.1 Academic Edition and my OS is Windows Vista. As for what the program does show when I run it, it just shows my two heading lines and then my totals-line without anything but the first field showing. I hope that helps.
I don't know for certain if this is the problem, but I can see a logic flow that isn't going to work very well...
First: 400-SALESMAN-NAME reads salesmen records from a file into working storage table SALESMAN-TABLE.
The file probably looks something like:
01Sales Guy One
02Lance Winslow
03Scott Peterson
04Willy Loman
When the read loop is done, SALESMAN-NUMBER will equal the table index because of
the way you load the table (using SM-NUMBER-IN to set the table subscript). No problem so far...
Next: 500-PROCESS-FILE loops through all rows in the SALESMAN-TABLE by running subscript ROUTINE-CHECK from 1 to 99 and performing 510-TABLE-SEARCH to write out the report for the salesman where the subscript equals SALESMAN-NUMBER...
Next: The SEARCH statement. This is where it all goes strange and never performs 520-WRITE-FILE.
This is why.
The SEARCH statement implements a linear search (SEARCH ALL is a binary search). SEARCH just increments the index associated with the searched table and then runs through a bunch of WHEN tests until one of them "fires" or the index runs off the end of the table. The index for your TABLE-ENTRIES table is IND-TABLE-ENTRIES. But you never set or reference it (this is the root of the problem). I will explain in a moment...
Notice that the WHEN part of your SEARCH is using subscript ROUTINE-CHECK. ROUTINE-CHECK was set in 500-PROCESS-FILE. Also notice that you only get to 520-WRITE-FILE if the SALESMAN-NUMBER matches the value of ROUTINE-CHECK - which it will do if a salesman with that number was read from the input file. This could work because you loaded the table such that the row number equals the salesman number back in 450-TABLE-LOAD.
Now, what happens if the input file does not contain a salesman where SM-NUMBER-IN equals 01?
Lets go through it, blow by blow...
ROUTINE-CHECK is set to 1, SEARCH is invoked and because the IND-TABLE-ENTRIES index associated with the searched table is less than the number of occurs in the table (it got initialized to zero on program load), the WHEN clauses are executed.
The first test is WHEN SALESMAN-NUMBER (ROUTINE-CHECK) = ROUTINE-CHECK. Since Salesman 1 doesn't exist, the SALESMAN-NUMBER will be zero and the test fails (0<>1).
The next WHEN clause is tried and it succeeds because (0=0); but this is a 'do nothing' option so another cycle of SEARCH is entered after IND-TABLE-ENTRIES is incremented.
Same results on this and all subsequent iterations through the SEARCHed WHEN list (none of the clauses match)... Repeat this loop until IND-TABLE-ENTRIES is incremented beyond the end of the table.
At this point the SEARCH terminates and control flows back to the next loop in 500-PROCESS-FILE. Nothing has been printed.
500-PROCESS-FILE then increments ROUTINE-CHECK by 1 (now it is 2). We have a salesman with a SALESMAN-NUMBER of 02 so we should get some output - right? Wrong! But why?
If you read up on the SEARCH verb you will find it does not reset the table index (in this case: IND-TABLE-ENTRIES). It starts using whatever value it has when the SEARCH is entered. You never reset it so it is already set beyond the end of the table. SEARCH just terminates and nothing gets printed - ever again.
Fixing the problem
Given that you have loaded TABLE-ENTRIES by salesman number in the first place, I don't see the purpose of using SEARCH. Just do something like:
500-PROCESS-FILE.
PERFORM VARYING ROUTINE-CHECK FROM 1 BY 1
UNTIL ROUTINE-CHECK > 99
IF SALESMAN-NUMBER (ROUTINE-CHECK) = ZERO
CONTINUE
ELSE
PERFORM 520-WRITE-FILE
END-IF
END-PERFORM.
Might also be a good idea to have an initialization loop for the table so that every SALESMAN-NUMBER is explicitly set to zero before you read the salesman file.
If you must use SEARCH in this program, then don't forget to set and use the associated table index variable when referencing the table being searched.
I've added this as a second answer, which I think is correct !
520-WRITE-FILE is not being performed because the SEARCH to call it is failing.
In 510-TABLE-SEARCH, I believe you need to search on the index declared for the table,
IND-TABLE-ENTRIES. You will probably need to re-code 500-PROCESS-FILE and 510-TABLE-SEARCH.
In another question, you asked about the SEARCH verb. fmartin gave a link describing how it works, with examples.
Pls. Change to this:
SELECT SALESAMT-FILE-OUT
ASSIGN TO 'SALESAMT.RPT'
ORGANIZATION IS LINE SEQUENTIAL
File Status is FILESTATUS.
And add this:
01 FILESTATUS.
02 FILESTATUS-1 Pic 9.
88 SUCCESSFULL Value 0.
88 END-OF-FILE Value 1.
88 INVALID-KEY Value 2.
88 PERMANENT-ERROR Value 3, 9.
02 FILESTATUS-2 Pic 9.
88 DUPLICATE-KEY Value 2.
88 NO-RECORD-FOUND Value 3.
88 FILE-IS-FULL Value 4.
Check FILESTATUS every time u do something with SALESAMT-FILE-OUT. (u can do with the other files as well).
With the help of this modification u will be able to see if there is any error when u do an IO.
This is the first step, so this is not the final answare for ure question..
"it just shows my two heading lines and then my totals-line"
In your paragraph 520-WRITE-FILE, you have the following code
IF SALESMAN-TOTAL > 0
MOVE SALESMAN-TOTAL TO DL-TOTAL
MOVE DETAIL-LINE TO SALESAMT-RECORD-OUT
WRITE SALESAMT-RECORD-OUT
AFTER ADVANCING 2 LINES
END-IF
If SALESMAN-TOTAL is zero, your program will not print detail lines.
It looks like you have a data or logic error in your totalling of SALESMAN-TOTAL.
I think that you have a fairly simple problem, which has to do with your current working directory.
In the environment division, you declare the file handles and assign them to file names.
When you debug the program, the input files are in your current working directory and are therefore resolved correctly.
When you run the program, I guess you're running it from a different directory, so the input files are not resolved and therefore the output file contains only a single header line.