Consider the following mwe divided in 3 files:

main.tex:

\documentclass[12pt]{report}

\usepackage{subfiles}
\newcommand{\onlyinsubfile}[1]{#1}
\newcommand{\notinsubfile}[1]{}

\usepackage{amsmath}

\begin{document}

\renewcommand{\onlyinsubfile}[1]{}
\renewcommand{\notinsubfile}[1]{#1}

main:

\begin{equation}\label{eqn:main}
    1+1=2
\end{equation}

\subfile{subfile1}

\end{document}

subfile1.tex:

\documentclass[main.tex]{subfiles}

\onlyinsubfile{
    \usepackage{amsmath}
    \usepackage{xr}
    \externaldocument{main}
}

\begin{document}

Subfile1 

\begin{equation}
\label{eqn:a}
    a= b+c
\end{equation}

1: main ref: \ref{eqn:main}

\renewcommand{\onlyinsubfile}[1]{}
\renewcommand{\notinsubfile}[1]{#1}
\subfile{subfile2}

\end{document}

subfile2.tex:

\documentclass[main.tex]{subfiles}

\onlyinsubfile{
    \usepackage{amsmath}
    \usepackage{xr}

    \externaldocument{main} 
    \externaldocument{subfile1} 
}

\begin{document}

2: subfile ref: \ref{eqn:a}

2: main ref \ref{eqn:main}

\end{document}

If I typeset main.tex I get (as expected)

main.pdf

The problem is that, if I compile subfile1.tex (or subfile2.tex) separately the reference numberings clash and I get the following:

subfile1.pdf:

subfile1

subfile2.pdf:

subfile2

Is there a way to get the proper numberings? In my example I only have a couple of equations, but in general I may have theorems, definitions and other environments, so it would probably be very tedious to "manually" initialize every counter at the beginning of each subfile.

up vote 1 down vote accepted

You wish the same numbering both within the pdf-file that comes from compiling main.tex and in the pdf-files that come from compiling subfile1.tex / subfile2.tex?

If so, you need, when compiling subfile1.tex / subfile2.tex, to initialize the values of the counters to the values these counters have when compiling main.tex.

Solution 1:

For doing so, you can place labels and use a combination of the xr-package and Heiko Oberdiek's refcount-package.

You also may wish to have a mechanism for checking whether the reference in question is to be found in the same document or is to be found in the external main.pdf.

This might be especially useful when not using the xr-package but the hyperref-package and the xr-hyper-package as in this case you need to decide whether the hyperlink created by the reference has to go to the same document or to the external main.pdf.

In the example below, the mechanism is formed by \localorexternallabel: This macro as argument takes the name of a label. In case the label is defined, that label-name will be used. In case it is not defined, the phrase coming from the macro \labelprefix will be prepended to the label-name which implies referencing the label from the external (main) document.

main.tex

\documentclass[12pt]{report}
\usepackage{amsmath}
%%%%%
% Either:
%\usepackage{xr-hyper}
%\usepackage{hyperref}
% Or:
\usepackage{xr}
%%%%% 
\usepackage{refcount}
\usepackage{subfiles}
\newcommand{\onlyinsubfile}[1]{#1}
\newcommand{\notinsubfile}[1]{}
\newcommand\labelprefix{}
\newcommand\localorexternallabel[1]{%
  \expandafter\ifx\csname r@#1\endcsname\relax
    \labelprefix
  \fi #1%
}


\begin{document}

\renewcommand{\onlyinsubfile}[1]{}
\renewcommand{\notinsubfile}[1]{#1}

main:

\begin{equation}\label{eqn:main}
    1+1=2
\end{equation}

\subfile{subfile1}

\end{document}

subfile1.tex

\documentclass[main.tex]{subfiles}

\onlyinsubfile{%
    \csname @ifpackageloaded\endcsname{xr-hyper}{%
      \externaldocument[MAIN]{main}[main.pdf]% xr-hyper in use; optional argument for url of main.pdf for hyperlinks
    }{%
      \externaldocument[MAIN]{main}% xr in use
    }%
    \renewcommand\labelprefix{MAIN}%
    % Initialize the counters via the labels belonging to the main document:
    \setcounter{equation}{\numexpr\getrefnumber{\labelprefix eqn:a}-1\relax}%
}

\begin{document}

Subfile1 

\begin{equation}
\label{eqn:a}
    a= b+c
\end{equation}

1: main ref: \ref{\localorexternallabel{eqn:main}}

\renewcommand{\onlyinsubfile}[1]{}
\renewcommand{\notinsubfile}[1]{#1}
\subfile{subfile2}

\end{document}

subfile2.tex

\documentclass[main.tex]{subfiles}

\onlyinsubfile{%
    \csname @ifpackageloaded\endcsname{xr-hyper}{%
      \externaldocument[MAIN]{main}[main.pdf]% xr-hyper in use; optional argument for url of main.pdf for hyperlinks
    }{%
      \externaldocument[MAIN]{main}% xr in use
    }%
    \renewcommand\labelprefix{MAIN}%
    % Initialize the counters via the labels belonging to the main document:
    % - no counters used -
}

\begin{document}

2: subfile ref: \ref{\localorexternallabel{eqn:a}}

2: main ref \ref{\localorexternallabel{eqn:main}}

\end{document}

main.pdf

enter image description here

subfile1.pdf

enter image description here

subfile2.pdf

enter image description here

By the way: You might be interested in the \includeonly-feature of the LaTeX 2e-kernel.



Solution 2:

When compiling subfile1.tex / subfile2.tex, you need to initialize the values of the counters to the values these counters have when compiling main.tex.

For doing this, you can borrow code from the LaTeX 2e-kernel's \include-\includeonly-mechanism for writing the values of all counters defined via \newcounter into a referencing-label which is abused for performing many calls to \setcounter instead of just delivering some numbers.

I suggest abusing a referencing-label for this because referencing-labels can be imported via \externaldocument into sub-files.

I did this with the macro \MoveCountersToOrFromLabel:

When it is used while compiling main.tex it will write \setcounter-calls for all counter-values as a single referencing-label to the .aux-file.

When it is used while compiling a sub-file, it will retrieve the counter-values from the corresponding external label of main.aux.

As the collection of counter-values is saved by means of a referencing-label, that referencing-label needs to have a name. That name is the argument of \MoveCountersToOrFromLabel.

Besides this:

Instead of macros \onlyinsubfile / \notinsubfile, you can within the preamble use \@ifclassloaded for forking depending on whether the documentclass subfiles was loaded also, which is not the case when compiling main.tex.

main.tex

\documentclass[12pt]{report}
\usepackage{amsmath}

% Either:
\usepackage{xr-hyper}
\usepackage{hyperref}
% Or:
%\usepackage{xr}

\makeatletter
\@ifundefined{@car}{\newcommand\@car{}\long\def\@car#1#2\@nil{#1}}{}%
\newcommand\setdefinedcounter[2]{%
  \@ifundefined{c@#1}{\newcounter{#1}}{}%
  \setcounter{#1}{#2}%
}%
\@ifclassloaded{subfiles}{%
  % Obviously we are in a sub-file as only sub-files load the subfile-class.
  \@ifpackageloaded{xr-hyper}{%
    \externaldocument[MAIN]{main}[main.pdf]% xr-hyper in use; optional argument for url of main.pdf for hyperlinks
  }{%
    \externaldocument[MAIN]{main}% xr in use
  }%
  \newcommand\labelprefix{MAIN}%
  %    Define \MoveCountersToOrFromLabel to extract the referencing-label holding the
  %    counter-values. This label is imported from main.tex/main.aux, thus \labelprefix
  %    is needed. The macro underlying that label is \r@\labelprefix<label-name> and
  %    we need the first undelimited argument of its expansion. This we grab via \@car.
  \newcommand\MoveCountersToOrFromLabel[1]{%
    \@bsphack
    % There are counters like section@level that get defined via
    % some hook (like \AtBeginDocument) after the preamble, thus
    % check if still in preamble, and if so, apply the hook, too:
    \ifx\@onlypreamble\@notprerr
      \expandafter\@firstoftwo
    \else
       \expandafter\@secondoftwo
    \fi{\@firstofone}{\AtBeginDocument}%
    {%
      \@ifundefined{r@\labelprefix#1}{}{%
        \expandafter\expandafter\expandafter\@car\csname r@\labelprefix#1\endcsname\@nil
      }%
    }%
    \@esphack
  }%
}{%
  % Obviously we are in the main document as the main document does not load the subfile-class.
  \newcommand\labelprefix{}%
  %    Define \MoveCountersToOrFromLabel to write counter-values to referencing-label:
  \newcommand\MoveCountersToOrFromLabel[1]{%
    \@bsphack
    \if@filesw 
      \protected@write\@auxout{%
        \let\savedwrite\write
        \def\write{\immediate\savedwrite}%
        \def\@elt##1{%
          \string\protect
          \string\setdefinedcounter{##1}{\the\@nameuse{c@##1}}\@percentchar^^J%
        }%
      }{%
        \string\newlabel{#1}{{\@percentchar^^J\cl@@ckpt}{}{}{}{}}%
      }%
    \fi
    \@esphack
  }%
}%
% Check whether the label in question is available in the current document or whether it
% needs to be retrieved from the external main.pdf/main.aux:
\newcommand\localorexternallabel[1]{%
  \expandafter\ifx\csname r@#1\endcsname\relax
    \labelprefix
  \fi#1%
}%
\makeatother

\usepackage{subfiles}

\begin{document}

main:

\begin{equation}\label{eqn:main}
    1+1=2
\end{equation}

\subfile{subfile1}

\end{document}

subfile1.tex

\documentclass[main.tex]{subfiles}
\MoveCountersToOrFromLabel{subfile1}
\begin{document}

Subfile1 

\begin{equation}
\label{eqn:a}
    a= b+c
\end{equation}

1: main ref: \ref{\localorexternallabel{eqn:main}}

\subfile{subfile2}

\end{document}

subfile2.tex

\documentclass[main.tex]{subfiles}
\MoveCountersToOrFromLabel{subfile2}
\begin{document}

2: subfile ref: \ref{\localorexternallabel{eqn:a}}

2: main ref \ref{\localorexternallabel{eqn:main}}

\end{document}

main.pdf

enter image description here

subfile1.pdf

enter image description here

subfile2.pdf

enter image description here

  • Thank you very much, that's a nice solution! The downside is that I manually have to initialize every counter I'm going to use in every subfile...I was hoping for some trick to automagically take care of every counter. I know of \includeonly, I actually switched from includeonly to subfiles because includeonly forces you to specify which file you want to compile in the "main" file, and I found it a bit awkward at times. – Manlio Dec 8 at 22:01
  • I tested for a bit and it works perfectly! That's amazing, thank you very much! I honestly feel this should be included in the subfile package, maybe as an optional feature you can activate with a parameter. Do you think it may be cause any trouble to redefine \ref as \ref{\localorexternallabel{#1}} ? Or maybe it is better to just define a new \myref? – Manlio Dec 9 at 9:48
  • @Manlio Neither can I recommend redefining \ref as there are so many packages also doing their changes to that command (e.g., the hyperref-package turns \ref into a command both with a "starred" and a "non-starred" variant), nor can I recommend defining a command \myref as that might break syntax-highlighting and label-ref-management completely with many TeX input editors. – Ulrich Diez Dec 9 at 9:54
  • Thank you very much, I'm sorry I cannot upvote you more than once! If you're interested, I think you should consider dropping an email to the authors of the package to suggest this extension. I personally feel that having "coherent" numberings is not an extremely subjective need and there may be other people like me who have this need. – Manlio Dec 9 at 10:12
  • @Manlio I don't do this for the upvotes. :-) I do this because when I started using (La)TeX it frustrated me from time to time and therefore I nowadays from time to time wish to beat the machine. :-) Now you are one of the beta-testers of the extension. ;-) I hesitate turning the thing into a package/into an extension of the subfiles-mechanism because there are so many things left to be configured by the user, e.g., xr/xr-hyper and \externaldocument with the correct (optional) arguments and prefixes. Perhaps a section in the subfiles-package's manual about how to implement such things... – Ulrich Diez Dec 9 at 10:29

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.