


When programming with ActiveX controls and OLE objects, you can pass one- or two-dimensional COBOL tables to methods or properties that expect "SAFEARRAY" parameters. The runtime automatically converts a one- or two-dimensional COBOL table to an OLE SAFEARRAY, as long as it contains only one elementary item that is USAGE HANDLE or USAGE HANDLE OF VARIANT.
The OLE SAFEARRAY data type can contain elements of any type. Therefore, you must convert your COBOL data into VARIANT type data before adding it to the array. To do this, use the C$SETVARIANT library routine. C$SETVARIANT creates a new variant to store the data if the initial value of the handle item passed to it is LOW-VALUES or SPACES. It is your responsibility to free this variant using the DESTROY verb.
To use SAFEARRAYs:
1. Declare a table in working-storage that has one or two OCCURS clauses.
2. If specified, the second OCCURS clause must be on an item that is subordinate to the item with the first OCCURS clause.
3. The table must contain only one elementary item that is USAGE HANDLE or USAGE HANDLE OF VARIANT. ("OF VARIANT" is optional but makes the code more readable).
4. Call C$SETVARIANT for each handle item in the table to convert the COBOL data to VARIANT type data.
5. Use the name of this table wherever a property or method requires a SAFEARRAY.
For example, Microsoft Chart Control has a property called ChartData. The value of this property is a SAFEARRAY. Each element of the array is a data point value for the chart.
01 myTable.
03 filler occurs 5 times.
05 chart-data usage handle of variant.
screen section.
01 screen-1.
03 mschart-1
MSChart
line 3, column 5, size 50, lines 16.
03 my-button push-button, "E&xit Program",
ok-button,
line 32, cline 23, column 27, size 13.
procedure division.
Main-Logic.
perform varying col-number from 1 by 1 until col-number > 5
call "c$setvariant"
using col-number, chart-data(col-number)
end-perform.
display standard graphical window,
title "ActiveX Table MSChart Sample - tblchart.cbl"
lines 37, size 66, background-low.
display screen-1.
modify mschart-1
ChartData = myTable.
perform, with test after, until exit-button-pushed
accept screen-1
end-perform.
perform varying col-number from 1 by 1 until col-number > 5
destroy chart-data(col-number)
end-perform.
destroy screen-1.
stop run.
Notice that the initial values of the chart-data table elements are spaces. When C$SETVARIANT is called with the chart-data items set to spaces, it creates new VARIANT handles and sets the chart-data item to the VARIANT handle.
Later the DESTROY statement destroys these handles and releases the associated memory. The DESTROY statement also sets the chart-data item to low-values to allow multiple destroys of the same handle item without any negative effects.
Here is an example of a table with two OCCURS clauses passed as a two-dimensional SAFEARRAY to the ChartData property. Microsoft Chart Control takes the "string" elements of this array to be the x-axis labels and the numeric elements to be two series of chart data.
77 col-label pic x(20).
77 series-2-data pic 99.
01 myTable.
03 filler occurs 5 times.
05 filler occurs 3 times.
07 chart-data usage handle of variant.
screen section.
01 screen-1.
03 mschart-1
MSChart
line 3, column 5, size 50, lines 16.
03 my-button push-button, "E&xit Program",
ok-button,
line 32, cline 23, column 27, size 13.
procedure division.
Main-Logic.
perform varying col-number from 1 by 1 until col-number > 5
string "Label " delimited by size
col-number delimited by size
into col-label
call "c$setvariant"
using col-label, chart-data(col-number,1)
call "c$setvariant"
using col-number, chart-data(col-number,2)
multiply col-number by 2 giving series-2-data
call "c$setvariant"
using series-2-data, chart-data(col-number,3)
end-perform.
display standard graphical window,
title "ActiveX Table MSChart Sample - tblchart.cbl"
lines 37, size 66, background-low.
display screen-1.
modify mschart-1
ChartData = myTable.
perform, with test after, until exit-button-pushed
accept screen-1
end-perform.
perform varying col-number from 1 by 1 until col-number > 5
destroy chart-data(col-number,1)
destroy chart-data(col-number,2)
destroy chart-data(col-number,3)
end-perform.
destroy screen-1.
stop run.