[Solved] Accessing the content of a "Transient Document"

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
pjoyez
Posts: 4
Joined: Wed Apr 12, 2017 10:07 am

[Solved] Accessing the content of a "Transient Document"

Post by pjoyez »

I am trying to write a macro that operates on graphics that are embedded in documents. The basics for this can be taken in viewtopic.php?f=21&t=43010. However, that macro accesses images in the DocumentStorage which reflects the last saved state of the document. I would like my macro to work also on unsaved documents. For this, I understand that I need to get the images from the "Transient Document" whose url I can get using ThisComponent.NameSpace or ThisComponent.StringValue, but at the moment I cannot figure how to access the content of the "Pictures" subfolder of that transient document. I guess I would need to use stuff like com.sun.star.comp.ucb.TransientDocumentsContentProvider, but I cannot understand how it is supposed to be used just by reading the doc, and I could not find any example code snippet... Could anyone guide me for achieving this?
Last edited by Hagar Delest on Mon Apr 17, 2017 11:14 am, edited 1 time in total.
Reason: tagged solved.
LibreOffice 5.3 on Ubuntu 16.14
User avatar
RoryOF
Moderator
Posts: 34586
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: accessing the content of a "Transient Document"

Post by RoryOF »

The usual starting point for information on detailed macro programming is Andrew Pitonyak's work on macro programming, downloadable from
http://www.pitonyak.org/oo.php
Apache OpenOffice 4.1.15 on Xubuntu 22.04.4 LTS
pjoyez
Posts: 4
Joined: Wed Apr 12, 2017 10:07 am

Re: accessing the content of a "Transient Document"

Post by pjoyez »

Thank you RoryOF, I know Andrew Pitonyak's macro examples and book. AFAICT the only place where transient documents are mentioned in Pitonyak's documents is when he explains how to "Access OOo's internal storage system" using "The coolest trick [he] know[s]", which is typing "vnd.sun.star.tdoc:/" in the open file dialog (which, by the way, does not work on my system).

I came here precisely because I have not found there (nor elsewhere) how to access an url such as : vnd.sun.star.tdoc:/3/Pictures/10004E0F00001A84000006CF85DF5AD8B99B01BB.svg. It is probably not that difficult, but you cannot just pretend you open a regular file.
LibreOffice 5.3 on Ubuntu 16.14
ms777
Volunteer
Posts: 177
Joined: Mon Oct 08, 2007 1:33 am

Re: accessing the content of a "Transient Document"

Post by ms777 »

... maybe this helps a bit as a starter. Run it in a writer doc with one or more jpg embedded

Good luck,

ms777

Code: Select all

Sub Main

'get the images in ThisComponent.GraphicObjects
sMes = "pictures contained in GraphicObjects: " & ThisComponent.GraphicObjects.Count

for k=0 to ThisComponent.GraphicObjects.Count-1
  sMes = sMes & Chr(13) & Chr(10) & ThisComponent.GraphicObjects.getByIndex(k).graphicUrl
  next
msgbox sMes

'get the images in ThisComponent.DocumentStorage
asElementNames = ThisComponent.DocumentStorage.getByName("Pictures").ElementNames
sMes = "pictures contained in DocumentStorage: " & (UBound(asElementNames)+1)
for k=0 to UBound(asElementNames)
  sMes = sMes & Chr(13) & Chr(10) & asElementNames(k)
  next
msgbox sMes


oPicGraphicObjects = ThisComponent.GraphicObjects.getByIndex(0)
xray oPicGraphicObjects

oPicStorage = ThisComponent.DocumentStorage.getByName("Pictures").getByName(asElementNames(0))
xray oPicStorage


'Example: insert the first image into an ImageControl. The ImageControl must already be present, on the first form, and must be named "ImageControl".

oImageControl = ThisComponent.DrawPage.Forms.getByIndex(0).getByName("ImageControl")

oProvider = createUnoService("com.sun.star.graphic.GraphicProvider") 
Dim oPropsIN(1)as new com.sun.star.beans.PropertyValue 
oPropsIN(0).Name  = "InputStream" 
oPropsIN(0).Value = oPicStorage.InputStream
oImageControl.Graphic = oProvider.queryGraphic(oPropsIN()) 

End Sub
pjoyez
Posts: 4
Joined: Wed Apr 12, 2017 10:07 am

Re: accessing the content of a "Transient Document"

Post by pjoyez »

What you propose is more or less what I started with : it accesses images in the DocumentStorage, but this does not work with unsaved documents. I'd like a macro that works in all cases. Thanks anyway ms777.
LibreOffice 5.3 on Ubuntu 16.14
User avatar
RoryOF
Moderator
Posts: 34586
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: accessing the content of a "Transient Document"

Post by RoryOF »

Why not cause your macro to Save the document to a temporary name before looking for the pictures? If you do not subsequently require the document, your macro could afterwards delete it.
Apache OpenOffice 4.1.15 on Xubuntu 22.04.4 LTS
User avatar
karolus
Volunteer
Posts: 1158
Joined: Sat Jul 02, 2011 9:47 am

Re: Accessing the content of a "Transient Document"

Post by karolus »

Hallo

I use regulary the "Trick" mentioned above to write python-code directly into embedded python-scripts, it works also with unsaved docs.
Below parts of the python-code for the job:

Code: Select all


#…<snip>…        
        sfa = createUnoService( "com.sun.star.ucb.SimpleFileAccess")
        
        pythonfolder = ('vnd.sun.star.tdoc:/'
                     '{}/Scripts/python'.format(doc.RuntimeUID))

        fileuri = "{}/{}".format(pythonfolder, filename)
        if sfa.exists(fileuri):
            if mode == 'a':
                message = ("Appending to %s in doc: %s" % (filename , doc.Title))            
            else:
                print("Overwriting %s in doc: %s" % (filename, doc.Title))
        else:
            print("Writing to %s in doc: %s" %(filename, doc.Title))
                        
        sfa.createFolder(pythonfolder)    
        tempfile = NamedTemporaryFile(mode=mode)
        temppath = tempfile.name
        tempuri = uno.systemPathToFileUrl(temppath)
                        
        if sfa.exists(fileuri) and mode=='a':
            sfa.copy(fileuri, tempuri)
            with open(temppath) as t:
                t = t.read()
            doublefuncs = test_unique_func_names(t, content)
            if doublefuncs:
                tempfile.delete
                print('Interrupt appending to {} @ {}, '
                      'because double Functionnames: ``{}´'
                      ''.format(filename, doc.Title, ', '.join(doublefuncs)))               
                return
            print(message)             
            
        with io.open(temppath, mode, encoding='utf-8') as f:
            f.write(content)
        sfa.copy(tempuri, fileuri)
        tempfile.delete
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
Libreoffice 7.4 on Debian 12 (Bookworm) (on RaspberryPI4)
Libreoffice 7.6 flatpak on Debian 12 (Bookworm) (on RaspberryPI4)
ms777
Volunteer
Posts: 177
Joined: Mon Oct 08, 2007 1:33 am

Re: Accessing the content of a "Transient Document"

Post by ms777 »

... and if storing the doc to disk is not possible due to lack of rights you can also store your document to a storage in memory:

Code: Select all

oDoc = ThisComponent

oStorageFac = createUnoService("com.sun.star.embed.StorageFactory") 
oStorage    = oStorageFac.createInstance
oStream     = oStorage.openStreamElement("ms777", com.sun.star.embed.ElementModes.READWRITE) 

Dim storeProps(0) as new com.sun.star.beans.PropertyValue
storeProps(0).Name = "OutputStream"
storeProps(0).Value = oStream
oDoc.storeToUrl("private:stream", storeProps())
pjoyez
Posts: 4
Joined: Wed Apr 12, 2017 10:07 am

Re: Accessing the content of a "Transient Document"

Post by pjoyez »

Many thanks Karolus, your reply blew away some of my misconceptions!

1) The content of transient docs IS accessible as any other file (you can even write to it!). I was thinking opposite because I got an error when trying to access my image in it, but this was because:

2) the transient document does NOT contain the image, unless the document was already saved (So it's just the same as accessing the Document storage!). I was mislead to think that would be different based on the documentation found here : https://www.openoffice.org/ucb/docs/ucp ... c-ucp.html
"All documents that have been loaded – regardless of their persistent document format--- or that have been created but not yet saved to any storage medium, are supported.[...] The document contents provided by the [Transient Document Content Provider] represent live data, which may differ from any persistent representation of the document, for instance, because the user modified the document after loading, but did not yet save it."
Your post also gives me the workaround: I'll be able write the image myself in the transient document at the time I insert it.

Thanks too, ms777. I was thinking to use the temporary files, but using that temporary storage in memory could be useful in some cases.
LibreOffice 5.3 on Ubuntu 16.14
Post Reply