Automatically generate data summary at the beginning of the document

automationauxiliary-filesmacros

Within my report I want do define several structural damages and I want to automatically generate a summary table at the beginning of the document.
Here is an example of how far I have come so far and what I want to achieve.

\documentclass{article}

\usepackage{etoolbox}
\usepackage{pgffor}

\parindent=0pt

\newcounter{cntClassA}\newcounter{cntClassB}\newcounter{cntClassC}\newcounter{cntAddTmp}

\makeatletter

\newcommand\defineDamageKey[4] { \expandafter\edef\csname damage.#1.#2.#3\endcsname{#4} }

\newcommand{\addDamage}[3]{%
%
    \ifstrequal{#1}{A}{\stepcounter{cntClassA} \setcounter{cntAddTmp}{\thecntClassA} }{}%
    \ifstrequal{#1}{B}{\stepcounter{cntClassB} \setcounter{cntAddTmp}{\thecntClassB} }{}%
    \ifstrequal{#1}{C}{\stepcounter{cntClassC} \setcounter{cntAddTmp}{\thecntClassC} }{}%
%
    \defineDamageKey{#1}{\thecntAddTmp}{description}{#2}%
    \defineDamageKey{#1}{\thecntAddTmp}{solution}{#3}%
    \defineDamageKey{#1}{\thecntAddTmp}{ID}{#1-\thecntAddTmp}%
%
    \printDamage{#1}{\thecntAddTmp}%
}

\newcommand{\printDamage}[2]{%
    \textbf{ID:} \@nameuse{damage.#1.#2.ID}\\%
    \textbf{Damage class:} #1\\%
    \textbf{Description:} \@nameuse{damage.#1.#2.description}\\%
    \textbf{Solution:} \@nameuse{damage.#1.#2.solution}\\%
}

\newcommand{\damageSummary}[1]{%
    \newcount\damageCountForClass
%
    \ifstrequal{#1}{A}{ \damageCountForClass=\thecntClassA }{}%
    \ifstrequal{#1}{B}{ \damageCountForClass=\thecntClassB }{}%
    \ifstrequal{#1}{C}{ \damageCountForClass=\thecntClassC }{}%
%
    \foreach \n in {1,...,\damageCountForClass}%
    {%
        \textbf{\@nameuse{damage.#1.\n.ID}:} \@nameuse{damage.#1.\n.description}\\
    }%
}

\makeatother

\begin{document}

\section{Building 1}

\addDamage{A}{Broken window}{Fix window}

\addDamage{B}{Wrong wall paint}{Repaint}


\section{Building 2}

\addDamage{C}{Leaky windows}{Seal windows}

\addDamage{A}{Defective electrics}{Fix electrics}


\section{Summary}

\damageSummary{A}
\damageSummary{B}
\damageSummary{C}


\end{document}

enter image description here

My basic idea was to define my data as key/value pairs with structured named macros:

\@namedef{damage.A.1.description}{description damage A-1}
\@namedef{damage.A.1.solution}{solution damage A-1}
\@namedef{damage.A.2.description}{description damage A-2}

But now I want to have the summary table at the beginning of the document! Am I right that this only works with AUX files?

I've just started with low level TeX / macro writing and tried to figure out how to do this by examining the todonotes package (as the \todo and \listoftodos would possible a similar mechanism). But I dont get it.

So is my current solution actual a good starting point or do I need a different approach? Could anyone give me a hint how to achieve this?

Best Answer

Edit: hyperref-support is added in case you wish hyperlinks from the summary to the place of the document where the damage is described.

If you don't mind having an auxiliary-file whose name is of pattern ⟨expansion of jobname⟩.Damageclass⟨name of damage-class⟩ for each damage-class, then you can probably do with LaTeX 2ε's \addtocontents-\@starttoc-meachanism. I used description-environments for listing the items. How to tweak the description-environment depends on the documentclass in use and may turn out tricky.

The example needs to be compiled three times without having auxiliary-files deleted between runs until everything matches out correctly. (First run creates auxiliary files. Second run creates description-item-labes of summaries and stores measurements in the aux-file. Third run uses measurements from aux-file.)

\documentclass{article}
\usepackage{hyperref}

\makeatletter
\newcommand\maxIDwidth{0pt}%
\AtBeginDocument{\providecommand\r@maxIDwidthpreviousrun{0pt}}%
\AtEndDocument{%
  \protected@write\@auxout{}{\string\newlabel{maxIDwidthpreviousrun}{\maxIDwidth}}%
}%
\DeclareRobustCommand\damageSummaryItem[3]{%
  \item[%
    \setbox\scratchbox\hbox{#1}%
    \ifdim\maxIDwidth<\wd\scratchbox\xdef\maxIDwidth{\the\wd\scratchbox}\fi
    \rlap{\hbox{\@ifundefined{hyperlink}{\@secondoftwo}{\hyperlink}{#3}{#1}}}%
    \hbox to\r@maxIDwidthpreviousrun{\hfill}%
  ]%
  #2%
}%
\newbox\scratchbox
\newcommand\addDamage[3]{%
   %#1 - Damage class
   %#2 - Damage description
   %#3 - Fix/Solution description
   \@ifundefined{c@Damageclass@#1}{%
     \newcounter{Damageclass@#1}%
     \expandafter\gdef\csname theDamageclass@#1\endcsname{#1\mbox{-}\arabic{Damageclass@#1}}%
   }{}%
   \begingroup
   \begin{description}%
   \itemsep=0pt
   \parskip=0pt
   \item[{\refstepcounter{Damageclass@#1}ID:%
     \addtocontents{Damageclass#1}{%
       \damageSummaryItem{\csname theDamageclass@#1\endcsname:}{#2}{\@ifundefined{@currentHref}{}{\@currentHref}}\protected@file@percent
     }%
   }]\csname theDamageclass@#1\endcsname
   \item[{Damage class:}]#1%
   \item[{Description:}]#2%
   \item[{Solution:}]#3%
   \end{description}%
   \endgroup
}%
\newcommand\damageSummary[1]{%
  \begingroup
  \IfFileExists{\jobname.Damageclass#1}{%
    \@ifundefined{hyperlink}{\@firstoftwo}{%
      {\expandafter}\expandafter\ifx\csname hyper@last\endcsname\relax
      \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    }%
  }{\@secondoftwo}%
  {%
    \begin{description}%
    \itemsep=0pt
    \parskip=0pt
    \@starttoc{Damageclass#1}%
    \par\vskip-\@topsepadd\vskip-\parskip
    \end{description}%
  }{\@starttoc{Damageclass#1}}%
  \endgroup
}%
\makeatother

\begin{document}

\section{Summary}
\damageSummary{A}
\damageSummary{B}
\damageSummary{C}

\section{Building 1}

\addDamage{A}{Broken window}{Fix window}

\addDamage{B}{Wrong wall paint}{Repaint}

\section{Building 2}

\addDamage{C}{Leaky windows}{Seal windows}

\addDamage{A}{Defective electrics}{Fix electrics}

\end{document}

enter image description here

The question "Use LaTeX to produce parts lists?" and the answers to it might be of interest to you— a similar problem is addressed there. In the answers you find a different approach which is based on the package datatool and a .csv-file.

Related Question