views:

348

answers:

1

I'm trying to get Office 2007/2010 application embedded inside a Java application using SWT using the following code:

import java.awt.Canvas;
import javax.swing.JFrame;

import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.ole.win32.*;
import org.eclipse.swt.widgets.*;

public class EmbeddingTest extends Canvas {
    private void initOleViewer(String target) {
        Display display = new Display();
        Shell shell = SWT_AWT.new_Shell(display, this);
        shell.setLayout(new FillLayout());

        OleFrame oleFrame = new OleFrame(shell, SWT.NONE);

        OleControlSite oleControlSite = new OleControlSite(oleFrame, SWT.NONE, "Word.Document");
        oleControlSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);

        OleAutomation word = new OleAutomation(oleControlSite);

        int[] applicationId = word.getIDsOfNames(new String[]{"Application"});
        Variant property = word.getProperty(applicationId[0]);
        OleAutomation application = property.getAutomation();

        int[] documentId = application.getIDsOfNames(new String[]{"Documents"});            
        property = application.getProperty(documentId[0]);
        OleAutomation documents = property.getAutomation();

        shell.open();
        Variant[] arguments = new Variant[] { new Variant(target) };
        int[] automationIDs = documents.getIDsOfNames(new String[]{"Open", "FileName"});
        documents.invokeNoReply(automationIDs[0], arguments, new int[]{automationIDs[1]});

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    public static void main(String[] args) {
        JFrame jFrame = new JFrame("Embedding Test");
        jFrame.setVisible(true);

        EmbeddingTest viewer = new EmbeddingTest();
        jFrame.add(viewer);
        jFrame.setSize(600, 600);

        viewer.initOleViewer(args[0]);
    }
}

When I don't try to call 'Open' on the document object Word embeds successfully inside the application but the whole file menu is disabled. When I call 'Open' the application crashes with the following error (DISP_E_EXCEPTION):

Exception in thread "main" org.eclipse.swt.SWTException: Action can not be performed. result = -2147352567
 at org.eclipse.swt.ole.win32.OLE.error(Unknown Source)
 at org.eclipse.swt.ole.win32.OleAutomation.invokeNoReply(Unknown Source)
 at EmbeddingTest.initOleViewer(EmbeddingTest.java:68)
 at EmbeddingTest.main(EmbeddingTest.java:88)

Does anyone know how to fix this problem or an alternative solution to embed Office apps in Java? Thanks!



Update:

Querying the IDs for 'Open' and 'FileName' separately returns null for 'FileName' so its incorrect. I've also tried without the named parameter without any success:

documents.invokeNoReply(automationIDs[0], arguments);
+1  A: 

Why aren't you doing any error handling, result checking, or assertions? Remember that getIDsOfNames(..) will silently fail and return null values for unrecognized names.

Try printing the value ofdocuments.getLastError() after catching the offending exception.

Gunslinger47
'FileName' seems to be a problem since it returns an ID of 0. But documents.getLastError() just returns null.
Luke Quinane
@Luke: The docs say it should be `null` in case of an error, so the filename ID could still be correct. Perhaps indicating that it's the 0th parameter? Speaking of docs, do you have a link for the `Word.Document` specification?
Gunslinger47
Here's the documentation that I've been looking at: http://msdn.microsoft.com/en-us/library/bb216319(office.12).aspx
Luke Quinane
I wonder why `Format` is listed as "Required" there when there are code examples where it isn't used? Anyway, @Luke, are you using absolute or relative paths? It could be as simple as file-not-found or even an unsupported file type or corrupted file.
Gunslinger47