TL;DR
exams2nops()
does not support this and will not be extended in this direction because its focus is generating PDF exams for printing/scanning/etc.
exams2pdf()
can be customized to use different LaTeX templates and you can try to set up a suitable template using the {hyperref}
package.
- The support for the resulting PDF forms differs a lot between PDF viewers, typically with Acrobat Reader being the only one with decent support.
- My personal experience with the heterogeneity on students' systems plus sending solutions via e-mail is that this is not a very reliable solution but would be the source of a lot of problems. Personally, I would avoid going down this road.
- If your university hosts a Moodle system, I would recommend generating exams via
exams2moodle()
. At least the responsibility for the stability of the system is then with the university.
Details:
By using the {hyperref}
package you can use the {Form}
environment with commands like \CheckBox{}
, \TextEntry{}
, etc. A brief overview is given here: https://tex.stackexchange.com/questions/14842/creating-fillable-pdfs
A more elaborate worked example is available at: https://martin-thoma.com/creating-pdf-forms-with-latex/
Based on these I adapted the exam.tex
template provided within the R/exams package and set up a form.tex
template. The full LaTeX code is included below. This tries to do the following:
- Set up a form that can be submitted by e-mail when completed.
- The form consists of "fixed" fields for name and student ID.
- Then it sets up commands
\exnum
, \exstring
, exmchoice
etc. that can be used by exams2pdf()
. See Section 3 in vignette("exams", package = "exams")
for details. Thus, these commands are repeated as often as necessary for a given exam.
- At the end there are buttons to "Submit" or "Clear" the form.
For illustration, try:
exams2pdf(
c("deriv.Rmd", "swisscapital.Rmd", "boxplots.Rmd", "ttest.Rmd", "function.Rmd", "lm.Rmd"),
template = "form.tex"
)
where form.tex
from below needs to be in your current working directory.
The result is a form1.pdf
displayed automatically in your default PDF viewer (see options(pdfviewer = ...)
). Alternatively, you can also add an argument dir = "."
to store the file in your current working directory.
For me on Debian GNU/Linux with TeXLive this works and produces a PDF file that can be viewed and filled in using the Evince PDF viewer. However, neither "Submit" nor "Clear" works.
When I open the same file under Acrobat Reader in Windows 10, then only the TextEntry fields for Name/ID work, the others don't. The check boxes work but all checkboxes for (a) are linked, as are all (b), etc.
My impression is that composing the {Form}
on the fly like this does not work for Acrobat Reader. But I would appreciate pointers how this can be fixed. An alternative would be to exactly code the form you need for a specific exam with unique name
tags in all form elements etc.
Bonus note:
The template below also activates the {attachfile}
LaTeX package which can be used to embed files (e.g., data sets) into the PDF. This works for me but only under Acrobat Reader. To automatically convert all \url{}
commands (as created for the lm
exercise, used above) into \attachfile{}
commands, the development version of exams2pdf()
gained an argument attachfile = FALSE
which can be set to TRUE
. See this thread in the R/exams forum on R-Forge for more details:
https://R-Forge.R-project.org/forum/forum.php?thread_id=32091&forum_id=4377&group_id=1337
LaTeX template: form.tex
\documentclass[10pt,a4paper]{article}
%% packages
\usepackage[utf8]{inputenc}
\usepackage{a4wide,color,verbatim,Sweave,url,xargs,amsmath,booktabs,longtable,eurosym}
%%% %% optionally: two-column layout for exercise form
%%% \usepackage{multicol}
%% embed supplementary data files etc.
\usepackage{attachfile}
\attachfilesetup{color=0.5 0 0}
%% support PDF forms
\usepackage{hyperref}
%% new environments
\newenvironment{question}{\item}{}
\newenvironment{solution}{\comment}{\endcomment}
\newenvironment{answerlist}{\renewcommand{\labelenumi}{(\alph{enumi})}\begin{enumerate}}{\end{enumerate}}
%% paragraphs
\setlength{\parskip}{0.7ex plus0.1ex minus0.1ex}
\setlength{\parindent}{0em}
%% compatibility with pandoc
\providecommand{\tightlist}{\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\setkeys{Gin}{keepaspectratio}
%% fonts: Helvetica
\usepackage{helvet}
\IfFileExists{sfmath.sty}{
\RequirePackage[helvet]{sfmath}
}{}
\renewcommand{\sfdefault}{phv}
\renewcommand{\rmdefault}{phv}
\newcommandx{\exmchoice}[9][2=-,3=-,4=-,5=-,6=-,7=-,8=-,9=-]{%
\CheckBox[name=a, width=1em]{(a)}~~%
\if #2- \else \CheckBox[name=b, width=1em]{(b)}~~ \fi%
\if #3- \else \CheckBox[name=c, width=1em]{(c)}~~ \fi%
\if #4- \else \CheckBox[name=d, width=1em]{(d)}~~ \fi%
\if #5- \else \CheckBox[name=e, width=1em]{(e)}~~ \fi%
\if #6- \else \CheckBox[name=f, width=1em]{(f)}~~ \fi%
\if #7- \else \CheckBox[name=g, width=1em]{(g)}~~ \fi%
\if #8- \else \CheckBox[name=h, width=1em]{(h)}~~ \fi%
\if #9- \else \CheckBox[name=i, width=1em]{(i)}~~ \fi%
}
\newcommandx{\exclozechoice}[9][2=-,3=-,4=-,5=-,6=-,7=-,8=-,9=-]{\setcounter{enumiii}{1}%
\CheckBox[name=ca, width=1em]{\roman{enumiii}.} \stepcounter{enumiii}%
\if #2- \else \CheckBox[name=cb, width=1em]{\roman{enumiii}.} \stepcounter{enumiii} \fi%
\if #3- \else \CheckBox[name=cc, width=1em]{\roman{enumiii}.} \stepcounter{enumiii} \fi%
\if #4- \else \CheckBox[name=cd, width=1em]{\roman{enumiii}.} \stepcounter{enumiii} \fi%
\if #5- \else \CheckBox[name=ce, width=1em]{\roman{enumiii}.} \stepcounter{enumiii} \fi%
\if #6- \else \CheckBox[name=cf, width=1em]{\roman{enumiii}.} \stepcounter{enumiii} \fi%
\if #7- \else \CheckBox[name=cg, width=1em]{\roman{enumiii}.} \stepcounter{enumiii} \fi%
\if #8- \else \CheckBox[name=ch, width=1em]{\roman{enumiii}.} \stepcounter{enumiii} \fi%
\if #9- \else \CheckBox[name=ci, width=1em]{\roman{enumiii}.} \fi%
}
\newcommand{\exnum}[9]{\TextField[name=num, width=4cm]{}}
\newcommand{\exstring}[1]{\TextField[name=string, width=4cm]{}}
%% new commands
\makeatletter
\newcommand{\ID}[1]{\def\@ID{#1}}
\newcommand{\Date}[1]{\def\@Date{#1}}
\ID{00001}
\Date{YYYY-MM-DD}
%% \exinput{header}
\newcommand{\myID}{\@ID}
\newcommand{\myDate}{\@Date}
\makeatother
%% headings
\markboth{\textnormal{\bf \large Statistics Exam: \myID}}%
{\textnormal{\bf \large Statistics Exam: \myID}}
\pagestyle{myheadings}
\begin{document}
%% title page
\thispagestyle{empty}
{\sf
\textbf{\LARGE{R University}}
\textbf{\large{Statistics Exam \myDate \hfill Exam ID \myID}}
\vspace*{2cm}
\begin{Form}[action=mailto:info@example.com,encoding=html,method=post]
\begin{tabular}{ll}
\textbf{Name} & \TextField[name=Name, width=10cm]{}\\
\textbf{Student ID} & \TextField[name=ID, width=10cm]{}\\
\end{tabular}
\vspace*{1cm}
%%% \begin{multicols}{2}
%% \exinput{questionnaire}
%%% \end{multicols}
\Submit{Submit} ~~ \Reset{Clear}
\end{Form}
}
\newpage
\begin{enumerate}
%% \exinput{exercises}
\end{enumerate}
\end{document}