1

i want to use newcommand for position of textblock (xvalue, yvalue) and variable from file excel (\No).

But error: missing begin{document} and i can not get value from newcommand when i use \xvalue\No

My minimal coding:

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\documentclass{article}
\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}

\newcommand*{\xvalue1}{1}%
\newcommand*{\yvalue1}{2}%

\newcommand*{\xvalue2}{2}%
\newcommand*{\yvalue2}{3}%

\newcommand*{\xvalue3}{4}%
\newcommand*{\yvalue3}{1}%

\newcommand*{\xvalue4}{2.5}%
\newcommand*{\yvalue4}{3.5}%

\newcommand*{\xvalue5}{0.5}%
\newcommand*{\yvalue5}{7}%

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \No=NoCol}%
{%
\begin{textblock*}{5cm}(\xvalue\No cm,\yvalue\No cm)
\A
\end{textblock*}
\pagebreak
\newpage
}%

\end{document}

Thank in advance

  • 3
    You can't (usually) have numbers in command names. Replace \yvalue1 by \yvaluea and so on – Phelype Oleinik Dec 10 '19 at 1:58
3

I do agree with Phelype that one should not usually define macros with numbers in (even though this is possible with \csname...\endcsname), but I do not think this is necessary here. Rather, I think you are looking for \ifcase here. In more detail, the way you define the commands fails because they contain numbers, and, as pointed out by Phelype, this does not quite work with \newcommand(*). However, you do not need that either. Rather, you need to make sure that, say, \xvalue1 expands to 1, \xvalue2 to 2, \xvalue3 to 4 etc. This can be achieved with \ifcase.

\newcommand{\xvalue}[1]{\ifcase#1 % case #1=0
\or1% case #1=1
\or2% case #1=2
\or4% case #1=3
\or2.5% case #1=4
\or0.5% case #1=5
\fi}

Using the same for \yvalue and removing the comments leads to a working code.

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\documentclass{article}
\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}
\newcommand{\xvalue}[1]{\ifcase#1
\or1\or2\or4\or2.5\or0.5\fi}
\newcommand{\yvalue}[1]{\ifcase#1
\or2\or3\or1\or3.5\or7\fi}

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \No=NoCol}%
{%
\begin{textblock*}{5cm}(\xvalue\No cm,\yvalue\No cm)
\A
\end{textblock*}
\pagebreak
\newpage
}%

\end{document}

enter image description here

|improve this answer|||||
1

[  Schrödinger's cat already gave the (in my opinion) best solution via \ifcase.
Nonetheless my play instinct is now awake. ;-)       ]

Phelype Oleinik already pointed out that the attempt of having macro-names with digits/non-letters leads to problems.

In case you wish this anyway, I can offer a macro \NameToCs which acts as follows:

\NameToCs⟨stuff not in curly braces and without curly braces⟩{NameOfCs}
→
⟨stuff not in curly braces and without curly braces⟩\NameOfCs

The control-sequence-token \NameOfCs is created by applying \csname..\endcsname to the NameOfCs-argument.
The NameOfCs-argument may also contain digits and the like.
⟨stuff not in curly braces and without curly braces⟩ may be empty.

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\documentclass{article}

\begingroup
\makeatletter
\@firstofone{%
  \endgroup
  \newcommand\exchange[2]{#2#1}%
  \@ifdefinable\NameToCs{%
    \long\def\NameToCs#1#{\romannumeral0\InnerNameToCs{#1}}%
  }%
  \newcommand\InnerNameToCs[2]{%
    \expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}%
  }%
}%


\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}

\NameToCs\newcommand*{xvalue1}{1}%
\NameToCs\newcommand*{yvalue1}{2}%

\NameToCs\newcommand*{xvalue2}{2}%
\NameToCs\newcommand*{yvalue2}{3}%

\NameToCs\newcommand*{xvalue3}{4}%
\NameToCs\newcommand*{yvalue3}{1}%

\NameToCs\newcommand*{xvalue4}{2.5}%
\NameToCs\newcommand*{yvalue4}{3.5}%

\NameToCs\newcommand*{xvalue5}{0.5}%
\NameToCs\newcommand*{yvalue5}{7}%

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \No=NoCol}%
{%
\begin{textblock*}{5cm}(\NameToCs{xvalue\No} cm,\NameToCs{yvalue\No} cm)%
\A
\end{textblock*}%
%\pagebreak %  Why \pagebreak and \newpage
%\newpage   %  _inside_ the \DTLforeach-loop?
            %  With \raggedbottom and 1 column-mode \pagebreak and \newpage are more or less the same.
            %  With \flushbottom and 1 column-mode \pagebreak yields that vertical gaps _between_
            %  paragraphs stretch so that the page is filled with text to the bottom while
            %  \newpage yields that the page is filled with a large empty vertical space from the last
            %  line of the page down to the bottom of the page.
            %  Therefore \newpage seems obsolete after \pagebreak.
            %  Besides this the textblock*-environment places things in a way where the page-building-apparatus
            %  does not "realize" that things are placed on the page. Therefore \pagebreak/\newpage in this
            %  example don't have an effect because the page-building-apparatus still "thinks" that no
            %  material for ejecting a page was collected yet that could be ejected due to \pagebreak/\newpage.
}%
\null
\newpage

\end{document}

Having coordinates (X-Values and Y-Values of As (and Bs)) within another database and merging the processing of both databases via a nested loop probably is fun, too.
In the examples below the primary key common to both databases is "NoCol". (It is not clear to me why this is named "NoCol" instead of "NumberOfRow" ;-)

You can do this by means of another .csv-file:

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\begin{filecontents*}{Acoordinates.csv}
NoCol, AXValue, AYValue
1,1,2
2,2,3
3,4,1
4,2.5,3.5
5,0.5,7
\end{filecontents*}

\documentclass{article}

\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}
\DTLloaddb{myacoordinates}{Acoordinates.csv}

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \NumberOfRowInTestCSV=NoCol}%
{%
  \DTLforeach*{myacoordinates}{\NumberOfRowInAcoordinatesCSV=NoCol, \Ax=AXValue, \Ay=AYValue}%
  {%
    \ifx\NumberOfRowInTestCSV\NumberOfRowInAcoordinatesCSV
      \begin{textblock*}{5cm}(\Ax cm,\Ay cm)%
      \A
      \end{textblock*}%
    \fi
  }%
}%
\null
\newpage

\end{document}

You can also do this by maintaining the database(s) for the coordinates "by hand":

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\documentclass{article}

\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}

\DTLnewdb{myacoordinates}%
\DTLaddcolumn{myacoordinates}{NoCol}%
\DTLaddcolumn{myacoordinates}{AXValue}%
\DTLaddcolumn{myacoordinates}{AYValue}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{1}%
  \DTLnewdbentry{myacoordinates}{AXValue}{1}%
  \DTLnewdbentry{myacoordinates}{AYValue}{2}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{2}%
  \DTLnewdbentry{myacoordinates}{AXValue}{2}%
  \DTLnewdbentry{myacoordinates}{AYValue}{3}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{3}%
  \DTLnewdbentry{myacoordinates}{AXValue}{4}%
  \DTLnewdbentry{myacoordinates}{AYValue}{1}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{4}%
  \DTLnewdbentry{myacoordinates}{AXValue}{2.5}%
  \DTLnewdbentry{myacoordinates}{AYValue}{3.5}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{5}%
  \DTLnewdbentry{myacoordinates}{AXValue}{0.5}%
  \DTLnewdbentry{myacoordinates}{AYValue}{7}%

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \NumberOfRowInTestCSV=NoCol}%
{%
  \DTLforeach*{myacoordinates}{\NumberOfRowInAcoordinatesCSV=NoCol, \Ax=AXValue, \Ay=AYValue}%
  {%
    \ifx\NumberOfRowInTestCSV\NumberOfRowInAcoordinatesCSV
      \begin{textblock*}{5cm}(\Ax cm,\Ay cm)%
      \A
      \end{textblock*}%
    \fi
  }%
}%
\null
\newpage

\end{document}

Perhaps excel can create a .csv-file for you where coordinates of As (and Bs) are stored also:

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, AXValue, AYValue
A1,B1,1,2
A2,B2,2,3
A3,B3,4,1
A4,B5,2.5,3.5
A5,B5,0.5,7
\end{filecontents*}

\documentclass{article}

\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}
\DTLloaddb{myacoordinates}{Acoordinates.csv}

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \Ax=AXValue, \Ay=AYValue}%
{%
  \begin{textblock*}{5cm}(\Ax cm,\Ay cm)%
  \A
  \end{textblock*}%
}%
\null
\newpage

\end{document}
|improve this answer|||||

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.