1

So I have been using cross-references so far in Overleaf using this idea from StackExchange, which was adapted in Overleaf itself here. My question is, when I am finally combining main.tex and SI.tex in a single PDF file, how does that work? Or is it better to use the subfiles package?

I need a way in which to put these files in a single PDF and still have the cross-references work. Externally combining them will of course result in reference jump fail.

1
  • 1
    Overleaf have its own support team for its users, it's better to contact them...
    – MadyYuvi
    Oct 16, 2019 at 5:03

1 Answer 1

1

What exactly do you mean when talking about combining two .tex-files (i.e. TeX source codes for two documents) into a single .pdf-file? What workflow do you have in mind?
I ask because source-code and resulting .pdf-file are different things.

Be that as it may.

In case overleaf can also produce .dvi-files instead of .pdf-files and you can run the programs dviconcat and dvipdfm or dvipdfmx, concatenating documents and creating a .pdf-file might be feasible.

One problem one might encounter when concatenating files are the names of destinations for hyperlinks:

When creating all .pdf-files by means of LaTeX, using the hyperref-package, different .pdf-files may have named destinations of equal name. (The names of the destinations usually come from the names of LaTeX-counters and the values of these counters at the time of creating the destination in question.) Thus there is the need of taking steps for ensuring uniqueness of destination names for hyperlinks within that .pdf-file that comes into being as the result of concatenating.

As a means of ensuring uniqueness of destination-names, the hyperref-package nowadays has the \HyperDestNameFilter-feature.

\HyperDestNameFilter is explained in section 3.2 Options for destination names of the manual of the hyperref package.

Here is a quote from that section:

If the final PDF file is going to be merged with another file, then the destination names might clash, because both documents might contain chapter.1 or page.1. Also hyperref sets anchor with name Doc-Start at the begin of the document. This can be resolved by redefining \HyperDestNameFilter. Package hyperref calls this macro each time, it uses a destination name. The macro must be expandable and expects the destination name as only argument. As example, the macro is redefined to add a prefix to all destination names:

\renewcommand*{\HyperDestNameFilter}[1]{\jobname-#1}

In document docA the destination name chapter.2 becomes docA-chapter.2.

Another problem one might encounter when concatenating .pdf-files are cross-references between those files that get concatenated.

The only solution to this problem I found by now is not creating .pdf-files from the single .tex-documents but creating .dvi-files while having hyperref loaded with the dvipdfm- or dvipdfmx-driver-option.

Then you can concatenate the single .dvi-files, using the program dviconcat (dviconcat is part of many TeX distributions, e.g., texlive and MiKTeX), and afterwards convert the resulting .dvi-file to .pdf-file, using the dvipdfm-program or the dvipdfmx-program which also is part of many TeX distributions.

(I also tried the dvips-route but that did not work out.)

Instead of the xr-package you need to use the xr-hyper-package and when creating .dvi-files for concatenation you need to redefine \XR@@dURL to take the \HyperDestNameFilter-prefix into account and to disregard \XR@URL (which holds the url of the external file) for those external documents that are to be concatenated with the current document.

In the examples below

  • all documents to be concatenated must use a \HyperDestNameFilter-prefix.
  • no two documents may have the same \HyperDestNameFilter-prefix.
  • it is assumed that all files that are to be concatenated use different \HyperDestNameFilter-prefixes which have in common that they all contain the phrase MyDocument while no destination-name itself may contain that phrase.
    Thus the presence/absence of the phrase MyDocument within the name of a destination is taken as an indicator by the macro \HyperDestNameFilter for deciding whether a \HyperDestNameFilter-prefix needs to be attached or not:
  • \HyperDestNameFilter is (re)defined to attach a prefix only in case the name of the destination neither contains the phrase MyDocument nor contains the token \empty.
  • additional infrastructure is provided for xr-hyper's command \externaldocument:
    1. The command \SetNextExternalFilesHyperDestNameFilterPrefix{...} is to be used for specifying the \HyperDestNameFilter-prefix that was in use when creating the external document in question. (In case no \HyperDestNameFilter-prefix was in use, you can specify \SetNextExternalFilesHyperDestNameFilterPrefix{\empty}.)
    2. The commands \UseURL and \DoNotUseURL. These commands are to be used for specifying whether \externaldocument shall/shall not take URLs to .pdf-files containing external documents into account. (In case the URL deviates from \externaldocument's first non-optional argument + .pdf/filename-extension, the URL can be specified in \externaldocument's last optional argument.)
      URLs shall not be taken into account with external documents that are to be concatenated with the current document.
      URLs shall be taken into account with external documents that are not to be concatenated with the current document. (As URL specify the URL of the .pdf-file which contains the external document in question.)
  • \XR@@dURL is redefined
    • to be capable of disregarding the url where the .pdf-file containing the external document in question can be found:
      Urls are disregarded in case the \externaldocument-command in question is preceded by \DoNotUseURL.
      Urls are not disregarded in case the \externaldocument-command in question is preceded by \UseURL.
    • to attach to the argument #4 (that argument denotes the name of the named destination connected to the external referencing-label in question) the \HyperDestNameFilter-prefix which was used with the external document in question.
  • each \externaldocument-command for importing referencing-data of an external document that is to be concatenated with the current document must go along with a command \SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument...} and with a command \DoNotUseURL.
  • each \externaldocument-command for importing referencing-data of an external document that is not to be concatenated with the current document must go along with a command \SetNextExternalFilesHyperDestNameFilterPrefix{...} for providing information about the \HyperDestNameFilter-prefix that was in use when creating the external document in question and with a command \UseURL. In case a HyperDestNameFilter-Prefix was not in use when creating such a file, you can specify \SetNextExternalFilesHyperDestNameFilterPrefix{\empty}.

The examples below are to form a scenario with three documents.

The title of the first document is "My Document 1".
The file containing the source code of the first document is MyDocument1.tex.

The title of the second document is "My Document 2".
The file containing the source code of the second document is MyDocument2.tex.

The title of the third document is "My Document 3".
The file containing the source code of the third document is MyDocument3.tex.

The documents "My Document 1" and "My Document 2" will end up in the .pdf-file MyDocument1and2.pdf.

The document "My Document 3" will remain separate and end up in the .pdf-file MyDocument3.pdf.

Compiling/concatenating-instructions:

Have MyPatches.tex and MyDocument1.tex, MyDocument2.tex and MyDocument3.tex in the same directory.

Make that directory the active directory/current directory/whatsoever.

Alternatingly compile MyDocument1.tex, MyDocument2.tex, MyDocument3.tex using latex until both MyDocument1.dvi and MyDocument2.dvi and MyDocument3.dvi exist in that directory and MyDocument1.log and MyDocument2.log and MyDocument3.log neither contain requests to run latex again nor contain warnings about undefined references.

Call the program dviconcat for concatenating MyDocument1.dvi and MyDocument2.dvi into MyDocument1and2.dvi:
dviconcat -o MyDocument1and2.dvi MyDocument1.dvi MyDocument2.dvi

Call dvipdfmx for converting MyDocument1and2.dvi to MyDocument1and2.pdf:
dvipdfmx MyDocument1and2.dvi

Call dvipdfmx for converting MyDocument3.dvi to MyDocument3.pdf:
dvipdfmx MyDocument3.dvi

If everything worked out,

  • MyDocument1and2.pdf should consist of the content of "My Document 1" and "My Document 2". Cross-references within MyDocument1and2.pdf between "My Document 1" and "My Document 2" should cause navigation within MyDocument1and2.pdf. Cross-references within MyDocument1and2.pdf to "My Document 3" should cause opening and showing and scrolling within MyDocument3.pdf.
  • MyDocument3.pdf should consist of the content of "My Document 3". Cross-references within MyDocument3.pdf to "My Document 1" or "My Document 2" should cause loading and showing and scrolling within MyDocument1and2.pdf.

MyPatches.tex

%%====================================================================
%% Fixes for hyperref-drivers xetex and dvipdfm/dvipdfmx - apply them
%% _after_ loading the hyperref package:
%%====================================================================
\begingroup
\def\tempa{hxetex}%
\ifx\Hy@driver\tempa\expandafter\@secondoftwo\else\expandafter\@firstofone\fi
{%
  \def\tempa{hdvipdfm}%
  \ifx\Hy@driver\tempa\expandafter\@firstofone\else\expandafter\endgroup\expandafter\@gobble\fi
}{%
  \endgroup
  %%--------------------------------------------------------------------
  %% Fix hxetex's and hdvipdfm's  \hyper@linkfile  by adding a group for
  %% preventing erroneous warnings
  %%
  %%  Package hyperref Warning: Invalid page number (0)
  %%  (hyperref)                for remote PDF file.
  %%  (hyperref)                Using page 1 on input line ...
  %%
  %% For more information see:
  %%  <https://github.com/latex3/hyperref/issues/107#issue-513025725>
  %%--------------------------------------------------------------------
  \def\hyper@linkfile#1#2#3{%
    \begingroup % <--- \begingroup inserted
    \leavevmode
    \Hy@BeginAnnot{%
      \def\Hy@pstringF{#2}%
      \Hy@CleanupFile\Hy@pstringF
      \Hy@pstringdef\Hy@pstringF\Hy@pstringF
      \Hy@pstringdef\Hy@pstringD{#3}%
      \Hy@MakeRemoteAction %<-- Without the group the effects of \Hy@MakeRemoteAction 
                           %    will be global, causing erroneous warnings.
      \@pdfm@mark{%
        bann<<%
          /Type/Annot%
          /Subtype/Link%
          \ifHy@pdfa /F 4\fi
          \Hy@setpdfborder
          \Hy@setpdfhighlight
          \ifx\@filebordercolor\relax
          \else
            /C[\@filebordercolor]%
          \fi
          /A<<%
            /S/GoToR%
            /F(\Hy@pstringF)%
            /D%
            \ifx\\#3\\%
              [\Hy@href@page\@pdfremotestartview]%
            \else
              (\Hy@pstringD)%
            \fi
            \Hy@SetNewWindow
            \Hy@href@nextactionraw
          >>%
        >>%
      }%
      \Hy@colorlink\@filecolor
    }%
    #1\Hy@xspace@end
    \Hy@EndAnnot
    \endgroup % <--- \endgroup inserted
  }%
  %%--------------------------------------------------------------------
  %% Add special for making named destinations reachable from "outside":
  %% For more information see:
  %%  <https://tug.org/pipermail/dvipdfmx/2019-May/000003.html>
  %%--------------------------------------------------------------------
  \special{dvipdfmx:config C 0x10}%
}%
%%=============================================================================
%% Additional infrastructure for xr-hyper's \externaldocument so you can
%% specify 
%% - external files' \HyperDestNameFilter-pefix
%% - whether URLs of external files shall be used or not be used.
%%   (They shall not be used when dvi-files get concatenated via dviconcat
%%    before converting to pdf.)
%%=============================================================================
%%-----------------------------------------------------------------------------
%% Fork whether argument contains the phrase "MyDocument"
%%.............................................................................
\@ifdefinable\UD@GobbleToMyDocument{\long\def\UD@GobbleToMyDocument#1MyDocument{}}%
\newcommand\UD@CheckWhetherNoMyDocument[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToMyDocument#1MyDocument}%
}%
%%-----------------------------------------------------------------------------
%% Fork whether argument contains the token "\empty"
%%.............................................................................
\@ifdefinable\UD@GobbleToEmpty{\long\def\UD@GobbleToEmpty#1\empty{}}%
\newcommand\UD@CheckWhetherNoEmpty[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToEmpty#1\empty}%
}%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%--------------------------------------------------------------------
%% A place-holder for external files'  \HyperDestNameFilter-pefix
%%.............................................................................
\newcommand\NextExternalFilesHyperDestNameFilterPrefix{}%
%%-----------------------------------------------------------------------------
%% Set external files'  \HyperDestNameFilter-pefix
%%.............................................................................
\newcommand\SetNextExternalFilesHyperDestNameFilterPrefix[1]{%
 \renewcommand\NextExternalFilesHyperDestNameFilterPrefix{#1}%
}%
%%-----------------------------------------------------------------------------
%% Take into account URL of external file/
%% don't take into account URL of external file.
%%.............................................................................
\newcommand\UseURL{\global\DontUseURLfalse}%
\newcommand\DoNotUseURL{\global\DontUseURLtrue}%
\newif\ifDontUseURL
%%-----------------------------------------------------------------------------
%% Change \XR@@dURL to take the \HyperDestNameFilter-prefix of the external file
%% into account and to omit \XR@URL
%%-----------------------------------------------------------------------------
\def\XR@@dURL#1#2#3#4#5\\{%
  {#1}{#2}%
  \if!#4!%
  \else
    {#3}{\NextExternalFilesHyperDestNameFilterPrefix#4}%
    \ifDontUseURL{}\else{\XR@URL}\fi
  \fi
}%

MyDocument1.tex

\documentclass{article}

\usepackage{xr-hyper}
\usepackage[dvipdfmx]{hyperref}

\makeatletter
\input MyPatches.tex
%%-----------------------------------------------------------------------------
%% Change \HyperDestNameFilter to add the prefix "MyDocument1-" in case the name
%% of the destination doses not already contain the phrase "MyDocument" or the 
%% token "\empty":
%%
%% !!!! The \HyperDestNameFilter-prefix varies from file to file/
%% !!!! from document to document
%%.............................................................................
\renewcommand*{\HyperDestNameFilter}[1]{%
  \UD@CheckWhetherNoEmpty{#1}{\UD@CheckWhetherNoMyDocument{#1}{MyDocument1-}{}}{}#1%
}%
%%-----------------------------------------------------------------------------
\makeatother

\DoNotUseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument2-}%
\externaldocument[MyDocument2-]{MyDocument2}[MyDocument1and2.pdf]%

\UseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument3-}%
\externaldocument[MyDocument3-]{MyDocument3}%


\begin{document}

\title{My Document 1}
\author{Me, Myself and I}    
\maketitle
\newpage

\section{First section of My Document 1}
\label{LabelInMyDocument1}

\noindent
The source code of \textbf{My Document 1} is contained in \textbf{MyDocument1.tex.}\\
The source code of section \textbf{First section of My Document 1} contains
the referencing-label \textbf{LabelInMyDocument1}.\\
The target-file of \textbf{My Document 1} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 2} is contained in \textbf{MyDocument2.tex.}\\
The source code of section \textbf{First section of My Document 2} contains
the referencing-label \textbf{LabelInMyDocument2}.\\
The target-file of \textbf{My Document 2} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 3} is contained in \textbf{MyDocument3.tex.}\\
The source code of section \textbf{First section of My Document 3} contains
the referencing-label \textbf{LabelInMyDocument3}.\\
The target-file of \textbf{My Document 3} will be \textbf{MyDocument3.pdf}.\\


\bigskip\noindent
\textbf{Referencing}

\bigskip\noindent
\verb|\ref{LabelInMyDocument1}| yields:\ref{LabelInMyDocument1}\\
\verb|\pageref{LabelInMyDocument1}| yields:\pageref{LabelInMyDocument1}\\
\verb|\ref{MyDocument2-LabelInMyDocument2}| yields:\ref{MyDocument2-LabelInMyDocument2}\\
\verb|\pageref{MyDocument2-LabelInMyDocument2}| yields:\pageref{MyDocument2-LabelInMyDocument2}\\
\verb|\ref{MyDocument3-LabelInMyDocument3}| yields:\ref{MyDocument3-LabelInMyDocument3}\\
\verb|\pageref{MyDocument3-LabelInMyDocument3}| yields:\pageref{MyDocument3-LabelInMyDocument3}\\

\end{document}

MyDocument2.tex

\documentclass{article}

\usepackage{xr-hyper}
\usepackage[dvipdfmx]{hyperref}

\makeatletter
\input MyPatches.tex
%%-----------------------------------------------------------------------------
%% Change \HyperDestNameFilter to add the prefix "MyDocument2-" in case the name
%% of the destination doses not already contain the phrase "MyDocument" or the 
%% token "\empty":
%%
%% !!!! The \HyperDestNameFilter-prefix varies from file to file/
%% !!!! from document to document
%%.............................................................................
\renewcommand*{\HyperDestNameFilter}[1]{%
  \UD@CheckWhetherNoEmpty{#1}{\UD@CheckWhetherNoMyDocument{#1}{MyDocument2-}{}}{}#1%
}%
%%-----------------------------------------------------------------------------
\makeatother

\DoNotUseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument1-}%
\externaldocument[MyDocument1-]{MyDocument1}[MyDocument1and2.pdf]%

\UseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument3-}%
\externaldocument[MyDocument3-]{MyDocument3}%


\begin{document}

\title{My Document 2}
\author{Me, Myself and I}    
\maketitle
\newpage

\section{First section of My Document 2}
\label{LabelInMyDocument2}

\noindent
The source code of \textbf{My Document 1} is contained in \textbf{MyDocument1.tex.}\\
The source code of section \textbf{First section of My Document 1} contains
the referencing-label \textbf{LabelInMyDocument1}.\\
The target-file of \textbf{My Document 1} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 2} is contained in \textbf{MyDocument2.tex.}\\
The source code of section \textbf{First section of My Document 2} contains
the referencing-label \textbf{LabelInMyDocument2}.\\
The target-file of \textbf{My Document 2} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 3} is contained in \textbf{MyDocument3.tex.}\\
The source code of section \textbf{First section of My Document 3} contains
the referencing-label \textbf{LabelInMyDocument3}.\\
The target-file of \textbf{My Document 3} will be \textbf{MyDocument3.pdf}.\\


\bigskip\noindent
\textbf{Referencing}

\bigskip\noindent
\verb|\ref{MyDocument1-LabelInMyDocument1}| yields:\ref{MyDocument1-LabelInMyDocument1}\\
\verb|\pageref{MyDocument1-LabelInMyDocument1}| yields:\pageref{MyDocument1-LabelInMyDocument1}\\
\verb|\ref{LabelInMyDocument2}| yields:\ref{LabelInMyDocument2}\\
\verb|\pageref{LabelInMyDocument2}| yields:\pageref{LabelInMyDocument2}\\
\verb|\ref{MyDocument3-LabelInMyDocument3}| yields:\ref{MyDocument3-LabelInMyDocument3}\\
\verb|\pageref{MyDocument3-LabelInMyDocument3}| yields:\pageref{MyDocument3-LabelInMyDocument3}\\

\end{document}

MyDocument3.tex

\documentclass{article}

\usepackage{xr-hyper}
\usepackage[dvipdfmx]{hyperref}

\makeatletter
\input MyPatches.tex
%%-----------------------------------------------------------------------------
%% Change \HyperDestNameFilter to add the prefix "MyDocument3-" in case the name
%% of the destination doses not already contain the phrase "MyDocument" or the 
%% token "\empty":
%%
%% !!!! The \HyperDestNameFilter-prefix varies from file to file/
%% !!!! from document to document
%%.............................................................................
\renewcommand*{\HyperDestNameFilter}[1]{%
  \UD@CheckWhetherNoEmpty{#1}{\UD@CheckWhetherNoMyDocument{#1}{MyDocument3-}{}}{}#1%
}%
%%-----------------------------------------------------------------------------
\makeatother

\UseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument1-}%
\externaldocument[MyDocument1-]{MyDocument1}[MyDocument1and2.pdf]%

\UseURL
\SetNextExternalFilesHyperDestNameFilterPrefix{MyDocument2-}%
\externaldocument[MyDocument2-]{MyDocument2}[MyDocument1and2.pdf]%


\begin{document}

\title{My Document 3}
\author{Me, Myself and I}    
\maketitle
\newpage

\section{First section of My Document 3}
\label{LabelInMyDocument3}

\noindent
The source code of \textbf{My Document 1} is contained in \textbf{MyDocument1.tex.}\\
The source code of section \textbf{First section of My Document 1} contains
the referencing-label \textbf{LabelInMyDocument1}.\\
The target-file of \textbf{My Document 1} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 2} is contained in \textbf{MyDocument2.tex.}\\
The source code of section \textbf{First section of My Document 2} contains
the referencing-label \textbf{LabelInMyDocument2}.\\
The target-file of \textbf{My Document 2} will be \textbf{MyDocument1and2.pdf}.\\

\bigskip\noindent
The source code of \textbf{My Document 3} is contained in \textbf{MyDocument3.tex.}\\
The source code of section \textbf{First section of My Document 3} contains
the referencing-label \textbf{LabelInMyDocument3}.\\
The target-file of \textbf{My Document 3} will be \textbf{MyDocument3.pdf}.\\


\bigskip\noindent
\textbf{Referencing}

\bigskip\noindent
\verb|\ref{MyDocument1-LabelInMyDocument1}| yields:\ref{MyDocument1-LabelInMyDocument1}\\
\verb|\pageref{MyDocument1-LabelInMyDocument1}| yields:\pageref{MyDocument1-LabelInMyDocument1}\\
\verb|\ref{MyDocument2-LabelInMyDocument2}| yields:\ref{MyDocument2-LabelInMyDocument2}\\
\verb|\pageref{MyDocument2-LabelInMyDocument2}| yields:\pageref{MyDocument2-LabelInMyDocument2}\\
\verb|\ref{LabelInMyDocument3}| yields:\ref{LabelInMyDocument3}\\
\verb|\pageref{LabelInMyDocument3}| yields:\pageref{LabelInMyDocument3}\\

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .