Запускать макрос из LibreOffice с расширением JAVA

Я пытаюсь запустить макрос (макрос находится в Writer Standard.Voto.Main) с помощью кнопки Java в расширении.

Это кнопка:

<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);

без ошибок. Вы можете мне помочь?

1 ответ

Гораздо проще вызывать базовый макрос непосредственно из диалогового окна. Это работает, даже если остальная часть расширения использует 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. Это позволило увидеть сообщения об ошибках.

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 -> Macros -> Organize Macros -> LibreOffice Basic, Под My Macros & Dialogs -> Standard -> Votoвставьте этот код:

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

Далее следуйте инструкциям Get Started. расширять dialog -> ActionOneDialog.xdl и перейти к Source Вкладка. Вставьте следующий код после </dlg:button>,

<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 -> Action One и нажмите Voto, Результат должен быть таким:

результат

РЕДАКТИРОВАТЬ 2:

Исходя из моего опыта, невозможно вставить поле из обработчика события диалога. Вместо этого подождите, пока диалог не завершится, и вставьте поле.

Для этого проекта, он должен работать, чтобы изменить show() в ActionOneDialog.java. После команды dialog.execute(), напишите Java-код для вставки поля с помощью диспетчера.

Другие вопросы по тегам