4

I have a large file database.tex with a lot of questions and solutions in the format of the ExSheets package. If I include multiple questions with one \includequestions command, the questions are included in the order of there definition in database.tex. So there is no difference between the following two lines

\includequestions[IDs={q1,q2}]{database.tex}
\includequestions[IDs={q2,q1}]{database.tex}

If I want a specific order or the questions I need multiple \includequestions commands:

\includequestions[IDs={q2}]{database.tex}
\includequestions[IDs={q1}]{database.tex}

But database.tex is large and I want to include 6 or more questions in a specific order. Thus, typesetting needs more than 1 minute. Is there a better and faster way?


Update: I forgot to mention that I use a custom header for questions and solutions (to keep it easy I only give the code for the header of questions):

...
\begin{question}[ID=q1,subtitle={T1}]
...

\def\loesung{}

\ExplSyntaxOn  
\DeclareInstance{exsheets-heading}{myhead}{default}{
  number-post-code = {\hspace{1em}\textbf{\tl_use:N \l__exsheets_questions_subtitle_tl}~%
  \ifdef{\loesung}{\color{blue}\tiny(\texttt{\tl_use:N \l__exsheets_questions_id_tl})}{}
  } ,
  join = {
    title[r,B]number[l,B](.333em,0pt)
  } ,
  attach = {
    main[l,vc]title[l,vc](0pt,0pt)
  }
}
\ExplSyntaxOff

\RenewQuSolPair
  {question}[][headings=myhead]
  {solution}[][headings=myhead]

If I use the answer from @cgnieder, I get:

enter image description here

  • Short answer: no. \includequestions{<file> always includes questions in the order they're given in the file since at some point it simply boils down to \input{<file>}. – clemens Jul 14 '14 at 13:36
  • The update essentially means: if you really want the ID printed then you have to stick with your current work flow. The IDs were never meant for printing... in my approach below the printed questions have new IDs! (The subtitle could be added to my answer...) – clemens Jul 15 '14 at 9:30
1

Here is a possible workaround: the idea is to include the questions but hide them, i.e., print nothing. exsheets question properties then allow to print the needed parts selectively.

Caution: The code below is a hack that uses internal functions so it may break in future versions of exsheets...

In order to hide the questions when included a few hacks are needed:

\cs_new_protected:Npn \hidequestions
  {
    \keys_set:nn {exsheets}
      {
        headings=blank ,
        skip-below=0pt
      }
    \cs_set:Npn \__exsheets_save_and_print_question_body:n ##1
      { \exsheets_set_question_properties:n { question-body = {##1} } }
    \cs_set_eq:NN \exsheets_h_or_vspace:N \use_none:n
  }

A little bit more work is needed to print the questions (but no use of internal functions this time so the following is safe to use). The idea is to map over a comma separated list of IDs and print a question for each containing the question body of the original question for each ID. The questions must get 0 as value for points and bonus points if no points are given to avoid errors which means we need to check them first.

\tl_new:N \l_exsheets_this_question_points_tl
\tl_new:N \l_exsheets_this_question_bonus_tl

\cs_new_protected:Npn \printquestions #1
  {%
    \clist_map_inline:nn {#1}
      {
        % check if points are given or unknown,
        % if yes feed `0' to the heading:
        \prop_get:NnNF \g__exsheets_question_property_points_prop
          {##1}
          \l_exsheets_this_question_points_tl
          { \tl_set:Nn \l_exsheets_this_question_points_tl {0} }
        % same for bonus points
        \prop_get:cnNF {g__exsheets_question_property_bonus-points_prop}
          {##1}
          \l_exsheets_this_question_bonus_tl
          { \tl_set:Nn \l_exsheets_this_question_bonus_tl {0} }
        % typeset the question:
        \begin{question}{
            \l_exsheets_this_question_points_tl +
            \l_exsheets_this_question_bonus_tl
          }
          \exsheets_get_question_property:nn {question-body} {##1}
        \end{question}
      }
  }

With the above defined functions and a file exercises.tex which contains

\begin{question}[ID=q1]
  Q1
\end{question}
\begin{question}[ID=q2]
  Q2
\end{question}
\begin{question}[ID=q3]
  Q3
\end{question}

the document body

\begin{document}

\printquestions{q3,q1}

\hidequestions
\includequestions{exercises.tex}

\end{document}

gives

enter image description here

A warning: This approach has some drawbacks

  • most notably: \totalpoints and friends will count the points of the questions two times: once when included and the second time when printed.
  • \ForEachQuestion will loop over the questions twice for the same reason.
  • others I didn't think of, yet, ...

The complete code:

\documentclass{article}
\usepackage{exsheets}

\usepackage{filecontents}
\begin{filecontents*}{exercises.tex}
\begin{question}[ID=q1]
  Q1
\end{question}
\begin{question}[ID=q2]
  Q2
\end{question}
\begin{question}[ID=q3]
  Q3
\end{question}
\end{filecontents*}

\DeclareInstance{exsheets-heading}{blank}{default}{
  inline = true ,
  above = 0pt ,
  below = 0pt ,
}

\ExplSyntaxOn
\cs_new_protected:Npn \hidequestions
  {
    \keys_set:nn {exsheets}
      {
        headings=blank ,
        skip-below=0pt
      }
    \cs_set:Npn \__exsheets_save_and_print_question_body:n ##1
      { \exsheets_set_question_properties:n { question-body = {##1} } }
    \cs_set_eq:NN \exsheets_h_or_vspace:N \use_none:n
  }

\tl_new:N \l_exsheets_this_question_points_tl
\tl_new:N \l_exsheets_this_question_bonus_tl

\cs_new_protected:Npn \printquestions #1
  {%
    \clist_map_inline:nn {#1}
      {
        % check if points are given or unknown, if yes feed `0' to the heading:
        \prop_get:NnNF \g__exsheets_question_property_points_prop
          {##1}
          \l_exsheets_this_question_points_tl
          { \tl_set:Nn \l_exsheets_this_question_points_tl {0} }
        % same for bonus points
        \prop_get:cnNF {g__exsheets_question_property_bonus-points_prop}
          {##1}
          \l_exsheets_this_question_bonus_tl
          { \tl_set:Nn \l_exsheets_this_question_bonus_tl {0} }
        \begin{question}{
            \l_exsheets_this_question_points_tl+\l_exsheets_this_question_bonus_tl
          }
          \exsheets_get_question_property:nn {question-body} {##1}
        \end{question}
      }
  }
\ExplSyntaxOff

\begin{document}

\printquestions{q3,q1}

\hidequestions
\includequestions{exercises.tex}

\end{document}
  • I have a litte problem with this solution. I use custom headers, but \printquestions doesn't print the subtitle an the id. Also an empty header for all included questions is given. Please see the updated question. – Ivo Jul 15 '14 at 9:13
  • @Ivo of course not since you never mentioned anything about subtitles in your questions. But it's easy to update: subtitles are question properties as well and can be retrieved just like the question-body. – clemens Jul 15 '14 at 9:17
  • @Ivo BTW: the code above needs an up to date exsheets. But then nothing is printed after \hidequestions which I have checked in my solution by putting +\includequestions{exercises.tex}+ – clemens Jul 15 '14 at 9:20
  • Is this sort of thing now easier with xsim? I ask because I haven't yet upgraded to xsim and this would nudge me big time. – PatrickT Nov 22 '17 at 4:06
  • 1
    @PatrickT this should indeed be a lot easier with xsim. – clemens Nov 22 '17 at 7:33

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.