Re: Multidimensional array as parameter

"Mcnamara, Sean D" <[email protected]> Wed, 4 Jan 2006 11:51:36 -0500
Newsgroups gmane.comp.windows.devel.jawin
Message-ID <57F935D6BB6B2543AF5D835DCE7CAF270F8DFD@MD61EX100.ad.honeywell-tsi.com>
Hello,

I am not a (very) experienced developer with Jawin myself, but I do have a
suggestion for you that you may find helpful. Often, when the Jawin API
doesn't support some functionality I need, I'll create a new Visual Basic
project (assuming you have Visual Basic 6.0 or Visual Studio or otherwise)
that does as much native-side work as possible, wrap that into a function or
subprocedure, and expose that in an ActiveX DLL which depends on
MSVBVM60.dll (the Visual Basic virtual machine) plus any other references
you're using (in your case, Excel's COM dll.)

Once you've accomplished that,  just use System.loadLibrary for MSVBVM60.dll
or include it in your classpath; then generate Jawin wrappers for your
simple COM DLL you've created in VB. This can be done in any COM language,
but I like VB because you can use a VBA.Collection to wrap almost anything,
including a multidimensional array.

1. Generate a COM wrapper for the _Collection dispatch and the Collection
CoClass from the Jawin code generator. This object is in MSVBVM60.dll
(invariably this is in %windir%\system32 for any useful Windows system since
win98.)

2. Since the Collection class encapsulates VB Objects (which translate
directly to Java Objects) you should be able to use Java to instantiate a
single _Collection instance, and use its Add method natively to add
one-dimensional Java arrays to it. As I understand it, Jawin SHOULD
automatically do any necessary translation from Java arrays into VB arrays
before passing the members of the Collection, which thus far could be ANY
java.lang.Object, into the native COM framework. Make sure however that any
types you use in the one-dimensional arrays are either primitives, String,
or a native type that you already have a Jawin wrapper for.

3. Pass this _Collection as one of two parameters to your Visual Basic DLL.
The other parameter could be the Excel.Worksheet object you want to add the
data to, and any other locational info you need (for instance, the top-left
Cell of the range to fill.)

4. Your implementation of the Visual Basic DLL will unwrap the Collection as
a one-dimensional set of one-dimensional arrays; by definition, a 2d matrix.
Since this is all done on the native side with a single Jawin call, there is
no JNI overhead involved in the iterative filling of the spreadsheet -- your
only performance hit might be a slight one from using the Collection object,
which is a LITTLE hefty. However, I suspect that if you are using huge
amounts of data, the runtime of using an optimized native code versus
hundreds of Jawin calls is decidedly in favor of the native approach. If you
wrote this using C++ linked to Excel rather than the Visual Basic VM, you
could get significantly more performance, too.

I'm not sure in particular about the assumption I make in point #2, that
Jawin will convert the Java arrays to VB arrays, but I believe it will do
so. If not, you may be able to subclass VBA.Collection (C++ may be required
here) to be strongly-typed to accept only arrays as its members, not generic
VB Objects. This would force Jawin to generate Java code that makes the JNI
bridge more obvious to Jawin at runtime.

If I'm totally off base here I hope I'm told otherwise -- my use of Jawin is
ongoing and I may be faced with this exact problem in the future.

Thanks,
Sean

-----Original Message-----
From: Discussion of Java/Win32/COM integration with Jawin
[mailto:[email protected]] On Behalf Of Frank Bos
Sent: Wednesday, January 04, 2006 10:49 AM
To: [email protected]
Subject: [JAWIN] Multidimensional array as parameter

Hi,

I'm trying to use Jawin to fill an Excel sheet using a Java application.
For my application it is important to use "bulk" methods to set the values
for all cells in a range, because otherwise it will get too slow.

According to the Excel api, it should be possible to use a two-dimensional
array to set the "Value" property of a "Range" object. Unfortunately I
haven't been able to get this to work using Jawin. If I use a (one
dimensional) array, then it is possible to set a complete row of values
using a single Jawin call, but that is not good enough because my
application will output many rows to Excel (and not so many columns).

Example code:

public class JawinTest {
  public static void main(String args[]) {
    try {
      Ole32.CoInitialize();

      DispatchPtr app = new DispatchPtr("Excel.Application");
      app.put("Visible", true);
      DispatchPtr books = (DispatchPtr)app.get("Workbooks");
      DispatchPtr book = (DispatchPtr) books.invoke("Add");
      DispatchPtr sheets = (DispatchPtr)book.get("Worksheets");
      DispatchPtr sheet = (DispatchPtr)sheets.get("Item", new Integer(1));

      // Create a range which contains 3 cells
      DispatchPtr range1 = (DispatchPtr)sheet.get("Range", "A1:A3");

      // This will fill cells A1, A2 and A3 with "TestValue"
      range1.put("Value", "TestValue");

      // The three cells get value "TestValue1".
      // The other values get ignored!
      DispatchPtr range2 = (DispatchPtr)sheet.get("Range", "B1:B3");
      range2.put("Value2", new String[]
         {"TestValue1", "TestValue2", "TestValue3"});

      // Try a 2-dimensional array instead. Cells remain empty.
      DispatchPtr range3 = (DispatchPtr)sheet.get("Range", "C1:C3");
      range3.put("Value", new String[][] {
        {"TestValue1"},
        {"TestValue2"},
        {"TestValue3"}});

      // Maybe this way? Nope, doesn't work either.
      range3.put("Value", new String[][] {  {"TestValue1", "TestValue2",
"TestValue3"}});

      // Try filling a row instead. That works!
      // The three cells get different values.
      DispatchPtr range4 = (DispatchPtr)sheet.get("Range", "D1:F1");
      range4.put("Value", new String[]
        {"TestValue1", "TestValue2", "TestValue3"});

      Ole32.CoUninitialize();
    } catch (COMException exc) {
      exc.printStackTrace();
    }
  }
}

Am I doing something wrong or does Jawin have no support for 2d arrays? It
would be great if anyone can help me with this!

-- Frank

NOTICE: This communication, including any attachment, contains information
that may be confidential or privileged,
and is intended solely for the entity or individual to whom it is addressed.
If you are not the intended recipient, please notify
 the sender at once, and you should delete this message and are hereby
notified that any disclosure, copying, or distribution
of this message is strictly prohibited. Nothing in this email, including any
attachment, is intended to be a legally binding signature.