4

I have a CSV file containing a list of names, numbers and optionally pictures. This file is to be displayed in a multi-column table, with the name (and optionally appended picture as icon) in one column, the number in another and a free column in the third. It's important that the picture/icon is appended directly to the name and is not in a separate column.

In order to accomplish this, I have tried combining the answer to an earlier question of mine regarding dynamic multi-column tables and this answer about post-processing columns using other values from the CSV, but am unable to produce the desired result; here is my attempt as an MWE:

\documentclass[a4paper]{extarticle}

\usepackage{lmodern}

\usepackage{graphicx}
\graphicspath{ {images/} }

\usepackage[left=1.2cm,right=1.2cm,top=2cm,bottom=1cm]{geometry}

\usepackage{tabularx}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.11}

\begin{filecontents*}{data.csv}
    Name,Number,Picture
    name1,1,
    name2,2,
    name3,3,ex1.png
    name4,4,
    name5,5,
    name6,6,
    name7,7,
    name8,8,
    name9,9,ex2.png
    name10,10,
    name11,11,
\end{filecontents*}

\pgfplotstableread[col sep=comma]{data.csv}{\datatable}

\begin{document}
    \pgfplotstableset{create on use/XXX/.style={create col/set={}}}%

    \noindent
    \pgfplotstabletypeset[string type,
    begin table=\begin{tabularx}{\textwidth},
        end table=\end{tabularx},
    every head row/.style={output empty row,after row=\hline},
    every last row/.style={after row=\hline},
    columns={Name,Number,XXX,Name,Number,XXX},
    display columns/0/.style={select equal part entry of={0}{2},column type=|l,postproc cell content/.add code={%
            \pgfplotstablegetelem{\pgfplotstablerow}{Picture}\of\datatable%
            \pgfkeyssetvalue{/pgfplots/table/@cell content}{%
                \noexpand%
                \pgfkeysvalueof{/pgfplots/table/@preprocessed cell content}%
                ~\pgfplotsretval%
                %~\includegraphics[height=\lineheight]{\pgfplotsretval}%
            }%
        }%
    },
    display columns/1/.style={select equal part entry of={0}{2}},
    display columns/2/.style={column type=X|},
    display columns/3/.style={select equal part entry of={1}{2},column type=l,postproc cell content/.add code={%
            \pgfplotstablegetelem{\pgfplotstablerow}{Picture}\of\datatable%
            \pgfkeyssetvalue{/pgfplots/table/@cell content}{%
                \noexpand%
                \pgfkeysvalueof{/pgfplots/table/@preprocessed cell content}%
                ~\pgfplotsretval%
                %~\includegraphics[height=\lineheight]{\pgfplotsretval}%
            }%
        }%
    },
    display columns/4/.style={select equal part entry of={1}{2}},
    display columns/5/.style={column type=X|}
    ]{\datatable}
\end{document}

If one uncomments the \includegraphics statements, the code doesn't even compile. I'd guess a check is needed on whether there is data in the Picture column for the current row; and apart from that, the current content needs to be fetched reliably, as what I've currently got always grabs "datatable as content, although it at least compiles.

I've tried approaching this multiple times already, but even with help of search engines and the PGFPlotsTable documentation I can't seem to tackle this rather peculiar problem, so I'd appreciate any kind of help.

Final Solution; accepted answer adapted to multi-column MWE

This is very close to the code I am using right now and is a combination of the accepted answer and the multi-column MWE I've given in the question.

\documentclass[a4paper]{extarticle}

\usepackage{lmodern}

\usepackage{graphicx}
\graphicspath{ {images/} }

\usepackage[left=1.2cm,right=1.2cm,top=2cm,bottom=1cm]{geometry}

\usepackage{tabularx}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.11}

\usepackage{graphicx}
\graphicspath{ {images/} }

\begin{filecontents*}{data.csv}
    Name,Number,Picture
    name1,1,
    name2,2,
    name3,3,ex1.png
    name4,4,
    name5,5,
    name6,6,
    name7,7,
    name8,8,
    name9,9,ex2.png
    name10,10,
    name11,11,
\end{filecontents*}

\pgfplotstableread[col sep=comma]{data.csv}{\datatable}

\def\zz\ignorespaces#1\unskip{%
    \ifx\count#1\count
    \gdef\temp{}%
    \else
    \gdef\temp{%
        \kern.2em%
        \smash{\raisebox{-.3em}{\includegraphics[height=1.2em]{#1}}}}%
    \fi}

\begin{document}
    \pgfplotstableset{create on use/XXX/.style={create col/set={}}}%

    \noindent
    \pgfplotstabletypeset[string type,
    begin table=\begin{tabularx}{\textwidth},
        end table=\end{tabularx},
    every head row/.style={output empty row,after row=\hline},
    every last row/.style={after row=\hline},
    columns={Picture,Name,Number,XXX,Picture,Name,Number,XXX},
    display columns/0/.style={select equal part entry of={0}{2},column type = @{}>{\zz}l@{} },
    display columns/1/.style={select equal part entry of={0}{2},column type=|l<{\temp}},
    display columns/2/.style={select equal part entry of={0}{2}},
    display columns/3/.style={column type=X|},
    display columns/4/.style={select equal part entry of={1}{2},column type = @{}>{\zz}l@{} },
    display columns/5/.style={select equal part entry of={1}{2},column type=l<{\temp}},
    display columns/6/.style={select equal part entry of={1}{2}},
    display columns/7/.style={column type=X|}
    ]{\datatable}
\end{document}
  • You don't want to post-process the cell content, I don't think. Post-processing, as I understand it, only affects the format of the columns after the contents have been typeset. You are trying to alter the contents of the cells, so I think you need to do it earlier. This gets it to compile and gets the name etc. to show up correctly. (i.e. deleting postproc does this much.) Don't know about the graphics but note that I think the software expects numerical data by default. – cfr Mar 7 '15 at 0:36
  • Well, removing the postproc actually reverts the names to the default state; not appending the graphic paths, as I intended to do with ~\pgfplotsretval, earlier fetching the path via \pgfplotstablegetelem{\pgfplotstablerow}{Picture}\of\datatable. – Big-Blue Mar 7 '15 at 2:22
3
+50

You can put the image name into a table column and just pick it up within the table to typeset in the next column if not empty.

enter image description here

\documentclass[a4paper]{extarticle}

\usepackage{lmodern}

\usepackage{graphicx}
\graphicspath{ {images/} }

\usepackage[left=1.2cm,right=1.2cm,top=2cm,bottom=1cm]{geometry}

\usepackage{tabularx}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.11}

\begin{filecontents*}{data.csv}
    Name,Number,Picture
    name1,1,
    name2,2,
    name3,3,ex1.png
    name4,4,
    name5,5,
    name6,6,
    name7,7,
    name8,8,
    name9,9,ex2.png
    name10,10,
    name11,11,
\end{filecontents*}

\pgfplotstableread[col sep=comma]{data.csv}{\datatable}

\def\zz\ignorespaces#1\unskip{%
\ifx\count#1\count
\gdef\temp{}%
\else
\gdef\temp{%
\kern.2em%
\smash{\raisebox{-.3em}{\includegraphics[height=1.7em]{#1}}}}%
\fi}
\begin{document}
    \pgfplotstableset{create on use/XXX/.style={create col/set={}}}%

    \noindent
    \pgfplotstabletypeset[string type,
    begin table=\begin{tabularx}{\textwidth},
        end table=\end{tabularx},
    every head row/.style={output empty row,after row=\hline},
    every last row/.style={after row=\hline},
    columns={Picture,Name,Number,XXX},
    display columns/0/.style={column type = @{}>{\zz}l@{} },
    display columns/1/.style={column type = l<{\temp} },
    display columns/2/.style={column type = l },
    display columns/3/.style={column type=X|},
    ]{\datatable}
\end{document}
  • Thank you for this answer! This indeed works mostly as it is supposed to, so thanks for that. I didn't even know that doing it this way is possible. A problem that occurs is that the images are a bit larger vertically than the lines, so they sometimes overlap with longer names. This should be easily fixable though. Would you mind detailing how this works? I mean, I'm glad it does, but I seem unable to grasp why. This mostly looks like TeX magic to me, most of the time I've used the etoolbox package for more complex statements. – Big-Blue Mar 12 '15 at 1:04
  • @Big-Blue the image overlapping is because I made it height=1.7em which is probably larger than the line space then hid the height with \smash I used 1em originally but then by the time the entire page shrunk to a bitmap here it hardly showed. the array column preamble >{...} syntax comes from the array package and inserts the commands into each cell. in the first column \zz gets the cell content as argument and then globally defines \temp to do nothing or insert an image, that in turn is used in the second column. – David Carlisle Mar 12 '15 at 1:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.