The natural complement to import_xlsx(). Accepts either a combined
data.frame (as produced by import_xlsx() with
combine = TRUE) or a list of data.frames, and writes the result
to disk.
The output destination is controlled by a single path
argument – there are no separate modes to choose:
path ends in .xlsx – write
everything into a single workbook: one sheet per list
element, or (for data.frame input) one sheet per
file_col / sheet_col value.
path is anything else – treat it as a
directory and write one .xlsx file per list
element or per file_col value. For data.frame
input that also has a sheet_col column, each file contains
one sheet per sheet_col value, which reproduces the
original file/sheet layout read by import_xlsx().
res <- list(res1 = data1, res2 = data2, res3 = data3)
# Directory mode -- writes res1.xlsx, res2.xlsx, res3.xlsx
export_xlsx(res, path = "output/")
# Single-file mode -- one workbook with sheets res1, res2, res3
export_xlsx(res, path = "output/all.xlsx")Each element must be a data.frame, data.table, or
tibble; types may be mixed and column sets may differ. Missing
names are filled in as Sheet1, Sheet2, ...; supplied names
must be unique.
export_xlsx(
data,
path,
file_col = "excel_name",
sheet_col = "sheet_name",
sheet_name = "Sheet1",
drop_cols = TRUE,
overwrite = TRUE,
verbose = FALSE
)A data.frame / data.table / tibble,
or a list of such objects. For list input,
names become file names (directory mode) or sheet names
(single-file mode).
character(1). Output destination. A path ending
in .xlsx (case-insensitive) is a
single workbook; anything else is an
output directory. Missing directories are
created recursively.
character(1). Column identifying the source file
(data.frame input only). Default
"excel_name".
character(1). Column identifying the source sheet
(data.frame input only). Default
"sheet_name".
character(1). Sheet name used when a
data.frame has neither tracking column.
Default "Sheet1".
logical(1). If TRUE (default), the
tracking columns are removed from the exported sheets
(data.frame input only).
logical(1). Allow overwriting existing files.
When FALSE, all targets are checked
before anything is written, so a failure never
leaves a partial export behind. Default TRUE.
logical(1). Print a message for every file and
sheet written. Default FALSE.
Invisibly, a named character vector of written file paths.
In directory mode it is named by list element / file_col value;
in single-workbook mode it is named by path.
writexl writes .xlsx via a minimal C library with no Java or
Perl dependency. It is fast and produces small files, at the cost of no
cell formatting, formulas, or styles. For those, use openxlsx2.
Sheet names are limited to 31 characters, may not contain
[ ] * ? / \ :, and may not start or end with an apostrophe.
File names have characters that are invalid on Windows replaced by
_. If sanitising or truncating makes two names collide
(Excel compares sheet names case-insensitively), suffixes such as
_2, _3 are appended.
# Example 1: A plain data.frame -> one workbook, one sheet
out_file <- file.path(tempdir(), "mtcars.xlsx")
export_xlsx(mtcars, path = out_file, sheet_name = "mtcars")
invisible(file.remove(out_file))
# Example 2: data.table input works exactly the same way
out_file <- file.path(tempdir(), "mtcars_dt.xlsx")
export_xlsx(data.table::as.data.table(mtcars),
path = out_file, sheet_name = "mtcars")
invisible(file.remove(out_file))
# Example 3: One sheet per group in a single workbook
# Each Species value becomes a sheet; keep the Species column
out_file <- file.path(tempdir(), "iris_by_species.xlsx")
export_xlsx(iris, path = out_file, file_col = "Species", drop_cols = FALSE)
invisible(file.remove(out_file))
# Example 4: One file per group (directory mode: no .xlsx extension)
out_dir <- file.path(tempdir(), "iris_by_species")
out_files <- export_xlsx(iris, path = out_dir, file_col = "Species")
basename(out_files)
#> [1] "setosa.xlsx" "versicolor.xlsx" "virginica.xlsx"
unlink(out_dir, recursive = TRUE)
# Example 5: Round-trip the layout produced by import_xlsx(combine = TRUE)
# Rows are routed back to their original file and sheet
combined <- data.frame(
excel_name = c("sales", "sales", "costs"),
sheet_name = c("2024", "2025", "2024"),
amount = c(100, 120, 80)
)
out_dir <- file.path(tempdir(), "roundtrip")
out_files <- export_xlsx(combined, path = out_dir) # sales.xlsx, costs.xlsx
basename(out_files)
#> [1] "sales.xlsx" "costs.xlsx"
unlink(out_dir, recursive = TRUE)
# Example 6: Named list -> single workbook, one sheet per element
out_file <- file.path(tempdir(), "combined.xlsx")
res <- list(res1 = iris, res2 = mtcars)
export_xlsx(res, path = out_file)
invisible(file.remove(out_file))
# Example 7: Named list -> directory, one file per element
out_dir <- file.path(tempdir(), "combined")
out_files <- export_xlsx(res, path = out_dir) # res1.xlsx, res2.xlsx
basename(out_files)
#> [1] "res1.xlsx" "res2.xlsx"
unlink(out_dir, recursive = TRUE)