在 Java 中嵌入 Office

发布于 2024-09-10 02:48:48 字数 2649 浏览 4 评论 0原文

我正在尝试使用 SWT 使用以下代码将 Office 2007/2010 应用程序嵌入到 Java 应用程序中:

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):

线程“main”中出现异常 org.eclipse.swt.SWTException:无法执行操作。结果=-2147352567
 在 org.eclipse.swt.ole.win32.OLE.error(来源未知)
 在 org.eclipse.swt.ole.win32.OleAutomation.invokeNoReply(来源未知)
 在 EmbeddingTest.initOleViewer(EmbeddingTest.java:68)
 在 EmbeddingTest.main(EmbeddingTest.java:88)

有谁知道如何解决此问题或在 Java 中嵌入 Office 应用程序的替代解决方案?谢谢!



更新:

单独查询“Open”和“FileName”的 ID 会为“FileName”返回 null,因此它不正确。我也尝试过不使用命名参数,但没有成功:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

山有枢 2024-09-17 02:48:48

为什么不进行任何错误处理、结果检查或断言?请记住,getIDsOfNames(..) 将默默失败,并为无法识别的名称返回 null 值。

捕获有问题的异常后,尝试打印 documents.getLastError() 的值。

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.

叹梦 2024-09-17 02:48:48

您需要使用Word.Application,因为Word.Document不会让您使用自动化功能,至少这是我的经验。当我实施自动化和 Ole 时,我分两步完成。

  1. 以自动化模式(Word.Application)打开Word文档,执行一些自动化任务并关闭
  2. 打开的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");
    }
}

You need to use Word.Application, because Word.Document will not let you use automation features, this is my experience at least. When I implemented automation and Ole I did it in 2 steps.

  1. Opened word document in automation mode (Word.Application), didsome automation tasks and closed
  2. Opened word document as Word.Document. Automation tasks did not work, but it was an OLE object. User can edit document, but save options are disabled. You can however add extra menu and do something like Ole.Save. Then captured document can be processed furter.

Here you find example of how to open document in Word.Application.
Then according to my experience you should save it and open in OLE as Word.Document.
Showing Word.Application can be skipped.

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");
    }
}
伏妖词 2024-09-17 02:48:48

我已更新代码以使用 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");
}
}

I have updated the code to use OleClientSite instead of OleControlSite and it works for me.

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");
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文