The purpose of this writing is to demonstrate how to set up a latexmk project that synchronizes tables automatically from “LibreOffice Calc” sheets. The setup rebuilds the .pdf and the intermediate .csv files whenever you change something in the “LibreOffice Calc” document. Note, that you can adapt the setting easily to any program that can generate .csv files through a command-line call.

Here comes the setup in short:

  1. Add a folder /tables to the project and move your .ods tables there.
  2. Add a .latexmkrc file to the root directory of your project with the following content:

sub ods2csv {
    if($_[0] eq ""){
    my $sourceods = "$_[0].ods";
    my $sourcecsv = "$_[0].csv";
    system("libreoffice --headless --convert-to csv \"".$sourceods."\" --outdir tables");
    system("python src/ \"".$sourcecsv."\"  --inplace");

# Make sure all the dependencies get build initially.
# You may change the path in the following to match you setup.
my @files = <tables/*.ods>;
my @dep_files = ();
foreach (@files) {
  @dep_files = (@dep_files, $_)

# For each table call the ods2csv function.
foreach (@dep_files) {
    my ($filetype) = $_ =~ /^.*\.(.*)$/igs;
    my ($filename) = $_ =~ /^(.*)\..+/igs;

    if($filetype eq "ods"){
        if(-e $filename.".csv"){

add_cus_dep tells latexmk that it can retrieve .csv files from .ods files by using the ods2csv function. This function returns immediately if it was called without arguments. First, we create variables containing the filenames we are working with. Then, we call libreoffice in a headless mode to generate a .csv file from it. In the preceding line, we run the python script that transforms the .csv to the syntax that the latex package csvsimple can easily handle. A separate writing discusses the python script You can find a lot of information on csvsimple online.

Then the interesting stuff happens. For some reason the above is not enough for latexmk to build the .csv file if it does not exist yet. Hence, we iterate across every .ods file in /tables and call the ods2csv function once per file. Then the .csv files exist and latexmk can do its magic of keeping them up-to-date. Find a demo project on GitHub with a full working setup here:

I hope this tweak of .latexmkrc helped your workflow.