# LAB-5569: ODFDOM - Changing ODF documents using the new opensourced multi-tiered API

Expected Duration: 100 minutes
Contacts: Svante.Schubert Steffen Grund

Introduction | Exercise 0 | Exercise 1 | Exercise 2 | Exercise 3 | Exercise 4 | Summary
7. Introduction Steps to Follow Summary ## Exercise 4: Export Data from OpenOffice.org as .csv (30 minutes) In this exercise, an export function (with some additions, it could develop into a filter) for OpenOffice.org is written, using the odf toolkit. This exercise shows how data from a spreadsheet can be manipulated with Java inside of the OpenOffice.org process. For this, an Extension for OpenOffice.org is created. Extensions can bring additional functionalities to OpenOffice.org that are missing from the original program. OpenOffice.org can be customized with Extensions. ### Steps to Follow Configure the "OpenOffice.org API plugin for Netbeans". See http://wiki.services.openoffice.org Create a new OpenOffice.org Add-On project Click "Next". Figure-01: Create an Add-On project. Enter the following names in the correct places. Confer to the screenshot, if you are in doubt. Project Name should be "ExportExample". The Main Class Name will change accordingly. Enter "odfdom.example4" as Java package. Note: Do not forget to change <lab_root> with something meaningful. Finally make sure to have "Create Toolbar" enabled and "Create Menu" disabled. This will produce an extension to OpenOffice.org that brings its own toolbar with it. Click "Next" again afterwards. Figure-02: Define Project Names Enter "Export" in the spaces shown in the screenshot. Click "Next" again afterwards. Figure-03: Define Function Name Simply enable the "Spreadsheet" context here. Click "Finish". Figure-04: Enable Spreadsheet Import the same jar files as described in exercise 2, step 6. You do not need to add any new files, since everything is generated by NetBeans and the plugin. Open "ExportExample.java". Look for the `dispatch(...)` method. When someone clicks on the button that was defined during project creation, this method will be executed. Add the following lines:
       try {
           exportFile();
       } catch (Exception ex) {
           Logger.getLogger(ExportExample.class.getName()).log(Level.SEVERE, null, ex);
       }
   The complete `dispatch(...)` method should look like this:
       // com.sun.star.frame.XDispatch:
       public void dispatch(com.sun.star.util.URL aURL,
               com.sun.star.beans.PropertyValue[] aArguments) {
           if (aURL.Protocol.compareTo("odfdom.example4.ExportExample:") == 0) {
               if (aURL.Path.compareTo("Export") == 0) {
                   try {
                       exportFile();
                   } catch (Exception ex) {
                       Logger.getLogger(ExportExample.class.getName()).log(Level.SEVERE, null, ex);
                   }
               }
           }
8. Now implement the `exportFile()` function. Do not forget to edit the <lab_root> path. In this function lies the challenge of this exercise, but more to that later. First store the current file as a temporary document.
           /**
            * Export the csv file
            */
           private void exportFile() throws Exception {
               ////////////////////////////////////////////////////////////////
               // OpenOffice.org API handling
               // 0 save file first
               XModel xModel = m_xFrame.getController().getModel();
               XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class, xModel);
               File file = File.createTempFile("temp", ".ods");
               String url = getUrl(file);
               xStorable.storeToURL(url, new PropertyValue[0]);
   Then create a file to write the content to.
               ////////////////////////////////////////////////////////////////
               // 1 Create a file for output
               String exportFileName = "output.csv";
               FileWriter exportFileWriter = new FileWriter(exportFileName);

               // CHALLENGE!

               // close the writer
               exportFileWriter.close();
           }
9. Implement the `getUrl()` helper function.
           /**
            * Get OpenOffice.org URL from a system file
            * @param file a file on the file system
            * @return the path of the file as OpenOffice.org URL
            */
           private String getUrl(File file) {
               String path = file.getPath().replace('\\', '/');
               if (!path.startsWith("/")) {
                   path = "/".concat(path);
               }
               path = "file://".concat(path);
               return path;
           }
10. This is the complete "ExportExample.java" file.
        package odfdom.example4;

        import com.sun.star.beans.PropertyValue;
        import com.sun.star.frame.XModel;
        import com.sun.star.frame.XStorable;
        import com.sun.star.uno.UnoRuntime;
        import com.sun.star.uno.XComponentContext;
        import com.sun.star.lib.uno.helper.Factory;
        import com.sun.star.lang.XSingleComponentFactory;
        import com.sun.star.registry.XRegistryKey;
        import com.sun.star.lib.uno.helper.WeakBase;
        import java.io.File;
        import java.io.FileWriter;
        import java.io.IOException;
        import java.util.logging.Level;
        import java.util.logging.Logger;
        import javax.xml.xpath.XPath;
        import javax.xml.xpath.XPathConstants;
        import javax.xml.xpath.XPathFactory;
        import org.odftoolkit.odfdom.doc.OdfDocument;
        import org.odftoolkit.odfdom.doc.OdfFileDom;
        import org.odftoolkit.odfdom.doc.element.table.OdfTableCell;
        import org.odftoolkit.odfdom.doc.element.table.OdfTableRow;
        import org.odftoolkit.odfdom.dom.OdfNamespace;
        import org.w3c.dom.NodeList;

        public final class ExportExample extends WeakBase
                implements com.sun.star.lang.XServiceInfo,
                com.sun.star.frame.XDispatchProvider,
                com.sun.star.lang.XInitialization,
                com.sun.star.frame.XDispatch {

            private final XComponentContext m_xContext;
            private com.sun.star.frame.XFrame m_xFrame;
            private static final String m_implementationName = ExportExample.class.getName();
            private static final String[] m_serviceNames = {
                "com.sun.star.frame.ProtocolHandler"};

            public ExportExample(XComponentContext context) {
                m_xContext = context;
            }

            ;

            public static XSingleComponentFactory __getComponentFactory(String sImplementationName) {
                XSingleComponentFactory xFactory = null;

                if (sImplementationName.equals(m_implementationName)) {
                    xFactory = Factory.createComponentFactory(ExportExample.class, m_serviceNames);
                }
                return xFactory;
            }

            public static boolean __writeRegistryServiceInfo(XRegistryKey xRegistryKey) {
                return Factory.writeRegistryServiceInfo(m_implementationName,
                        m_serviceNames,
                        xRegistryKey);
            }

            // com.sun.star.lang.XServiceInfo:
            public String getImplementationName() {
                return m_implementationName;
            }

            public boolean supportsService(String sService) {
                int len = m_serviceNames.length;

                for (int i = 0; i < len; i++) {
                    if (sService.equals(m_serviceNames[i])) {
                        return true;
                    }
                }
                return false;
            }

            public String[] getSupportedServiceNames() {
                return m_serviceNames;
            }

            // com.sun.star.frame.XDispatchProvider:
            public com.sun.star.frame.XDispatch queryDispatch(com.sun.star.util.URL aURL,
                    String sTargetFrameName,
                    int iSearchFlags) {
                if (aURL.Protocol.compareTo("odfdom.example4.ExportExample:") == 0) {
                    if (aURL.Path.compareTo("Export") == 0) {
                        return this;
                    }
                }
                return null;
            }

            // com.sun.star.frame.XDispatchProvider:
            public com.sun.star.frame.XDispatch[] queryDispatches(
                    com.sun.star.frame.DispatchDescriptor[] seqDescriptors) {
                int nCount = seqDescriptors.length;
                com.sun.star.frame.XDispatch[] seqDispatcher =
                        new com.sun.star.frame.XDispatch[seqDescriptors.length];

                for (int i = 0; i < nCount; ++i) {
                    seqDispatcher[i] = queryDispatch(seqDescriptors[i].FeatureURL,
                            seqDescriptors[i].FrameName,
                            seqDescriptors[i].SearchFlags);
                }
                return seqDispatcher;
            }

            // com.sun.star.lang.XInitialization:
            public void initialize(Object[] object)
                    throws com.sun.star.uno.Exception {
                if (object.length > 0) {
                    m_xFrame = (com.sun.star.frame.XFrame) UnoRuntime.queryInterface(
                            com.sun.star.frame.XFrame.class, object[0]);
                }
            }

            // com.sun.star.frame.XDispatch:
            public void dispatch(com.sun.star.util.URL aURL,
                    com.sun.star.beans.PropertyValue[] aArguments) {
                if (aURL.Protocol.compareTo("odfdom.example4.ExportExample:") == 0) {
                    if (aURL.Path.compareTo("Export") == 0) {
                        try {
                            exportFile();
                        } catch (Exception ex) {
                            Logger.getLogger(ExportExample.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }

            public void addStatusListener(com.sun.star.frame.XStatusListener xControl,
                    com.sun.star.util.URL aURL) {
                // add your own code here
            }

            public void removeStatusListener(com.sun.star.frame.XStatusListener xControl,
                    com.sun.star.util.URL aURL) {
                // add your own code here
            }

            private void exportFile() throws Exception {
                ////////////////////////////////////////////////////////////////
                // OpenOffice.org API handling
                // 0 save file first
                XModel xModel = m_xFrame.getController().getModel();
                XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class, xModel);
                File file = File.createTempFile("temp", ".ods");
                String url = getUrl(file);
                xStorable.storeToURL(url, new PropertyValue[0]);
                // 1 Craete a file for output
                String exportFileName = "output.csv";
                FileWriter exportFileWriter = new FileWriter(exportFileName);

                exportFileWriter.close();
            }

            private String getUrl(File file) {
                String path = file.getPath().replace('\\', '/');
                if (!path.startsWith("/")) {
                    path = "/".concat(path);
                }
                path = "file://".concat(path);
                return path;
            }
        }
Select the "Projects" tab and then click right on the project node and select "Debug in Target OpenOffice.org" to verify that the Add-On works and to debug it. Figure-05: Debug the project in OpenOffice.org To trigger the functionality, open Calc in OpenOffice.org and click on "Export" to execute the new function. For the actual functionality, take a look at the challenge. Figure-06: Result ### Challenge The example until now is meaningless. Use the created variable `exportFileWriter` to write data to the csv file, and get the data from the stored ods document. Hint: reuse code from example 3 to collect the data from the spreadsheet (ods file). ### Summary In this exercise, the toolkit was used as a part of the OpenOffice.org functionality to add new functions to the OpenOffice.org feature set. Back to top To summary