Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flextable autofit in a Rmarkdown to word doc causes table to go outside page margins

Hi I am trying to use flextable in an Rmarkdown .doc document to format my tables. I like the simple formatting options that flextable gives (but open to other similar packages) but have found something that I thought should be a basic function doesn't always work.

I want to fit the table to the width of the word document so that if required text will wrap within a column to fit, but if there is free space available on the page columns will be made wider, but not to the extent that the column is so wide that not all data is shown.

I have made an example below to show my problem. By default all columns are the same width and text is wrapped to fit, but there is therefore space wasted. I want to fit columns to the data (using autofit) but this then makes the columns so wide they go off the screen. I'm hoping for a happy-medium with mpg, vs and carb wider but some text wrapping still happening. E.g. I want this:

Desired output

Obviously I can manually change widths using flextable::width but my table is made through an automated process so I don't know how wide I want each column to be.

Here is my example which shows the problems either with or eithout autofit

---
title: "TestTable"
output: word_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)


suppressWarnings(suppressPackageStartupMessages({library(knitr)
  library(pander)
  library(flextable)
  library(tidyverse)
library(flextable)}))
```

## Normal Table
Without extra formatting, wraps text so that it fits on the page, but there is no need for column widths to be equal and could be wider on the page

```{r, echo=FALSE, results = 'asis' }
mydata <- mtcars %>% head(3) %>% select(mpg, cyl, hp,vs, gear, carb) %>%
  mutate(mpg = paste0(mpg, "with extra stuff to make long"),
         vs = paste0(vs, "+ extra stuff"),
         carb = paste0(carb, "also with extra stuff to make longer"))

mytable <- mydata  %>% flextable(theme_fun = theme_box)

mytable

```
## Table With autofit  
But table with autofit goes off the edges of the page


```{r, echo=FALSE, results = 'asis' }

mytable %>% autofit()

```


## Table With autofit and manual breaks
And if manual breaks are inserted into the column autofit makes the columns too wide an they still go off the edges of the page

```{r, echo=FALSE, results = 'asis' }

mydataWithBreaks <- mtcars %>% head() %>% select(mpg, cyl, hp,vs, gear, carb) %>%
  mutate(mpg = paste0(mpg, "\nwith extra stuff\n to make long"),
         vs = paste0(vs, "+\n extra stuff"),
         carb = paste0(carb, "\nalso with extra stuff\n to make longer"))

mydataWithBreaks  %>% flextable(theme_fun = theme_box)%>% autofit()



```
like image 810
Sarah Avatar asked Jul 24 '19 04:07

Sarah


2 Answers

I have written a function to fit the table to the page which works well for now, although I'm still a bit surprised that there is no built in function to do this which would (for example) know the width of the page itself, so if any one knows any still keen to hear.

FitFlextableToPage <- function(ft, pgwidth = 6){

  ft_out <- ft %>% autofit()

  ft_out <- width(ft_out, width = dim(ft_out)$widths*pgwidth /(flextable_dim(ft_out)$widths))
  return(ft_out)
}
like image 89
Sarah Avatar answered Sep 18 '22 15:09

Sarah


FYI - I ran into this same problem today and used your code (thank you). But it still was bothering me because I couldn't get it quite right. I noticed on the Officedown package website (same author; https://github.com/davidgohel/officedown) they used set_table_properties(layout = "autofit") so I tried that. For whatever reason it worked as expected when doing that! I also was using officedown with default settings, so maybe the two worked well together.

like image 28
bumbledore Avatar answered Sep 16 '22 15:09

bumbledore