1

For a project I am working on (see also my question about setting the column type in pgfplots procedually), I would like to create a wrapper macro \fancyTable, which calls pgfplotstable in the background. The wrapper macro is intended for users which are not so familiar with LaTeX and should automate the table setup process.
One nice-to-have feature would be that the table can span multiple pages (which I already achieved via longtable). For better readability, a caption at the beginning of the table and on the top of each new page would be favorable. It would also be convenient, if the table header would be repeated on each page; but from what I understand based upon the pgfplotstable manual, this is not achievable with pgfplotstable on its own.

Starting point

I took a look at different suggestions (here and the answer by user11232/David Carlisle) on tex.stackexchange. From the latter one, I was able to construct a MWE:

\documentclass{scrreprt} % standalone or minimal do not work well with longtable

\usepackage{pgfplotstable}
\pgfplotsset{compat=1.17}

\usepackage{longtable}
\usepackage{multicol} % required for letting additional caption span over all cols
\usepackage{colortbl}
\usepackage{booktabs}

\usepackage[%
    paperheight=6.5cm,paperwidth=13cm, %
    left=0.5cm,right=0.5cm,top=0.25cm,%
    bottom=0.25cm, includeheadfoot %
]{geometry} % used to make page size smaller and therewith facilitate page break testing

% Formatting the caption
\usepackage[labelfont={bf}]{caption}
\captionsetup{format=plain,labelformat=simple,font=small,labelsep = colon}

\begin{filecontents}{pgfplotstable_longtable_multicap.csv}
    date, time, time zone, event
    1, 00:00, CET, server installation finished
    2, 00:05, CET, server successfully booted
    3, 00:06, CET, starting xyz daemon
    4, 00:10, CET, admin login
    5, 23:58, CET, sudo reboot
    6, 23:59, CET, server reboot
\end{filecontents}

\begin{document}
    % source: https://tex.stackexchange.com/questions/297412/define-and-use-column-styles-in-pgfplotstable
    \pgfplotstableset{
        center bold column/.style={%
            /pgfplots/table/display columns/#1/.style={%
                column type={>{\fontseries{bx}\selectfont}c},%
            }
        },
        left bold column/.style={%
            /pgfplots/table/display columns/#1/.style={%
                column type={>{\fontseries{bx}\selectfont}l},%
            }
        },
    }
    
    \pgfplotstabletypeset[
        begin table=\begin{longtable},% force pgfplotstable
        end table=\end{longtable},% to use the longtable environment
        col sep=comma,%
        header=true, % specific header data
        % source: https://tex.stackexchange.com/questions/66504/pgfplotstable-longtable-with-caption-and-repeating-header
        every head row/.append style={
            before row={\caption{The caption above the start of the table.}\\[0.5cm]},
            after row=\midrule\endfirsthead
        },
        every first row/.append style={
            before row={
                \multicolumn{\pgfplotstablecols}{c}{}\\ \caption[]{Caption on top of every new page.}\\ % setting caption to span over all columns
                \toprule
            },%
            after row=\endhead
        },
        every odd row/.style={before row={\rowcolor[gray]{0.9}}},% highlighting of every second data row
        string type,% necessary for correct processing of table content
        center bold column/.list={0,1,2}, % setting all columns bold
        left bold column/.list={3}, % setting all columns bold
        postproc cell content/.append style={
            /pgfplots/table/@cell content/.add={\fontseries{\seriesdefault}\selectfont}{} % removing bf from all table content 
        }
    ]{pgfplotstable_longtable_multicap.csv}
\end{document}

The compilation yields the following document: enter image description here

Like desired, a caption with different content is typeset on each page. However, the rowcolor highlighting on the second page does not work as it is supposed to. More importantly, the table data gets "randomly" changed: The first entry (which is supposed to be on page 1, row 1) gets shifted to the second page, first row. For the kind of data I am expecting to process with the planned wrapper macro, this is not acceptable.

Attempt 1: Treat header as normal data

Since the header=true option limited the possible header data types, I decided to treat the header as a standard string:

header=false, % header treated as data
every head row/.style={%
    output empty row,%
},%
every first row/.append style={%
    before row={%
        \caption{The caption above the start of the table.}\\[1.25cm] 
        \endfirsthead 
        %
        \multicolumn{\pgfplotstablecols}{c}{\caption[]{Caption on top of every new page.}} \\% what if caption style changes?
        \midrule 
        \endhead
    },%
    after row={%
        \midrule
    }%
},% 

Now, the document will not compile. There is the following error message:

! Misplaced \noalign.
\caption ->\noalign 
                    {\global \@captionabovefalse }\scr@caption 
l.80    ]{pgfplotstable_longtable_multicap.csv}

The error is definitely coming from the second call of \caption, because if I just insert plain text, the MWE will compile:

\documentclass{scrreprt} % standalone or minimal do not work well with longtable

\usepackage{pgfplotstable}
\pgfplotsset{compat=1.17}

\usepackage{longtable}
\usepackage{multicol} % required for letting additional caption span over all cols
\usepackage{colortbl}
\usepackage{booktabs}

\usepackage[%
    paperheight=6.5cm,paperwidth=13cm, %
    left=0.5cm,right=0.5cm,top=0.25cm,%
    bottom=0.25cm, includeheadfoot %
]{geometry} % used to make page size smaller and therewith facilitate page break testing

% Formatting the caption
\usepackage[labelfont={bf}]{caption}
\captionsetup{format=plain,labelformat=simple,font=small,labelsep = colon}

\begin{filecontents}{pgfplotstable_longtable_multicap.csv}
    date, time, time zone, event
    1, 00:00, CET, server installation finished
    2, 00:05, CET, server successfully booted
    3, 00:06, CET, starting xyz daemon
    4, 00:10, CET, admin login
    5, 23:58, CET, sudo reboot
    6, 23:59, CET, server reboot
\end{filecontents}

\begin{document}
    % source: https://tex.stackexchange.com/questions/297412/define-and-use-column-styles-in-pgfplotstable
    \pgfplotstableset{
        center column/.style={%
            /pgfplots/table/display columns/#1/.style={%
                column type=c,%
            }
        },
        left column/.style={%
            /pgfplots/table/display columns/#1/.style={%
                column type=l,%
            }
        },
    }
    
    \pgfplotstabletypeset[
        begin table=\begin{longtable},% force pgfplotstable
        end table=\end{longtable},% to use the longtable environment
        col sep=comma,%
        header=false, % header treated as data
        every head row/.style={%
            output empty row,%
        },%
        every first row/.append style={%
            before row={%
                \caption{The caption above the start of the table.}\\[0.5cm] 
                \endfirsthead 
                %
                \multicolumn{\pgfplotstablecols}{c}{Caption on top of every new page.} \\[0.5cm]% what if caption style changes?
                \midrule 
                \endhead
            },%
            after row={%
                \midrule
            }%
        },%
        every odd row/.style={before row={\rowcolor[gray]{0.9}}},% highlighting of every second data row
        string type,% necessary for correct processing of table content
        center column/.list={0,1,2}, % setting all columns bold
        left column/.list={3}, % setting all columns bold
        % alternative way for getting bold "header"
        % source: https://tex.stackexchange.com/questions/130835/pgfplotstable-one-row-in-bold
        postproc cell content/.append code={
            \count0=\pgfplotstablerow
            \advance\count0 by1
            \ifnum\count0=1
            \pgfkeysalso{@cell content=\textbf{#1}}%
            \fi
        },
    ]{pgfplotstable_longtable_multicap.csv}
\end{document}

This produces the following result: enter image description here

The data is now typeset in the correct order, but the "caption" does not match the default of the document

Questions

  1. Is there a way to get a second call of \caption working? For example with \noalign (which I could not get to work)?
  2. Can the settings of \usepackage{caption} be accessed to manually craft a "caption", which looks identical to the real \caption macro?

1 Answer 1

2

An alternative solution with catchfile and tabularray packages:

\documentclass{scrreprt}

\usepackage[
  paperheight=7.5cm, paperwidth=13cm,
  left=0.5cm, right=0.5cm, top=0.25cm,
  bottom=0.25cm, includeheadfoot
]{geometry} % used to make page size smaller and therewith facilitate page break testing

\usepackage{xcolor}
\usepackage{catchfile}
\usepackage{tabularray}

\begin{filecontents*}{mydata.csv}
    date, time, time zone, event
    1, 00:00, CET, server installation finished
    2, 00:05, CET, server successfully booted
    3, 00:06, CET, starting xyz daemon
    4, 00:10, CET, admin login
    5, 23:58, CET, sudo reboot
    6, 23:59, CET, server reboot
\end{filecontents*}

\CatchFileDef{\mydata}{mydata.csv}{\catcode`\^^M=\active}

\ExplSyntaxOn
\group_begin:
  \catcode`\^^M=\active %
  \cs_gset_protected:Npn \NormalizeData #1 {%
    \tl_greplace_all:Nnn #1 {^^M} {\\}%
    \tl_greplace_all:Nnn #1 {,} {&}%
  }%
\group_end:
\ExplSyntaxOff

\NormalizeData{\mydata}

\begin{document}

\begin{longtblr}[
  expand = \mydata,
  caption = {The Caption of the Table},
]{
  colspec = {clcl},
  hline{1,Z} = {0.08em},
  hline{2} = {0.05em},
  row{even} = {gray9},
  row{1} = {font=\bfseries},
  rowhead = 1,
}
 \mydata
\end{longtblr}

\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .