If I have the COBOL structure like this:
(the structure should be like this because I have to convert it using XML Generate Function, the variable name just sample)
01. MyData.
02. Corp-Entity
03. Corp-Branch1.
04. Address.
05. AddressLine1 PIC X(20).
05. AddressLine2 PIC X(20).
05. PostalCode PIC 9(05).
04. PIC-Entity.
05. Address.
06. AddressLine1 PIC X(20).
06. AddressLine2 PIC X(20).
06. PostalCode PIC 9(05).
How to move a value in 05. AddressLine1?
If I write this code:
move valueAddressLine1 to AddressLine1
in Address
in Corp-Brach1
in MyData
But this code is valid for 06. AddressLine1
move valueAddressLine1 to AddressLine1
in Address
in PIC-Entity
Error Message:
"AddressLine1 of Address of PIC-Entity" was not a uniquely defined name.
The definition to be used could not be determined from the context. The reference to the name was discarded.
Pre-notes:
That code won't work because of the periods after the level numbers, get rid of these.
To have a unique name you don't need the full qualification. For example the following is fine:
move valueAddressLine1 to AddressLine1
in PIC-Entity
Answer:
In cases like this: "fix" the COBOL side by using a name that can be accessed uniquely, in most cases by its "parent" items and where this isn't possible like your 04 Address by using a different name (for example 04 corp-address) .
As you want this structure in XML you may use the NAME phrase as IBM's docs XML element name and attribute name formation says:
In the XML documents that are generated from identifier-2, the XML element names and attribute names are obtained from the NAME phrase if specified; otherwise they are derived from the names of the data item specified by identifier-2 and from any eligible data-names that are subordinate to identifier-2.
IBM's docs on XML GENERATE statement have details on this. For the given sample and assumed 2 corp-branches:
XML GENERATE variable-name
FROM Corp-Entity
NAME OF corp-address in corp-branch1 IS 'Address'
corp-address in corp-branch2 IS 'Address'
Related
Moving data to COMP-3 fields after UNSTRING.
UNSTRING is working fine but I am not able to move data to COMP-3 fields without an S0C7 data exception abend.
I think it is an issue with storing data.
Below is my COBOL program.
IDENTIFICATION DIVISION.
PROGRAM-ID. ADDPROG.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 VALUEA PIC X(20) VALUE '64.99|64.99'.
01 NOA PIC S9(9)V9(02).
01 NOB PIC S9(9)V9(02).
01 NOC PIC S9(9)V99 COMP-3.
01 NOD PIC S9(9)V99 COMP-3.
PROCEDURE DIVISION.
000-MAIN.
DISPLAY "EARLIER".
DISPLAY 'NOA-' NOA.
DISPLAY 'NOB-' NOB.
DISPLAY "AFTER".
UNSTRING VALUEA
DELIMITED BY '|'
INTO NOA,NOB.
DISPLAY 'NOA-' NOA.
DISPLAY 'NOB-' NOB.
MOVE NOA TO NOC.
MOVE NOB TO NOD.
DISPLAY 'NOC-' NOC.
DISPLAY 'NOD-' NOD.
STOP RUN.
Output I am getting after compiling.
Please let me know is there any other way to move data to COMP-3 fields or to avoid this error.
Your code has two main problems. To see them you first have to understand that your UNSTRING into NOA and NOB works like any other character-to-character MOVE.
So it starts from the left and moves character after character until one field ends and if necessary adds some blanks to fill up the receiving field.
So problem one is that NOA contains the value left-justified while according to your PIC-clause it should be right-justified, so you would need an intermediate PIC X(12) JUSTIFIED RIGHT field that you UNSTRING to.
The second problem that is causing the S0C7 is that your PIC-clause does not include a decimal-point. The V specifies the implied position of the decimal point but it would not show on output nor is it handled correctly when parsing the field-contents. To have a field that correctly handles the decimal point you should have a PIC S9(9)V.9(02).
Please also see this question.
Like piet.t said, the UNSTRING statement is like a alphanumeric move. Therefore my suggestion is to:
make NOA and NOB be alphanumeric (PIC X(12)), and
change your move statements to include WITH CONVERSION so that it will convert the numeric data in the alphanumeric field into COMP-3.
Your decimal data field are wrong just have . Like 01 NOA PIC S9(9).(02) In them! Same with noc variabile then it should run.
To move data from a numeric field to a COMP-3 field, you need to make sure that the data in the numeric field is valid for the COMP-3 field. A COMP-3 field stores packed decimal data, which means that the digits of the number are packed into two-digit decimal fields. The decimal point is not stored, and the sign of the number is stored in the last nibble of the field.
When initializing the following variables:
01 BATCH-REC.
03 BATCH-VERSION PIC X(2).
03 BATCH-FIELDS PIC X(682).
03 BATCH-REC-01 REDEFINES BATCH-FIELDS.
05 B01-OH-DTL-REC.
07 B01-PE-ID PIC X(12).
07 B01-PMT-DISC-TERMS PIC S9(4) COMP.
07 B01-PMT-DISC-AMT PIC S9(18) COMP.
using the command
INITIALIZE BATCH-REC.
the variables B01-PMT-DISC-TERMS is initialized to value +08224 and B01-PMT-DISC-AMT is initialized to +314885530818453536.
What could the reason be? Would it be a good idea to MOVE a blank space to those variables after initializing? I dont want to change that BATCH-REC code to add a default value on them.
The INITIALIZE statement will not initialize redefined fields. If you want the redefined fields to be initialized, you must identify them in some way. For example,
INITIALIZE BATCH-VERSION BATCH-REC-01
This will initialize the elementary fields to SPACES or ZEROS depending on their PICTURE. BATCH-FIELDS will not be initialized.
Item 3, below applies, in this case. From the 2002 standard for INITIALIZE:
5) The receiving-operand in each implicit MOVE or SET statement is determined by applying the following steps in order:
a) First, the following data items are excluded as receiving-operands:
Any identifiers that are not valid receiving operands of a MOVE statement, except data items of category data-pointer, object-reference, or program-pointer.
If the FILLER phrase is not specified, elementary data items with an explicit or implicit FILLER clause.
Any elementary data item subordinate to identifier-1 whose data description entry contains a REDEFINES or RENAMES clause or is subordinate to a data item whose data description entry contains a REDEFINES clause. However, identifier-1 may itself have a REDEFINES clause or be subordinate to a data item with a REDEFINES clause.
In this case I think you will find your INITIALIZE statement did initialize your PIC X data to spaces. The value you have for B01-PMT-DISC-TERMS is x'2020' and the value for B01-PMT-DISC-AMT is x'2020202020202020' with the leading digit cut off, possibly due to reporting of the value being limited to the picture clause of 18 digits.
Regardless, I agree with #RickSmith and believe he is correct in his solution to your problem.
I have fixed-point numbers in file, one in each line, in this format S9(6)V9(2) but when they are actually read, I'm getting non numeric errors while trying to put them in math operations. What is more, when I try to display them in program, a number that is written in file as 567123.45 is saved in variable as +567123.04. And for example the number from file 123.45 is saved in variable as +123.45.00 and it provokes the following error 'WS-VALUE' not numeric: '123.45 0' during a math operation. Why is that?
I'm using OpenCobolIDE 4.7.4 for Windows.
EDIT:
File has records of the following form separated by new lines (read by READ operation record after record):
01 WS-OPERATION.
05 WS-ID PIC A(2).
05 WS-CLIENT PIC 9(5).
05 WS-COUNTRY PIC A(4).
05 WS-VALUE PIC S9(6)V9(2).
The reason is that you try to un-edit a field. 567123.45 in the data is not conforming to PIC S9(6)V9(2) but to -9(6).9(2). - internal stored data vs. print-data.
Simply changing the definition and use MOVE WS-VALUE TO WS-VALUE-INTERNAL (which is defined like you want to) may work with a specific compiler (and specific data) but I'd go a different route:
I'd suggest to always validate the data before doing something with it (the file may be broken or external edited).
At least check the simple numeric data like WS-CLIENT for IS NUMERIC and either do a full validation on the data field WS-VALUE or at least use MOVE FUNCTION NUMVAL(WS-VALUE) TO WS-VALUE-INTERNAL.
I have a copy book like :
01 MY-STRUCTURE.
05 STRUCTURE-NAME PIC X(20).
05 STRUCTURE-DATE PIC X(8).
05 STRUCTURE-LIB PIC 9(3).
How can I get the name of my fields?
I want to have a program that can get any copybook and write dynamically its fields and values.
I want to write it to an output file like this :
"STRUCTURE-NAME-> TOTO"
"STRUCTURE-DATE-> 19780301"
"STRUCTURE-LIB -> 123"
In the z/OS world, depending upon your compiler level, you can use the debugging information generated by the compiler to do introspection on your names. To do this, you will need to save your ADATA at compile time.
I have a two possible solutions:
You save the names of the fields of the copy in a internal table. And secuential reads the table for your write your output.
Dynamical allocation, is more complicated but it's possible. You allocate the copy in your program using bpxwdyn (subroutine IBM).
You create a subprogram, with name of copy, the length is fixed (80), the name of library of copys, and allocate this copy in subprogram. Then, You can fill a internal table with his datas.
Eg:
http://mainframe-tips-and-tricks.blogspot.com.es/2011/12/cobol-sample-program-for-dynamic-file.html
IF AWA-REQ-DATE < WS-JULIAN-DATE
MOVE VAR1 to VAR2
The AWA-REQ-DATE is a binary integer i.e. PIC S9(09) COMP, whereas Julian date is PIC X(10) VALUE SPACES.
Both have Julian date inside them like 2013031 & 2013099.
This gives:
ERROR:REQ-DATE (BINARY INTEGER)" was compared with "WS-JULIAN-date (ALPHANUMERIC)". Discarded
Can I compare then with converting one of them to other format right here in code?
All your four-digit-year Julian dates will contain seven digits. They are dates, so naturally are positive.
It is unclear why you have a nine-digit, signed, binary to hold such or date. Nor a 10-byte alphanumeric. It is also unclear why this should have an initial value of SPACE.
01 WS-JULIAN-DATE VALUE SPACE.
05 WS-JULIAN-DATE-NUM PIC 9(7).
05 FILLER PIC XXX.
This assumes all your WS-JULIAN-DATE values are left-aligned.
IF AWA-REQ-DATE < WS-JULIAN-DATE
MOVE VAR1 to VAR2
END-IF
Hopefully VAR1 and VAR2 are just sample names for the question. If not, please make them meaningful, as it will make it much easier for the next person reading the program to understand. And that might be you.
If the values of WS-... are not guaranteed to be NUMERIC, test them for NUMERIC and take appropriate action (according to your spec) if they are not.
The nine-digit binary will potentially generate extra code beyond what is needed.
Another possibility is:
01 WS-AWA-REQ-JULIAN-DATE VALUE SPACE.
05 WS-AWA-REQ-JULIAN-DATE-NUM PIC 9(7).
05 FILLER PIC XXX.
MOVE AWA-REQ-DATE TO WS-AWA-REQ-JULIAN-DATE-NUM
IF WS-AWA-REQ-JULIAN DATE < WS-JULIAN-DATE
MOVE VAR1 to VAR2
END-IF
Which you choose can depend on what else you are doing with the fields.
Also, if one is "invariant", convert that to the same format as the variable one, once only.
In the various ISO/ANSI COBOL standards, comparing alphanumeric (PIC X) and numeric (PIC 9) is like comparing apples and oranges. There are defined rules. Of course, each compiler has different ways of interpreting the standard. Therefore, you are best off converting one of the fields to the other format and comparing those. Bill Woodger has some good comments about which field to convert, and how.
In summary, you should always compare like data types. For numeric items, it's best if you can compare the same COMP format, but sometimes this can't be done. If that is the case, you need to read your compiler documentation to see how comparisons are performed between different computational types, and any gotchas (such as COMP-4 and COMP-5 in IBM's Enterprise COBOL).
The answer probably depends on which compiler you are using. On GNU Cobol, the comparison works after applying FUNCTION NUMVAL to the Julian (text) date.
As the error message is describing: a numeric value PIC S9(9) COMP cannot be compared to a string PIC X(10).
A COMP variable is a system dependent, numeric representation of the value. There are variations to the internal representation (binary, BCD,...) used for COMPutation. The value of your date is,depending on the machine though, internally represented as: 0011110 10110111 01100111
Display variables are storing each position of your variable according to an encoding standard (ASCII, EBCDIC, UNICODE). Again depending on your machine and the encoding table, the representation of your variable might be: 00110010 00110000 00110001 00110011 00110000 00111001 00111001
I do some guessing here in order to address the underlying problem
First guess: The alpha definition PIC X(10) looks like the date is in printing format and should contain separators in order to make it 10 characters long
21.02.2014
123456789A
Such a variable shouldn't hold a julian date after all and you probably need a date comparing function.
Second guess: for some displaying reason, you want to have a variable of 10 characters long, holding the julian date in the first 7 characters. In this case, I'd define a structure and you can keep your comparison as is:
01 WS-JULIAN-DATE-PRINT VALUE SPACE.
05 WS-JULIAN-DATE PIC 9(7).
05 FILLER PIC X(3).