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

Creating a macro - Writing a Script - Using the API

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

Postby pjoyez » Fri Apr 14, 2017 10:00 am

I am trying to write a macro that operates on graphics that are embedded in documents. The basics for this can be taken in https://forum.openoffice.org/en/forum/v ... 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
pjoyez
 
Posts: 4
Joined: Wed Apr 12, 2017 10:07 am

Re: accessing the content of a "Transient Document"

Postby RoryOF » Fri Apr 14, 2017 10:04 am

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.3 on Xubuntu 16.04 (mostly 64 bit version) and infrequently on Win2K/XP
14 October 2016 was Pooh's 90th birthday
User avatar
RoryOF
Moderator
 
Posts: 24934
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: accessing the content of a "Transient Document"

Postby pjoyez » Fri Apr 14, 2017 1:40 pm

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
pjoyez
 
Posts: 4
Joined: Wed Apr 12, 2017 10:07 am

Re: accessing the content of a "Transient Document"

Postby ms777 » Fri Apr 14, 2017 5:45 pm

... 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   Expand viewCollapse view
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
ms777
Volunteer
 
Posts: 129
Joined: Mon Oct 08, 2007 1:33 am

Re: accessing the content of a "Transient Document"

Postby pjoyez » Fri Apr 14, 2017 6:58 pm

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
pjoyez
 
Posts: 4
Joined: Wed Apr 12, 2017 10:07 am

Re: accessing the content of a "Transient Document"

Postby RoryOF » Fri Apr 14, 2017 7:01 pm

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.3 on Xubuntu 16.04 (mostly 64 bit version) and infrequently on Win2K/XP
14 October 2016 was Pooh's 90th birthday
User avatar
RoryOF
Moderator
 
Posts: 24934
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: Accessing the content of a "Transient Document"

Postby karolus » Fri Apr 14, 2017 10:10 pm

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   Expand viewCollapse view


#…<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 - 5.1 … 5.3.2.2 on Linux Mint17
User avatar
karolus
Volunteer
 
Posts: 843
Joined: Sat Jul 02, 2011 9:47 am

Re: Accessing the content of a "Transient Document"

Postby ms777 » Sat Apr 15, 2017 5:57 pm

... 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   Expand viewCollapse view
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())
ms777
Volunteer
 
Posts: 129
Joined: Mon Oct 08, 2007 1:33 am

Re: Accessing the content of a "Transient Document"

Postby pjoyez » Sun Apr 16, 2017 6:47 pm

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
pjoyez
 
Posts: 4
Joined: Wed Apr 12, 2017 10:07 am


Return to Macros and UNO API

Who is online

Users browsing this forum: No registered users and 3 guests