Доступ к таблицам, сохранение файлов Excel, Java, Java Com Bridge (Jacob jacob-1.16) - PullRequest
0 голосов
/ 09 января 2012

Я посмотрел на прилагаемый пример Excel последней версии Java Com Bridge (jacob-1.16) и был немного разочарован, потому что он создает новый файл Excel и работает с ним.

Я хотел бы иметь доступ к существующему файлу Excel из Java, в данном случае с именем 'JACOBWithExcel.xls', но с любым файлом Excel все должно быть в порядке.

Пример SourceForge для Excel отлично работает на моем компьютере, и когда я изменил его для доступа к существующему файлу Excel, я столкнулся со следующими проблемами:

1. Я не смог получить существующий лист в книге, хотя я пытаюсь так же, как я получил книгу:

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

Этот код сгенерирует следующее исключение: com.jacob.com.ComFailException: Невозможно сопоставить имя для dispid: Рабочие таблицы

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: Невозможно сопоставить имя для dispid: SaveAs

3 .; Я не знаю, как начать работу со следующими простыми, но очень распространенными операциями Excel, насколько синтаксис Java для Java COM bridge:

(Включен здесь код Excel VBA, который я пытаюсь реализовать в Java)

Выбор одной ячейки: Range ( "A4"). Выберите

Скопировать выбранный диапазон в буфер обмена:

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

Спасибо за вашу помощь.

P.S:.

Полный код приложения:

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

}
}

Ответы [ 2 ]

0 голосов
/ 02 декабря 2016

Отказ от ответственности: в этом ответе я буду ссылаться на свойства объекта MS Excel, методы и типы объектов в двойных кавычках, чтобы избежать путаницы.Мой ответ на этот вопрос следующий:

Привет,

. Важно понимать иерархию, которой обладает API Excel.А также поиск, какие типы методов, свойств или событий доступны на каждом уровне иерархии.Сейчас я собираюсь ответить на ваши вопросы.

В вопросе 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.Проблема в том, что переменная «Отправка рабочей книги» по-прежнему является объектом типа «Рабочие книги», а не «Рабочая книга», что вы ошибочно предположили.Правильным способом является сохранение возвращаемого значения вашего вызова метода «Open», который дает вам конкретный объект «Workbook» и после этого использует методы, доступные для этого типа объекта.Точно следующий документ 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.Допустим, вам нужны значения внутри объекта Range, потому что получение свойств объектов, которые требуют параметров, выполняется немного иначе, чем свойство обычного значения.Для этого вам нужно сначала перейти к объекту «Рабочий лист» и получить из него свойство «Диапазон».

//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 ссылок, поэтому извините, если эти ссылки не работают должным образом.

0 голосов
/ 12 марта 2012

Hy,

на самом деле я могу ответить только на ваш первый вопрос прямо сейчас. Я использую этот код, и он работает для * .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

Надеюсь, что это поможет для первого выстрела / это больше, чем вам нужно, чем показано в примерах (думаю, вы посмотрели на них)

...