 |
OpenOffice and Java MacrosHere are a few pointers about creating Java macros for OpenOffice and embedding them in odf files. If the samples don't work here are a few basic things to try:
Remember to Set Macro Security to medium setting so that it ask if it's allowed to run macros and then re-open your document so that you have permission to run macros. Security settings can be changed in:
Tools
Options
Security
Macro Security
Medium
|
|
If you get errors like: java.lang.UnsupportedClassVersionError: Bad version number in .class file it means that the JVM (Java) configured for Open Office is to old for the code, typically you want to use version 1.6.X or newer. To change the java used by Open Office go to: This should show you a list of all the available Java Virtual Machines, select a more recent one, confirm and restart Open Office. If you get errors classPathNotFound errors it means that required .jar libraries are not included, sometimes they are just missing from the classpath. When running Java Macro's the classpath is made three parts, internal Open Office classpath, the classpath options specified in the Java Virtual Machine selection section (see change JVM above) and parcel-descriptor.xml which accompanies your java macro. Although all the libraries under "OpenOffice Install Folder"/program/classes should be included by default it's often not, to remidy this simply add it as a classpath folder under the JVM selector section (see above). If you want to be able to call a macro from more than just the Run Macro menu you will need to overload the function name specified in percel-descriptor.xml to accept different format, here is an example enabling java macros to be called from A menu or a frame button. This is a modified version of the function in this example: Orginal Coce: http://user.services.openoffice.org/en/forum/viewtopic.php?f=45&t=1844"
public class Calc {
// When called from the Macro menu
public static void fillSpreadsheet(XScriptContext xSc) {
XModel model = xSc.getDocument();
fillSheet(getActiveSpreadsheet(model));
}
// When called from the Toolbar Menu
public static void fillSpreadsheet(XScriptContext xSc, Short ignored) {
fillSpreadsheet(xSc);
}
// When called from a Button or other ActionEvent
public static void fillSpreadsheet(XScriptContext xSc, com.sun.star.awt.ActionEvent e) {
fillSpreadsheet(xSc);
}
|
|
I also think it's important to mention how ODF files with java macros are made and how to bundle the two. ODF files are .zip files, you can access/edit them by treating them like any other zip file (.jar files are also zip files btw). In this example there is an extra directory structure in the ODF file for the Java Macro, the structure is as follows where calc is the name of the script and Calc.odf is the name of the document:
Calc.odf
Scripts
java
calc
calc.jar
parcel-descriptor.xml
|
|
Here is the structure of calc.jar (zip file):
calc.jar
Calc.class
META-INF
MANIFEST.MF
|
|
If you want to know the minimum safe JVM version to use you can find it inside the MANIFEST.MF file, typcial contents would be:
Manifest-Version: 1.0
Created-By: 1.6.0_01 (Sun Microsystems Inc.)
|
|
Here is the typical content of parcel-descriptor.xml
 |
<parcel language="Java" xmlns:parcel="scripting.dtd">
<script language="Java">
<locale lang="en">
<displayname value="Calc Fill Spreadsheet"/>
<description>
Fill a spreadsheet with some data
</description>
</locale>
<functionname value="Calc.fillSpreadsheet"/>
<logicalname value="Calc.fillSpreadsheet"/>
<languagedepprops>
<prop name="classpath" value="calc.jar"/>
</languagedepprops>
</script>
</parcel>
|
|
|
And the complete calc.java source file:
public class Calc {
// When called from the Macro menu
public static void fillSpreadsheet(XScriptContext xSc) {
XModel model = xSc.getDocument();
fillSheet(getActiveSpreadsheet(model));
}
// When called from the Toolbar Menu
public static void fillSpreadsheet(XScriptContext xSc, Short ignored) {
fillSpreadsheet(xSc);
}
// When called from a Button or other ActionEvent
public static void fillSpreadsheet(XScriptContext xSc, com.sun.star.awt.ActionEvent e) {
fillSpreadsheet(xSc);
}
private static XSpreadsheet getActiveSpreadsheet(XModel model) {
if (model == null)
return null;
// Get active spreadsheet
XController controller = model.getCurrentController();
XSpreadsheetView view = (XSpreadsheetView) UnoRuntime.queryInterface(XSpreadsheetView.class, controller);
return (view != null)? view.getActiveSheet(): null;
}
private static void fillSheet(XSpreadsheet sheet) {
if (sheet == null)
return;
try {
//
// Create a TEXT CELL
//
// Get cell by position
XCell cell = sheet.getCellByPosition(0, 0);
// Access the cell text
XText cellText = (XText) UnoRuntime.queryInterface(XText.class, cell);
// Get the text cursor of the cell text
XTextCursor textCursor = cellText.createTextCursor();
// Insert a string in the cell through the text cursor and overwrite the cell content
// Using 'false' as third parameter adds the inserted string
cellText.insertString(textCursor, "Java macro example", true);
//
// Access and modify VALUE CELLS
//
// Get cell by position
cell = sheet.getCellByPosition(0, 2);
// Set cell value
cell.setValue(2345);
// Get cell value and multiply the value by 4
double nDblValue = cell.getValue() * 4;
// Set cell value with result
sheet.getCellByPosition(0, 3).setValue(nDblValue);
//
// Create FORMULA CELLS
//
// Get cell by position
cell = sheet.getCellByPosition(0, 5);
// Set formula string
cell.setFormula("=1024/128");
// Get cell by name
cell = sheet.getCellByPosition(1, 3);
// Set formula string
cell.setFormula("=A3+A4");
//
// Fill CELL RANGE
//
// Get cell range by name
XCellRange cellRange = sheet.getCellRangeByName("C3:D4");
XCellRangeData data = (XCellRangeData) UnoRuntime.queryInterface(XCellRangeData.class, cellRange);
Object[][] values =
{
{new Double(3.3), new Integer(128)},
{new Double(4.4), new String("Entry")}
};
data.setDataArray(values);
} catch (com.sun.star.lang.IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// This example works with the following arguments:
// 1) A valid name of an OOo Calc document like "file:///c:/temp/calc.ods"
// 2) "private:factory/scalc" to create a new OOo Calc document
// 3) No argument at all to get the current OOo Calc document
String loadUrl = (args.length > 0)? args[0]: null;
try {
XComponentContext context = Bootstrap.bootstrap();
XMultiComponentFactory multiComponentFactory = context.getServiceManager();
Object desktopFrame = multiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", context);
XComponentLoader componentloader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class,desktopFrame);
Object component;
if (loadUrl != null) {
// Load the document
try {
component = componentloader.loadComponentFromURL(loadUrl, "_blank", 0, new PropertyValue[0]);
} catch (Exception e) {
component = null;
}
} else {
// Get the current document
XDesktop desktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class,desktopFrame);
component = desktop.getCurrentComponent();
}
// Get the active spreadsheet of the componente
XModel model = (XModel)UnoRuntime.queryInterface(XModel.class, component);
XSpreadsheet activeSpreadsheet = getActiveSpreadsheet(model);
if(activeSpreadsheet == null) {
// Either the document couldn't be loaded, the loaded document wasn't
// a spreadsheet, there wasn't a current document or the current
// document wasn't a spreadsheet.
// Whatever the reason has been, we create a new spreadsheet.
component = componentloader.loadComponentFromURL("private:factory/scalc", "_blank", 0, new PropertyValue[0]);
model = (XModel) UnoRuntime.queryInterface(XModel.class, component);
activeSpreadsheet = getActiveSpreadsheet(model);
}
fillSheet(activeSpreadsheet);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.exit(0);
}
}
}
|
|
Keywords for google to direct lost people here: cant find method xscriptcontext com.sun.star.script.provider.XScriptContext com.sun.star.awt.ActionEvent parcel-descriptor.xml" Scripting framework errror java macro java macro button java macro menujava form button vnd.sun.star.script calc.Calc.fillSpreadsheet language=Java
|
Download Sample ODF file with a Macro Here |
|
|