0

我查看了包含的最新版本 Java Com Bridge (jacob-1.16) 的 Excel 示例,有点失望,因为它创建并处理了一个全新的 Excel 文件。

我想做的是从 Java 访问现有的 Excel 文件,在本例中名为“JACOBWithExcel.xls”,但任何 Excel 文件都应该没问题。

Excel 的 SourceForge 示例在我的机器上运行良好,当我修改它以访问现有的 Excel 文件时,我遇到了以下问题:

1.,我无法在工作簿中获取现有工作表,即使我正在尝试以与获取工作簿相同的方式:

Dispatch sheet = Dispatch.get(workbook, "Worksheets").toDispatch();  
Dispatch.call(sheet, "Select", new Object[]{"Sheet2"}).toDispatch();

此代码将生成以下异常:com.jacob.com.ComFailException: Can't map name to dispid: Worksheets

2.; 无法保存工作簿:

// Save the open workbook as "C:\jacob-1.16-M1\Test1.xls" file:
Dispatch.call(workbook, "SaveAs", new Variant("C:\\jacob-1.16-M1\\Test1.xls"),new   Variant("1"));

此代码将生成以下异常:com.jacob.com.ComFailException: Can't map name to dispid: SaveAs

3.; 我不知道如何开始使用以下简单但非常常见的 Excel 操作,就 Java COM 桥的 Java 语法而言:

(包括这里我试图用 Java 实现的 Excel VBA 代码)

选择单个单元格: Range("A4").Select

将选定范围复制到剪贴板:

Selection.Copy

选择要复制到的多单元格范围:

Range("D9:D17").Select

将剪贴板内容粘贴到选择:

ActiveSheet.Paste

重命名工作表:

Sheets("Sheet2").Select
Sheets("Sheet2").Name = "MySheet2"

格式化单元格,例如文本:

Selection.NumberFormat = "@"

删除行:

Rows(intI).Select
Selection.Delete Shift:=xlUp

并且可能...

对选择进行排序:

Selection.Sort Key1:=Range("A2"), Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=1, MatchCase:=False,  Orientation:=xlTopToBottom

查找工作表中的最后一个单元格:

ActiveSheet.Cells(65536, 1).End(xlUp).Select
intLastCellRow = Selection.Row

谢谢您的帮助。

PS:

应用程序的完整代码:

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

public class TestJACOBWithExcel {
public static void main(String[] args) {

String strInputDoc = "C:\\jacob-1.16-M1\\JACOBWithExcel.xls";  // file to be opened.

ComThread.InitSTA();

ActiveXComponent xl = new ActiveXComponent("Excel.Application"); // Instance of application object created.

try {
// Get Excel application object properties in 2 ways:
System.out.println("version=" + xl.getProperty("Version"));
System.out.println("version=" + Dispatch.get(xl, "Version"));

// Make Excel instance visible:
Dispatch.put(xl, "Visible", new Variant(true));

// Open XLS file, get the workbooks object required for access:
Dispatch workbook = xl.getProperty("Workbooks").toDispatch();
Dispatch.call(workbook, "Open", new Variant(strInputDoc),new Variant("1"));

Dispatch sheet = Dispatch.get(workbook, "Worksheets").toDispatch();
Dispatch.call(sheet, "Select", new Object[]{"Sheet2"}).toDispatch();

// put in a value in cell A22 and place a a formula in cell A23:
Dispatch a22 = Dispatch.invoke(sheet, "Range", Dispatch.Get, new Object[] { "A22" }, new int[1]).toDispatch();

Dispatch a23 = Dispatch.invoke(sheet, "Range", Dispatch.Get, new Object[] { "A23" }, new int[1]).toDispatch();

Dispatch.put(a22, "Value", "123.456");
Dispatch.put(a23, "Formula", "=A22*2");

// Get values from cells A1 and A2
System.out.println("a22 from excel:" + Dispatch.get(a22, "Value"));
System.out.println("a23 from excel:" + Dispatch.get(a23, "Value"));

// Save the open workbook as "C:\jacob-1.16-M1\Test1.xls" file:
Dispatch.call(workbook, "SaveAs", new Variant("C:\\jacob-1.16-M1\\Test1.xls"),new Variant("1"));

// Close the Excel workbook without saving:
Variant saveYesNo = new Variant(false);
Dispatch.call(workbook, "Close", saveYesNo);

} catch (Exception e) {
e.printStackTrace();
} finally {

// Quit Excel:
// xl.invoke("Quit", new Variant[] {});
ComThread.Release();
}

}
}
4

2 回答 2

0

嗨,

实际上我现在只能回答你的第一个问题。我使用此代码,它适用于 *.xltx 模板文件:

File file = new File("pathToOurTemplate");
ActiveXComponent excel = null;
  ComThread.InitSTA();
  try {
    excel = new ActiveXComponent("Excel.Application");
    Dispatch excelObject = excel.getObject();
    Dispatch workbooks = excel.getProperty("Workbooks").toDispatch();
    Dispatch workbook = Dispatch.call(workbooks, "Add", file.getAbsolutePath()).toDispatch();
} catch (...) 
//...

至少适用于 Office 2010、Java6_u23、Jacob 1.15_M4

希望这对第一次拍摄有所帮助/这比示例中显示的要多(我猜你看过那些)。

于 2012-03-12T18:27:35.533 回答
0

免责声明:在这个答案中,我将用双引号引用 MS Excel 对象属性、方法和对象类型,以避免一些混淆。我对这个问题的回答如下。

你好,

了解 excel API 所具有的层次结构很重要。并且还搜索在每个层次结构级别上可用的方法、属性或事件类型。我现在要回答你的问题。

在问题 1 中,您说您无法打开正确的工作表,那是因为您在错误类型的对象上获得了属性“工作表”。在您的代码片段中

Dispatch sheet = Dispatch.get(workbook, "Worksheets").toDispatch();
Dispatch.call(sheet, "Select", new Object[]{"Sheet2"}).toDispatch();

您在“工作簿”类型的对象上获得属性“工作表”,这是不正确的。该文档https://msdn.microsoft.com/EN-US/library/office/ff841074.aspx显示,“工作簿”没有属性“工作表”。问题在于您如何打开具体的“工作簿”对象。

Dispatch workbook = xl.getProperty("Workbooks").toDispatch();
Dispatch.call(workbook, "Open", new Variant(strInputDoc),new Variant("1"));

您在“工作簿”对象上调用方法“打开”,根据文档具有此方法,它会为您打开 MS Excel。问题是变量“调度工作簿”仍然是“工作簿”类型的对象,而不是您错误假设的“工作簿”。正确的方法是保存“打开”方法调用的返回值,它为您提供具体的“工作簿”对象,然后使用可用于该类型对象的方法。完全按照这里的 MS 文档https://msdn.microsoft.com/en-us/library/office/ff194819.aspx

所以打开具体工作表的正确方法是这样的:

//get "Workbooks" property from "Application" object
Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
//call method "Open" with filepath param on "Workbooks" object and save "Workbook" object
Dispatch workbook = Dispatch.call(workbooks, "Open", new Variant(strInputDoc)).toDispatch();
//get "Worksheets" property from "Workbook" object
Dispatch sheets = Dispatch.get(workbook, "Worksheets").toDispatch();
//Call method "Select" on "Worksheets" object with "Sheet2" param   
Dispatch.call(sheets, "Select", new Object[]{"Sheet2"}).toDispatch();
//probably again save "Worksheet" object and continue same way

问题 2 中的问题与问题 1 中的问题相同。

//calling method "SaveAs" on "Workbooks" object instead of "Workbook" type
Dispatch.call(workbook, "SaveAs", new Variant("C:\\jacob-1.16-M1\\Test1.xls"),new   Variant("1"));

所有其他问题与前两个问题的原理相同。在正确的 MS 对象上获取属性或调用方法。也不能强调,MS 文档对于任何使用 java-excel 通信的人来说是多么重要。

将仅提及一个示例,如何从某些 MS 对象中获取实际值。假设您想要“范围”对象内的值,因为获取需要参数的对象的属性与普通值属性的完成方式有些不同。为此,您需要先获取“工作表”对象并从中获取“范围”属性。

//lets say we have already some "Worksheet" object
Dispatch worksheet = ...;
//we want a property "Range" of "Worksheet" object with some macro
Variant range = Dispatch.invoke(worksheet, "Range", Dispatch.Get, new Object[]{"A1:L10"}, new int[1]);
//according to docu, you can specify format in which the value is returned
//im using 12 which is one of XML formats available
//in case no such param is provided default "textTable" format is returned
Variant value = Dispatch.invoke(range.getDispatch(), "Value", Dispatch.Get, new Object[]{12}, new int[1]);
//and get the value from it and you are done with MS Excel-Java communication
String xmlFormat = value.toString();



Worksheet.Range property docu:
msdn.microsoft.com/en-us/library/office/ff836512.aspx
Range.Value docu:
msdn.microsoft.com/en-us/library/office/ff195193.aspx

我不允许发布超过 2 个链接,如果这些链接不能正常工作,我很抱歉。

于 2016-12-02T10:43:48.727 回答