Встраивание Office в Java

Я пытаюсь получить приложение Office 2007/2010, встроенное в приложение Java, используя SWT, используя следующий код:

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]);
    }
}

Когда я не пытаюсь вызвать "Открыть" на объекте документа, Word успешно внедряется внутри приложения, но все меню файлов отключено. Когда я вызываю "Открыть", приложение выходит из строя со следующей ошибкой (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)

Кто-нибудь знает, как исправить эту проблему или альтернативное решение для интеграции приложений Office в Java? Спасибо!



Обновление:

Запрос идентификаторов для "Open" и "FileName" по умолчанию возвращает null для "FileName", поэтому он неверен. Я также пробовал без именованного параметра без каких-либо успехов:

documents.invokeNoReply(automationIDs[0], arguments);

Ответ 1

Почему вы не выполняете обработку ошибок, проверку результатов или утверждения? Помните, что getIDsOfNames(..) будет отключен и возвратит значения null для непризнанных имен.

Попробуйте напечатать значение documents.getLastError() после того, как поймаете исключение.

Ответ 2

Вам нужно использовать Word.Application, потому что Word.Document не позволит вам использовать функции автоматизации, это мой опыт, по крайней мере. Когда я реализовал автоматизацию и Ole, я сделал это за 2 шага.

  • Документ с открытым текстом в режиме автоматизации (Word.Application), задачи автоматизации dosome и закрытые
  • Открытый документ Word как Word.Document. Задачи автоматизации не работали, но это был объект OLE. Пользователь может редактировать документ, но параметры сохранения отключены. Однако вы можете добавить дополнительное меню и сделать что-то вроде Ole.Save. Затем захваченный документ может быть обработан.

Здесь вы найдете пример того, как открыть документ в Word.Application. Затем, согласно моему опыту, вы должны сохранить его и открыть в OLE как Word.Document. Показывать Word.Application можно пропустить.

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

import org.eclipse.swt.SWT;
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 = new Shell(display);
        OleFrame oleFrame = new OleFrame(shell, SWT.NONE);
        OleClientSite oleClientSite = new OleClientSite(oleFrame, SWT.NONE, "Word.Application");
        OleAutomation word = new OleAutomation(oleClientSite);



    Variant[] arguments;


    //open the file
    int[] id1 = word.getIDsOfNames(new String[]{"Documents"});
    Variant pVarResult = word.getProperty(id1[0]);
    OleAutomation resultDocuments = pVarResult.getAutomation();

    int[] id2 = resultDocuments.getIDsOfNames(new String[]{"Open"});

    arguments = new Variant[1];
    arguments[0] = new Variant(target);
    Variant invokeResult = resultDocuments.invoke(id2[0], arguments);

    resultDocuments.getIDsOfNames(new String[]{"ActiveDocument"});


     //show the word app, not necessary        
    arguments=new Variant[1];
    arguments[0] = new Variant(true);
    int[] id3 = word.getIDsOfNames(new String[]{"Visible"});
    word.setProperty(id3[0], arguments); 


        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("d:\\aaa.doc");
    }
}

Ответ 3

Я обновил код для использования OleClientSite вместо OleControlSite, и он работает для меня.

package com.test.swt;

import java.awt.Canvas;
import java.io.File;

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.OLE;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class EmbeddingTest extends Canvas {
private static final long serialVersionUID = 1L;

public 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);

    OleClientSite oleControlSite = new OleClientSite(oleFrame, SWT.NONE, "Word.Document", new File(target));
    oleControlSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
    shell.setSize(800, 600);
    shell.open();
    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("C:\\Users\\test.docx");
}
}