0

Here are several questions:

1- How to make the usage of \tcboxfit in the first raster row not distort the layout as shown below?

enter image description here

2- How to precisely calculate the dimensions summation passed to headheight option of geometry so that the header starts exactly at the page top border?

3- Why doesn't \iflastpage{\enlargethispage{-1cm}}{} work inside \NewDocumentCommand{\FillAnswerRules} to make a room for the End of the Exam text?

enter image description here

4- Why is not the space (nearly of \baselineskip) between the header and the mainstream text eliminated despite setting headsep = 0pt?

enter image description here

\documentclass{exam}
\usepackage[fontsize = 14pt]{scrextend}
\usepackage{lipsum}
\usepackage[xparse,breakable,raster,skins]{tcolorbox}
\tcbuselibrary{fitting}

\pagestyle{headandfoot}

\newcommand{\myfooter}{%
    \iflastpage{\raisebox{5pt}[0pt][0pt]{\large End of the Exam}}{}%
    \hrule\vspace{5pt}%
    Instructors%
}

\newcommand\headerBody{%
    \begin{tcbitemize}[
        raster valign = bottom,
        valign = bottom,
        raster columns = 2,
        blankest,
        raster after skip = 1ex,
        ]
        \tcboxfit[height = 3em, add to width = 2cm, halign = flush left,height=3em] University\\Faculty\\Program
        \tcbitem[add to width = -2cm, halign = flush right,] \includegraphics[height = 3em]{example-image}
    \end{tcbitemize}
    %
    \hrule
    %
    \begin{tcbraster}[
        raster columns = 3,
        valign = center,
        raster before skip = 1ex,
        raster after skip = 1ex,
        blankest
        ]
        \tcboxfit{Final\\Semester}
        \tcboxfit[before upper*=\centering]{Course Code}
        \tcboxfit[halign = flush right]{\textbf{date}\\\textbf{time}}
    \end{tcbraster}
    %
    \hrule
    %
    \begin{tcbraster}[
        raster columns = 1,
        valign = center, halign = flush center, 
        raster before skip = 1ex,
        raster after skip = 1ex,
        blankest
        ]
        \tcboxfit[interior engine = standard,colback = gray!20, top = 1ex, bottom = 1ex,]{\textbf{Course}}%
    \end{tcbraster}
    %
    \hrule
    %
    \begin{tcbraster}[
        raster columns = 1,
        valign = center, halign = flush center,
        raster before skip = 1ex,
        raster after skip = 1ex,
        blankest,
        ]
        \tcboxfit[top = 1ex, bottom = 1ex,]{This exam contains.}%
    \end{tcbraster}
    %
    \hrule%
}

\newcommand\headerContents{% https://tex.stackexchange.com/a/547910/2288 
    \begin{tcbraster}[
        fit algorithm=hybrid*,
        raster equal height = rows,
        raster halign = center, raster valign = center,
        raster equal skip = 0mm,
        raster force size = false,
        boxsep = 0pt,
        beforeafter skip = 0pt, 
        leftright skip = 0pt,
        raster right skip = 0pt,
        raster left skip = 0pt,
        raster before skip = 0pt,
        raster after skip = 0pt,
        nobeforeafter,
        height = 2em,
        raster rows=4,
        ]%
        \headerBody%
    \end{tcbraster}%
}


\firstpageheader{}{\headerContents}{}
\runningheader{}{\headerContents}{}

\firstpagefooter{}{\myfooter}{}
\runningfooter{}{\myfooter}{}

\ExplSyntaxOn

\keys_define:nn { diaa / answers }
{
    d .dim_set:N = \l__diaa_answers_distance_dim,
    t .dim_set:N = \l__diaa_answers_thickness_dim,
    c .tl_set:N  = \l__diaa_answers_color_tl,
    d .initial:n = 10mm,
    t .initial:n = 0.2pt,
    c .initial:n = gray,
}

\NewTColorBox { fillAnswerRules } { O{} }
{
    height~fill, text~fill, colback=white, boxrule=2pt, sharp~corners,
    boxsep=0pt, left=10pt, right=10pt, top=8pt, bottom=0pt, #1
}

\NewDocumentCommand{\FillAnswerRules}{O{}}
{
    \iflastpage{\enlargethispage{-1cm}}{}
    \begin{fillAnswerRules}
        \keys_set:nn { diaa / answers } { #1 }
        \leaders \hbox:n
        {
            \makebox[\textwidth][s]
            {
                \color{\l__diaa_answers_color_tl}
                \vrule width 0pt height 0.5\l__diaa_answers_distance_dim
                depth 0.5\l__diaa_answers_distance_dim
                \leaders \hrule height \l__diaa_answers_thickness_dim \hfill
            }
        }\vfill
        \null
    \end{fillAnswerRules}
}

\ExplSyntaxOff

\usepackage[
a4paper,
includehead, 
headsep=0pt,
includefoot, 
foot=0mm, 
bottom=20mm,
headheight = \dimexpr9em+9ex+0pt,
top=0mm,
showframe
]{geometry}

\begin{document}
    \begin{questions}
        \question 
        \begin{parts}
            \part \lipsum[1-2]
                \FillAnswerRules
                \FillAnswerRules
                
            \part \lipsum[1]
                \FillAnswerRules
        \end{parts}
    \end{questions} 
\end{document}
1
2

This solution puts the header into a savebox in order to the compute header height accurately. It also increments the page counter before \iflastpage inside \FillAnswerRules.

Note that \tcb@startbox etc. are not defined until \AtBeginDocument.

\documentclass{exam}
\usepackage[fontsize = 14pt]{scrextend}
\usepackage{lipsum}
\usepackage[xparse,breakable,raster,skins]{tcolorbox}
\tcbuselibrary{fitting}

\pagestyle{headandfoot}

\newcommand{\myfooter}{%
    \iflastpage{\raisebox{\dimexpr \height+\depth+5pt}[0pt][0pt]{\large End of the Exam}}{}%
    \hrule\vspace{5pt}%
    Instructors%
}

\newcommand\headerBody{%
    \begin{tcbitemize}[
        raster valign = bottom,
        valign = bottom,
        raster columns = 2,
        blankest,
        raster after skip = 1ex,
        ]
        \tcboxfit[height = 3em, add to width = 2cm, halign = flush left,height=3em] {University\\Faculty\\Program}
        \tcbitem[add to width = -2cm, halign = flush right,] \includegraphics[height = 3em]{example-image}
    \end{tcbitemize}
    %
    \hrule
    %
    \begin{tcbraster}[
        raster columns = 3,
        valign = center,
        raster before skip = 1ex,
        raster after skip = 1ex,
        blankest
        ]
        \tcboxfit{Final\\Semester}
        \tcboxfit[before upper*=\centering]{Course Code}
        \tcboxfit[halign = flush right]{\textbf{date}\\\textbf{time}}
    \end{tcbraster}
    %
    \hrule
    %
    \begin{tcbraster}[
        raster columns = 1,
        valign = center, halign = flush center, 
        raster before skip = 1ex,
        raster after skip = 1ex,
        blankest
        ]
        \tcboxfit[interior engine = standard,colback = gray!20, top = 1ex, bottom = 1ex,]{\textbf{Course}}%
    \end{tcbraster}
    %
    \hrule
    %
    \begin{tcbraster}[
        raster columns = 1,
        valign = center, halign = flush center,
        raster before skip = 1ex,
        raster after skip = 1ex,
        blankest,
        ]
        \tcboxfit[top = 1ex, bottom = 1ex,]{This exam contains.}%
    \end{tcbraster}
    %
    \hrule%
}

\usepackage[a4paper,
includehead, 
headheight=0pt,% will be reset \AtBeginDocument
headsep=0pt,
includefoot, 
foot=0mm, 
bottom=20mm,
top=0mm,
showframe]{geometry}

\newsavebox{\headerbox}
\AtBeginDocument{\savebox{\headerbox}{\begin{minipage}{\textwidth}
    \begin{tcbraster}[
        fit algorithm=hybrid*,
        raster equal height = rows,
        raster halign = center, raster valign = center,
        raster equal skip = 0mm,
        raster force size = false,
        boxsep = 0pt,
        beforeafter skip = 0pt, 
        leftright skip = 0pt,
        raster right skip = 0pt,
        raster left skip = 0pt,
        raster before skip = 0pt,
        raster after skip = 0pt,
        nobeforeafter,
        height = 2em,
        raster rows=4,
        ]%
        \headerBody%
    \end{tcbraster}%
\end{minipage}}

\geometry{headheight = {\dimexpr \ht\headerbox+\dp\headerbox}}
\enlargethispage{-\headheight}% first page only
}% end of \AtBeginDocument

\firstpageheader{}{\usebox\headerbox}{}
\runningheader{}{\usebox\headerbox}{}

\AddToHookNext{shipout/background}{\put({\dimexpr 1in+\oddsidemargin},{\dimexpr 20mm-\paperheight-\baselineskip})%
  {\parbox[t]{\textwidth}{\centering\myfooter}}}% first page footer
%\firstpagefooter{}{\myfooter}{}
\runningfooter{}{\myfooter}{}

\ExplSyntaxOn

\keys_define:nn { diaa / answers }
{
    d .dim_set:N = \l__diaa_answers_distance_dim,
    t .dim_set:N = \l__diaa_answers_thickness_dim,
    c .tl_set:N  = \l__diaa_answers_color_tl,
    d .initial:n = 10mm,
    t .initial:n = 0.2pt,
    c .initial:n = gray,
}

\NewTColorBox { fillAnswerRules } { O{} }
{
    height~fill, text~fill, colback=white, boxrule=2pt, sharp~corners,
    boxsep=0pt, left=10pt, right=10pt, top=8pt, bottom=0pt, #1
}

\NewDocumentCommand{\FillAnswerRules}{O{}}
{\stepcounter{page}\iflastpage{\enlargethispage{-1cm}}{}\addtocounter{page}{-1}% does not affect footer location
        \begin{fillAnswerRules}
        \keys_set:nn { diaa / answers } { #1 }
        \leaders \hbox:n
        {
            \makebox[\textwidth][s]
            {
                \color{\l__diaa_answers_color_tl}
                \vrule width 0pt height 0.5\l__diaa_answers_distance_dim
                depth 0.5\l__diaa_answers_distance_dim
                \leaders \hrule height \l__diaa_answers_thickness_dim \hfill
            }
        }\vfill
        \null
    \end{fillAnswerRules}
}

\ExplSyntaxOff

\begin{document}
    \begin{questions}
        \question 
        \begin{parts}
            \part \lipsum[1-2]
                \FillAnswerRules
                \FillAnswerRules

            \part \lipsum[1]
                \FillAnswerRules
        \end{parts}
    \end{questions} 
    
\end{document}
14
  • When running your answer using lualatex, I get this error: Undefined control sequence. \tcb@startbox ...x }{\tcb@w@upper }\tcb@lua@color {tcbcolupper}\kvtcb@fontup... l.89 \end{minipage}}
    – Diaa
    Jan 28 at 2:04
  • 1
    I revised the solution. Jan 28 at 20:37
  • Would you please help me understand: (1) what \height and \depth mean inside the definition of footer; where did they come from? (2) what does this trick do {\stepcounter{page}\iflastpage{\enlargethispage{-1cm}}{}\addtocounter{page}{-1}? (3) what made the gap below the header disappeared in your code? or what made it show up in my code?
    – Diaa
    Jan 29 at 3:23
  • 1
    \baselineskip depends on the font size, which is different inside the \raisebox than outside. So I used \height+\depth instead. They are computed by \raisebox based on the contents. Unlike most document classes, exam class does not increment the page counter until after the text area is formatted (before the footer is added), so the value will not match \iflastpage. I set \headheight to precisely the value needed to fit the header (\headerbox), rather than attempting to make the header match \headheight. Jan 29 at 4:42
  • Thanks for the explanation. Also, why did you need to use minipage with the box? In other words, what makes the header has extra space below without minipage?
    – Diaa
    Jan 29 at 11: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.