This is the 25th day article of LibreOffice Advent Calendar 2020.
In the first place, when I wrote "I wrote a Lisp interpreter (mal) in LibreOffice Basic", I wanted to prepare up to the point that "You can try REPL using Docker". However, I tried it a little and it seemed that I couldn't make it in time, so I put it off.
After that, I investigated it again and managed to move the REPL even though there were some suspicious points (I added it to the article).
So, I am writing this because it may be useful for someone to cut out and write only the part that executes the Basic macro with Docker. Where you can think of it, you can use it for test automation.
This is a minimal example using only the Standard
library + Module1
module.
Dockerfile
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get -y install --no-install-recommends \
libreoffice-calc \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# ~/.config/Generate libreoffice below
RUN libreoffice --headless --terminate_after_init
WORKDIR /root/work
sample.sh (script to be executed in the container)
escape_xml() {
cat \
| sed -e 's/&/\&/g' \
| sed -e 's/"/\"/g' \
| sed -e "s/'/\'/g" \
| sed -e 's/</\</g' \
| sed -e 's/>/\>/g'
}
print_basic_src() {
cat << BAS
Sub Main
Dim fid As Integer
fid = Freefile
Open "/tmp/output" For Binary Access Write As fid
Put(fid, 1, CStr(Time()) & Chr(10))
Close fid
End Sub
BAS
}
user_bas_dir="${HOME}/.config/libreoffice/4/user/basic"
mod_name=Module1
mod_file="${user_bas_dir}/Standard/${mod_name}.xba"
cat << XML > ${mod_file}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module
xmlns:script="http://openoffice.org/2000/script"
script:name="${mod_name}"
script:language="StarBasic"
>
$(print_basic_src | escape_xml)
</script:module>
XML
libreoffice \
--headless --norestore --nologo --nofirststartwizard --nolockcheck \
"vnd.sun.star.script:Standard.${mod_name}.Main?language=Basic&location=application"
cat /tmp/output
It may not be necessary to explain because it is short, but the processing content is as follows.
--Store the Basic code in ~/.config/libreoffice/4/user/basic/Standard/Module1.xba
――I think it's better to read and write XML properly if possible, but since it is a minimum sample, it overwrites Module1.xba
entirely.
--Execute macro with libreoffice
command
--The current time is written to a temporary file
--Display the contents output to the temporary file
#Build image
docker build -t libreoffice-basic:trial .
#Run
docker run --rm -v "$(pwd):/root/work" libreoffice-basic:trial bash sample.sh
If it works, the current time will be printed every time you run docker run ~
(it will be different from the Japanese time because you have not set the time zone).
At first, I tried to put the Basic code in a file and execute it, but in this case, I can not execute it without the GUI unless the security level is set to "low". He could change the security level without a GUI if he messed up the configuration file ... I thought about it and tried it, but I don't want to do that much ...
So, I settled on the method of registering and executing it as a user-managed macro (the one displayed as "My Macro" in the macro management dialog) instead of a file. With Docker, you can do it boldly without worrying about polluting the existing environment.
The location of user-managed macros is under ~/.config/libreoffice/4/user/basic
, but if you just install libreoffice with apt, this directory and other configuration files will not be generated. It is generated when LibreOffice is started once, but when it is started normally, it remains started, so you have to kill it separately ....
When I was wondering what to do, I was looking at the list of command line options and found an option called --terminate_after_init
, which, as the name suggests, seems to be prepared for this purpose.
Developer arguments:
--terminate_after_init
Exit after initialization complete (no documents loaded).
This is what I use in the Dockerfile. I haven't confirmed it in the document, so I'm sorry if it's used for other purposes.
In the above example, it is not necessary because it uses the existing Standard
library, but if you want to add another library, go to ~/.config/libreoffice/4/user/basic/script.xlc
. It is necessary to add.
Below is an example of adding a library called Mylib
.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE library:libraries PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "libraries.dtd">
<library:libraries xmlns:library="http://openoffice.org/2000/library" xmlns:xlink="http://www.w3.org/1999/xlink">
<library:library library:name="Standard" xlink:href="$(USER)/basic/Standard/script.xlb/" xlink:type="simple" library:link="false"/>
+ <library:library library:name="Mylib" xlink:href="$(USER)/basic/Mylib/script.xlb/" xlink:type="simple" library:link="false"/>
</library:libraries>
-Create a Docker image with LibreOffice Calc and run it headless --memo88
Recommended Posts