Highlighted
Absent Member.
Absent Member.
1469 views

[archive] Another question about Variant...

[Migrated content. Thread originally posted on 10 December 2004]

Hi everybody.

I'm trying to implement Crystal Reports ActiveX DRC in our ERP application and I've found a problem when passing dates. We are completely newbies in Windows programming (as you'll see soon) and I think that is the main trouble.

Well, once (not in depth) reviewed the Acucobol ActiveX syntax, I make the following assumptions:

a) Passing a Variant datatype to an ActiveX control implies the use of a variable, USAGE HANDLE OF VARIANT, which will be filled through C$SETVARIANT routine.

b) Acucobol automatically converts data passed by using a PICTURE basis. That is, a PIC X(n) variable will be passed as VT-BSTR, a PIC 9(n) as VT-I4 and a PIC 9(n)V9(n) as VT-R8 respectively.

c) Since Acucobol 6.20 is possible to specify "AS VARIANT_TYPE" on individual variables in the INQUIRE and MODIFY verbs.

Right until here (I think).

The problem comes when I try to pass a date variable to a VT-DATE variant type. As Acucobol does not provide automatic conversion for this type I don't know how to pass the date.

i.e. I have a PIC 9(08) variable in Acucobol in YYYYMMDD format. How can i translate this value to VT-DATE format ? Is there any equivalente data type (VT-I4, VT-R8, ...) ? What is the internal datatype structure of a VT-DATE Variant ?

Sorry. A lot of questions.

Regards.

P.S. The concept could be too applicable to CURRENCY (VT-CURRENCY) datatype.
0 Likes
9 Replies
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Read version 6.2 ECN2471: ActiveX/COM parameter type conversion specification(http://www.acucorp.com/support/supported/ecn/index.php ).

It describes new syntax using the "AS" keyword to pass data as a specific variant type(VT-DATE for instance) defined in the 6.2 activex.def file:

* VARIANT types
78 VT-NULL VALUE 1.
78 VT-I2 VALUE 2.
78 VT-I4 VALUE 3.
78 VT-R4 VALUE 4.
78 VT-R8 VALUE 5.
78 VT-CY VALUE 6.
78 VT-DATE VALUE 7.
78 VT-BSTR VALUE 8.
78 VT-DISPATCH VALUE 9.
78 VT-ERROR VALUE 10.
78 VT-BOOL VALUE 11.
78 VT-VARIANT VALUE 12.
78 VT-UNKNOWN VALUE 13.
78 VT-DECIMAL VALUE 14.
78 VT-I1 VALUE 16.
78 VT-UI1 VALUE 17.
78 VT-UI2 VALUE 18.
78 VT-UI4 VALUE 19.
78 VT-I8 VALUE 20.
78 VT-UI8 VALUE 21.
78 VT-INT VALUE 22.
78 VT-UINT VALUE 23.
78 VT-VOID VALUE 24.
78 VT-HRESULT VALUE 25.
78 VT-PTR VALUE 26.
78 VT-SAFEARRAY VALUE 27.
78 VT-CARRAY VALUE 28.
78 VT-USERDEFINED VALUE 29.
78 VT-LPSTR VALUE 30.
78 VT-LPWSTR VALUE 31.
78 VT-RECORD VALUE 36.
78 VT-FILETIME VALUE 64.
78 VT-BLOB VALUE 65.
78 VT-STREAM VALUE 66.
78 VT-STORAGE VALUE 67.
78 VT-STREAMED-OBJECT VALUE 68.
78 VT-STORED-OBJECT VALUE 69.
78 VT-BLOB-OBJECT VALUE 70.
78 VT-CF VALUE 71.
78 VT-CLSID VALUE 72.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Hello Dan,

I'd already read the ECN2471 and found it provides great advantage, but the problem is: I'm VERY NEWBIE in windows programming.

By using "AS VT-DATE" I can pass Date Variant Type but, and that's the question, I don't know what the VT-DATE variant expects. I think I can't simply set, using C$VARIANT, a PIC 9(08) VALUE (YYYYMMDD format) to a Variant VT-DATE datatype.

Perhaps I am very, very wrong, but I've the feeling 🙂 that I need to know the storage format of the vbDATE (VT-DATE) type. How the dates are represented ? With an 8 byte floating ? Using integer part for date and float for time ? How is stored year, month and day (algorithm) ?

Many questions, really.

Thanks for helping.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Interesting blog about VT_DATE here: http://blogs.msdn.com/ericlippert/archive/2003/09/16/53013.aspx

It mentions that VT_DATE is a double precision floating type which holds the elapsed number of days and time since Dec 30, 1899 for a date.

It would be interesting to know if Acucobol-GT will convert a PIC 9(08) date to the number of days elapsed since Dec 30, 1899 for you, or if you have to do this yourself. If the runtime is using the the OLEAUT32.DLL API when converting to VT_DATE then this might happen for you.

Have you actually tried passing PIC 9(08) AS VT_DATE yet?

It may also be that the runtime use the local regional date formats in the system to convert a long or short date string to a VT_DATE. I saw an example of this in PHP somewhere in the web.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Originally posted by DanM
Have you actually tried passing PIC 9(08) AS VT_DATE yet?
No, I still haven't tryed it because my case is a little more complex.

I need to invoke the @AddRows method of the Crystal CDO Object (@CrystalComObject), which adds a recordset to a virtual database (CDO) for further reporting.

This method uses a single argument (as stated in Crystal 10 DRC documentation):

AddRows
Sub AddRows(RowData)
Use this method to assign an array of data to the CDO Rowset.

Parameters
RowData
A standard Visual Basic two-dimensional array. The first dimension specifies the number of rows in the Rowset, while the second dimension specifies the number of fields for each row. A one-dimensional array is used to add a single row with
multiple fields. When this array is dimensioned, it must be defined As Variant. For example:
Dim Rows(11, 3) As VariantThis example creates an array that will hold 12 rows with 4 fields. You must assign data to all cells in the array before assigning the array to the Rowset using AddRows. Example
cdoRowset.AddRows Rows
The following snipplets are from the Acocobol coding of the routine implied:
...

DATA DIVISION.

[i]* Generic dataset used to call Crystal DRC Automation Server.[/i]
[i]* Used only inside this routine.[/i]
77  H-CDO              HANDLE OF @CrystalComObject.
77  NUM-CDO            PIC 9(02). [I]| Number of fields (passed by the caller)[/I]
78  MAX-CDO            VALUE 20.
01  [B]TABLE-CDO[/B].  [I]| Array passed to ActiveX[/I]
     03 OCCURS 1 TO MAX-CDO TIMES DEPENDING ON NUM-CDO.
        05 [b]FIELD-CDO[/b] HANDLE OF VARIANT.

...

[i]* Item passed from parent procedure.[/i]
[i]* Used to hide complexity to caller processes[/i]
[i]* which simply passes field collections (and its types !!!).[/i]
01  FIELD-VALUE-TABLE OCCURS MAX-CDO TIMES
    03  FIELD-TYPE         PIC X(10). [I]| Actually: "STRING"/"NUMBER"/"CURRENCY"/"DATE"[/i]
    03  W-STRING           PIC X(100). [I]| Acucobol converts to VT_STRING[/I]
    03  W-NUMBER           PIC 9(10).  [I]| Acucobol converts to VT_I4[/I]
    03  W-CURRENCY         PIC S9(10)V999. [I]| Acucobol converts to VT_R8[/I]
    03  [b]W-DATE[/b]             PIC 9(08). [b][I]| Acucobol converts to ? VT_I4 (will not work)[/I][/b]

...

PROCEDURE DIVISION.

...


[i]* Set values of the fields array[/i]
[i]* as specified by the caller process.[/i]
PERFORM VARYING C-CDO FROM 1 BY 1 UNTIL C-CDO > NUM-CDO
    EVALUATE FIELD-TYPE(C-CDO)
        WHEN "STRING"
            CALL "C$SETVARIANT" USING W-STRING(C-CDO)   FIELD-CDO(C-CDO)
        WHEN "NUMERIC"
            CALL "C$SETVARIANT" USING W-NUMBER(C-CDO)   FIELD-CDO(C-CDO)
        WHEN "CURRENCY"
            CALL "C$SETVARIANT" USING W-CURRENCY(C-CDO) FIELD-CDO(C-CDO)
        [B]WHEN "DATE"[/B]
            [B]CALL "C$SETVARIANT" USING [I]W-DATE(C-CDO)[/I]     FIELD-CDO(C-CDO)[/B]
    END-EVALUATE
END-PERFORM.

[i]* Invoke the method passing the array.[/i]
MODIFY H-CDO @AddRows([B]TABLE-CDO[/B]).


As you can (probably, the example colud be much more clear) see, if FIELD-TYPE = "DATE", will not work because I'm passing a PIC 9(08), that will be converted to VT_I4 (I don't know the storage format of VT_DATE but probably mismatches) with a value of, in example, 20041212.

Your clues (thanks) points to do a format conversion calculating the date (days from Dec 30, 1899) and to use a DOUBLE FLOAT type but, until solid confirmation, I'm unsure this could be the best method.

Opinions needed !!!
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Rule 1: Always try things. (At least when they are as small as this).

Anyway, while you can use the AS VT_DATE phrase to override default values, you are right, it will not do the casting for you. Simply because the runtime will have no idea what you are sending, or at best guess.

Thus, what the runtime does, is to move whatever numeric value is in your source data directly without altering it.

Which means, you will have to generate the value yourself.

To do this, you can use the API function DosDateTimeToVariantTime. You will find this one in OleAut32.dll.

Now, how do you make a Dos Date Time?

You can build it all up starting with:
SystemTimeToFileTime.

System Time is based on day, month, year, hrs, min and so on. This will give you FileTime. Which can be used as a foundation for the function FileTimeToDosDateTime. With this DosDateTime you can then call the DosDateTimeToVariantTime. Note that when you do these functions and want to implement the DOUBLE datatype, you should allocate that as:

77 MYDATE USAGE PIC X(4) COMP-N.

Aside of this. A note on other issues discussed in this thread:

You normally don't need to worry about VARIANT in ACUCOBOL-GT, the only case I can think of is when you deal with SAFEARRAY and if there is a need to override the autotranslation of the runtime (rare).
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Originally posted by gforseth
Rule 1: Always try things. (At least when they are as small as this).

Sorry. I've already tried and, as you predicted, don't works.

Originally posted by gforseth
You normally don't need to worry about VARIANT in ACUCOBOL-GT, the only case I can think of is when you deal with SAFEARRAY and if there is a need to override the autotranslation of the runtime (rare).

2 of 2. What a lucky man. :mad:


I'll try the DosDateTimeToVariantTime function (although the real code is even a little more tricky (dirty Crystal Reports) than the posted example).

Thanks Gisle.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Take a look at the SystemTimeToVariantTime in OLEAUT32.DLL as well: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/automat/htm/chap7_38dh.asp

Allows for a wider range of dates than DosDateTimeToVariantTime and it uses SYSTIME structure so you don't need to convert to FILETIME.

The structure for SYSTIME is here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemtime_str.asp

So, you should be able to create this structure in working storage, pass it to SystemTimeToVariantTime function and get back a double representing the variant time, which you should be able to pass to Crystal Reports AS VT_DATE.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Thanks for the information about SystemTimeToVariantTime function Dan. It's a more direct approach.

However, I can't pass the variant "AS VT_DATE" because, as the previous example shows, I'm passing a SAFEARRAY not a single Variant...

...unless, of course, Gisle obtains that the development guys extend "AS VT_TYPE" functionality to C$SETVARIANT 😄 .
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Another question about Variant...

Good idea.
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.