Variant arguments & com function calls

Alex Kotchnev <[email protected]>
Newsgroups gmane.comp.windows.devel.jawin
Message-ID <LISTSERV%[email protected]>
I was wondering if someone could provide some advice on passing Variant
arguments into functions exposed by com objects. Here is an example:

I am trying to invoke the MS Excel Workbook.SaveAs function. When I
generated the stubs with jawin browser it looks like this:
    /**
    *

    * @param Filename
    * @param FileFormat
    * @param Password
    * @param WriteResPassword
    * @param ReadOnlyRecommended
    * @param CreateBackup
    * @param AccessMode
    * @param ConflictResolution
    * @param AddToMru
    * @param TextCodepage
    * @param TextVisualLayout
    * @return void
    **/
    public void SaveAs(Variant Filename,Variant FileFormat,Variant
Password,Variant WriteResPassword,Variant ReadOnlyRecommended,Variant
CreateBackup,int AccessMode,Variant ConflictResolution,Variant
AddToMru,Variant TextCodepage,Variant TextVisualLayout) throws COMException
    {

  invokeN("SaveAs", new Object[] {Filename, FileFormat,
Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, new Integer
(AccessMode), ConflictResolution, AddToMru, TextCodepage,
TextVisualLayout});

    }

The VB signature is as follows:
Sub SaveAs([Filename], [FileFormat], [Password], [WriteResPassword],
[ReadOnlyRecommended], [CreateBackup], [AccessMode As XlSaveAsAccessMode =
xlNoChange], [ConflictResolution], [AddToMru], [TextCodepage],
[TextVisualLayout])

As is evident from the method signature, most of the arguments are
variants. Now, from looking at Variant, it has a million different fields
that can be set (and it appears when the Com function retrieves from
Variant only the field that it needs). So, the first question is, how to
know exactly which field in Variant has to be set ? Digging in a little
further into the Office documentation, it seems that for example for the
FileFormat Variant, it needs to be one of the values in the FileFormat
classes (the values are all ints). It would make sense to assign these to
the intVal property of Variant, if the documentation says they are strings
I should probably assign into the bstrVal. However, trying that I get
a "org.jawin.COMException: 8000ffff: passed end of stream in the
marshalling layer" error message. So, I wonder, which property of Variant
should I assign these values to ?

The second question concerns default arguments. In VB it appears that some
of the arguments can be marked as optional, and the function can be invoked
without them (e.g. if I use DispatchPtr.invoke(...) I can invoke the
function with only one argument. However, using the generated Java stub, I
have to pass all Variant arguments. When I pass just empty Variants (e.g.
constructed only with new Variant() and no values assigned to the fields)
Looking on MSDN, it appears that C# has a way of specifying that some
arguments are not being used by giving them a value of Type.Missing:

// C#
// Save the document. In a real application,
// you'd want to test to see if the file
// already exists. This will overwrite any previously
// existing documents.
Object fileName = @"C:\Test\MyNewDocument.doc";
Object fileFormat = Type.Missing;
Object lockComments = Type.Missing;
Object password = Type.Missing;
Object addToRecentFiles = Type.Missing;
Object writePassword = Type.Missing;
Object readOnlyRecommended = Type.Missing;
Object embedTrueTypeFonts = Type.Missing;
Object saveNativePictureFormat = Type.Missing;
Object saveFormsData = Type.Missing;
Object saveAsAOCELetter = Type.Missing;
Object encoding = Type.Missing;
Object insertLineBreaks = Type.Missing;
Object allowSubstitutions = Type.Missing;
Object lineEnding = Type.Missing;
Object addBiDiMarks = Type.Missing;

ThisDocument.SaveAs(ref fileName, ref fileFormat, ref lockComments,
  ref password, ref addToRecentFiles, ref writePassword,
  ref readOnlyRecommended, ref embedTrueTypeFonts,
  ref saveNativePictureFormat, ref saveFormsData,
  ref saveAsAOCELetter, ref encoding, ref insertLineBreaks,
  ref allowSubstitutions, ref lineEnding, ref addBiDiMarks);

MSDN says the following about Type.Missing:
"Use the Missing field for invocation through reflection to obtain the
default value of a parameter. If the Missing field is passed in for a
parameter value and there is no default value for that parameter, an
ArgumentException is thrown."


I dug around Jawin to see if something resembles that, but I couldn't find
it. So, the second question is, what is the equivalent of the Type.Missing
that can be assigned to java Variants so that they are treated by the Com
function as the unused arguments ?

Finally, looking at the xml from the Jawin Type Browser, here is how one of
the parameters is defined:

 <parameter name="FileFormat" type="12" typeString="VT_VARIANT"
typePointer="VT_PVARIANT" javaString="Variant"
javaObjectType="org.jawin.Variant" javaSignature=""
javaNativeString="jobject" javaNativeArray="jobjectArray"
cppString="COleVariant" cppDirect="VTS_VARIANT" cppPointer="VTS_PVARIANT">
  <modifier flag="NONE"/>
  <modifier flag="IN"/>
  <modifier flag="OPT"/>
  <idl flag="null"/>
 </parameter>

Although I don't fully understand what everything means, the <modifier>
elements seem to indicate that this is an IN parameter, and that it is
optional. However, I can't seeem to figure out what I have to put into the
Variant object for the function call to succeed. I tried just constructing
an empty Variant() and not put any values into the public members, but the
Com function doesn't like it.




To summarize the questions questions:
1. When there is a function that takes a Variant, which field in Variant
would have to be set ? I understand that maybe there is no general rule for
this, but at least a hint would be helpful...
2. Is there an equivalent to the C# Type.Missing, or some other way to
indicate that the argument has to take its default value in the Com
function invocation ?

I have to say I am very impressed with the project. Recently I was poking
around using JNI for some Windows specific functionality, and seeing how
Jawin simplifies things was a completely "Wow" experience. Until now I was
mostly restricted to the facilities Java offered to me as a programmer,
which largely ignored the possibilities of writing for Windows specific
functionality.

Just as a side note, I am using Jawin in combination with Jython and the
combination provides quite capable and useful scripting environment.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.