1

I would like to dynamically create multiple tables & TikZ pictures out of a single pgfPot database.

This MWE shows how to generate a single table and TikZ picture out of the given data.csv. The code is basically derived from this post

\documentclass{article}
\usepackage[a4paper,margin=10mm]{geometry}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\usepackage{mwe}

%PowerOutlet
\tikzset{
 pics/powerOutlet/.style={
  code={
   \begin{scope}[scale=0.4]
     \draw[red,very thick](0,0)--(0,10);
     \draw[red,very thick](-10,10)--(10,10);
     \draw[red,very thick,line cap=round](-10,20) arc[start angle=180,end angle=360,radius=10];
  \end{scope}
  }
 }
}

%Example data for MWE
\begin{filecontents}{data.csv}
Image,ID,Floor,X-Pos,Y-Pos
powerOutlet,A1F5F,GroundFloor,1,2
powerOutlet,7ZF3I,UpperFloor,20,1
\end{filecontents}
\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}
\pgfmathtruncatemacro\CSVDataRows{\pgfplotsretval-1} 

%Define Components for TikZ Picture
\tikzset{
pics/ElectricComponent/.style={
  code={
    \tikzset{ElectricComponent/.cd, #1}
    \pic{powerOutlet};
  }
},
ElectricComponent/floor/.initial={0}%
}

\begin{document}
\section*{Table}
\begin{center}
\pgfplotstabletypeset[
font=\ttfamily,
col sep=comma,
columns={Image,ID,Floor,X-Pos,Y-Pos},
columns/Image/.style={
    column name=Image,
    assign cell content/.code={
        \pgfkeyssetvalue{/pgfplots/table/@cell content}{
            \fbox{\raisebox{-0.5\height}{\tikz{\pic[scale=0.04]{##1};}}}
        }
    }
},
columns/ID/.style={
  column name=ID,
  string type
},
  columns/Floor/.style={
  column name=Floor,
  string type
},
  columns/X-Pos/.style={
  column name=X-Pos
},
  columns/Y-Pos/.style={
  column name=Y-Pos,
  column type/.add={}{|}
},
  column type/.add={|}{},
  after row={\hline},
  every head row/.style={before row=\hline}
]{\csvdata}
\end{center}

\section*{Graphic}
\begin{center}%
\scalebox{0.1}{%
\begin{tikzpicture}
%\node[inner sep=0pt] (ground_floor){\includegraphics{../Images/Layout/GroundFloor.png}};
\node[inner sep=0pt] (ground_floor){\includegraphics[scale=10]{example-image}};
\begin{scope}
\foreach \row in {0,...,\CSVDataRows}{
\pgfplotstablegetelem{\row}{ID}\of{\csvdata}
\pgfmathsetmacro{\i}{"\pgfplotsretval"}
\pgfplotstablegetelem{\row}{Floor}\of{\csvdata}
\pgfmathsetmacro{\f}{"\pgfplotsretval"}
\pgfplotstablegetelem{\row}{X-Pos}\of{\csvdata}
\pgfmathsetmacro{\x}{\pgfplotsretval}
\pgfplotstablegetelem{\row}{Y-Pos}\of{\csvdata}
\pgfmathsetmacro{\y}{\pgfplotsretval}
\pic[transform shape] at (\x,\y){
ElectricComponent={
floor={\f}
}};}
\end{scope}
\end{tikzpicture}
}
\end{center}
\end{document}

Now I would like to dynamically create more than one Table and TikZ picture based on the Floor information from my data.csv. In this case two Table's and two TikZ picture's should be created (GroundFloor / UpperFloor).

So all data.csv information which are set to GroundFloor should only be shown in the GroundFloor related table and the GroundFloor related TikZ picture. And the same for the UpperFloor.

To determine if a Floor identifier is valid, I would like to use something like \IfFileExists{../Images/Layout/__FLOOR__.png}{Valid}{\errmessage{Floor not supported!}} This step is mandatory, because I always need to include the dedicated floor.png to every TikZ picture. This can be seen in the commented out line of the TikZ picture. %\node[inner sep=0pt] (ground_floor){\includegraphics{../Images/Layout/GroundFloor.png}};

3
  • To only print rows where Floor is GroundFloor, put row predicate/.code={ \edef\tempfloorname{GroundFloor} \pgfplotstablegetelem{#1}{Floor}\of\csvdata \ifx\pgfplotsretval\tempfloorname\else \pgfplotstableuserowfalse \fi }, as first option to \pgfplotstabletypeset. If you want to reuse this multiple times, it might be good idea to create a macro (take care of the right number of #s= Mar 1 at 13:44
  • You can do a similar test for the tikzpicture to only print the \pics from the correct Floor. Mar 1 at 13:46
  • And finally for an error message you could (ab)use \PackageError{<package>}{<message>}{<some info>}, like in \IfFileExists{../Images/Layout/__FLOOR__.png}{}{\PackageError{}{Floor not supported!}{}}. Mar 1 at 13:49

1 Answer 1

1

You can grab the current value from the Floor column and check whether it is equal to GroundFloor (or to UpperFloor or whatever) using a basic \ifx. You can do this test when typesetting the table and exclude rows where this test yields FALSE via row predicate.

\documentclass{article}
\usepackage[a4paper,margin=10mm]{geometry}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\usepackage{mwe}

%PowerOutlet
\tikzset{
    pics/powerOutlet/.style={
        code={
            \begin{scope}[scale=0.4]
                \draw[red,very thick](0,0)--(0,10);
                \draw[red,very thick](-10,10)--(10,10);
                \draw[red,very thick,line cap=round](-10,20) 
                    arc[start angle=180,end angle=360,radius=10];
            \end{scope}
        }
    }
}

%Example data for MWE
\begin{filecontents}{data.csv}
Image,ID,Floor,X-Pos,Y-Pos
powerOutlet,A1F5F,GroundFloor,1,2
powerOutlet,7ZF3I,UpperFloor,20,1
\end{filecontents}
\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}
\pgfmathtruncatemacro\CSVDataRows{\pgfplotsretval-1} 

\begin{document}

\edef\tempfloorname{GroundFloor}

\section*{Table}
\begin{center}
\pgfplotstabletypeset[
    row predicate/.code={
        \pgfplotstablegetelem{#1}{Floor}\of\csvdata
        \ifx\pgfplotsretval\tempfloorname\else
            \pgfplotstableuserowfalse
        \fi
    },
    font=\ttfamily,
    col sep=comma,
    columns={Image,ID,Floor,X-Pos,Y-Pos},
    columns/Image/.style={
        column name=Image,
        assign cell content/.code={
            \pgfkeyssetvalue{/pgfplots/table/@cell content}{
                \fbox{\raisebox{-0.5\height}{\tikz{\pic[scale=0.04]{##1};}}}
            }
        }
    },
    columns/ID/.style={
        column name=ID,
        string type
    },
        columns/Floor/.style={
        column name=Floor,
        string type
    },
        columns/X-Pos/.style={
        column name=X-Pos
    },
        columns/Y-Pos/.style={
        column name=Y-Pos,
        column type/.add={}{|}
    },
    column type/.add={|}{},
    after row={\hline},
    every head row/.style={before row=\hline}
]{\csvdata}
\end{center}

\section*{Graphic}
\begin{center}%
\scalebox{0.1}{%
    \begin{tikzpicture}
    \node[inner sep=0pt] (floor) {
        \IfFileExists{\tempfloorname .png}{
            \includegraphics[scale=5]{\tempfloorname}
        }{\PackageError{}{Floor not supported!}{}}
    };
    \begin{scope}
    \foreach \row in {0,...,\CSVDataRows}{
        \pgfplotstablegetelem{\row}{Floor}\of{\csvdata}
        \ifx\pgfplotsretval\tempfloorname\relax
            \pgfplotstablegetelem{\row}{ID}\of{\csvdata}
            \pgfmathsetmacro{\i}{"\pgfplotsretval"}
            \pgfplotstablegetelem{\row}{X-Pos}\of{\csvdata}
            \pgfmathsetmacro{\x}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{Y-Pos}\of{\csvdata}
            \pgfmathsetmacro{\y}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{Image}\of{\csvdata}
            \pgfmathsetmacro{\t}{"\pgfplotsretval"}
            \pic[transform shape] at (\x,\y) {\t};
        \fi
    }
    \end{scope}
    \end{tikzpicture}
}
\end{center}
\end{document}

enter image description here


A fully automatic variant that prints one page for every unique floor could be something like the following:

\documentclass{article}
\usepackage[a4paper,margin=10mm]{geometry}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

%PowerOutlet
\tikzset{
    pics/powerOutlet/.style={
        code={
            \begin{scope}[scale=0.4]
                \draw[red,very thick](0,0)--(0,10);
                \draw[red,very thick](-10,10)--(10,10);
                \draw[red,very thick,line cap=round](-10,20) 
                    arc[start angle=180,end angle=360,radius=10];
            \end{scope}
        }
    }
}

%Example data for MWE
\begin{filecontents}{data.csv}
Image,ID,Floor,X-Pos,Y-Pos
powerOutlet,A1F5F,GroundFloor,1,2
powerOutlet,F2CB3,GroundFloor,2,3
powerOutlet,7ZF3I,UpperFloor,20,1
\end{filecontents}
\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}
\pgfmathtruncatemacro\CSVDataRows{\pgfplotsretval-1} 

\pgfplotstablesave[
    col sep=comma,
    columns={Floor},
    sort cmp=string <,
    unique={Floor}
]{\csvdata}{floor-data.csv}
\pgfplotstableread[col sep=comma]{floor-data.csv}{\csvfloordata}
\pgfplotstablegetrowsof{\csvfloordata}
\pgfmathtruncatemacro\CSVFloorDataRows{\pgfplotsretval-1} 

\pgfplotstableset{
    row predicate/.code={
        \pgfplotstablegetelem{#1}{Floor}\of\csvdata
        \ifx\pgfplotsretval\tempfloorname\else
            \pgfplotstableuserowfalse
        \fi
    },
    font=\ttfamily,
    col sep=comma,
    columns={Image,ID,Floor,X-Pos,Y-Pos},
    columns/Image/.style={
        column name=Image,
        assign cell content/.code={
            \pgfkeyssetvalue{/pgfplots/table/@cell content}{
                \fbox{\raisebox{-0.5\height}{\tikz{\pic[scale=0.04]{##1};}}}
            }
        }
    },
    columns/ID/.style={
        column name=ID,
        string type
    },
        columns/Floor/.style={
        column name=Floor,
        string type
    },
        columns/X-Pos/.style={
        column name=X-Pos
    },
        columns/Y-Pos/.style={
        column name=Y-Pos,
        column type/.add={}{|}
    },
    column type/.add={|}{},
    after row={\hline},
    every head row/.style={before row=\hline}
}

\newcommand{\PrintFloor}[1]{
    \edef\tempfloorname{#1}
    
    \section*{Table}
    \begin{center}
    \pgfplotstabletypeset{\csvdata}
    \end{center}
    
    \section*{Graphic}
    \begin{center}%
    \scalebox{0.1}{%
        \begin{tikzpicture}
        \node[inner sep=0pt] (floor) {
            \IfFileExists{\tempfloorname .png}{
                \includegraphics[scale=5]{\tempfloorname}
            }{\PackageError{}{Floor not supported!}{}}
        };
        \begin{scope}
        \foreach \row in {0,...,\CSVDataRows} {
            \pgfplotstablegetelem{\row}{Floor}\of{\csvdata}
            \ifx\pgfplotsretval\tempfloorname\relax
                \pgfplotstablegetelem{\row}{ID}\of{\csvdata}
                \pgfmathsetmacro{\i}{"\pgfplotsretval"}
                \pgfplotstablegetelem{\row}{X-Pos}\of{\csvdata}
                \pgfmathsetmacro{\x}{\pgfplotsretval}
                \pgfplotstablegetelem{\row}{Y-Pos}\of{\csvdata}
                \pgfmathsetmacro{\y}{\pgfplotsretval}
                \pgfplotstablegetelem{\row}{Image}\of{\csvdata}
                \pgfmathsetmacro{\t}{"\pgfplotsretval"}
                \pic[transform shape] at (\x,\y) {\t};
            \fi
        }
        \end{scope}
        \end{tikzpicture}
    }
    \end{center}
    
    \clearpage
}

\begin{document}

\foreach \floor in {0,...,\CSVFloorDataRows} {
    \pgfplotstablegetelem{\floor}{Floor}\of{\csvfloordata}
    \PrintFloor{\pgfplotsretval}
}

\end{document}
9
  • Great! Is there a way to first of all just read out data.csv and store all different Floors in an array and then iterate through all of them? Then the example is completely build up dynamically and in the future I don't need to care when I would like to add something like a garage or when I decide to switch from floor view to lets say room view...
    – PascalS
    Mar 1 at 14:54
  • The idea behind is just to add the new floor data in data.csv and adding the new floor plan .png => The rest is working out of the box :)
    – PascalS
    Mar 1 at 14:58
  • @PascalS I would probably not parse the list again, but just create an array with the possible floors in the right order. Otherwise, I can't imagine how to sort the floors since you don't have numbers and alphabetic sorting is probably also not feasible. Mar 1 at 15:52
  • Hmm I would just parse through the data.csv and add an element to my dynamic floor array when the new element is not part of the existing array. The sort topic is implicide solved because the data.csv will be read from top to bottom. So I can influence the order.
    – PascalS
    Mar 1 at 16:10
  • @PascalS I extended my answer. Mar 2 at 14:38

You must log in to answer this question.

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