Макрос для excel на java

I need to generate an Excel sheet from the data fetched from a database through Java.
For that, I need to call some VBA Macro functions while generating that Excel.
Can anybody help me with how to call VBA Macro from Java code?

Gaffi's user avatar

Gaffi

4,3118 gold badges45 silver badges73 bronze badges

asked Oct 17, 2011 at 5:41

Parth Trivedi's user avatar

1

I don’t really understand your overall approach to generate Excel sheet from the data in a database. Normally, I’d use Apache POI as proposed by Vivek.

However, if you really need to call an Excel macro in a sheet, then you need two things:

First, you need a JAVA-to-COM bridge like JACOB, COM4J or a similar tool. It is sufficient if it supports automation interfaces. It doesn’t need to have full COM support.

Second, using the JAVA-to-COM bridge, you should start Excel, load the Excel sheet, run the macro, save it and close Excel. So you have to call the equivalent of:

Set Wb = Application.Workbooks.Open FileName
Application.Run MacroName
Wb.Save
Application.Quit

answered Oct 17, 2011 at 6:17

Codo's user avatar

CodoCodo

73.9k17 gold badges165 silver badges201 bronze badges

0

If you can’t use JACOB or COM4J you can make a Visual Basic Script and run the script from your Java program.

To create the script open notepad and write something like this:

Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("myExcel.xlsm")

objExcel.Application.Run "myExcel.xlsm!MyMacroName" 
objExcel.ActiveWorkbook.Close

objExcel.Application.Quit
WScript.Quit

Save it as myVBS.vbs and you can call it like this from your Java code:

cmd = "you_path\myVBS.vbs";
Runtime.getRuntime().exec(cmd);

Nathaniel Ford's user avatar

answered Aug 27, 2015 at 18:20

Luis Herrería's user avatar

You might also be able to capture an event in excel when a worksheet changes you can have the even call whatever macro you want it to, so if you want to call the macro «Blue» you can write «blue» in a hidden worksheet then Excel will capture the change, when you capture the change you can see what was written and do some if ifelse statements to get to the macro you want to call for that instance. Not really good coding, but an easy workaround. I would do the other methods myself though.

answered Oct 17, 2011 at 17:35

Jon49's user avatar

Jon49Jon49

4,3844 gold badges36 silver badges73 bronze badges

4

solution that works for me:
java code:

try {
Runtime.getRuntime().exec("wscript yourPth\myVBS.vbs");
} catch (IOException e) {
System.out.println(e);
System.exit(0);
}

myVBS.vbs script:

Set objShell = CreateObject("WScript.Shell")
Dim cur
cur = "urpath to myVBS.vbs script"
WScript.Echo cur

ExcelMacroExample

Sub ExcelMacroExample() 

Dim xlApp 
Dim xlBook 
Dim xlsFile
xlsFile = cur & "myExcel.xlsm"

Set xlApp = CreateObject("Excel.Application") 
Set xlBook = xlApp.Workbooks.Open(xlsFile) 
xlApp.Run "moduleName"
xlApp.Save
xlApp.Quit 

End Sub 

answered May 16, 2018 at 12:19

Rahul k's user avatar

I am not sure if it is possible to call macro directly from Java. But you can populate the data in excel sheet & call the macro when the user opens the excel sheet for the first time. You would be able to populate data in a excel sheet containing macros using Apache POI tool — http://poi.apache.org/spreadsheet/index.html

answered Oct 17, 2011 at 5:47

Vivek Viswanathan's user avatar

3

Время на прочтение
3 мин

Количество просмотров 44K

Работа с таблицей Excel из Java

Собственно возникла проблема — обработать данные из таблицы и на их основе получить другую таблицу.

Вариантов решения этой проблемы несколько:

  1. Макрос — единственной проблемой является VBA, на изучение которого времени нет совершенно, да и не нравится его синтаксис
  2. Приложение на C# тут вроде все хорошо, но к машине на которой будет выполняться данное приложение сразу предъявляется много дополнительных требований:
    • .NET Framework
    • Установленный офис
    • установленная основная сборка взаимодействия (PIA) для приложения Office

  3. связка Java и библиотека Apache POI—на этом способе я и хочу остановиться подробнее

Apache POI — это Java API для доступа к документам формата Microsoft.

Собственно для работы с таблицами Excel предназначен проект POI-HSSF. На данный момент есть 2 варианта библиотеки:

  1. POI 3.5 beta 5, and Office Open XML Support (2009-02-19)—идет работа над поддержкой формата Office 2007
  2. POI 3.2-FINAL Released (2008-10-19) — последний стабильный релиз

Я расскажу о работе с версией 3.2
Основным классом для работы с таблицей Excel является класс HSSFWorkbook пакета org.apache.poi.hssf.usermodel, представляющий книгу Excel.

Для чтения книги из файла можно применить следующий код:

public static HSSFWorkbook readWorkbook(String filename) {
       try {
               POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filename));
               HSSFWorkbook wb = new HSSFWorkbook(fs);
               return wb;
       }
       catch (Exception e) {
               return null;
       }
}

Метод возвращает объект класса HSSFWorkbook если все удачно и null в другом случае.

Для сохранения изменений можно применить следующий метод:

public static void writeWorkbook(HSSFWorkbook wb, String fileName) {
       try {
               FileOutputStream fileOut = new FileOutputStream(fileName);
               wb.write(fileOut);
               fileOut.close();
       }
       catch (Exception e) {
               //Обработка ошибки
       }
}        

Метод записывает книгу wb в файл fileName

Для работы с листами рабочей книги предназначен класс HSSFSheet.
Объект класса HSSFSheet можно получить следующими способами:

  • По имени
    HSSFSheet sheet= wb.getSheet("Лист 3")
  • По номеру (нумерация начинается с 0)
    HSSFSheet sheet= wb.getSheet(0)
  • Создание нового листа
    HSSFSheet sheet= wb.createSheet(["имя листа"])

Следующим объектом является строка — HSSFRow.
Получить доступ к объекту строки можно также 3 способами:

  • По индексу (индексация начинается с 0)
    HSSFRow row = sheet.getRow(index)
  • Через итератор

    Iterator rowIter = sheet.rowIterator();
    while (rowIter.hasNext()) {
           HSSFRow row = (HSSFRow) rowIter.next();
    }

  • Создание новой строки
    HSSFRow row=sheet.createRow(0);

Ну и последним объектом на пути доступа к данным является объект класса HSSFCell — ячейка строки.
Получить доступ к ячейке можно из объекта строки следующими способами:

  • По индексу ячейки (индексация начинается с 0)
    HSSFCell cell = row.getCell(0);
  • Через итератор

    Iterator cellIter = row.cellIterator();
    while (cellIter.hasNext()) {
           HSSFCell cell = (HSSFCell) cellIter.next();
    }
    

  • Создание новой ячейки
    HSSFCell cell = row.createCell(0);

Из объекта ячейки можно уже получать и устанавливать непосредственно данные:

  • Логическое значение
    boolean b = cell.getBooleanCellValue();
    cell.setCellValue(b);
  • Дата
    Date date = cell.getDateCellValue();
    cell.setCellValue(date);
  • Числовое значение
    double d = cell.getNumericCellValue();
    cell.setCellValue(d);
  • Строковое значение
    String str = cell.getRichStringCellValue().getString();
    cell.setCellValue(new HSSFRichTextString(str));
  • Формула
    String formula = cell.getCellFormula();
    cell.setCellFormula(formula);

Этих знаний достаточно чтобы обрабатывать простые таблицы.
Библиотека также предоставляет богатые возможности по форматированию ячеек, по их слиянию, заморозке и т.д.
Подробное описание функций можно найти на их сайте.
Данный способ прежде всего ценен тем, что не требует установки самого офиса и пакета PIA.


  Перевод


  Ссылка на автора

Excel широко распространен практически на всех рабочих местах. Люди от крупных инвестиционных компаний и крупных инжиниринговых компаний до индивидуальных предпринимателей работают с помощью Excel.

В этой статье мы рассмотрим некоторые проблемыа такжепреимуществаиспользования Excel и как Java встроена в Excel эти проблемы могут быть преодолены.

Вам не нужно далеко ходить, чтобы найти критику Excel и случаев, когда его неправильное использование привело к большим потерям для компаний. За последние несколько лет было много случаев, когда ошибки в электронных таблицах Excel были, по крайней мере, частично виноваты в смущающих и дорогостоящих ошибках.

Excel snafu стоит фирме 24 миллиона долларов

Простая ошибка в электронной таблице стоила фирме колоссальные 24 миллиона долларов США. Ошибка привела к TransAlta, большой канадский генератор энергии …

www.theregister.co.uk

Как лондонская китовая катастрофа отчасти является результатом ошибки при использовании Excel

Это то, о чем люди начинают говорить в блогосфере, что должно дать паузу всей Уолл-стрит. Над…

www.businessinsider.com

С такими рисками, почему компании все еще используют Excel, и что они могут сделать, чтобы предотвратить подобные ситуации?

Основная причина, почему Excel так активно используетсяпроизводительность труда, Кто-то, использующий Excel, может выполнить невероятное количество сложной работы гораздо эффективнее, чем с помощью любого другого инструмента.

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

У большинства компаний нет ресурсов, чтобы иметь разработчиков, предназначенных для каждого бизнес-пользователя, и даже если бы они тогда сообщали о том, что необходимо, и повторяли, чтобы получить желаемый результат, было бы трудно конкурировать с отдельным «собравшимся» таблицей Excel.

Проблемы с Excel

Что в Excel делает его подверженным ошибкам? Само по себе ничего, но разработчики привыкли к этомууменьшитьтакие же риски в решениях, не основанных на Excel. Ниже приведен список некоторых слабых мест в том, как электронные таблицы Excel обычно разрабатываются.

  • Слишком много сложностей, Электронная таблица может начинаться довольно просто с нескольких ячеек и формул. Затем постепенно он растет и растет. Диапазоны дублируются для обработки все большего количества дел или нескольких наборов данных, пока трудно понять, что происходит. Задача все еще может быть достаточно простой, но из-за необходимого дублирования и того факта, что каждая ячейка может содержать только одну единицу данных, электронная таблица может сортироватьвзрыватьсяво что-то слишком сложное.
  • Минимальное или нет тестирование, Таблицы Excel подвергаются очень небольшим испытаниям. Обычно это не модульные тесты, написанные для кода VBA, и единственные функциональные тесты часто выполняются автором электронной таблицы на ограниченном наборе входных данных. Когда другой пользователь должен использовать ту же электронную таблицу, существует высокая вероятность того, что он не знаком с нюансами того, как она работает, и наткнется на какую-то ошибку, для которой никогда не было проверено.
  • Устаревшие или устаревшие данные, Соединить Excel с внешними источниками данных может быть сложно. Он может напрямую подключаться к базе данных, но что, если необходимые вам данные получены другой системой, или у вас нет прямого доступа к нужным данным? Данные часто копируются и вставляются из отчетов из других систем в Excel, часто без возможности узнать, когда данные были скопированы в последний раз или даже если они завершены.
  • Ошибки распространяются из-под контроля, Даже если вы знаете, что в электронной таблице есть ошибка, и вы выяснили, как ее исправить, как найти все экземпляры других электронных таблиц, которые скопировали и вставили один и тот же бит кода VBA, или даже просто копии точно такая же таблица? Скорее всего, вы не можете. Электронные таблицы копируются и отправляются по электронной почте, и между электронной таблицей, данными и кодом нет разделения.
  • Ад контроля версий, Когда вы работаете с большой таблицей и дошли до того, что она стабильна и работает, что вы делаете? Скорее всего, ответ — вы сохраните копию — возможно, с датой, добавленной к имени файла. Это примерно так же, как контроль версий в Excel. Что если изменение имеет непредвиденные последствия? Как вы знаете, когда это изменение было введено? Это почти невозможно!

Как мы можем решить эти проблемы?

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

По сути, Excel — это способ выражения отношений между вещами.A1это суммаB1а такжеС1,например,Где это начинает идти не так, когда эти отношения становятся все более и более сложными

Если бы вы хотели вычислитьA1дисперсия ежедневных возвратов временных рядовИксКак это будет выглядеть в Excel? Если вы опытный пользователь Excel, вы, возможно, представляете таблицу, представляющую временной ряд B, с дополнительными столбцами для вычисления возвращаемых значений и формулой для вычисления дисперсии. Но что, если теперь мы хотим вычислить отдачу для другогоNвременная последовательность? Скопировать и вставить формулы для каждого нового временного ряда? Вот так начинают появляться ошибки!

Гораздо лучше заключить в капсулуалгоритмвычисления дисперсии ежедневных возвратов временного ряда в функцию. Затем мы можем вызывать это повторно столько раз, сколько мы хотим, без риска того, что одна из промежуточных ячеек будет отредактирована или неправильно скопирована.

Теперь представьте, что вместо таблицы данных временной ряд может быть представлен одной ячейкой в ​​Excel. Если этого можно достичь, мы вернемся к простым отношениям между двумя клетками: «A1 = daily_returns_variance_of (B1)». Внезапно наша электронная таблица начинает выглядеть намного менее сложной!

У нас все еще есть проблема, что данные временного ряда должны откуда-то приходить. Вместо копирования и вставки из другой системы или базы данных, что если бы у нас была функция, которая загружала временные ряды из этой системы или базы данных напрямую? Таким образом, каждый раз, когда мы вычисляли электронную таблицу, мы знали, что данные были актуальными и полными! Чтобы продолжить предыдущий пример, мы могли бы иметьB1 = load_time_series (тикер, start_date, end_date)». Далее мы рассмотрим, как именно мы можем хранить весь набор данных в одной ячейке.

Часто это не просто человек, использующий Excel, который пишет функции, которые они используют. Предоставляя конечным пользователям полный набор функций Excel, технологические группы могут более эффективно поддерживать бизнес, чем если бы они просто создавали приложения с использованием только поверхностной интеграции Excel, например, экспорта отчетов.

Как Java помогает нам?

Размышляя о нашей электронной таблице и внедряя алгоритмы в функции и извлекая данные напрямую, а не копируя и вставляя, мы решили несколько важных проблем с электронными таблицами Excel. Мы еще не затронули вопрос о том, как можно написать эти функции, а также о проблемах, связанных с тестированием, исправлением ошибок и контролем версий.

Если бы мы решили написать все наши функции в VBA (и поверьте мне, это делают многие!), Мы бы не воспользовались каким-либо прогрессом в разработке программного обеспечения, достигнутым за последние 20 лет!

Java идет в ногу с современной разработкой программного обеспечения и может многое предложить по сравнению с VBA.

  • тестирование, В Java есть множество различных сред тестирования, каждый из которых имеет свои сильные и слабые стороны. Однако, какой бы вы ни выбрали, возможность запуска автоматических тестовых наборов для всей базы кода дает вам уверенность в том, что все происходит правильно. Это просто невозможно с VBA.
  • Обширная библиотека поддержки.Написание кода на VBA часто является случаем написания стандартных алгоритмов, которые можно найти в Интернете, и преобразования их в VBA. Хотите сделать что-то тривиальное, как сортировать массив данных? В Java это не проблема, но в VBA вы будете нести ответственность за то, чтобы убедиться, что ваш алгоритм сортировки работает, и без какого-либо тестирования. Теперь представьте, что пишете сложную модель ценообразования!
  • Храните код за пределами Excel.Код VBA обычно сохраняется в рабочей книге, поэтому при совместном использовании рабочих книг ошибки так сложно отследить. Если ваша электронная таблица вместо этого ссылается на скомпилированную библиотеку Java (JAR), то она является внешней по отношению ко всем электронным таблицам, которые ссылаются на нее, и может быть легко обновлена.
  • Контроль версий.Исходный код Java — это просто текст, поэтому его легко можно проверить в системе контроля версий. Большинство Java IDE имеют отличную поддержку для этого, поскольку это стандартная часть современной разработки программного обеспечения.
  • Среда разработки.Редактор VBA (VBE) не менялся годами. Он предлагает чуть больше, чем очень простой текстовый редактор с простейшими возможностями отладки. Java, с другой стороны, предлагает широкий выбор отличных IDE.

Но Java не является частью Excel!

Это правда, но в Excel есть концепция «надстроек», которая позволяет разработчикам расширять функциональные возможности Excel. Одна такая надстройка Jinx, надстройка Excel для Java,

С помощью дурной глаз Вы можете полностью отказаться от VBA и написать функции листа, макросы и меню полностью на Java.

Написание функции рабочего листа в Java так же просто, как добавление аннотации JExx @ExcelFunction в метод Java:

package com.mycompany.xladdin;

import com.exceljava.jinx.ExcelFunction;

/**
* A simple Excel function.
*/
public class ExcelFunctions {
/***
* Multiply two numbers and return the result.
*/
@ExcelFunction
public static double multiply(double x, double y) {
return x * y;
}
}

Вы можете вернуть все основные типы, которые вы ожидаете, а также 1d и 2d массивы. Для более сложных типов вы можете написать свои собственные преобразователи типов или вернуть объекты Java непосредственно в Excel в качестве дескрипторов объектов для передачи другому методу Java.

Джинкс это бесплатно скачать, Увидеть Руководство пользователя Jinx для получения дополнительной информации о том, как вы можете использовать Java в качестве замены для VBA

Что это было за возвращение временного ряда в виде одной ячейки?

Функции Jinx могут возвращать все стандартные типы, которые вы ожидаете (целые, двойные, массивы и т. Д.), Но также могут возвращать объекты Java! Когда возвращается сложный объект Java (например, класс, представляющий временной ряд, загруженный из базы данных), он возвращается в Excel как дескриптор объекта. Этот дескриптор объекта затем может быть передан другим функциям Jinx, а метод Java будет передан исходному объекту Java, возвращенному из первой функции.

Это чрезвычайно полезный метод для упрощения электронных таблиц, чтобы сохранить сложность данных, связанных с электронной таблицей. При необходимости объект может быть расширен до массива Excel с помощью функции массива Jinx.

Вы можете прочитать больше об этих дескрипторах объекта в Jinx Object Cache раздел руководства пользователя.

Другие языки

Эти методы не являются уникальными для Java.

То же самое можно сказать и о других языках JVM, таких как Scala или Котлин, Jinx работает со всеми языками JVM, не только с Java.

Другой популярный язык для написания надстроек Excel — это Python. Это может быть достигнуто с помощью Надстройка PyXLL для Excel,

We can create a
dynamic macro enabled excel by java:

We need to create
a excel sheet template with macro on server.

we can copy the
macro in a new excel sheet and write the data in that excel sheet.

We can create a
rule by which we can poluate the list in excel on the basis of
previous selected cell value

For this we need a
jar: POI 3.08  

/*
* class MacroEnabledExcelTemplateAction
*/

package com.tcs.reuse.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddressList;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.tcs.reuse.MacroEnabledExcelTemplateBus;


// TODO: Auto-generated Javadoc
/**
 * The Class MacroEnabledExcelTemplateAction.
 * 
 */
public class MacroEnabledExcelTemplateAction extends Action {

    /** The logger. */
    private static Logger logger = Logger
     .getLogger(com.tcs.reuse.action.MacroEnabledExcelTemplateAction.class);
    static String strHost = null;

    /**
     * Instantiates a new macro enabled excel template action.
     */
    public MacroEnabledExcelTemplateAction() {

  super();
  logger.debug("****In the constructor of MacroEnabledExcelTemplateAction**");
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.struts.action.Action#execute(org.apache.struts.action.
     * ActionMapping, org.apache.struts.action.ActionForm,
     * javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse)
     */

    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
     HttpServletRequest request, HttpServletResponse response)
     throws IOException, ServletException {

 logger.debug("ENTRY MacroEnabledExcelTemplateAction execute");
 /*
  * Variables declaration
  */
 HttpSession session = null;
 String userId = "";
 String tempPath = "";
 
 
 int newCellMainSheet = 0;
 int newRowMainSheet = 1;
 int totalNumberOfRows = 10;
 
 boolean existFolderAtServer = true;
 boolean deletedDir = false;

 ArrayList<String> errors = null;
 ArrayList<String> msg = null;
 final boolean hasAccess = true;

 InputStream inputFile = null;
 FileOutputStream outputFile = null;
 InputStream inputFile2 = null;
 File file = null;
 File existFile = null;

 DataValidationHelper dvHelper = null;
 DataValidationConstraint dvConstraint = null;
 DataValidation validation = null;
 CellRangeAddressList addressList = null;
 Row mainSheetRow = null;
 Cell mainSheetCell = null;
 HSSFCellStyle cs = null;
 HSSFCellStyle cs1 = null;
 HSSFCellStyle headerCS = null;
 HSSFCellStyle backgroundColor = null;
 HSSFFont font = null;
 HSSFFont font1 = null;
 HSSFFont headerFont = null;
 HSSFWorkbook wb = null;
 HSSFWorkbook wb2 = null;

 MacroEnabledExcelTemplateBus macroEnabledExcelTemplateBus;
 try {
     
  session = request.getSession(true);
     macroEnabledExcelTemplateBus = new MacroEnabledExcelTemplateBus();
     errors = new ArrayList<String>();
     msg = new ArrayList<String>();
     /*
      * Server folder path
      */
     tempPath = "C:Documents and SettingsRajDesktopExcel work";  
     // Use the server path where excel sheet templated to be uploaded
     logger.debug("Temp Folder path i.e. Server Folder :" + tempPath);
     if (userId != null) {
      logger.debug("user id not null");
      try {
       if (hasAccess) {
        // temp folder path for creating a temp template
        // We are creating a tempoarary template (person sprecific) so that more than one user can use the functuionality and 
        // original template remain uncorrupted
         tempFolderPath = tempPath + "" + userId;
         existFile = new File(tempFolderPath);
         logger.debug("existFile");
         /*
         * checking whether the folder already exists on the
         * given path
         */
         if (existFile.exists()) {
         // deleting the existing directory
         existFolderAtNAS = MacroEnabledExcelTemplateBus.deleteDir(existFile);
         logger.debug("existFolderAtServer "+ existFolderAtServer);
         }
         if (existFolderAtServer) {
          file = new File(tempFolderPath);
          // Creates the directory
          boolean b = file.mkdir();
          if (b) {
             // template with macros at  sever
             inputFile = new FileInputStream(tempPath+ "Template.xls");
             /*
              * copy the excel template with macro. True
              * is for copying all the attributes of
              * workbook
              */
             wb = new HSSFWorkbook(new POIFSFileSystem(inputFile), true);
               
             /*
              * writing the copied workbook to a new temp
              * template for processing
              */
             outputFile = new FileOutputStream(tempFolderPath+ "tempTemplate.xls");
             wb.write(outputFile);
             /*
              * Processing the temp template
              */
             inputFile2 = new FileInputStream(tempFolderPath+ "tempTemplate.xls");
             wb2 = new HSSFWorkbook(new POIFSFileSystem(inputFile2), true);
             /*
              * Building a data sheet and hide it. Data
              * sheet number is 1.
              */
               macroEnabledExcelTemplateBus.buildDataSheet(wb2);
               wb2.setSheetHidden(1, true);
             /*
              * Writing the data in main sheet
              */
             Sheet outputSheet = wb2.getSheetAt(0);
             // Setting the name of main sheet
             wb2.setSheetName(0, "MAIN DATA Sheet");
             // Creating the style for main sheet
             cs = wb2.createCellStyle();
             cs.setBorderBottom(CellStyle.BORDER_THIN);
             cs.setBorderLeft(CellStyle.BORDER_THIN);
             cs.setBorderRight(CellStyle.BORDER_THIN);
             // creating the font for main sheet
             font = wb2.createFont();
             font.setFontName("Arial");   // name of font
             font.setFontHeight((short) 200);
             // for setting the font we need to multiply the font size by 20.
             // For eg. setting font size 10, you need to multiply it by 20 i.e. 200.
             cs.setFont(font);
             /*
             * Getting the data for main sheet from DB
             */
             mainSheetData = macroEnabledExcelTemplateBus.getDataForMainSheet(parameter1, parameter2);
             totalNumberOfRows =  mainSheetData.length;
           
             /*
             *  adding Action Type validations
             */
             addressList = new CellRangeAddressList(1,totalNumberOfRows, 0, 0);
             dvHelper = outputSheet.getDataValidationHelper();
             dvConstraint = dvHelper.createFormulaListConstraint("Action"); // name od the list to be populated in excel sheet
             validation = dvHelper.createValidation(dvConstraint, addressList);
             outputSheet.addValidationData(validation);
             addressList = null;
             if (mainSheetData != null && mainSheetData.length > 0) {
              for (int rowCount = 0; rowCount < mainSheetData.length; ++rowCount) {
               // creating a new row for every record
               mainSheetRow = outputSheet.createRow(newRowMainSheet);
               
               // creating a new cell 
               mainSheetCell = mainSheetRow.createCell(newCellMainSheet);
               // writing the value in the cell
               mainSheetCell.setCellValue("");  // fetched it from db   mainSheetData[rowCount][6]
               // apply the css
                 mainSheetCell.setCellStyle(cs);
                 // setting the column width 
                 //we can give the integer value in palce of auto.
                 outputSheet.setColumnWidth(newCellMainSheet, auto);
                 // INCREASE THE VALUE TO CREATE A NEW CELL
                 ++newCellMainSheet;
 
                 // entity id data
                 mainSheetCell = mainSheetRow.createCell(newCellMainSheet);
                 // setting the cell datatype by default it is string
                 mainSheetCell.setCellType(Cell.CELL_TYPE_NUMERIC);
                 //writing the integer or double value
                 mainSheetCell.setCellValue(Double.parseDouble(mainSheetData[rowCount][6]));   
                 outputSheet.setColumnWidth(newCellMainSheet, 2560);
                 mainSheetCell.setCellStyle(cs);
                 ++newCellMainSheet;
                 /*
                 * adding  validations dat geeting populated on the basis of previous selected cellvalue
                 */
                 // 5 is column number from which the below validation applies 
                 // 6 is column number upto which the below validation applies
                 addressList = new CellRangeAddressList(rowCount + 1, rowCount + 1,5, 6);
                 dvHelper = outputSheet.getDataValidationHelper();
                 dvConstraint = dvHelper
                              .createFormulaListConstraint("INDIRECT(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE($E$"
                              + (rowCount + 2)+ ","&",""),"-",""),"/",""),",",""),"~","")," ",""))");
                 validation = dvHelper.createValidation(dvConstraint,addressList);
                 outputSheet.addValidationData(validation);
                 addressList = null;
                 // reset the cell value to 0 for creatibng the cell for new row 
                 newCellMainSheet = 0;
                 // creating the new row.
                 ++newRowMainSheet;
              }
             }
             // setting the content to response
             response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml");
             // setting the header name of excel sheet
             response.setHeader("Content-Disposition","attachment; filename=MACROEXCEL.xls");
             wb2.write(response.getOutputStream());
             // deleting the temp template and directory
             deletedDir = macroEnabledExcelTemplateBus.deleteDir(existFile);

            } else {
              logger.debug("Couldn't make a new folder.");
              // Couldn't make a new folder
            }
            } else {
            logger.debug("Folder already exists. getting error while deleting");
            // Folder already exists. getting error while deleting it.
          }
      }
     } 
    }
  } catch (FileNotFoundException fnfe) {
      logger.debug("error " + fnfe);
      
  } catch (IOException ioe) {
      logger.debug("error " + ioe);
      
  } catch (Exception e) {
      logger.debug("error " + e);
     
  } finally {
      // Flushing all the file streams
      inputFile.close();
      outputFile.close();
      inputFile2.close();
      wb2 = null;
      wb = null;
      file = null;
        existFile = null;
  }
     }else {
  logger.debug("user id is null");
  
     }

 } catch (NullPointerException npe) {
      logger.debug("error " + npe);
 } catch (Exception e1) {
      logger.debug("error " + e1);
 }
 
 return null;
    }
}
==============================================================================
/*
* class MacroEnabledExcelTemplateBus
*/

package com.tcs.reuse.business;

import java.io.File;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;



// TODO: Auto-generated Javadoc
/**
 * The Class MacroEnabledExcelTemplateBus.
 * 
 */
@SuppressWarnings("deprecation")
public class MacroEnabledExcelTemplateBus {
    /** The logger. */
    private static Logger logger = Logger.getLogger(package com.tcs.reuse.business.MacroEnabledExcelTemplateBus.class);
    

    /**
     * Builds the data sheet as tthe dummay databse to fetch the values for list in excel.
     * 
     * @param dataSheet
     *            the data sheet
     * @throws SQLException
     *             the sQL exception
     */
    public void buildDataSheet(HSSFWorkbook workbook) throws SQLException{
  Row row = null;
  Cell cell = null;
  Name name = null;
  String[][] countriesList = null;
  String[][] coverageTypeList = null;
  String poleTypeList[][] = null;
  String[][] iFGList = null;
  String[][] businessList = null;
  String[][] subBusinessList = null;
  String cellValue = "";
  String columnName = "A";
  int newCell = 0;
  int newRow = 0;
  Sheet dataSheet = workbook.createSheet("DataSheet");
  HSSFCellStyle style = workbook.createCellStyle();
  style.setBorderBottom((short) 10); // single line border
  style.setFillForegroundColor(HSSFColor.RED.index);
  /**
   * action data mapping starts new row value = 1 new cell number = 0;
   */
  // CREATING CELL FOR HEADER IN DATASHEET
  row = dataSheet.createRow(newRow);
  ++newRow;
  cell = row.createCell(newCell);
  cell.setCellValue("Action");
  cell.setCellStyle(style);
  // WRITING ALL THE Actions
  row = dataSheet.createRow(newRow);
  ++newRow;
  ++newRow;
  cell = row.createCell(newCell);
  cell.setCellValue(new HSSFRichTextString("Add"));
  ++newCell;
  cell = row.createCell(newCell);
  cell.setCellValue(new HSSFRichTextString("Update"));
  ++newCell;
  cell = row.createCell(newCell);
  cell.setCellValue(new HSSFRichTextString("Delete"));

  // CREATING THE FORMULA RANGE FOR Action
  columnName = getCellColumnCount(3);
  String actionFormulaRange = "Datasheet!$A$" + (newRow - 1) + ":$"+ columnName + "$" + (newRow - 1);

  // SETTING THE NAME OF THE Action LIST
  name = dataSheet.getWorkbook().createName();
  // Name of List
  name.setNameName("Action");
  name.setRefersToFormula(actionFormulaRange);
  newCell = 0;
  // password protecting the datasheet
  dataSheet.protectSheet("password");
    } // end of build datasheet method
    /**
     * Gets the data for main sheet.
     * 
     * @param listSize
     *            the list size
     * @return the data for main sheet
     * 
     * @storeProcedureParams
     */

    public String[][] getDataForMainSheet(String parameter1, String parameter2
     ) throws SQLException {
 String[][] dataForMainSheet = null;
 ArrayList tempData = null;
 DBUtilParam params = new DBUtilParam(3);
 try {
     // fetch the resuklt set from DB
 } catch (WFException wfe) {
     throw wfe;
 } catch (Exception e) { //
 } finally {
     params = null;
 }
 return dataForMainSheet;
    }

    /**
     * Cell column count for determining the last column number in excel.
     * 
     * @param listSize
     *            the list size
     * @return the string
     * @limitations maximum listSize 702
     */
    public String getCellColumnCount(int listSize) {
 String columnName = "A";
 String alphabetArray[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
  "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
  "V", "W", "X", "Y", "Z" };
 int firstCharIndex = listSize / 26;
 int secondCharIndex = listSize % 26;
 if (firstCharIndex == 0 && secondCharIndex != 0) {
     columnName = alphabetArray[secondCharIndex - 1];
 } else if (firstCharIndex != 0 && secondCharIndex == 0) {
     columnName = alphabetArray[firstCharIndex - 1];
 } else {
     columnName = alphabetArray[firstCharIndex - 1]
      + alphabetArray[secondCharIndex - 1];
 }
 return columnName;
    }

    /**
     * Replace special char from list name with blank.
     * 
     * @param listName
     *            the list name
     * @return the string
     */
    public String replaceSpecialCharFromName(String listName) {
 String arrSpecialChar[] = { "&", "-", "/", ",", "~", " " };
 String newString = listName;
 for (int i = 0; i < arrSpecialChar.length; i++)
     newString = StringUtils.replace(newString, arrSpecialChar[i], "");
 return newString;

    }

   

    /**
     * Deletes all files and subdirectories under dir. Returns true if all
     * deletions were successful. If a deletion fails, the method stops
     * attempting to delete and returns false.
     * 
     * @param dir
     * @return boolean
     */
    public static boolean deleteDir(File dir) {
 if (dir.isDirectory()) {
     String[] children = dir.list();
     for (int i = 0; i < children.length; i++) {
  boolean success = deleteDir(new File(dir, children[i]));
  if (!success) {
      return false;
  }
     }
 }

 // The directory is now empty so delete it
 return dir.delete();
    }
}

In a recent work task, the client-uploaded document (contract document) needs to be read-only protected in the background (sense read-only protection in strict sense, both locking and ensuring that you cannot unlock it yourself) Instead of the file itself being read-only or simply locked, so I thought of the way the word macro was called to manipulate the document. After research, this method is completely feasible, and has been realized. Because this kind of data network is difficult to find, so I will share my research experience.

Java needs to interact with the office by calling com. This can be done by writing jni itself. However, there are currently three open source projects that support java to com calls: com4j, j-Interop, and Jacob. Let’s take a brief introduction to these three projects.

Com4j, the project address is: http://java.net/projects/com4j/, has not been updated for a long time, to use this library, you need to download the relevant source code (also available through http://download.java.net/maven /2/org/jvnet/com4j/ This address to find the relevant compiled package) Compile or get the maven-com4j-plugin plugin via maven, then run tlbimp.jar (available at http://download.java.net/maven /2/org/jvnet/com4j/tlbimp/ found) or maven-com4j-plugin plugin to generate the model interface code of the relevant com component (of course, the prerequisite is to find the host file of the com component, this is somewhat difficult) Then use the code to call the relevant com component, it is still cumbersome to use, and there are some serious bugs.

j-Interop, the project address is: http://www.j-interop.org/, a pure java library, without using the jni way to call the com component. But its problem is that it can only call dcom (distributed com), it is to call dcom through CIFS protocol, so to use it, you must first configure the machine with dcom service, and at the same time, it is more troublesome, that is, you have to go Look for the ID of the dcom component (you can view it by running dcomcnfg).

Jacob, the project address is: http://sourceforge.net/projects/jacob-project/, the latest update is February 2011, this article will focus on how to call macros through this project.

After the project is introduced, it is now officially introduced how to call macros through Jacob. First, you need to download the Jacob distribution package, which should contain a jar package: jacob.jar (on the project’s classpath), two dll files: jacob-1.15-M4-x64.dll, jacob-1.15-M4-x86 .dll, two dll files, please select one according to the system architecture properties, and then put it in the path path (can also be placed directly under C:WINDOWSsystem32). This will start writing Java programs that call macros.

Call word macro

First step, recording a macro

In the d root directory (where the document is stored, there is no requirement) create a new word document named test1.doc, open it, and then record a macro (specifically record which kind of macro is free, you can call the parameter without calling, but the macro The way to save is to select «All Documents (Normal)» so that any document can call this macro), the macro name is macro1.

The second step is to undo the effect of macro1 in test1.doc (for example, if the macro is a paragraph of text, then delete the text) and save it to observe the test.

The third step is to write the java call code.


ActiveXComponent word=new ActiveXComponent("Word.Application");
Dispatch documents = word.getProperty("Documents").toDispatch();
Dispatch document = Dispatch.call(documents, "Open", "d:/test1.doc").toDispatch();//Specify the document to open and open it
Dispatch.call(word, "Run", new Variant("macro1"));//Run the macro on this document

The fourth step is to execute this java code.

After the execution is completed, you can find that the macro effect that was revoked is back, indicating that the macro call succeeded.

The fifth step, advanced features

Create a blank word document test2.doc in the same directory (not specified in the document storage directory), and then modify the above code to:


ActiveXComponent word=new ActiveXComponent("Word.Application");
Dispatch documents = word.getProperty("Documents").toDispatch();
Dispatch document = Dispatch.call(documents, "Open", "d:/test2.doc").toDispatch();//Specify the document to open and open it
Dispatch.call(word, "Run", new Variant("macro1"));//Run the macro on this document

Executing the above code, we can find that the macro we recorded on test1.doc can also run successfully on test2.doc (of course, you must save to «All Documents» when you select the macro to save).

In-depth exploration

The above example is just a very simple macro call with no parameters. How to call if there are parameters? In fact, the situation with parameters is not very complicated, just modify the java code above to modify it:


ActiveXComponent word=new ActiveXComponent("Word.Application");
Dispatch documents = word.getProperty("Documents").toDispatch();
Dispatch document = Dispatch.call(documents, "Open", "d:/test1.doc").toDispatch();//Specify the document to open and open it
Dispatch.call(word, "Run", new Variant("macro1"), new Variant(arg1), new Variant(arg2),..);//Run the macro on this document and include multiple parameters

Call excel macro

Calling the excel macro is a bit different from calling the word macro, because excel cannot save the macro to «All Documents», so you need to specify the specific document where the macro is located when calling the macro. The last statement needs to be written like this:


Variant result = Dispatch.call(excel, "Run", new Variant("test.xls!Module1.test"), / / ​​Here you need to explain the document where the macro is located
new Variant(arg1),
new Variant(arg2));

to sum up

Application scenarios that use java to directly call office macros are very useful, such as when encrypting, decrypting, and other protection of documents. Macro calls with parameters can even be flexibly written into template macros and then inject business data into related documents, and because they operate themselves through the office, office documents will never appear in other applications that use java to manipulate office documents. Document variability issues are very useful in the operation of certain important documents (such as contract documents with very strict document format requirements). In addition, Jacob itself can directly operate the office (including editing) by calling com, and the office document will not have any variation, but the coding difficulty may be relatively large. The specific operation mode is not described here. You can refer to the related API.

Скачать jacob-1.19.zip

https://sourceforge.net/projects/jacob-project/

Поместите jacob-1.19-x64.dll в каталог C: Windows System32

jacob.jar в проект

Excel необходимо сохранить как книгу с поддержкой макросов с расширением .xlsm.
 Документ о конкретных настройках Макрос
Настройка подстиля ()
'
 'Макрос настроек стиля
'

'
    Range("A1:C1").Select
    Selection.Font.Bold = True
    With Selection.Font
                 .Name = "Microsoft Yahei"
        .Size = 11
        .Strikethrough = False
        .Superscript = False
        .Subscript = False
        .OutlineFont = False
        .Shadow = False
        .Underline = xlUnderlineStyleNone
        .ThemeColor = xlThemeColorLight1
        .TintAndShade = 0
        .ThemeFont = xlThemeFontNone
    End With
    With Selection.Font
                 .Name = "Microsoft Yahei"
        .Size = 14
        .Strikethrough = False
        .Superscript = False
        .Subscript = False
        .OutlineFont = False
        .Shadow = False
        .Underline = xlUnderlineStyleNone
        .ThemeColor = xlThemeColorLight1
        .TintAndShade = 0
        .ThemeFont = xlThemeFontNone
    End With
    ActiveWindow.SmallScroll Down:=-9
    Range("A1:C8").Select
    With Selection
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlBottom
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With
    With Selection
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlCenter
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With
    ActiveWindow.SmallScroll Down:=-6
    Range("A1:C1").Select
    With Selection.Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = xlThemeColorDark1
        .TintAndShade = -0.149998474074526
        .PatternTintAndShade = 0
    End With
    Range("G3").Select
End Sub
 Специальные настройки вложенного документа ()
'
 'Параметры документа Макрос
'

'
End Sub
Макрос настройки стиля
Настройка подстиля ()
'
 'Макрос настроек стиля
'

'
    Range("A1:C1").Select
    Selection.Font.Bold = True
    With Selection.Font
                 .Name = "Microsoft Yahei"
        .Size = 11
        .Strikethrough = False
        .Superscript = False
        .Subscript = False
        .OutlineFont = False
        .Shadow = False
        .Underline = xlUnderlineStyleNone
        .ThemeColor = xlThemeColorLight1
        .TintAndShade = 0
        .ThemeFont = xlThemeFontNone
    End With
    With Selection.Font
                 .Name = "Microsoft Yahei"
        .Size = 14
        .Strikethrough = False
        .Superscript = False
        .Subscript = False
        .OutlineFont = False
        .Shadow = False
        .Underline = xlUnderlineStyleNone
        .ThemeColor = xlThemeColorLight1
        .TintAndShade = 0
        .ThemeFont = xlThemeFontNone
    End With
    ActiveWindow.SmallScroll Down:=-9
    Range("A1:C8").Select
    With Selection
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlBottom
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With
    With Selection
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlCenter
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With
    ActiveWindow.SmallScroll Down:=-6
    Range("A1:C1").Select
    With Selection.Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = xlThemeColorDark1
        .TintAndShade = -0.149998474074526
        .PatternTintAndShade = 0
    End With
    Range("G3").Select
End Sub
 Специальные настройки вложенного документа ()
'
 'Параметры документа Макрос
'

'
End Sub
JacobExcelTool.java
/*
 * Copyright © 2019 [email protected] Inc. All rights reserved
 * @package: com.ibm.jacob
 * @version V1.0
 */
package com.ibm.jacob;

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

/**
 * @author Moses *
 * @Date 2019/4/1
 */
public class JacobExcelTool {
    /**
           * Объект Excel
     */
    private ActiveXComponent xl = null;
    /**
           * Объект книги
     */
    private Dispatch workbooks = null;
    /**
           * Специальная рабочая тетрадь
     */
    private Dispatch workbook = null;
    /**
           * Получить объект коллекции листов
     */
    private Dispatch sheets = null;
    /**
           * Текущий лист
     */
    private Dispatch currentSheet = null;

    public ActiveXComponent getXl() {
        return xl;
    }

    public Dispatch getWorkbooks() {
        return workbooks;
    }

    public Dispatch getWorkbook() {
        return workbook;
    }

    /**
           * Открыть файл Excel
     *
           * @param filepath имя пути к файлу
           * @param отображается, отображать ли открытыми
           * @param readonly Следует ли открывать в режиме только для чтения
     */
    public void OpenExcel(String filepath, boolean visible, boolean readonly) {
        try {
                         // Очистить исходную переменную
            initComponents();
                         // Одновременно может выполняться только один поток, другие потоки заблокированы, ComThread.InitMTA (true); может запускаться несколько одновременно
            ComThread.InitSTA();
                         // объект Excel
            if (xl == null) {
                xl = new ActiveXComponent("Excel.Application");
            }
                         // Устанавливаем, отображать ли Excel
            xl.setProperty("Visible", new Variant(visible));
                         // объект книги
            if (workbooks == null) {
                workbooks = xl.getProperty("Workbooks").toDispatch();
            }
                         // Открыть конкретную книгу
            workbook = Dispatch.invoke(
                    workbooks, "Open", Dispatch.Method,
                    new Object[]{filepath, new Variant(false), new Variant(readonly)},
                    new int[1]).toDispatch();
        } catch (Exception e) {
            e.printStackTrace();
            releaseSource();
        }
    }

    /**
           * Сохранить книгу как
     *
           * @param filePath путь для сохранения как
     */
    public void SaveAs(String filePath) {
        Dispatch.invoke(workbook, "SaveAs", Dispatch.Method, new Object[]{filePath, new Variant(44)}, new int[1]);
    }

    /**
           * Закройте документ Excel
     *
           * @param f Значение неизвестно (закрыть или сохранить? По умолчанию false)
     */
    public void CloseExcel(boolean f, boolean quitXl) {
        try {
            Dispatch.call(workbook, "Save");
            Dispatch.call(workbook, "Close", new Variant(f));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (quitXl) {
                releaseSource();
            }
        }
    }

    /**
           * Освободить ресурсы
     */
    public void releaseSource() {
        if (xl != null) {
            xl.invoke("Quit", new Variant[]{});
            xl = null;
        }
        workbooks = null;
        ComThread.Release();
        System.gc();
    }

    /**
           * Добавить новый лист (лист) (после добавления он будет по умолчанию на текущий активный лист)
     */
    public Dispatch addSheet() {
        return Dispatch.get(Dispatch.get(workbook, "sheets").toDispatch(), "add").toDispatch();
    }

    /**
           * Изменить имя текущего рабочего листа
     *
     * @param newName
     */
    public void modifyCurrentSheetName(String newName) {
        Dispatch.put(getCurrentSheet(), "name", newName);
    }

    /**
           * Получить имя текущего рабочего листа
     *
     * @return
     */
    public String getCurrentSheetName() {
        return Dispatch.get(getCurrentSheet(), "name").toString();
    }

    /**
           * Получите название книги
     *
     * @return
     */
    public String getWorkbookName() {
        if (workbook == null) {
            return null;
        }
        return Dispatch.get(workbook, "name").toString();
    }

    /**
           * Получить объект коллекции листов
     *
     * @return
     */
    public Dispatch getSheets() {
        if (sheets == null) {
            sheets = Dispatch.get(workbook, "sheets").toDispatch();
        }
        return sheets;
    }

    /**
           * Получить текущий лист
     *
     * @return
     */
    public Dispatch getCurrentSheet() {
        currentSheet = Dispatch.get(workbook, "ActiveSheet").toDispatch();
        return currentSheet;
    }

    /**
           * Получите лист по имени листа
     *
     * @param name sheetName
     * @return
     */
    public Dispatch getSheetByName(String name) {
        return Dispatch.invoke(getSheets(), "Item", Dispatch.Get, new Object[]{name}, new int[1]).toDispatch();
    }

    /**
           * Получите рабочий лист через индекс рабочего листа (индекс первой книги равен 1)
     *
     * @param index
           * @return лист объекта
     */
    public Dispatch getSheetByIndex(Integer index) {
        return Dispatch.invoke(getSheets(), "Item", Dispatch.Get, new Object[]{index}, new int[1]).toDispatch();
    }

    /**
           * Получить общее количество листов
     *
     * @return
     */
    public int getSheetCount() {
        int count = Dispatch.get(getSheets(), "count").toInt();
        return count;
    }

    /**
           * Вызов макроса Excel
     *
           * @param macroName имя макроса
     */
    public void callMacro(String macroName) {
        Dispatch.call(xl, "Run", new Variant(macroName));
    }

    /**
           * Вызов макроса Excel
     *
           * @param macroName имя макроса
           * @param параметры передачи параметров
     */
    public void callMacro(String macroName, Object param) {
        Dispatch.call(xl, "Run", new Variant(macroName), new Variant(param));
    }

    /**
           * Значение записи ячейки
     *
           * @param sheet Лист, которым управляют
           * @param position Позиция ячейки, например: C1
           * Атрибут значения типа @param, например: value
     * @param value
     */
    public void setValue(Dispatch sheet, String position, String type, Object value) {
        Dispatch cell = Dispatch.invoke(sheet, "Range", Dispatch.Get, new Object[]{position}, new int[1])
                .toDispatch();
        Dispatch.put(cell, type, value);
    }

    /**
           * Значение чтения ячейки
     *
           * @param position Позиция ячейки, например: C1
     * @param sheet
     * @return
     */
    public Variant getValue(String position, Dispatch sheet) {
        Dispatch cell = Dispatch.invoke(sheet, "Range", Dispatch.Get, new Object[]{position}, new int[1])
                .toDispatch();
        return Dispatch.get(cell, "Value");
    }

    /**
           * Очистить исходную переменную
     */
    private void initComponents() {
        workbook = null;
        currentSheet = null;
        sheets = null;
    }
}
TestJacob.java
/*
 * Copyright © 2019 [email protected] Inc. All rights reserved
 * @package: com.ibm.jacob
 * @version V1.0
 */
package com.ibm.jacob;

import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import org.junit.Test;

/**
 * @author Moses *
 * @Date 2019/4/1
 */
public class TestJacob {
    @Test
    public void testMacro() {
        JacobExcelTool tool = new JacobExcelTool();
                 //включить 
                 tool.OpenExcel ("D: / temp / macro test.xlsm", ложь, ложь);
        Dispatch sheet = tool.getSheetByName("Sheet1");
        for (int i = 2; i <= 7; i++) {
            tool.setValue(sheet, "B" + i, "value", i * 1.2);
        }
                 // Вызов макроса Excel
                 tool.callMacro («Настройки документа»);
                 // Вызов макроса Excel
                 tool.callMacro («Настройка стиля»);
        Variant num = tool.getValue("B8", sheet);
        System.out.println(num);
                 // Закрываем и сохраняем, отпускаем объект
        tool.CloseExcel(true, true);
    }
}

Понравилась статья? Поделить с друзьями:
  • Макрос для excel копирование строк
  • Макрос в excel цена
  • Макрос для excel как редактировать
  • Макрос в excel функция впр в excel
  • Макрос в excel условие цвета