flextable supports a wide range of output formats. When working inside R Markdown or Quarto, the correct format is selected automatically. For standalone scripts, use the dedicatedDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/davidgohel/flextable/llms.txt
Use this file to discover all available pages before exploring further.
save_as_* functions.
R Markdown and Quarto
Placing a flextable object in a code chunk is all that is required. Theknit_print.flextable() method handles format detection automatically:
```{r}
ft <- flextable(head(airquality)) |>
theme_vanilla() |>
autofit()
ft
```
| Output format | Rendered as |
|---|---|
HTML (html_document, Quarto HTML) | Native HTML table with scoped CSS |
Word (word_document, Quarto Word) | Office Open XML table |
PDF (pdf_document, Quarto PDF) | LaTeX longtable |
PowerPoint (powerpoint_presentation, Quarto PPTX) | Native PowerPoint table |
Other formats (e.g., github_document) | PNG image fallback |
Quarto chunk options
```{r}
#| label: tbl-summary
#| tbl-cap: "Airquality sample"
ft
In Quarto, use `tbl-cap` and `label` chunk options for captions and cross-references. The `set_caption()` function is less useful in Quarto because Quarto manages captions itself.
### R Markdown chunk options
```r
knitr::opts_chunk$set(
ft.align = "center", # table alignment: "left", "center", "right"
ft.split = TRUE # allow Word rows to break across pages
)
```
Common per-chunk options:
| Option | Format | Description |
|---|---|---|
| `ft.align` | All | Table alignment (`"left"`, `"center"`, `"right"`) |
| `ft.split` | Word | Allow rows to break across pages |
| `ft.htmlscroll` | HTML | Enable horizontal scrolling |
| `ft.tabcolsep` | PDF | Space between text and cell borders (pt) |
| `ft.arraystretch` | PDF | Row height multiplier (default 1.5) |
| `ft.latex.float` | PDF | Float placement (`"none"`, `"float"`, `"wrap-r"`, etc.) |
| `ft.left`, `ft.top` | PowerPoint | Table position in inches |
### Printing inside loops
When generating tables inside a `for` loop in R Markdown, use `flextable_to_rmd()` with `results='asis'`:
```r
# In a chunk with results='asis'
for (nm in names(split_data)) {
flextable_to_rmd(flextable(split_data[[nm]]))
}
```
## HTML
### Save to a standalone HTML file
```r
ft1 <- flextable(head(iris)) |> theme_vanilla() |> autofit()
tf <- tempfile(fileext = ".html")
save_as_html(ft1, path = tf)
```
Pass multiple tables as named arguments — names become section headings:
```r
save_as_html(
`Iris data` = ft1,
`Mtcars data` = ft2,
path = "tables.html",
title = "My Tables"
)
```
### Use in Shiny
`htmltools_value()` returns an `htmltools` tag object suitable for `shiny::renderUI()`:
```r
library(shiny)
library(flextable)
ui <- fluidPage(
uiOutput("table_out")
)
server <- function(input, output, session) {
output$table_out <- renderUI({
ft <- flextable(head(iris)) |> autofit()
htmltools_value(ft)
})
}
```
<Note>
HTML output uses Shadow DOM to isolate table styles from the host page. This prevents conflicts with existing CSS but means the table's styles are scoped to a shadow root.
</Note>
## Word (DOCX)
### Save to a standalone Word file
```r
library(officer)
ft <- flextable(head(iris)) |> theme_vanilla() |> autofit()
save_as_docx(ft, path = "my_table.docx")
```
Control page layout with `officer::prop_section()`:
```r
sect_properties <- prop_section(
page_size = page_size(orient = "landscape", width = 8.3, height = 11.7),
type = "continuous",
page_margins = page_mar()
)
save_as_docx(
`Iris data` = ft1,
`Mtcars data` = ft2,
path = "tables.docx",
pr_section = sect_properties
)
```
### Embed in an officer Word document
For full control — including captions, bookmarks, and document flow — use `officer` directly:
```r
library(officer)
doc <- read_docx() |>
body_add_par("Table 1: Iris sample", style = "heading 2") |>
body_add_flextable(ft, align = "center")
print(doc, target = "report.docx")
```
`body_add_flextable()` respects all `set_caption()` settings, including auto-numbering via `officer::run_autonum()`, paragraph styles, and caption position.
## PowerPoint (PPTX)
### Save to a standalone PowerPoint file
```r
ft1 <- flextable(head(iris))
tf <- tempfile(fileext = ".pptx")
save_as_pptx(ft1, path = tf)
```
Named arguments become slide titles:
```r
save_as_pptx(
`Iris table` = ft1,
`Mtcars table` = ft2,
path = tf
)
```
### Embed in an officer PowerPoint document
Use `officer::ph_with()` for precise placement:
```r
library(officer)
ft <- flextable(head(iris))
doc <- read_pptx() |>
add_slide("Title and Content", "Office Theme") |>
ph_with(ft, location = ph_location_left())
print(doc, target = "slides.pptx")
```
<Note>
PowerPoint only supports fixed table layout. Use `autofit()` to adjust column widths. Images inside table cells are not supported — this is a PowerPoint limitation. Captions are also ignored in PowerPoint output.
</Note>
## RTF
```r
library(officer)
ft <- flextable(head(iris)) |> theme_vanilla() |> autofit()
tf <- tempfile(fileext = ".rtf")
save_as_rtf(ft, path = tf)
```
Like `save_as_docx()`, pass a `prop_section` object to control page layout and add page headers:
```r
sect_properties <- prop_section(
page_size = page_size(orient = "landscape", width = 8.3, height = 11.7),
type = "continuous",
page_margins = page_mar(),
header_default = block_list(
fpar(ftext("text for default page header"))
)
)
tf <- tempfile(fileext = ".rtf")
save_as_rtf(
`Iris table` = ft1,
`Mtcars table` = ft2,
path = tf,
pr_section = sect_properties
)
```
## PDF and LaTeX
flextable generates LaTeX via knitr. No separate save function is needed — place a flextable in a code chunk in an R Markdown or Quarto document with PDF output:
#| ft.tabcolsep: 4
#| ft.arraystretch: 1.8
flextable(head(airquality)) |> theme_booktabs() |> autofit()
Required LaTeX packages are injected automatically: `multirow`, `multicol`, `colortbl`, `hhline`, `longtable`, `array`, and `hyperref`. System fonts require `xelatex` or `lualatex`:
```yaml
# In YAML header
pdf-engine: xelatex
```
### Caching
When chunk caching is enabled, call `add_latex_dep()` in a non-cached chunk to ensure LaTeX dependencies are registered:
```r
add_latex_dep()
```
<Note>
The following properties are not supported in PDF output: `padding.top`, `padding.bottom`, `line_spacing`, and row `height`. Justified text is converted to left-aligned.
</Note>
## Images (PNG and SVG)
`save_as_image()` exports a flextable as a PNG or SVG file using the R graphics system:
```r
library(gdtools)
register_liberationsans()
set_flextable_defaults(font.family = "Liberation Sans")
ft <- flextable(head(mtcars)) |> autofit()
tf <- tempfile(fileext = ".png")
save_as_image(x = ft, path = tf)
init_flextable_defaults()
```
For SVG output, install the `svglite` package and use a `.svg` path:
```r
tf <- tempfile(fileext = ".svg")
save_as_image(x = ft, path = tf)
```
<Note>
Captions are not included in image exports. Captions are designed for document outputs (Word, HTML, PDF) where the table is embedded in a document flow.
</Note>
## R grid graphics
`gen_grob()` converts a flextable to a `grid` graphics object (`grob`). This is the function behind `save_as_image()` and the patchwork integration.
```r
library(ragg)
library(gdtools)
register_liberationsans()
set_flextable_defaults(font.family = "Liberation Sans")
ft <- flextable(head(mtcars))
gr <- gen_grob(ft, fit = "fixed", just = "center")
plot(gr)
```
The `fit` argument controls how the grob adapts to its parent viewport:
| Value | Behavior |
|---|---|
| `"auto"` (default) | Resize proportionally to fill the viewport |
| `"width"` | Resize horizontally only; height is unchanged |
| `"fixed"` | Fixed dimensions from column widths and row heights |
### patchwork integration
`wrap_flextable()` wraps a flextable for use in a [patchwork](https://patchwork.data-imaginist.com/) layout alongside ggplot2 plots:
```r
library(ggplot2)
library(patchwork)
ft <- flextable(head(mtcars, 5)) |> autofit()
p <- ggplot(mtcars, aes(mpg, hp)) + geom_point()
wrap_flextable(ft, just = "left") + p
```
For aligned row/column layouts with a neighboring plot, use `flex_body = TRUE` or `flex_cols = TRUE`:
```r
wrap_flextable(ft, flex_body = TRUE) + p + plot_layout(widths = c(1, 2))
```
flextable objects can also be added directly to a patchwork composition with `+` — `ggplot_add.flextable` is registered automatically when both packages are loaded.
## Format comparison
<CardGroup cols={2}>
<Card title="HTML" icon="code">
`save_as_html()` or `htmltools_value()` for Shiny. Full CSS styling. Shadow DOM isolation.
</Card>
<Card title="Word" icon="file-word">
`save_as_docx()` or `body_add_flextable()` via officer. Full caption and pagination support.
</Card>
<Card title="PowerPoint" icon="presentation">
`save_as_pptx()` or `ph_with()` via officer. Fixed layout only. No captions.
</Card>
<Card title="RTF" icon="file">
`save_as_rtf()`. Similar to Word support. Page headers and footers supported.
</Card>
<Card title="PDF / LaTeX" icon="file-pdf">
Automatic via knitr. Requires `xelatex` for system fonts.
</Card>
<Card title="PNG / SVG" icon="image">
`save_as_image()`. No captions. Requires `ragg` (PNG) or `svglite` (SVG).
</Card>
</CardGroup>