I am using flextable to produce tables for a pdf document rendered with rmarkdwown. I want to cross-reference the tables, but they do not produce the label needed for the cross reference to work.
My Minimum Reproducible Example
What follows is the content of the file test.Rmd:
---
title: "document title"
author: "author here"
date: "2022-01-20"
output:
pdf_document:
fig_caption: yes
includes:
in_header: header.tex
number_sections: yes
toc: yes
toc_depth: 4
latex_engine: xelatex
keep_tex: true
---
```{r, include = FALSE}
library(flextable)
library(bookdown)
opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, out.width = "85%", fig.align = "center")
```
```{r, tab.id = "anyTable", tab.cap = "Invented data", tab.lp = "tab:"}
a = data.frame(id = LETTERS[1:3], x = 1:3)
flextable(a) |> theme_vanilla()
```
```{r secondTable}
b = data.frame(id = LETTERS[4:6], x = 4:6)
flextable(b) |> theme_vanilla() |> set_caption(caption = "This is secondTable")
```
# Standard rmarkdown crossreference
Trying anyTable: \ref{tab:anyTable}.
Trying secondTable: \ref{tab:secondTable}.
# Bookdown crossreference
Trying anyTable: \@ref(tab:anyTable).
Trying secondTable: \@ref(tab:secondTable).
Contents of header.tex:
\usepackage{caption}
\renewcommand{\contentsname}{Contenidos}
\captionsetup[table]{name=Tabla}
\captionsetup[figure]{name=Figura}
%\usepackage{float} #use the 'float' package
%\floatplacement{figure}{H}
\usepackage{fancyhdr}
\pagestyle{fancy}
\usepackage{xcolor}
\usepackage{multicol}
\usepackage{pdflscape}
\newcommand{\blandscape}{\begin{landscape}}
\newcommand{\elandscape}{\end{landscape}}
When I do rmarkdown::render("test.Rmd", output_file = "test.pdf") the file is rendered in pdf, but the following warning comes out:
Output created: test.pdf
Warning message:
LaTeX Warning: Reference `tab:anyTable' on page 1 undefined on input line 198.
LaTeX Warning: Reference `tab:secondTable' on page 1 undefined on input line 20
0.
LaTeX Warning: There were undefined references.
If I check the .tex file, I can see that the captions are there, but they do not have the labels. The relevant lines of the intermediate test.tex file:
lines 106 to 109
\begin{longtable}[c]{|p{0.75in}|p{0.75in}}
\caption{Invented data
}\\
lines 153 to 156
\begin{longtable}[c]{|p{0.75in}|p{0.75in}}
\caption{This is secondTable
}\\
I expected that the caption line in the tex file was something like \caption{This is secondTable}\label{tab:secondTable}\\
What I’ve tried
- Changing latex engines (lualatex, pdflatex, xelatex).
- Editing the tex file (adding the label after the caption), but it fails to convert to dvi with multiple errors (mostly "undefined control sequence")
What am I doing wrong?
How can I cross-reference the tables produced by flextable?
Alternatively, I am open to other packages you may suggest. As some of the headers in my real data are somewhat complex (multi-span headers and the like), I would like to steer away from kable and kableExtra if at all possible.
>Solution :
You need to use a format from bookdown to get cross references, see https://bookdown.org/yihui/rmarkdown-cookbook/cross-ref.html
---
title: "document title"
author: "author here"
date: "2022-01-20"
output:
bookdown::pdf_document2:
fig_caption: yes
number_sections: yes
toc: yes
toc_depth: 4
latex_engine: xelatex
keep_tex: true
---
```{r, include = FALSE}
library(flextable)
library(knitr)
library(bookdown)
opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, out.width = "85%", fig.align = "center")
```
```{r, tab.id = "anyTable", tab.cap = "Invented data"}
a = data.frame(id = LETTERS[1:3], x = 1:3)
flextable(a) |> theme_vanilla()
```
```{r secondTable}
b = data.frame(id = LETTERS[4:6], x = 4:6)
flextable(b) |> theme_vanilla() |> set_caption(caption = "This is secondTable")
```
# Bookdown crossreference
Trying anyTable: \@ref(tab:anyTable).
Trying secondTable: \@ref(tab:secondTable).
