Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Table and Figure cross-reference officer R

I would like to be able to cross-reference a table or figure in a word document using the officer R package.

I have come across these materials so far but they do not seem to have a solution: https://davidgohel.github.io/officer/articles/word.html#table-and-image-captions and a similar question add caption to flextable in docx

In both of these I can only insert a caption as a level 2 header and not a true table caption.

What I want to be able to do in Word is Insert -> Cross-reference and go to Reference type: Table and see my caption there. Right now I can only see the caption under Numbered item.

Does this functionality exist in officer or anywhere else?

like image 959
Jordan Hackett Avatar asked Sep 20 '18 19:09

Jordan Hackett


2 Answers

In word, the table numbers use the { SEQ \\@ arabic } pattern, but references to them use { REF bookmark \h }. We can use this to make new code which can reference a SEQ field.

code:

ft <- regulartable(head(iris)) # create flextable
str <- paste0(' REF ft \\h ')  # create string to be used as reference to future bookmark

doc <- read_docx() %>%
  body_add_par('This is my caption' , style = 'Normal') %>% # add caption
  slip_in_seqfield(str = "SEQ Table \\@ arabic",           
                   style = 'Default Paragraph Font', 
                   pos = "before") %>% # add number for table
  body_bookmark('ft') %>%   # add bookmark on the number
  slip_in_text("Table ", 
               style = 'Default Paragraph Font', 
               pos = "before") %>% # add the word 'table'
  body_add_flextable(value = ft, align = 'left') %>% # add flextable
  body_add_break() %>%  # insert a break (optional)
  slip_in_text('As you can see in Table', 
               style = 'Default Paragraph Font', 
               pos = 'after') %>% # add the text you want before the table reference
  slip_in_seqfield(str = str,  
                   style = 'Default Paragraph Font', 
                   pos = 'after') %>% # add the reference to the table you just added
  slip_in_text(', there are a lot of iris flowers.', 
               style = 'Default Paragraph Font', 
               pos = 'after') %>% # add the rest of the text 
  print('Iris_test.docx') # print

Hope this helps :)

like image 86
morgan121 Avatar answered Oct 05 '22 15:10

morgan121


Just for the record, you can do this a bit easier now by using some helper functions from the {crosstable} package.

Disclaimer: I am the developer of that package and these functions were highly inspired by @morgan121's answer. Thanks Morgan!

Here is an example:

library(officer)
library(crosstable)
library(ggplot2)
options(crosstable_units="cm")

ft = regulartable(head(iris)) 
my_plot = ggplot(data = iris ) +
  geom_point(mapping = aes(Sepal.Length, Petal.Length))

doc = read_docx() %>% 
  body_add_title("Dataset iris", 1) %>%
  body_add_normal("Table \\@ref(table_iris) displays the 6 first rows of the iris dataset.") %>%
  body_add_flextable(ft) %>%
  body_add_table_legend("Iris head", bookmark="table_iris") %>%
  body_add_normal("Let's add a figure as well. You can see in Figure \\@ref(fig_iris) that sepal length is somehow correlated with petal length.") %>%
  body_add_figure_legend("Relation between Petal length and Sepal length", bookmark="fig_iris") %>% 
  body_add_gg2(my_plot, w=14, h=10, scale=1.5)

print(doc , 'Iris_test.docx')    

More info on https://danchaltiel.github.io/crosstable/articles/crosstable-report.html.

As with morgan121's code, you have to select all the text in MS Word and press F9 twice for the numbers to update properly.

like image 27
Dan Chaltiel Avatar answered Oct 05 '22 15:10

Dan Chaltiel