【问题标题】:Run Macro from LibreOffice extension JAVA从 LibreOffice 扩展 JAVA 运行宏
【发布时间】:2017-03-31 16:36:10
【问题描述】:

我正在尝试从扩展中的 java 按钮运行宏(宏在 Writer Standard.Voto.Main 中)。

这是按钮:

<dlg:button dlg:id="Bt_voto" dlg:tab-index="2" dlg:left="78" dlg:top="15" dlg:width="52" dlg:height="12" dlg:tag="B" dlg:value="Voto"><script:eventscript:event-name="on-performaction" script:macro-name="vnd.sun.star.UNO:ConfigChange" script:language="UNO"/>

我从这个类中调用方法:

public boolean callHandlerMethod(XDialog dialog, Object eventObject, String methodName)
        throws WrappedTargetException {
    if (methodName.equals(ConfigChange)) {

        try {
            String param = "";
            // String cmd =
            // "Standard.Conversion.ConvertHTMLToWord?langauge=Basic&location=application";
            String cmd = "Standard.Voto.Main?langauge=Basic&location=Document";
            System.out.println("Running macro on " + param);
            Macro macObj = new Macro();
            macObj.executeMacro(cmd, new Object[] { param });
            System.out.println("Completed?");
            onOkButtonPressed();
        } catch (Exception e) {
            System.out.println(e.toString());
            // e.printStackTrace();
        }

Macro.class 是:

class Macro {

    public Object executeMacro(String strMacroName, Object[] aParams) throws BootstrapException
    {

        String oooExecFolder = "C:/Program Files (x86)/LibreOffice 5/program";


        try {
            System.out.println("Completed1");
            XComponentContext xContext = BootstrapSocketConnector.bootstrap(oooExecFolder);
            XMultiComponentFactory xMultiComponentFactory = xContext.getServiceManager();
            XComponentLoader xcomponentloader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class,xMultiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", xContext));
            System.out.println("Completed2");


            com.sun.star.text.XTextDocument mxDoc = openWriter(xContext);

            XScriptProviderSupplier xScriptPS = (XScriptProviderSupplier) UnoRuntime.queryInterface(XScriptProviderSupplier.class, xcomponentloader);
            XScriptProvider xScriptProvider = xScriptPS.getScriptProvider(); 
            XScript xScript = xScriptProvider.getScript("vnd.sun.star.script:"+strMacroName); 

            short[][] aOutParamIndex = new short[1][1];
            Object[][] aOutParam = new Object[1][1];

            aParams = new String[2];

            @SuppressWarnings("unused")
            Object result = xScript.invoke(aParams, aOutParamIndex, aOutParam);
            System.out.println("xScript invoke macro " + strMacroName);

        } catch (Exception e) { 
            throw new RuntimeException(e);

        }
        return oooExecFolder; 
    }

    public static com.sun.star.text.XTextDocument openWriter(com.sun.star.uno.XComponentContext xContext)
    {

        com.sun.star.frame.XComponentLoader xCLoader; 
        com.sun.star.text.XTextDocument xDoc = null; 
        com.sun.star.lang.XComponent xComp = null; 

        try { 
            // get the remote office service manager 
            com.sun.star.lang.XMultiComponentFactory xMCF = 
                xContext.getServiceManager(); 

            Object oDesktop = xMCF.createInstanceWithContext( 
                                        "com.sun.star.frame.Desktop", xContext); 

            xCLoader = (com.sun.star.frame.XComponentLoader) 
                UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, 
                                          oDesktop); 
            com.sun.star.beans.PropertyValue [] szEmptyArgs = 
                new com.sun.star.beans.PropertyValue [0];
           /*
            ArrayList<PropertyValue> props = new ArrayList<PropertyValue>();
            PropertyValue p = new PropertyValue();
            p.Name = "Hidden";
            p.Value = new Boolean(true);
            props.add(p);

            PropertyValue[] properties = new PropertyValue[props.size()];
            props.toArray(properties);
            String strDoc = "private:factory/swriter";
            xComp = xCLoader.loadComponentFromURL(strDoc, "_blank", 0, properties);            
            */
            String strDoc = "private:factory/swriter"; 
            xComp = xCLoader.loadComponentFromURL(strDoc, "_blank", 0, szEmptyArgs); 
            xDoc = (com.sun.star.text.XTextDocument) 
                UnoRuntime.queryInterface(com.sun.star.text.XTextDocument.class, 
                                          xComp); 

        } catch(Exception e){  
            System.err.println(" Exception " + e); 
            e.printStackTrace(System.err); 
        }        
        return xDoc; 
    }
}

如果我运行这个类,引导程序可以工作,但它会在这一行终止:

XComponentContext xContext = BootstrapSocketConnector.bootstrap(oooExecFolder);

没有错误。你能帮帮我吗?

【问题讨论】:

    标签: java macros libreoffice libreoffice-writer


    【解决方案1】:

    直接从对话框中调用 Basic 宏要容易得多。即使扩展的其余部分使用 Java,这仍然有效。请务必使用正确的Script URI

    <dlg:button dlg:id="Bt_voto" dlg:tab-index="3" dlg:left="173" dlg:top="88" dlg:width="51" dlg:height="13" dlg:value="Voto">
      <script:event script:event-name="on-performaction" script:macro-name="vnd.sun.star.script:Standard.Voto.Main?language=Basic&amp;location=application" script:language="Script"/>
    </dlg:button>
    

    但是,如果您出于其他原因确实需要使用 Java,请继续阅读。您似乎试图合并来自两个不同项目的代码:

    问题是有些命令应该只执行一次,每个项目都执行,导致重复。不要引导第二次。相反,将上下文存储在某处,以便在需要时将其传递给 Macro 类。

    以下是对我有用的代码的相关部分。为了测试,我在 StarterProjectImpl.java 中添加了一个 main 方法。这使得可以看到错误消息。

    public static void main (String [] args) {
        com.sun.star.uno.XComponentContext xContext = null;
        try {
            xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
            ActionOneDialog actionOneDialog = new ActionOneDialog(xContext);
            actionOneDialog.show();
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }
    
    public ActionOneDialog(XComponentContext xContext) {
        m_xContext = xContext;
        this.dialog = DialogHelper.createDialog("ActionOneDialog.xdl", xContext, this);
    }
    
    public boolean callHandlerMethod(XDialog dialog, Object eventObject, String methodName) throws WrappedTargetException {
        if (methodName.equals(ConfigChange)) {
            try {
                String cmd = "Standard.Voto.Main?language=Basic&location=application";
                Macro macObj = new Macro(m_xContext);
            }
        }
    
    public Object executeMacro(String strMacroName, Object[] aParams)
    {
        String oooExecFolder = "C:/Program Files (x86)/LibreOffice 5/program";
        try {
            XMultiComponentFactory xMultiComponentFactory = m_xContext.getServiceManager();
            Object oDesktop = xMultiComponentFactory.createInstanceWithContext( 
                            "com.sun.star.frame.Desktop", m_xContext); 
            XComponentLoader xcomponentloader = (com.sun.star.frame.XComponentLoader) 
                UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, 
                                      oDesktop); 
            com.sun.star.text.XTextDocument mxDoc = openWriter(m_xContext);
    
            XScriptProviderSupplier xScriptPS = (XScriptProviderSupplier) UnoRuntime.queryInterface(
                    XScriptProviderSupplier.class, mxDoc);
            XScriptProvider xScriptProvider = xScriptPS.getScriptProvider(); 
            XScript xScript = xScriptProvider.getScript("vnd.sun.star.script:"+strMacroName); 
        } catch (Exception e) { 
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    

    编辑

    以下是分步说明。在 LibreOffice 中,转到 Tools -&gt; Macros -&gt; Organize Macros -&gt; LibreOffice Basic。在My Macros &amp; Dialogs -&gt; Standard -&gt; Voto 下,粘贴以下代码:

    Sub Main
        MsgBox("Hello, Voto!")
    End Sub
    

    接下来关注Get Started instructions。 展开 dialog -&gt; ActionOneDialog.xdl 并转到 Source 选项卡。在&lt;/dlg:button&gt;之后粘贴以下代码。

    <dlg:button dlg:id="Bt_voto" dlg:tab-index="4" dlg:left="100" dlg:top="88" dlg:width="51" dlg:height="13" dlg:value="Voto">
      <script:event script:event-name="on-performaction" script:macro-name="vnd.sun.star.script:Standard.Voto.Main?language=Basic&amp;location=application" script:language="Script"/>
    </dlg:button>
    

    现在运行它来添加扩展。最后在 LibreOffice 中,转到 Starter Project -&gt; Action One 并单击 Voto。结果应该是这样的:

    编辑 2

    根据我的经验,无法从对话框事件处理程序中插入字段。而是等到对话框执行完毕后再插入字段。

    对于这个项目,应该可以修改 ActionOneDialog.java 中的show()。在命令 dialog.execute() 之后,编写 Java 代码以使用调度程序插入字段。

    【讨论】:

    • 感谢您的快速回复,另一个问题,如果我从按钮调用宏,则方法 configchange 变为除非或否?您在 startprojectimpl 中编写的这段代码?感谢您的耐心等待
    • 如果按钮直接调用Basic,则不需要Macro类。如果按钮通过 Java 调用 Basic,那么这些方法与它们在您的代码中的位置相同,除了我放在 StarterProjectImpl.java 中的主例程。构造函数进入ActionOneDialog.java
    • 我使用默认的 starterproject 重新启动项目。 pastebin.com/tnbYXA99 这是我的 StarterProjectImpl.java 如果我运行该类,我没有错误并且 LibreOffice 启动,我手动创建一个新文档并且底部工作良好(也是宏工作)。但如果启动扩展,则按钮不起作用。你能帮我实现这个类吗?非常感谢
    • 你能把整个项目发布到像Dropbox这样的网站上下载吗?
    • 我重新启动了,就是这个项目:github.com/smehrbrodt/libreoffice-starter-extension,我只在 ActionOneDialog.java 类中添加了引导程序。我尝试了很多东西,但只有当我使用 main 并启动类时宏才会启动。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-17
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多