Date: prev next · Thread: first prev next last
2013 Archives by date, by thread · List index


Main Issue: How to export PDF files using one PDF per page from a LibreOffice BASIC macro
Related Issue: How to change any values with a macro when exporting to PDF files

I've left my original question intact, but this includes the answer - this code and the two links 
will show you what you need to know to write a macro for LibreOffice that can export a PDF with 
whatever settings you desire.  I'm saving the code to last (right before the text of the original 
question).

These web pages are geared toward Java, and things do work differently in Java, in many cases, than 
they do in BASIC.  The first is a tutorial on how to export a PDF file from LO in Java:

http://wiki.openoffice.org/wiki/API/Tutorials/PDF_export

A few issues to note if you're looking through this:
- You do not need most of the objects created in the Java program.  You can use ThisComponent in a 
BASIC macro and that gives you access to the interfaces and models and so forth needed to get the 
information or to do what you need to do.
- "PDF Export filter data" is the main section you'll need.  It includes information about all the 
PDF settings that can be used in the PropertyValue object "FilterData"  They're the same in Java as 
in BASIC.

The second page contains a Java example of someone setting almost any property possible for 
exporting a PDF:

http://forum.openoffice.org/en/forum/viewtopic.php?t=1804

This page helped me because, even after multiple readings, I still misunderstood (and didn't know 
it was a misunderstanding) one paragraph in the first linked page, so it clarified a major point 
for me.


About My Code: The code below is a macro that will export an ODT file as multiple PDFs - one PDF 
per page of the original document, all stored in a directory that is the same name as the original 
document's name but with "-PDF" instead of ".odt" at the end.  PDF File names are in the format of 
"Page-0001.pdf" with the page number always as 4 digits, with leading zeros.  I've added a number 
of comments that should explain most of what's needed.  I don't know how to also include, here, the 
dialog box I use.  It has a text label that can be set to whatever you want and has a progress bar 
(we see how that's accessed in the code) and the progress bar is updated each time a page is done.

There are two issues with the progress bar.  The first is that I had to put in a 1 millisecond wait 
after it is updated, or it wouldn't update (I guess LO gives priority to running the macro code 
than in updating the GUI).  The other is that, on my dialog, I added a "Cancel" button, but I have 
two problems there.  One is that it doesn't seem to respond, and the other is that I wish I could 
pass a pointer to the progress bar so I can keep the dialog in my library and easily tell it, from 
any macro, what method to use when Cancel is clicked on.

Here is the source code:
-------------
REM  *****  BASIC  *****
REM **********************************************************
REM Export an ODT file from LibreOffice to multiple PDF files.
REM This creates one PDF file for each page of the document.
REM
REM This program can help in terms of teaching or examples for
REM several issues in BASIC macros:
REM    1) Adjusting settings for PDF Export
REM    2) Finding information about the document, such as the
REM       total number of pages
REM    3) Using a progress bar that updates during execution
REM       of a Macro
REM
REM
REM Copyright (C) 2013 by Hal Vaughan, hal@halblog.com
REM **********************************************************

Sub ExportMultiPagePDF

'Specify thtat it load my dialogs - haven't tested in new LO builds,
' but in OpenOffice, if the libraries weren't specifically loaded, I'd
' get error codes
        DialogLibraries.LoadLibrary("HalLib")
        oDoc = ThisComponent
        
'We're going to save the multiple PDF files in a directory with the same name
' as the original document - but with "-PDF" added to it.  LO creates the
' directory automatically when saving the files, so that's one task we don't need
' to worry about.  If the document has not been saved, we exit.  If it has been,
' we get the URL, then remove the ".odt" and add "-PDF" to it.
'
'While there are other ways to check if a document is an odt file, since we 
' require that the document already be saved, it's easiest to just check the file
' extension.
        If Not oDoc.hasLocation() Then
                MsgBox "Cannot Export Multipage PDFs without first saving the file."
                Stop
        EndIf
        
'getPageCount (in this file) does the work of finding out how many pages
' there are in the document
        iTotal = getPageCount()
        sName = oDoc.getURL()
'       MsgBox "Frame Title: " + sName
        sExt = Right(sName, 4)
        If sExt <> ".odt" Then
                MsgBox "Unable to decode extension."
                Stop
        EndIf
        dirName = Left(sName, Len(sName) - 4) + "-PDF"

'Add a progress bar because this can take time on longer documents
        pbBar = Dialogs.EasyProgressBar("Converting to multiple PDFs", iTotal)
        
'Loop through each page, create a 4 digit number made out of the page
' number but with leading zeros so a directory listing will show the files
' in order.
'IMPORTANT: Note the "Wait 1" statemetn after updating the progress bar.
' Without this, the progress bar will not update (at least on OS X).  Apparently
' the GUI doesn't get time to update while the the macro is running, so a WAIT
' statement allows it to update
        For i = 1 to iTotal
                sFix = i
                sFix = "0000" + sFix
                sFix = Right(sFix, 4)
                fName = dirName + "/" + "Page-" + sFix + ".pdf"
                savePageAsPDF(fName, i)
                pbBar.ProgressValue = i
                Wait 1
        Next i

'Unceremonious exit.  The progress bar will complete and the dialog disappears.
' There's no real need to put up a dialog box and require a mouse click to to
' finish up.  It's just a pain to the user.

End Sub


'Get the number of pages from the document.
'
'Get the document properties, then look through the property names until we find
' "PageCount" and that's the number we need.
'No actual reason for going backwards through the elements that I can remember, but
' when I first wrote this functino I may have had a reason.
'Note that, in case of error, we set the PageCount to 0 by default and only change
' it if  the actual count is greater than -1
Function getPageCount()
        oProps = ThisComponent.getDocumentProperties()
        aStats = oProps.DocumentStatistics
REM Loop through the array of c.s.s.beans.NamedValue
        For i = uBound(aStats) to 0 Step -1
                x = aStats(i)
                If x.Name = "PageCount" Then Exit For
        Next
        getPageCount = 0
        if i > -1 then getPageCount = x.Value
End Function


'This is the part of this macro that was the most difficult to deal with, since it
' took a lot of online searching, using different terms, to find what amounted to
' the two or three sources I needed to tell me just what to do here.
'The first thing done is converting the page number to a page range.  That's not
' necessary, since the single page number is enough, but it's left here as a reminder
' that we're working with a page range string that will be parsed, so it could be
' something more complex, like "1,2,5,7-10,12-15"
'Next we need a property value to be passed as an argument to the storeToURL method
' within the document.  The first property MUST be "FilterName" with the "writer_pdf_Export"
' value. That's enough for a PDF export, but if you want to change any settings, then the
' second property MUST be named "FilterData" and is another PropteryValue ojbect that contains
' the settings for all the properties that we want to change from the default.  In this case,
' we want to export only one page, so we set "PageRange" to the page number.
'Please note that this is a PropertyValue passed as a value WITHIN another PropertyValue object.
'It is not passed as a 3rd parameter, but as part of the 2nd paremeter.  (The wording on one page
' on this confused me and led to hours of research to clarify this.)
Sub SavePageAsPDF(fileName As String, pageNum As Integer)
        pRange = CStr(pageNum) + "-" + CStr(pageNum)
        
        Dim conversionProps(2) as new com.sun.star.beans.PropertyValue 
        conversionProps(0).Name = "FilterName" 
        conversionProps(0).Value = "writer_pdf_Export"
        
        Dim filterProps(1) as new com.sun.star.beans.PropertyValue 
        filterProps(0).Name = "PageRange"
        filterProps(0).Value = CStr(pageNum)
        
        conversionProps(1).Name = "FilterData"
        conversionProps(1).Value = filterProps
        
        ThisComponent.storeToURL(fileName, conversionProps)
End Sub

'Create a progress bar to display while a function is ongoing, so the user doesn't think
' things have frozen up.
'1st parameter is a string to use as a label, perhaps saying what is going on, and the
' 2nd parameter is how many steps there are to whatever is being done.  It returns the
' actual progress bar and all that is needed in other code is to use:
'
'    epBar = EasyProgressBar("Processing your stuff", 132)
'(and replace epBar with whatever name you want to use, the string with your label and
' the '132' with the number of steps your task will take.
'To set the progress bar to a position, do this:
'    epBar.ProgressValue = x
' (of course, use whatever variable names you want and 'x' will be the number of the
' completeted item)
'
'If you're using this code as an example, or to make your own macro, you need to use your
' on library name in place of "HalLib" and create a dialog with a text label named "TextInfo"
' and a progress bar named "ProgressBar".)
Function EasyProgressBar (Description As String, totalSteps As Integer) As Object
        DialogLibraries.LoadLibrary("HalLib")
        oDialog = createUnoDialog(DialogLibraries.HalLib.SimpleProgressBar)
        oDialog.setVisible(TRUE)
        oDialog.GetControl("TextInfo").Text = Description
        oDialog.GetControl("TextInfo").setVisible(TRUE)
        pbModel = oDialog.Model.ProgressBar
        pbModel.ProgressValueMin = 0
        pbModel.ProgressValueMax = totalSteps
        oDialog.getControl("ProgressBar").setVisible(TRUE)
        EasyProgressBar = pbModel
End Function

On Dec 27, 2012, at 6:48 PM, Hal Vaughan <hal@halblog.com> wrote:

I'm exporting ODT files to PDF, but I want to export only 1 page at a time, so I'm using a BASIC 
macro to handle this.

I've been searching, but since somewhere around 3-4am EST, I have not been able to access 
oooforum.org and most links lead to there.

I can't find examples elsewhere that show me how to export a PDF file from in BASIC or how to 
specify, again, from BASIC, what pages to export.

Can anyone give me links for examples that are not on oooforum.org?  Or tell me what classes I 
would be using for this so I can look them up in the IDL to find out how to specify the page (or 
pages) to export and how to use the PDF exporter?


Thank you.



Hal

-- 
For unsubscribe instructions e-mail to: users+help@global.libreoffice.org
Problems? http://www.libreoffice.org/get-help/mailing-lists/how-to-unsubscribe/
Posting guidelines + more: http://wiki.documentfoundation.org/Netiquette
List archive: http://listarchives.libreoffice.org/global/users/
All messages sent to this list will be publicly archived and cannot be deleted

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.