Copying Impress slides by macro

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
Jan_J
Posts: 167
Joined: Wed Apr 29, 2009 1:42 pm
Location: Poland

Copying Impress slides by macro

Post by Jan_J »

Recently I tried to write a routine that merges slides from 2 or more Impress documents. It has got a form of Python function. Copying has been implemented using .uno:Copy service. Here's the code:

Code: Select all

# coding: utf8

import sys
import os
import time
import uno
import pyuno

def mergeFromURL(desk, dispatcher, doc1, url, dt = 1.0):

    ctr1 = doc1.getCurrentController()
    frame1 = ctr1.Frame

    doc2 = desk.loadComponentFromURL(url, "_blank", 0, ())
    ctr2 = doc2.getCurrentController()
    frame2 = ctr2.Frame

    dispatcher.executeDispatch(frame1, ".uno:DiaMode", "", 0, ())
    dispatcher.executeDispatch(frame2, ".uno:DiaMode", "", 0, ())

    for i in range(doc2.DrawPages.Count):

        page2 = doc2.DrawPages.getByIndex(i)
        ctr2.setCurrentPage(page2)
        dispatcher.executeDispatch(frame2, ".uno:Copy", "", 0, ())
        time.sleep(dt)
       
        page1 = doc1.DrawPages.getByIndex(doc1.DrawPages.Count-1)
        ctr1.setCurrentPage(page1)
        dispatcher.executeDispatch(frame1, ".uno:Paste", "", 0, ())
        time.sleep(dt)

    dispatcher.executeDispatch(frame1, ".uno:DrawingMode", "", 0, ())
    doc2.close(False)

def fileNameToUrl(fname):
    if fname[0:7] != 'file://':
        fname = os.path.realpath(fname)
        return pyuno.systemPathToFileUrl(fname)
    else:
        return fname

def mergeFiles(ctx, desk, filelist, outname):
    doc =  desk.loadComponentFromURL("private:factory/simpress", "_blank", 0, ())
    dispatcher = ctx.ServiceManager.createInstanceWithContext("com.sun.star.frame.DispatchHelper", ctx)
    for fname in filelist:
        mergeFromURL(desk, dispatcher, doc, fileNameToUrl(fname))
    doc.DrawPages.remove(doc.DrawPages.getByIndex(0))
    doc.storeAsURL(fileNameToUrl(outname), ())
    doc.close(False)

def asMacro():
    ctx = XSCRIPTCONTEXT.getComponentContext()
    desk = XSCRIPTCONTEXT.getDesktop()
    infiles = [
                    "c:/users/my_user/slides1.odp",
                    "c:/users/my_user/slides2.odp",
                  ]
    outfile = "c:/users/my_user/output.odp"
    mergeFiles(ctx, desk, infiles, outfile)

def asService():
    assert len(sys.argv) >= 2
    localContext = uno.getComponentContext()
    resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext)
    ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
    desk = ctx.ServiceManager.createInstanceWithContext( "com.sun.star.frame.Desktop", ctx)
    infiles = sys.argv[1 : -1]
    outfile = sys.argv[-1]
#    infiles = [
#                    "c:/users/my_user/slides1.odp",
#                    "c:/users/my_user/slides2.odp",
#                  ]
#    outfile = "c:/users/my_user/output.odp"
    mergeFiles(ctx, desk, infiles, outfile)

if __name__ == '__main__':
    asService()
(see also http://forum.openoffice.org/pl/forum/vi ... 8847#p8847)

1. The script, however, makes full copy of the content only when Impress is running in visual mode. Trying to use it in server (or --headless) mode on Linux with no X Server results in partial copying (slides are inserted, but the content is not complete). I suspect the Copy service to be dependent on GUI. Any idea how to get near equivalent feature usable with no X environment?

2. Similar StarBasic code can be run as macro inside Impress session. It uses wait() function in place of time.sleep(). Call of Python routine as a macro is not successfull: copying is not executed, no matter how long the time lag is.
Last edited by Jan_J on Mon Sep 02, 2013 2:53 pm, edited 1 time in total.
JJ ∙ https://forum.openoffice.org/pl/
LO (7.6) ∙ Python (3.11|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)
pasty757
Posts: 24
Joined: Mon Nov 12, 2012 3:25 pm

Re: Copying Impress slides by macro

Post by pasty757 »

I use the following to copy a "template slide" which exists in the deck to make a new slide... I haven't tried without having the GUI active... but this does the job for me.

Code: Select all

Sub SwitchMode(ModeNum As Integer)
       
	Dim oDispatch As Object
    Dim Modes(1) As String
	Dim oFrame As Object
	Wait 500
    Modes(0) = ".uno:DrawingMode"   'Normal
    Modes(1) = ".uno:DiaMode"       'Sorter
	' Other modes ".uno:OutlineMode", ".uno:NotesMode", ".uno:HandoutMode"
 
    oFrame   = oReportDeck.CurrentController.Frame
    oDispatch = createUnoService("com.sun.star.frame.DispatchHelper")
	oDispatch.executeDispatch(oFrame, Modes(ModeNum), "", 0, Array())
	Wait 500
End Sub



Function LoadSlide(templateName as String) As String
	' Duplicate the template slide and use this ... 

	Dim oSlide as Object
	Dim oPage as Object
	Dim NoArg()
	oDispatch = createUnoService( "com.sun.star.frame.DispatchHelper")
	oSlide = oSlides.getByName(templateName)		' Get the slide template
	switchMode(0)	'Switch to normal
	oReportDeck.CurrentController.setCurrentPage(oSlide)
	switchMode(1) 	'Switch to sorter
	oReportDeck.CurrentController.setCurrentPage(oSlide)
	oProvider = oReportDeck.CurrentController.Frame
	' Will use Copy and Paste approach
	oDispatch.executeDispatch(oProvider, ".uno:Copy","", 0, NoArg())
	SwitchMode(0) 	'Switch to normal
	oSlide = oSlides.getByIndex(oSlides.Count()-1)	' Go to last slide...
	oReportDeck.CurrentController.setCurrentPage(oSlide)
	SwitchMode(1)	'Swithch to sorter
	oReportDeck.CurrentController.setCurrentPage(oSlide)
	oDispatch.executeDispatch(oProvider, ".uno:Paste", "", 0, NoArg())
	iSlides = iSlides + 1							' Increment the slide counter
	LoadSlide = "ReportDeck - " & iSlides			       ' Set the return value
	oSlide = oSlides.getByIndex(oSlides.Count()-1)
	oSlide.name = "ReportDeck - " & iSlides			' Give the slide a name.

End Function
Lotus Symphony / OpenOffice 4.0.0 on Windows XP
Jan_J
Posts: 167
Joined: Wed Apr 29, 2009 1:42 pm
Location: Poland

Re: Copying Impress slides by macro

Post by Jan_J »

Yes, that is very similar to mine, apart form the language. Basic version of my code also runs OK as a macro.
I have problems with different behaviour of Wait (Basic) and os.sleep (Python) functions, and with C&P when GUI is not present.
JJ ∙ https://forum.openoffice.org/pl/
LO (7.6) ∙ Python (3.11|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)
Post Reply