Встраивание 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");
}
}