1

I am trying to compile a document where a section is made up of various subsections (one for each topic I want to report), each of them made up of a different number of subsubsections (varying depending on the topic).

As the number of topics, as well as the number of subsections is likely to change in future, I need to automatize the process.

Ideally, what I need to achieve is like

Pseudo-Code

foreach \section in {a,b,c}{
   \section{section}
   foreach \subsection in {1,2,3}{
       \subsection{\subsection}
       \input{file}
   }
}

Where file is a composite name made by \subsection\textunderscore\section.tex

I found several suggestions. The one I think best suits my need is this \ForEach fails with underscores. However, I could not find a way to access the outer loop item to include the levelitem into the name within the inner loop, the one defining the first part of the name of the file I want to input.

I am relatively new to loops in latex (and also to latex, to a certain extent) so I am surely missing something.

I have only been able to make the first loop working. The solution might lie in the \ForEachSublevel command, but even reading the forarray manual, I have not been able to come up with a solution.

Below, my code

\documentclass[a4paper,11pt]{article}

% Packages
\usepackage[margin=2.5cm]{geometry}
\usepackage[stable]{footmisc}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{float}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{setspace}
\usepackage{enumitem}
\usepackage{booktabs}
\usepackage[para]{threeparttable}
\usepackage{tabularx}
\usepackage{ragged2e}
\usepackage{graphicx}

% ----------------------------
% FORARRRAY TO LOOP WITH UNDERSCORES
% https://tex.stackexchange.com/questions/456693/foreach-fails-with-underscores

\usepackage{forarray}

\newif\iffilename
\global\filenamefalse
\makeatletter
\newcommand\myunderscore{%
  \iffilename
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi{\string_}{\textunderscore}%
}%
\makeatother

% -----------------------------
\usepackage{bookmark}
\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}
\usepackage{natbib}
% ------------------------------------------

\begin{document}
\section{Results}

% https://tex.stackexchange.com/questions/456693/foreach-fails-with-underscores
\ForEach{,}%
{%
      {% Open local scope
      \subsection{SYNTH OUTCOME ON \thislevelitem \hspace{1pt} OUTCOME}%

      }% Ends local scope
}% ForEach ends here
{%
ipc\myunderscore ruleoflaw,ipc\myunderscore politicalrights,ipc\myunderscore gender,ipc\myunderscore socprotection,ipc\myunderscore business,ipc\myunderscore health,ipc\myunderscore work,ipc\myunderscore edu,ipc\myunderscore security,ipc\myunderscore environment,ipc\myunderscore minority,ipc\myunderscore cvrights,ipc\myunderscore womenrights,ipc\myunderscore corrupt% Needed comment
}%
\end{document}

2 Answers2

2

Welcome to TeX.SE! I believe you want something like this:

\documentclass{article}
\usepackage{expl3}

\ExplSyntaxOn
\cs_new_eq:NN \clistmapinline \clist_map_inline:nn
\ExplSyntaxOff

\begin{document}

  \clistmapinline{a, b, c}{%
    \section{Section #1}%
    \clistmapinline{1, 2, 3}{%
      \subsection{Subsection ##1}%
      \input{##1_#1.tex}%
    }%
  }

\end{document}

This reads the following files: 1_a.tex, 2_a.tex, 3_a.tex, 1_b.tex, 2_b.tex, 3_b.tex, 1_c.tex, 2_c.tex, and 3_c.tex.

\clistmapinline replaces #1 with the thing being iterated on, and ## with a single #. Therefore, when the outer loop has been unrolled, all occurrences of ##1 in the inner loop code have become #1. This is why the inner code has access to its current item with ##1 and to the outer current item with #1.

\textunderscore is for typesetting. For an underscore that is part of the name of a file to input, you need a plain underscore.

Here is the output with obvious dummy contents in each input file.

screenshot

frougon
  • 24,283
  • 1
  • 32
  • 55
0

Here's the directory listing:

Results_ipc_politicalrights.tex
Results_ipc_ruleoflaw.tex
Statements_ipc_politicalrights.tex
Statements_ipc_ruleoflaw.tex
santi.aux
santi.log
santi.pdf
santi.tex

I abbreviated the list of files to two, for simplicity. The mock files just contain the file name without ipc and underscores.

Code:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\cycle}{mm}
 {
  \santi_cycle:nn { #1 } { #2 }
 }

\int_new:N \g__santi_cycle_int
\cs_generate_variant:Nn \clist_map_function:nN { nc }

\cs_new_protected:Nn \santi_cycle:nn
 {
  \int_gincr:N \g__santi_cycle_int
  \cs_set:cn { \__santi_cycle_name: } { #2 }
  \clist_map_function:nc { #1 } { \__santi_cycle_name: }
  \int_gdecr:N \g__santi_cycle_int
 }
\cs_new:Nn \__santi_cycle_name:
 {
  __santi_cycle_\int_to_roman:n { \g__santi_cycle_int } :n
 }
\ExplSyntaxOff

\begin{document}

\cycle{Statements,Results}{%
  \section{#1}
  \cycle{
    ipc\string_ruleoflaw,
    ipc\string_politicalrights,
    %ipc\string_gender,
    %ipc\string_socprotection,
    %ipc\string_business,
    %ipc\string_health,
    %ipc\string_work,
    %ipc\string_edu,
    %ipc\string_security,
    %ipc\string_environment,
    %ipc\string_minority,
    %ipc\string_cvrights,
    %ipc\string_womenrights,
    %ipc\string_corrupt
  }{
    \subsection{SYNTH OUTCOME ON ##1 OUTCOME}
    \input{#1_##1}
  }
}

\end{document}

The assumption is that you have files named

<section>_ipc_<subsection>.tex

Adapt to your needs.

The \cycle macro loops over the list given as first argument, executing what's specified in the second argument, where #1 stands for the current item. This code can contain another \cycle, but its second argument must refer to the current item of the inner cycle with ##1 (using #1 is allowed to refer to the current item of the outer cycle).

enter image description here

egreg
  • 1,121,712