https://github.com/zytc2009/BigTeam_learning
分类: Java
2010-11-08 16:57:16
使用的Eclipse版本:3.3.1
使用的jdk版本:5.0
显示结果:\
注意
嵌入Excel的方法是createExcelPart(Shell shell)
Excel.Sheet为Excel的Id,如果要嵌入Word,则其Id为Word.Document
这是OleClientSite#doVerb()的参数的解释及可选的值:
verb – an integer value mapping to one of the following pre-defined verb values:
· OLE.OLEIVERB_PRIMARY - Specifies the action that occurs when an end user double-clicks the object in its container. The object, not the container, determines this action. If the object supports in-place activation, the primary verb usually activates the object in place.
· OLE.OLEIVERB_SHOW - Instructs an object to show itself for editing or viewing. Called to display newly inserted objects for initial editing and to show link sources. Usually an alias for some other object-defined verb.
· OLE.OLEIVERB_OPEN - Instructs an object, including one that otherwise supports in-place activation, to open itself for editing in a window separate from that of its container. If the object does not support in-place activation, this verb has the same semantics as OLEIVERB_SHOW.
· OLE.OLEIVERB_HIDE - Causes an object to remove its user interface from the view. Applies only to objects that are activated in-place.
· OLE.OLEIVERB_INPLACEACTIVATE - Activates an object in place without displaying tools, such as menus and toolbars, that end users need to change the behavior or appearance of the object. Single-clicking such an object causes it to negotiate the display of its user-interface tools with its container. If the container refuses, the object remains active but without its tools displayed.
· OLE.OLEIVERB_UIACTIVATE - Activates an object in place, along with its full set of user-interface tools, including menus, toolbars, and its name in the title bar of the container window.
· OLE.OLEIVERB_DISCARDUNDOSTATE - Used to tell objects to discard any undo state that they may be maintaining without deactivating the object.
如果光看解释看不明白的话,可以实际操作看看效果
package com.jrkui.example.excel;
import java.io.File;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.Variant;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
public class ExcelShell {
public static void main(String[] args) {
new ExcelShell().open();
}
public void open()
{
Display display = Display.getDefault();
Shell shell = new Shell();
shell.setSize(600,400);
shell.setText("Excel Window");
shell.setLayout(new FillLayout());
//使Excel的菜单栏显示
shell.setMenuBar(new Menu(shell,SWT.BAR));
createExcelPart(shell);
shell.open();
while(!shell.isDisposed()){
if(!display.readAndDispatch())
display.sleep();
}
display.close();
}
/**
* 使Excel嵌入到shell中
* @param shell
*/
private void createExcelPart(Shell shell)
{
//OleFrame实际上是一个Composite,用于放置OLE控件
OleFrame oleFrame = new OleFrame(shell,SWT.NONE);
//OleClientSite提供一个场所用于把OLE对象嵌入到容器中,在这里“Excel.Sheet”表示的OLE对象是Excel
OleClientSite clientSite = new OleClientSite(oleFrame,SWT.NONE,"Excel.Sheet");
setValueForA1Cell(clientSite);
//OleClientSite在显示OLE对象时所做的动作,这里的动作是OLEIVERB_SHOW,显示
clientSite.doVerb(OLE.OLEIVERB_SHOW);
}
/**
* Sheet的Id
*/
private static final int SHEET_ID = 0x000001e5;
/**
* 单元格的Id
*/
private static final int CELL_ID = 0x000000c5;
/**
* 单元格值的Id
*/
private static final int CELL_VALUE_ID = 0x00000006;
/**
* 为第一个Sheet页的A1单元格赋值
* @param clientSite
*/
private void setValueForA1Cell(OleClientSite clientSite)
{
//获得Excel的workbook对象
OleAutomation workbook = new OleAutomation(clientSite);
//获得workbook的第一个Sheet页
OleAutomation sheet = workbook.getProperty(SHEET_ID,new Variant[]{new Variant(1)}).getAutomation();
//获得Sheet页的A1单元格
Variant cellA1Variant = sheet.getProperty(CELL_ID, new Variant[]{new Variant("A1")});
OleAutomation cellA1 = cellA1Variant.getAutomation();
//为A1单元格赋值
cellA1.setProperty(CELL_VALUE_ID, new Variant("Hello OLE!"));
//获得A1单元格的值并输出到控制台上
System.out.println(cellA1Variant.getString());
}
}
显示效果:
控制台输出:Hello OLE!
解释:
l 原理:
? 使用SWT进行OLE操作时,所有的对OLE对象的引用都是通过OlE定义的Id获得,获得各个对象的Id方法稍后会进行说明
? 所有的动作都通过OleAutomation对象进行,OleAutomation可以代表任一OLE对象,如Workbook、Worksheet、Range。可以通过getProperty()方法获得它的属性,也可以用setProperty()方法为它的属性赋值
? Variant对象一般是封装了OLE对象的值,可以通过它进行值传入及获得相应的值,也可以通过它获得OleAutomation对象
? 如果想对单元格进行操作(如:赋值、取值),则:
ü 首先要取得Workbook的引用:
OleAutomation workbook = new OleAutomation(clientSite);
在这里OleClientSite对象就代表着Workbook对象,需要把OleClientSite转换成OleAutomation对象以便进行下一步动作
ü 然后需要获得第一个Sheet页的引用:
OleAutomation sheet = workbook.getProperty(SHEET_ID,new Variant[]{new Variant(1)}).getAutomation();
需要知道Worksheet的Id(0x000001e5),因为在OLE中获得Worksheet的方法是的返回值是一个数组,所以需要传入一个参数“1”,表示数组的第一个元素,在这里参数“1”是通 过new Variant[]{new Variant(1)}传入的
ü 获得A1单元格的引用:
Variant cellA1Variant = sheet.getProperty(CELL_ID, new Variant[]{new Variant("A1")});OleAutomation cellA1 = cellA1Variant.getAutomation();
在OLE中代表单元格的是Range:范围,可以表示一个单元格也可以表示一个单元格区域。实际上一个单元格就是一个特殊的Range, Range的Id是0x000000c5。Range是通过Worksheet 获得的,需要传入的参数为字符串(用Variant进行包装),可以为一个(代表一个单元格,如new Variant[]{new Variant("A1")}),也可以为两个(代表一个单元格区域,如new Variant[]{new Variant("A1"), new Variant("D4")}),因为我们要对单元格进行赋值,所以需要获得Range的OleAutomation对象
ü 为A1单元格赋值:
cellA1.setProperty(CELL_VALUE_ID, new Variant("Hello OLE!"));
Range的值(Value)的属性的Id是0x00000006,在这里传入一个字符串作为单元格的值
ü 获得A1单元格的值:
System.out.println(cellA1Variant.getString());
取值的动作需要通过Variant对象进行,所以获得A1单元格的值就需要通过cellA1Variant对象
l 获得OLE对象的Id
? 微软提供一个工具OleView.exe,可列出当前机器上的所有类别信息,以及每一种类别下的组件对象列表,这个工具貌似可以从VS或VC上获得,如果没有这个工具的话也可以上网下,我下的版本在使用的时候少了一个dll库,这个也可以上网去下
? 查找Excel的Id:
Excel的Id在Document ObjectsàMicrosoft Excel WorkSheet项里,选中这一项可以看到有一些tab页,其中在Registry tab页中记录了该项的详细休息,一项项找,可以发现Excel在我的机子 上的Id是Excel.Sheet (VersionIndependentProgID = Excel.Sheet),通过这个Id就可以使用new OleClientSite(oleFrame,SWT.NONE,"Excel.Sheet")这个方法获得Excel的引用了
? 查找Excel组件下的对象(如,WorkSheet、Range)需要打开另一个窗口ITypeLib Viewer:
右键点击Microsoft Excel WorkSheetà选择View Type Information…
? 获得WorkSheet(因为这个工具没有查找的功能,所以找起来有点费劲,点击Toolbar上的第二个按钮可以进行分类):
因为WorkSheet是通过Workbook获得的(是它的一个属性),而Workbook已经通过OleAutomation workbook = new OleAutomation(clientSite)方法获得了,所以这时候我们查找WorkSheet要 在Workbook中找
ü 找到dispinterface _Workbooks (注意:有下划线。如果使用了分类功能,在Dispinterfaces节点下)
ü 打开Methods节点(Methods:顾名思义,表示该对象的所有方法的集合)
ü 在众多Method中找到Sheets:
可以在右边的信息框中知道,这个方法是获得一组Sheets(WorkSheet),其id是0x000001e5,是一个proget类型的方法(get类型),帮助文档的id是0x000101e5(一般用不上),方法描述是Sheets* Sheets();,没有参数
? 获得单元格也是同样的道理
ü 找到dispinterface _Worksheet
ü 找到MethodsàRange,得知:这个方法是获得一组Range对象,是一个是一个proget类型的方法(get类型),方法描述是Range* Range([in] VARIANT Cell1, [in, optional] VARIANT Cell2),这里的“in”表示传入的参数,“optional”表示这个参数是可选的,即可要可不要。
ü 传入的参数以单元格的location表示(如:A1,D2,E5),一个参数表示一个单元格,两个参数表示两个参数代表的单元格区域(如:A1 * D5)
? 查找单元格的Value的属性
ü 找到dispinterface Range
ü 找到MethodsàValue,这里会发现有两个Value,实际上它们的Id都是一样,但是代表不同的意思,一个是获得Range的Value属性(proget),一个是为Range的Value属性赋值(propput)
ü 为Value属性赋值,方法描述是void Value([in, optional] VARIANT RangeValueDataType, [in] VARIANT rhs)
ü 获得Value属性的值,方法描述是VARIANT Value([in, optional] VARIANT RangeValueDataType)