代碼:
packagecom.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!
解釋:
原理:
使用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對象
獲得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();,沒有參數
可以在右邊的信息框中知道,這個方法是獲得一組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)