includefile procedure

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
golmatt
Posts: 5
Joined: Thu Mar 05, 2020 2:28 pm

includefile procedure

Post by golmatt »

I must make a procedure in java (preferred, but are accepted others languages, also).

The procedure must process the fields created by user with:

Insert -> Field -> More field.. -> Functions -> Input field ->

Code: Select all

[#includefile "toinclude.odt"]
The process must replace the fields with the contents of the files indicated.

In attachment:
maintemplate.odt (document with fields)
toinclude.odt
toinclude2.odt
result.odf (final result of processing)

Thanks in advance.
Attachments
includefile.zip
documents
(25.79 KiB) Downloaded 173 times
Apache OpenOffice 4.1.7 on Windows 10 pro 64 bit
User avatar
RoryOF
Moderator
Posts: 34618
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: includefile procedure

Post by RoryOF »

golmatt wrote:I must make a procedure in java (preferred, but are accepted others languages, also).
Is this a homework project?
Apache OpenOffice 4.1.15 on Xubuntu 22.04.4 LTS
golmatt
Posts: 5
Joined: Thu Mar 05, 2020 2:28 pm

Re: includefile procedure

Post by golmatt »

RoryOF wrote:Is this a homework project?
I must extends xdocreport reporting functionality

https://github.com/opensagres/xdocreport
Apache OpenOffice 4.1.7 on Windows 10 pro 64 bit
golmatt
Posts: 5
Joined: Thu Mar 05, 2020 2:28 pm

Re: includefile procedure

Post by golmatt »

This is a solution

Code: Select all

	        ...
	        com.sun.star.text.XText xText = xTextDocument.getText();
	         
	        com.sun.star.text.XTextFieldsSupplier xTextFieldsSupplier = UnoRuntime.queryInterface(
	        		com.sun.star.text.XTextFieldsSupplier.class, xTextDocument);
	        
	        XEnumerationAccess textFields = xTextFieldsSupplier.getTextFields();
	        
	        XEnumeration enumeration = textFields.createEnumeration();
	         
	        while (enumeration.hasMoreElements()) {
	        	com.sun.star.uno.Any textField = (com.sun.star.uno.Any) enumeration.nextElement();
	        	
	        	com.sun.star.text.XTextField xTextField = (com.sun.star.text.XTextField) 
	        			UnoRuntime.queryInterface(
	        					com.sun.star.text.XTextField.class, textField);

	        	String presentation = xTextField.getPresentation(false);
	        	
	        	if (presentation.startsWith("[#includefile")) {
	        		int start = presentation.indexOf("\"", 0);
	        		int end = presentation.indexOf("\"", start +1);
	        		if (end > start) {
	        			String filenameUrl = presentation.substring(start +1, end);
	        			XTextCursor cursor = xText.createTextCursor();
	        			
	        			cursor.gotoRange(xTextField.getAnchor().getStart(), false);
	        			
	        			xText.removeTextContent(xTextField);

	        			com.sun.star.document.XDocumentInsertable xDocIns = UnoRuntime.queryInterface(
	                    		com.sun.star.document.XDocumentInsertable.class, cursor);
	        			xDocIns.insertDocumentFromURL(filenameUrl, new PropertyValue[0]);
	        		}
	        	}
	        }
How can I optimize the code by testing if the xTextField is an Input Field before getPresentation call?
Apache OpenOffice 4.1.7 on Windows 10 pro 64 bit
User avatar
Lupp
Volunteer
Posts: 3553
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: includefile procedure

Post by Lupp »

Every textfield type needs to support characteristic services.

Code: Select all

REM Basic:
...
textFields = ThisComponent.TextFields
For Each textField In textFields
    If textField.supportsService("com.sun.star.text.TextField.Input") Then
        REM Whatever you want to do
    End If
Next textField
...
See also https://api.libreoffice.org/docs/idl/re ... Field.html.
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
golmatt
Posts: 5
Joined: Thu Mar 05, 2020 2:28 pm

Re: includefile procedure

Post by golmatt »

Lupp wrote:Every textfield type needs to support characteristic services.

Code: Select all

REM Basic:
...
textFields = ThisComponent.TextFields
For Each textField In textFields
    If textField.supportsService("com.sun.star.text.TextField.Input") Then
        REM Whatever you want to do
    End If
Next textField
...
See also https://api.libreoffice.org/docs/idl/re ... Field.html.
I didn't find the corrispondent "textField.supportsService("com.sun.star.text.TextField.Input")" in java.
Apache OpenOffice 4.1.7 on Windows 10 pro 64 bit
User avatar
Lupp
Volunteer
Posts: 3553
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: includefile procedure

Post by Lupp »

I'm not a user of java, but...

supportsSevice() doesn't need a specific implementation for java, but is a method of the uno object which must work as excpected as soon as the object is accessible at all the uno way. If not, the bridge is broken.

Did you correctly instantiate the ServiceManager for uno in your java code?
Does anything using uno services work as expected in your program?
How did you get access (open/create) to the document?
What do you get with aVariable = myTextField.getSupportedServiceNames()?
Did you regard that the service names are compared for identity (case sensitive)?
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
golmatt
Posts: 5
Joined: Thu Mar 05, 2020 2:28 pm

Re: includefile procedure

Post by golmatt »

This is full code:

Code: Select all

    public static void main(String args[]) {
        // You need the desktop to create a document
        // The getDesktop method does the UNO bootstrapping, gets the
        // remote servie manager and the desktop object.
        com.sun.star.frame.XDesktop xDesktop = null;
        xDesktop = getDesktop();

        try {
	        com.sun.star.text.XTextDocument xTextDocument =
	            openTextdocument( xDesktop, "file:///c:/temp/modello.odt");
	        
	        com.sun.star.text.XText xText = xTextDocument.getText();
	         
	        com.sun.star.text.XTextFieldsSupplier xTextFieldsSupplier = UnoRuntime.queryInterface(
	        		com.sun.star.text.XTextFieldsSupplier.class, xTextDocument);
	        
	        XEnumerationAccess textFields = xTextFieldsSupplier.getTextFields();
	        
	        XEnumeration enumeration = textFields.createEnumeration();
	         
	        while (enumeration.hasMoreElements()) {
	        	com.sun.star.uno.Any textField = (com.sun.star.uno.Any) enumeration.nextElement();
	        	
	        	com.sun.star.text.XTextField xTextField = (com.sun.star.text.XTextField) 
	        			UnoRuntime.queryInterface(
	        					com.sun.star.text.XTextField.class, textField);
	        	
	        	String presentation = xTextField.getPresentation(false);
	        	
	        	if (presentation.startsWith("[#includefile")) {
	        		int start = presentation.indexOf("\"", 0);
	        		int end = presentation.indexOf("\"", start +1);
	        		if (end > start) {
	        			String filenameUrl = presentation.substring(start +1, end);
	        			XTextCursor cursor = xText.createTextCursor();
	        			
	        			cursor.gotoRange(xTextField.getAnchor().getStart(), false);
	        			
	        			xText.removeTextContent(xTextField);

	        			com.sun.star.document.XDocumentInsertable xDocIns = UnoRuntime.queryInterface(
	                    		com.sun.star.document.XDocumentInsertable.class, cursor);
	        			xDocIns.insertDocumentFromURL(filenameUrl, new PropertyValue[0]);
	        		}
	        	}
	        }
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
        }

        System.out.println("Done");

        System.exit(0);
    }


    public static com.sun.star.frame.XDesktop getDesktop() {
        com.sun.star.frame.XDesktop xDesktop = null;
        com.sun.star.lang.XMultiComponentFactory xMCF = null;

        try {
            com.sun.star.uno.XComponentContext xContext = null;

            // get the remote office component context
            //xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
            String oooExeFolder = "C:/Program Files/LibreOffice/program/";
            xContext = BootstrapSocketConnector.bootstrap(oooExeFolder);

            // get the remote office service manager
            xMCF = xContext.getServiceManager();
            if( xMCF != null ) {
                System.out.println("Connected to a running office ...");

                Object oDesktop = xMCF.createInstanceWithContext(
                    "com.sun.star.frame.Desktop", xContext);
                xDesktop = UnoRuntime.queryInterface(
                    com.sun.star.frame.XDesktop.class, oDesktop);
            }
            else
                System.out.println( "Can't create a desktop. No connection, no remote office servicemanager available!" );
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
            System.exit(1);
        }


        return xDesktop;
    }

    public static com.sun.star.text.XTextDocument openTextdocument(
        com.sun.star.frame.XDesktop xDesktop , String url)
    {
        com.sun.star.text.XTextDocument aTextDocument = null;

        try {
        	com.sun.star.lang.XComponent xComponent = openDocument(xDesktop, "swriter", url);
            aTextDocument = UnoRuntime.queryInterface(
                com.sun.star.text.XTextDocument.class, xComponent);
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
        }

        return aTextDocument;
    }


    protected static com.sun.star.lang.XComponent openDocument(
        com.sun.star.frame.XDesktop xDesktop,
        String sDocumentType, String url )
    {
        com.sun.star.lang.XComponent xComponent = null;
        com.sun.star.frame.XComponentLoader xComponentLoader = null;
        com.sun.star.beans.PropertyValue xEmptyArgs[] =
            new com.sun.star.beans.PropertyValue[0];

        try {
            xComponentLoader = UnoRuntime.queryInterface(
                com.sun.star.frame.XComponentLoader.class, xDesktop);
            
            xComponent  = xComponentLoader.loadComponentFromURL(
                url, url, 0, xEmptyArgs); //properties
        }
        catch( Exception e) {
            e.printStackTrace(System.err);
        }

        return xComponent ;
    }
There are not these methods:

Code: Select all

textField.getSupportedServiceNames()
xTextField.getSupportedServiceNames()
textField.supportsService(...)
xTextField.supportsService(...)
Apache OpenOffice 4.1.7 on Windows 10 pro 64 bit
User avatar
Lupp
Volunteer
Posts: 3553
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: includefile procedure

Post by Lupp »

As I already told, I am not a user (nor a friend) of Java. My only glances on the Language/System were about 20 years ago and didn't convince me of needing to study it to more detail. The code you posted didn't change my mind, in specific not concerning the usage controlling LibreOffice/AOO. (I'm not sure whether or not the bloated C-like appearance is unavoidable.)
Anyway: The interface XServiceInfo (https://api.libreoffice.org/docs/idl/re ... 18f9881e74) is an indispensable means using the uno API. If the bridge from your Java to the API cannot be configured to support it, it isn't suitable for the purpose.
You surely studied https://wiki.openoffice.org/wiki/Docume ... _Implement or similar info.
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
Post Reply