PreviewXMLtoPDF and merging output documents

MoneyWorks Gold 9.1.7 has a new function for converting the "xml" output format (from DoReport and DoForm) to PDF. On its own, this isn't especially useful, since you can just output to PDF in the first place. However, it is possible to use this to merge multiple output files into one PDF, or even insert blank pages by massaging the XML files.

Proof of concept:

constant meta = "XML/PDF merging"

/*

    Outputting forms and reports as "xml" looks like this (this is the format used by the MoneyWorks Preview window) 

    <?xml version="1.0"?>
    <document>
        <paperrect left="-20" top="-20" right="655" bottom="936" />
        <pagerect left="0" top="0" right="635" bottom="889" />
        <meta>
            <title>Balance Sheet</title>
            <generated>26/02/24, 12:20:58 PM</generated>
            <generator>MoneyWorks-macOS-x64</generator>
        </meta>
        <page decimal_sep="46" pageNum="1">
        ...
        </page>
    </document>

    PreviewXMLtoPDF converts one (valid) XML file to PDF
    
    To merge multiple preview XML files, you need to massage the xml a bit to keep the merged XML valid
    In particular, the page numbers must remain sequential
    
    MergePreviewFiles is a q&d function to merge a list of files
    
    Caveat: This will only work if the page sizes, orientation, and scaling of all of the files are the same
    because PreviewXMLtoPDF will not change the PDF page size/scale/orientation halfway through the document

*/

on MergePreviewFiles(a)
    let outfile = File_Open("TMP/merged.xml", "w")
    let numfiles = CountElements(a)
    let pagenum = 0
    foreach k in array a
        let path = a[k]
        let f = File_Open(path)
        let seenHdr = false
        while 1
            let line = File_ReadLine(f)
            if line == NULL or line = ""
                break
            endif
            if TextToNum(k) > 1 and trim(line, true) = "<pagerect@"
                let seenHdr = true
                continue
            endif
            if TextToNum(k) < numfiles and (trim(line, true) = "</document>")
                break
            endif
            if TextToNum(k) > 1 and not seenHdr
                continue
            endif
            if trim(line, true) = "<page@"
                let line = Regex_Replace(line, `pageNum="[0-9]+"`, `pageNum="` + pagenum+`"`)
                let pagenum = pagenum + 1
            endif
            
            File_Write(outfile, line)
        endwhile
        File_Close(f)
    endfor
    let outpath = File_Path(outfile)
    File_Close(outfile)
    return outpath
end

on Load
    let a = CreateArray()
    let a[1] = DoForm("Balance Forward Basic", "xml", "code=`SMITH`") // statement
    let a[2] = DoForm("Product Invoice 1", "xml", "namecode=`SMITH`") // invoices
    //let a[3] = DoReport("Balance Sheet", "xml", "Balance Sheet") // will run into scaling issues
        
    let final = MergePreviewFiles(a)
    let p = PreviewXMLtoPDF(final)
    File_Move(p, "Merged_Forms_"+TimeStamp(TSZ_LOCAL, "%Y-%m-%d_%H%M%S")+".pdf") // move to automation files folder
end
Posted in Esoterica, MWScript | Comments Off on PreviewXMLtoPDF and merging output documents