Converting documents with Caché and LibreOffice

Primary tabs

In this article I'll show you how you can easily convert between many different document formats, these to be precise:

  • in: html, odt, doc, docx, rtf, sdw, txt...
  • out: html, odt, docx, rtf, pdf, txt, tex, xhtml...

and many more, check out this table. We'll use LibreOffice as a conversion engine.

LibreOffice Installation

On windows go to the download page, application installs like pretty much any windows takes 200 mb.

On linux either use package manager (recommended) or go to the download page

  • Ubuntu: apt-get install libreoffice-core libreoffice-write
  • RHEL: yum install libreoffice-core libreoffice-write

Note that on linux you'll need at least version 4 (current is 5.2, if you're on old distro, refer to this guide).

Post installation

After installation is done, make sure that Caché can access "soffice" application

  • On windows add "C:\Program Files (x86)\LibreOffice 5\program" (may differ due to version installed)  to system PATH, if you're running Caché with default settings, or to the user PATH under which you run Caché if you modified that setting. Guide.
  • If you installed via package manager, "soffice" should be in path, otherwise  add to PATH manually

Use

Import code into Caché and you're ready to goconvert.

Call from the terminal:

set sc = ##class(Converter.LibreOffice).convert(source, target, format)
write $System.Status.GetErrorText(sc)

Where:

  • source - file to convert
  • target - result file
  • format - specification for target file. Possible values: docx,html,mediawiki,csv,pptx,ppt,wmf,emf,svg,xlsx,xls. More possible values here.

Example

To convert doc into docx call:

set sc = ##class(Converter.LibreOffice).convert("C:\temp\1.doc", "C:\temp\1.docx", "docx")
write sc
>1

Code

Here's some interesting snippets:

/// Get path to libreoffice/soffice
ClassMethod getSO()
{
    if $$$isWINDOWS {
        set path = "soffice"
    } else {
        set path = "export HOME=/tmp && unset LD_LIBRARY_PATH && soffice"
    }
    return path
}

Note, that in linux we additionally set HOME variable (it should be writable to Caché user) and remove LD_LIBRARY_PATH variable. This is important for LibreOffice (particularly in web context). If you need LD_LIBRARY_PATH variable, add additional call to reset it later.

/// Convert a file %1 into %2 format and place it into %3 directory (name equal to %1 name, extension = %2) using %4 - LibreOffice
Parameter COMMAND = "%4 --headless --writer --convert-to %2 --outdir %3 %1";

/// Convert source into format and place it into targetDir
ClassMethod executeConvert(source, targetDir, format) As %Status
{
    // Libreoffice needs targetDir without last slash
    set:$e(targetDir,*)=..#SLASH targetDir = $e(targetDir, 1, *-1)
    
    set timeout = 100
    set cmd = $$$FormatText(..#COMMAND, source, format, targetDir, ..getSO())
    return ..execute(cmd, timeout)
}

$$$FormatText macro can be used to make OS commands more readable (use it instead of concatenation!).

Conclusions

If you need to convert between a large number of document formats this project can be useful.

Links

Replies

This is a nice tool. The link under Use chapter is not working. Please correct that.

Hi,

instead of : path = "export HOME=/tmp && unset LD_LIBRARY_PATH && soffice"

you can use path = "export HOME=$(eval echo ~$(id -u -n)) && unset LD_LIBRARY_PATH && soffice". 
That way soffice will use the home directory of the cache user running the job. It could be usefull, specialy if you need to add or modify parameters into the registrymodifications.xcu file.

HI. I have tried this but getting this error even after giving all rights to directory

set sc = ##class(Converter.LibreOffice).convert("C:\Temp\a.csv", "C:\TempC:\InterSystems\Ensemble2018\mgr\Temp\b.xlsx", ".xlxs")

ERROR #5001: Error moving 'C:\InterSystems\Ensemble2018\mgr\Temp\145158\a..xlxs1C:\TempC:\InterSystems\Ensemble2018\mgr\Temp\b.xlsx' with code: -2

C:\TempC:\InterSystems\Ensemble2018\mgr\Temp\b.xlsx

Replace with: C:\InterSystems\Ensemble2018\mgr\Temp\b.xlsx

enlightened The article is considered as InterSystems Data Platform Best Practice.

Has anyone had success using this or a similar solution running Health Connect/HealthShare on an AIX 7.2 platform? LibreOffice does not provide AIX-specific packages.

No. But what I did was make a html table and saved in a xls file.

That works. Not most elegant solution but does work 

Appreciate the response but what I'm looking to do is convert RTF to PDF and then base64 encode it.

I think virtual PDF printer can help in this situation.

From a cursory search LibreOffice does not seem to be ported to AIX. You can try to compile it from source with AIX Toolbox for Linux Applications.

Hi,  does anyone have an example to convert a file using LibreOffice, html file upload and JavaScript? Thanks.

Convert a file using LibreOffice code is available in the article above, file upload example is available here.