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
4,3118 gold badges45 silver badges73 bronze badges
asked Oct 17, 2011 at 5:41
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
CodoCodo
73.8k17 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);
answered Aug 27, 2015 at 18:20
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
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
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
3
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(); } }
XL4J — Native Excel XLL Add-ins in Java
THIS PROJECT IS PRE-RELEASE, THE BETA RELEASE IS COMING SOON (DELAYED DUE TO LAST MINUTE ISSUE)
Sign up to be notified when the project is opened for public beta or visit the
XL4J Commercial Site for more information.
Introduction
XL4J is a Java and native code library that allows you to build native-quality Excel Add-ins using only standard Java tooling (Maven + JDK). It lets you write high performance custom Excel functions and commands for end users, but also works as a dynamic rapid application development tool in its own right.
In addition to supporting the standard Excel types (numbers, strings, dates, booleans, etc.) it also supports Java objects in the form
of object handles. This means you can store any complex object in a single Excel sheet cell, allowing much more complex applications. A background incremental garbage collector prevents discarded and overwritten objects from hanging around.
Table of contents
- Overview (this document)
- Objectives
- Requirements
- Features
- Writing Excel user-defined functions
- Calling constructors and methods on Java objects
- Configuration and easy logging access
- Deployment features
- Add-in features
- Roadmap
- Features in development
- Features in the pipeline
- Limitations
- Settings & Configuration
- Logging
- Tutorial
- Hints & Tips on Writing Add-ins
- Debugging & Troubleshooting
- API Reference
- Native code structure & Walkthrough
- Background about Excel Types for Developers
Objectives
- Make no compromises
- allowing developers to access any functionality they would be able to through a pure native XLL project written in C++. This
means you don’t have to choose between convenience and power.
- allowing developers to access any functionality they would be able to through a pure native XLL project written in C++. This
- Make it easy
- Put your data where your users are using it and hugely increase productivity and reduce development cycles by making it really
easy to expose data to users without complex and inflexible UI engineering. - super easy to start development — just annotate a method with @XLFunction and watch XL4J do the rest.
- super easy deployment — just create a Maven project, include a dependency and maven assembly file and build the Add-in directory
or deploy to a maven repository.
- Put your data where your users are using it and hugely increase productivity and reduce development cycles by making it really
- Production-grade
- make consideration of real-world production usage with XCOPY install, access to logs, pre-deployment configuration, etc.
- Reasonable licensing
- Dual license GPL/Commercial means you can get your feet wet without an up-front commitment and use in personal or
open source projects without payment. - Each commerical license provides perpetual Add-in distribution and source code license for latest version at time of purchase.
- Per developer-seat licensing, with royalty-free end-user licensing (you pay per developer, not per deployment).
- Dual license GPL/Commercial means you can get your feet wet without an up-front commitment and use in personal or
Requirements
- Build requirements
- Java modules (most users will only ever need to use the Java modules as dependencies)
- JDK8 is required to build all modules, although only one example package actually requires JDK8 so modification for JDK7 is
trivial - Maven 3.2+ (although it should be possible to use Gradle or Ant/Ivy with very few alterations)
- JDK8 is required to build all modules, although only one example package actually requires JDK8 so modification for JDK7 is
- Native modules (most users will not need to build the native modules)
- Visual Studio 2013 AND Visual Studio 2015 are required if you wish to rebuild them. The free Community Editions are probably
enough although all development is done on the Enterprise edition.
- Visual Studio 2013 AND Visual Studio 2015 are required if you wish to rebuild them. The free Community Editions are probably
- Java modules (most users will only ever need to use the Java modules as dependencies)
- Runtime requirements
- Java 8 Runtime Environment (or 7 with minor adjustments).
- Bitness must match Excel version.
- Excel 2010, 2013 or 2016.
- 32-bit builds are fully tested, 64-bit builds are experimental but do work.
- Java 8 Runtime Environment (or 7 with minor adjustments).
- Windows 7, 8, 8.1 or 10. Only 64-bit versions are tested but 32-bit versions should be fine.
- Builds may run on Windows Vista, but it is unsupported.
- Windows XP is not supported.
Features
Writing Excel user-defined functions
- System will automatically scan your code for @XLFunction annotations and register them with Excel.
@XLFunction(name = "MyAdd") public static double myadd(final double one, final double two) { return one + two; }
See the tutorial for more complex examples that return objects and arrays, including documentation and more.
- Automatic marshalling (conversion) from Java to Excel types and back again.
- Primitive types (and Boxed equivalents)
- JSR-310/Java 8 dates
- 1D/2D Arrays
- Full object-handling system maintains a garbage-collected heap for objects, necessary for long-running sheets
- Support for varargs
- All the types of functions and features normally available to Excel XLLs
- Volatile functions
@XLFunction(volatile=true)
which are always recalculated (e.g. =TODAY()). - Macro-equivalent functions
@XLFunction(isMacroEquivalent=true)
run single-threaded but can call more Excel
APIs such as those that modify other cells (useful for dumping data onto a sheet without using an array formula). THIS ISN’T CURRENTLY HUGELY USEFUL BECAUSE CALLBACKS ARE NOT YET AVAILABLE - Multi-thread safe functions
@XLFunction(isMultiThreadSafe=true)
which Excel can call from multiple calculation threads.
This is the default. - Asynchronous functions
@XLFunction(isAsynchronous=true)
which enable long-running operations to not block Excel
- Volatile functions
- Call XLL API from different contexts
- XLL API calls can be made from the caller’s Excel calculation thread or from the Excel main thread depending on context required.
Excel documentation specifies that many API calls can only be safely made from the main Excel thread. CURRENTLY IN DEVELOPMENT
- XLL API calls can be made from the caller’s Excel calculation thread or from the Excel main thread depending on context required.
Calling constructors and methods on Java objects
The follwing example allows you to create and show a Swing JFrame with no coding at all:
A | B | |
---|---|---|
1 | =JConstruct("javax.swing.JFrame", "My Window Title") |
=JConstruct("javax.swing.JButton", "Click me!") |
2 | =JMethod(A1, "setSize", 300, 200) |
|
3 | =After(A2, JMethod(A1, "add", B1)) |
|
4 | =After(A3, JMethod(A1, "setVisible", TRUE)) |
which looks like this in Excel — note the object handles with the >> prefix followed by the type and the handle number:
Breaking this example down:
- The
JConstruct
function calls the named class’s constructor with any supplied arguments and returns an object handle. The first
constructor that the system is able to convert the argument list for will be chosen. - The
JMethod
function calls a method named in the second argument on the object handle passed in as the first argument with
any subsequently supplied parameters. The first method that the system is able to convert the argument list for will be chosen. - The
After
function is a utility function that allows you to specify that this cell should be evaluated after another one. In this
case it allows us to specify that we want theadd
method called after thesetSize
method, and thesetVisible
method after that.
If we don’t do this, we can find that Excel can choose an ordering we didn’t want. Note this is only really an issue when we’re
side-effecting a java object, which we should generally avoid anyway.
Evaluating the sheet results JFrame appearing:
Configuration and Easy Logging Access
By default there are toolbar icons for opening the settings dialog, and opening the Java and C++ Logs in Notepad (or default
.log
file viewer). These can be disabled for end users if preferred.
- Support for custom tool icons on the Add-in ribbon via a super-simple extension to the configuration file. CURRENTLY IN DEVELOPMENT
Deployment features
- Zero-install (a.k.a. XCOPY install) works for non-Adminstrator users who lack permission to install software — you
just copy the files, point Excel at the .xll file using the Add-in manager, and off you go. - Allow hosting installation files on a network share where they can be easily updated.
- No COM registration, no registry modifications whatsoever.
- No manually-run background server.
- Installation can be custom configured to hide configuration and developer options from end users.
- White labelling. Add-in name can be changed by simply renaming XLL file.
- In-built access to logs without digging around in Temp directories or CLI windows.
Add-in features
- Non-blocking background function registration means Excel doesn’t blacklist your Add-in for extended startup times.
- Mark-and-sweep style garbage collector allows long running data-driven spreadsheets to keep memory requirements stable.
- Support for all Excel function types
- Macro-equivalent (single-threaded, but allows certain extra features)
- Multi-threaded
- Volatile
- Asynchronous (** in development **)
- Easy-to-use configuration dialog allows
- Custom VM options, with common options available via tick-box (max heap, remote debugging, JNI checks, logging level)
meaning you don’t have to remember the options. - Add items to classpath individually, multi-select or scan a whole folder for jars.
- Custom VM options, with common options available via tick-box (max heap, remote debugging, JNI checks, logging level)
- Auto-detects existing installed JVM enabled via the Java control panel applet.
- Bundled JVMs coming soon.
Roadmap
Features in development
There are various architectural choices that have been made to enable specific future features. These features can be considered the
highest priority:
- Bundled JVM. Allow inclusion of a JVM with the installation files meaning user does not have to even know Java is used and
simplifying deployment. Should be relatively simple. - Out-of-process JVM. This is relatively easy given the JVM is implemented as a COM object and all interaction is already
via only COM types and interfaces.- Allows multiple JVMs.
- No memory limitations.
- Multiple XL4J add-ins at the same time.
- Good performance due to highly optimized Windows LPC mechanism which uses shared memory for IPC when appropriate.
- Excel high-performance XLL C API access that can provide all kinds of extra functionality. Important that these functions can be
called back from the calling thread. This is a tricky requirement in the out-of-process context, but a method to achieve it has
already been found.- Access to caller information (e.g. which cell or cells are being computed).
- Read and write data into arbitrary cells without using array formulas (only certain types of function are allowed
to do this). - Evaluate arbitrary Excel formulas.
- Schedule commands to be called after a given period of time (possibly repeatedly).
- Add custom dialog boxes, menus, toolbars (although this functionality is probably best achieved in other ways).
- Much more…
- Toolbar support — allow the simple addition of new toolbar buttons linked to custom commands. See below for full ribbon support.
- Per-cell exception display. Allow developer to double-click on cell that caused error and see the last Exception + stack trace
thrown in that cell.
Features in the pipeline
These are features we know how to implement but aside from identifying what is required, nothing has been started yet.
- COM RTD server to allow real-time data to be pushed from Java into Excel.
- General COM API access — The most comprehensive API for Excel access is via the COM API. The COM API allows things not available
via the XLL API, such as ability to format cells, recalculate cells and ranges, and much more. So why not only provide COM access?
The reason is that the COM API can be rather slow, and there are still some things that can only be done via the XLL C API. - Heap serialization to XLS file on save/load.
- Full Ribbon support. Ribbon support requires more COM integration as a pre-requisite.
- Easy exposing of user defined functions to VBA.
- Dynamic class updating — support dynamic updaing of classes by your IDE feeding through to the Add-in without a restart.
- Dynamic class addition — fully dynamic updates including adding and removing new functions at run-time (a la JRebel).
- Object inspector pop-up window.
- Excel help topics from JavaDocs.
- Argument hints using tooltips.
- Arbitrary Java REPL style (e.g.
=Java("MyClass obj = MyClass.of($1)", A1); return obj.getCount();
).
Limitations
There are a few limitations with the current build. These should slowly disappear with time.
- Excel 2010 is the minimum supported version.
- This is the first version to support asynchronous functions, which allow us to avoid a psuedo-asynchronous framework to support
Excel 2007. Additionally, Excel 2007 has some nasty bugs prior to the first service packs and is going out of support early 2017. - Versions prior to 2007 don’t support multi-threading at all, support much smaller sheets, and don’t have Unicode support.
- This is the first version to support asynchronous functions, which allow us to avoid a psuedo-asynchronous framework to support
- The JVM has a limitation of one JVM per process. This means you cannot install more than one XL4J-based Add-in at the same time.
Because the JVM interface is a pure COM interface, it will be relatively easy to switch to an out-of-process version within the
first updates. - No ribbon support currently, toolbar uses the C API, which doesn’t fully support the ribbon functionality. It should be possible
to build a wrapper XLA to install a ribbon if needed before official support is added. - 32-bit JVM limits maximum heap as it needs to share address space with Excel. This will go away once we move to an
out-of-process JVM with the first updates. - 64-bit Add-in/JVM combination builds and appears fine but hasn’t been as tested as the 32-bit build.
I am not familiar with Linux though
To be more details, We developed our application in JSP and wrote the data into Open Office Calc document in order to display dynamic charts. We tried other APIs that link Java to Ms. Excel, but some cannot create dynamic charts, some were expensive and tedious in codings. So, using the OpenOffice API is quite good.
But in Open Office itself, it has a bug on the charts generated. Let say we generate a bar chart containing 10 rows of data, which means 10 bars shown on the chart. When we display the Data Label, the 1st bar would never had any value. After generated the report, we will save in .xls format because most clients PCs are Windows based.
Here are the steps:
1. We created an .xls document as a template with a macro built-in. The macro is basically to show all the data labels. When we execute the data labels from Excel, it will show every value on every bar.
2. We use Java and Open Office API to open the document, write whatever information we need and generate the chart.
3. Save the .xls file after writing
4. This is the step that is being done manually now. We have to manual open up each report generated, and click Macro -> Run in order to show all the value on each bar.
So, we need to get rid of that manual step as it is very tedious when we need to open up all the reports just to run the macro, and we always have hundreds of reports generated every time
Regards,
Jenty
Перевод
Ссылка на автора
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,