1

I'd like to construct tables with some macros. I have created an environment with a variable amount of columns. One of the macros is supposed to create a row of entries that have no vertical lines. I've used \multicolumn for that. It's working fine, but I have to write out all multicolumn calls, so it is usable for only one size. Instead, I'd prefer the \lyrics command to perform like \chords below.

How could this be achieved? I'm guessing some sort of parsing or splitting would need to be involved, followed by the wrapping and joining again. This answer addresses splitting by comma. I've not found any methods for splitting by ampersand. But if the splitting can be done, I guess some loop would work from then on.

Alternatively, I have used a column styling method as described here. Maybe a similar approach could be taken. But obviously the \multicolumn command cannot be left incomplete before the column itself and then completed after the column.

I realised, that for this particular problem, another way of removing the vertical lines would be enough, but I still think wrapping cells this way is an interesting problem. So any help on either issue is greatly appreciated!


Here's an example.

\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[finnish]{babel}

\newenvironment{sheets}[1]{%
    \newcommand{\chords}[1]{##1 \\ \multicolumn{1}{l}{} \\[-1em]}
    \newcommand{\lyrics}[4]{\multicolumn{1}{l}{##1} & \multicolumn{1}{l}{##2} & \multicolumn{1}{l}{##3} & \multicolumn{1}{l}{##4} \\[0.5em]}
    \begin{tabular}{l*{\numexpr#1-1}{|l}}
}{\end{tabular}}

\begin{document}

\begin{sheets}{4}
    \chords{C & C & Am & G}
    \lyrics{Paada daa pa paada}{daa, pa paada}{daa paapa da da}{daa}
    \chords{C Dm & C & C G & C}
    \lyrics{Daa paada da paa da}{daa papaa paada}{da pa pa pa daa daa}{daa}
\end{sheets}

% I'd like to be able to write:
% \begin{sheets}{4}
%     \chords{C & C & Am & G}
%     \lyrics{Paada daa pa paada & daa, pa paada & daa paapa da da & daa}
%     \chords{C Dm & C & C G & C}
%     \lyrics{Daa paada da paa da & daa papaa paada & da pa pa pa daa daa & daa}
% \end{sheets}

\end{document}

Here's what it looks like.

Example image

2
\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
%\usepackage[finnish]{babel}

\makeatletter
%%----------------------------------------------------------------------
%% Exchange two arguments:
%%......................................................................
\newcommand\UD@exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
  \@secondoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% Expandable extraction of first item of ampersand-list:
%%......................................................................
%%
%% \UD@ExtractFirstAmpersandArg{<ampersand list>}
%%
%% yields:
%% 
%% <first item/first ampersand-delimited argument from ampersand-list>
%%
%% <ampersand-list> is considered a sequence of ampersand-delimited arguments.
%%
%% The <first item/first ampersand-delimited argument from ampersand list> 
%% will be extracted. The remainder of the <ampersand list> will be discarded.
%%
%% Due to \romannumeral0-expansion, the result will be delivered after
%% two expansion-steps/after having \UD@ExtractFirstAmpersandArg "hit" via
%% two \expandafter(-chains).
%%......................................................................
\newcommand\UD@gobbledot{}\def\UD@gobbledot.{}%
\newcommand\UD@gobbletoampersand{}\long\def\UD@gobbletoampersand#1&{}%
\newcommand\UD@removeampersand{}\long\def\UD@removeampersand#1&{#1}%
\newcommand\UD@RemoveFromAmpersandTillUD@SelDOm{}%
\long\def\UD@RemoveFromAmpersandTillUD@SelDOm#1&#2\UD@SelDOm{#1&}%
\newcommand\UD@ExtractFirstAmpersandArg[1]{%
  \romannumeral0%
  \UD@ExtractFirstAmpersandArgLoop{.#1&\UD@SelDOm}%
}%
\newcommand\UD@ExtractFirstAmpersandArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoampersand#1}%
  {%
     \UD@exchange{ }{\expandafter\expandafter\expandafter}%
     \expandafter\UD@gobbledot\UD@removeampersand#1%
  }%
  {%
    \expandafter\UD@ExtractFirstAmpersandArgLoop
    \expandafter{\UD@RemoveFromAmpersandTillUD@SelDOm#1}%
  }%
}%
%%----------------------------------------------------------------------
%% Check whether argument contains ampersand which is not nested in
%% braces:
%%......................................................................
%% \UD@CheckWhetherNoAmpersand{<Argument which is to be checked>}%
%%                         {<Tokens to be delivered in case that argument
%%                           contains no ampersand>}%
%%                         {<Tokens to be delivered in case that argument
%%                           contains ampersand>}%
\newcommand\UD@CheckWhetherNoAmpersand[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoampersand#1&}%
}%
%%----------------------------------------------------------------------
%% \lyricsb{<ampersand-list>}
%%
%% iterates on <ampersand-list> and wraps each element into
%% \multicolumn{1}{l}{<element>} and separates the calls to
%% \multicolumn by " & " and attaches " \\[0.5em]".
%%
%% E.g.,  \lyricsb{ A & B & C }
%% yields 
%% \multicolumn{1}{l}{ A } & \multicolumn{1}{l}{ B } & \multicolumn{1}{l}{ C }
%%
%% If you wish, you can move the definition of \lyricsb into the
%% definition of the sheets-environment.
%%......................................................................
\newcommand\lyricsb{\romannumeral0\lyricsAmpersandloop{ }}%
\newcommand\lyricsAmpersandloop[2]{%
   \UD@CheckWhetherNoAmpersand{#2}{%
      #1\multicolumn{1}{l}{#2} \\[0.5em]%
   }{%
     \expandafter\UD@exchange\expandafter{\expandafter{\UD@gobbletoampersand#2}}{%
       \expandafter\lyricsAmpersandloop\expandafter{%
         \romannumeral0\UD@exchange{ }{\expandafter\expandafter\expandafter}%
         \expandafter\UD@exchange
         \expandafter{%
         \expandafter{%
         \romannumeral0\UD@exchange{ }{\expandafter\expandafter\expandafter}%
         \UD@ExtractFirstAmpersandArg{#2}}}%
         {#1\multicolumn{1}{l}} & %
       }%
     }%
   }%
}%
%%----------------------------------------------------------------------
\makeatother

\newenvironment{sheets}[1]{%
    \newcommand{\chords}[1]{##1 \\ \multicolumn{1}{l}{} \\[-1em]}
    \newcommand{\lyrics}[4]{\multicolumn{1}{l}{##1} & \multicolumn{1}{l}{##2} & \multicolumn{1}{l}{##3} & \multicolumn{1}{l}{##4} \\[0.5em]}
    \begin{tabular}{l*{\numexpr#1-1}{|l}}%
}{\end{tabular}}

\begin{document}

\begin{sheets}{4}
    \chords{C & C & Am & G}
    \lyrics{Paada daa pa paada}{daa, pa paada}{daa paapa da da}{daa}
    \chords{C Dm & C & C G & C}
    \lyrics{Daa paada da paa da}{daa papaa paada}{da pa pa pa daa daa}{daa}
\end{sheets}

\bigskip    

% I hope I did everything correctly and you are able to write:
\begin{sheets}{4}
    \chords{C & C & Am & G}
    \lyricsb{Paada daa pa paada & daa, pa paada & daa paapa da da & daa}
    \chords{C Dm & C & C G & C}
    \lyricsb{Daa paada da paa da & daa papaa paada & da pa pa pa daa daa & daa}
\end{sheets}

\end{document}

enter image description here

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.