| Type: | Package |
| Title: | Export Data Frames to Excel 'xlsx' Format |
| Version: | 2.0.0 |
| Description: | Zero-dependency data frame to xlsx exporter based on 'libxlsxwriter' https://libxlsxwriter.github.io. Fast and no Java or Excel required. |
| License: | BSD_2_clause + file LICENSE |
| Copyright: | Jeroen Ooms. For copyright notices of bundled third-party code (libxlsxwriter and dependencies), see COPYRIGHT. |
| Encoding: | UTF-8 |
| URL: | https://ropensci.r-universe.dev/writexl https://docs.ropensci.org/writexl/ |
| BugReports: | https://github.com/ropensci/writexl/issues |
| Suggests: | grDevices, graphics, spelling, readxl, nycflights13, testthat (≥ 3.2.0), xml2, bit64, knitr, rmarkdown |
| VignetteBuilder: | knitr |
| Language: | en-US |
| SystemRequirements: | zlib |
| Config/testthat/edition: | 3 |
| Config/roxygen2/version: | 8.0.0 |
| NeedsCompilation: | yes |
| Packaged: | 2026-08-05 12:30:06 UTC; bill |
| Author: | Jeroen Ooms |
| Maintainer: | Bill Denney <wdenney@humanpredictions.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-08-05 14:50:02 UTC |
Test whether an object is an 'xl_comment'
Description
Test whether an object is an 'xl_comment'
Usage
is_xl_comment(x)
Arguments
x |
An object. |
Value
'TRUE' if 'x' inherits from '"xl_comment"'.
See Also
Other cell content:
xl_cell_general(),
xl_comment(),
xl_formula(),
xl_rich_run(),
xl_rich_string()
Test whether an object is an 'xl_format'
Description
Test whether an object is an 'xl_format'
Usage
is_xl_format(x)
Arguments
x |
An object. |
Value
'TRUE' if 'x' inherits from '"xl_format"'.
See Also
Other cell formatting:
xl_color(),
xl_format(),
xl_format_groups
Version
Description
Shows version of bundled libxlsxwriter.
Usage
lxw_version()
Export to xlsx
Description
Writes a data frame to an xlsx file. To create an xlsx with (multiple) named
sheets, simply set x to a named list of data frames.
Usage
write_xlsx(
x,
path = tempfile(fileext = ".xlsx"),
col_names = TRUE,
format_headers = TRUE,
na = NA,
use_zip64 = FALSE,
constant_memory = NA,
constant_memory_threshold = 128 * 1024^2
)
Arguments
x |
a data frame, an [xl_sheet], an [xl_workbook], or a (named) list of data frames / 'xl_sheet's that become the sheets in the xlsx |
path |
a file name to write to |
col_names |
write column names as the header row at the top of the sheet? |
format_headers |
apply the workbook's header format to that header row?
The default header format is bold and centered; change it with
|
na |
what to write where a value has none. 'NA' (the default) leaves
the cell blank, as writexl has always done; anything else is written in
its place, keeping its own type. Shorthand for
|
use_zip64 |
use zip64 to enable support for 4GB+ xlsx files. Not all platforms can read this. |
constant_memory |
stream rows to disk instead of building the whole workbook in memory. 'NA' (the default) decides per workbook: on for large data, off for small, and always off when a feature needs it off. 'TRUE' forces it on for a workbook that would otherwise be judged too small; 'FALSE' forces it off. Features that cannot be written while streaming — merged ranges, tables, embedded images and multi-cell array formulas — turn it off regardless, with a warning if 'TRUE' was asked for, because the alternative is a file that opens cleanly and is missing cells. |
constant_memory_threshold |
how much extra memory not streaming would have to cost, in bytes, before streaming is worth it. Default 128 MiB. The cost is *estimated* from the number of cells in the workbook, using a fixed per-cell figure calibrated against a range of data; the true cost varies with the data, and is lowest for text that repeats. Streaming saves memory but produces slightly larger files, so it is not used for workbooks small enough that the saving would not be noticed. |
Details
Supports strings, numbers, booleans and dates automatically. For cell
formatting (fonts, fills, borders, number formats, ...), worksheet layout
(column widths, frozen panes, ...), and workbook metadata, wrap columns with
xl_cell_general, sheets with xl_sheet, and the
whole workbook with xl_workbook. See the "Formatting and
workbook properties" vignette and xl_format.
See Also
Other workbook settings:
xl_properties(),
xl_workbook()
Examples
# Roundtrip example with single excel sheet named 'mysheet'
tmp <- write_xlsx(list(mysheet = iris))
readxl::read_xlsx(tmp)
General cell objects for Excel writing
Description
'xl_cell_general' creates a vector of cell objects, each optionally containing a **value**, a **formula**, and/or a **hyperlink**. It is the fundamental building block used internally by [xl_formula()] and [xl_hyperlink()], and can be used directly for mixed-type columns or cells that combine multiple features (e.g., a formula with a pre-calculated result, or a URL with separate display text and tooltip).
An 'xl_cell_general' behaves like a vector: it has a 'length()', supports '[', '[[', 'c()' and 'rep()', and recycles automatically when assigned to a data frame column of a different length (just like [xl_formula()]). It is deliberately not a list, so that 'df[, j] <- cells' assigns one column rather than being read as a list of them.
‘df[i, j] <- x' sets that cell’s ‘value', whatever 'x'’s type; a formula needs [xl_formula()], since a cell column carries no column-wide notion of "these are all formulas".
'as.character()' returns what each cell displays, so a cell built for a sheet can be reused wherever a plain string is wanted — [xl_merge()]'s or [xl_comment()]'s 'value', for instance. A cell that carries only a formula shows 'NA': its displayed value comes from Excel, not from writexl.
Usage
xl_cell_general(
value = NULL,
formula = NULL,
hyperlink = NULL,
format = NULL,
comment = NULL,
array = FALSE,
dynamic = FALSE,
array_range = NULL,
na = NA
)
## S3 method for class 'xl_cell_general'
as.character(x, ...)
Arguments
value |
An atomic vector or a list of scalars, one per cell. Use 'NA' for a cell that is empty unless 'na' says otherwise (see 'na' below, and note that a workbook-wide 'na' reaches these values too). A list enables mixed types across cells in the same column (e.g., 'list(1.5, "text", TRUE)'). Date and POSIXct scalars are supported and formatted as in [write_xlsx()]. When 'hyperlink' is also set for the same cell, a **character** 'value' is used as the display text shown in the cell instead of the raw URL; all other types are ignored for hyperlink cells. |
formula |
A character vector of Excel formulas (each must start with '"="'), or 'NA' for cells with no formula. When both 'value' and 'formula' are supplied for the same cell, 'value' is used as a pre-calculated result stored alongside the formula via 'worksheet_write_formula_num()' (numeric value) or 'worksheet_write_formula_str()' (character value). This allows static xlsx exports that display formula text in the formula bar but do not require Excel to recalculate on open. |
hyperlink |
A character vector of URLs, or a list where each element is 'NA', a single character URL, or a named list with elements:
Supply a character 'value' alongside 'hyperlink' to show custom display text in the cell instead of the raw URL. The hyperlink is written via 'worksheet_write_url_opt()'. |
format |
An [xl_format] object (applied to every cell), or a list of 'xl_format' objects (one per cell, recycled), or 'NULL' for no formatting. Build formats with [xl_font()], [xl_fill()], [xl_border()], [xl_align()], [xl_num_format()] and [xl_protection()], combined with [xl_format()] or ‘+'. When a cell’s value is a date/time and its format sets no number format, the default date/time number format is applied automatically. |
comment |
Cell comments (notes): a character vector of comment text (one per cell, recycled; 'NA' for no comment), a single [xl_comment()] (recycled to every cell), or a list mixing strings / 'xl_comment' / 'NA' per cell. 'NULL' for no comments. |
array, dynamic |
Logical (one per cell, recycled): how the cell's 'formula' is stored. 'array = TRUE' writes a legacy *array* (Ctrl-Shift- Enter) formula; 'dynamic = TRUE' writes a modern *dynamic array* formula, which Excel spills over as many cells as the result needs. Neither can carry a character 'value', because Excel stores no cached string result for an array formula. On a cell that has no 'formula' the flags are inert, so a single 'array = TRUE' can be recycled across a column that mixes formula and value cells. |
array_range |
The range a legacy array formula covers, for the rare case where it must be declared: an Excel range string ('"C2:C11"') or a 'list(rows = , cols = )' spec, one per cell ('NA' for none). It must start at the cell holding the formula, and must extend into cells the sheet does not otherwise write — the range is padded on write, so an overlap would have the padding and the sheet's own values overwrite each other. Leave it unset for almost everything: a single-cell 'dynamic' formula spills automatically in Excel 365 / 2021, and a single-cell 'array' formula is the right spelling for a 'SUMPRODUCT'-style aggregate. Supplying it forces the workbook out of the memory-efficient row-streaming mode, since libxlsxwriter cannot pad an array range while streaming. |
na |
What to write in a cell that has no value, one per cell and recycled. ‘NA' (the default) inherits the column’s [xl_col_spec()]‘(na = )', and failing that the workbook’s [xl_properties()]'(na = )'; a cell that sets its own overrides both. This is also how a cell asks for a blank where the column or workbook would otherwise substitute something — give it the value you want, '""' for an empty string. |
x |
An 'xl_cell_general'. |
... |
Ignored. |
Value
An object of class 'c("xl_cell_general", "xl_cell")', which is a list of length 'n' where each element is a named list with fields 'value', 'formula', 'hyperlink', 'format', 'comment', 'array', 'dynamic' and 'array_range'.
See Also
[xl_formula()], [xl_hyperlink()], [write_xlsx()]
Other cell content:
is_xl_comment(),
xl_comment(),
xl_formula(),
xl_rich_run(),
xl_rich_string()
Examples
# Value-only cell
xl_cell_general(value = 42)
# Formula with a pre-calculated numeric result (static export)
xl_cell_general(value = 42.0, formula = "=SUM(A1:A10)")
# Hyperlink with display text (value) and tooltip
xl_cell_general(
value = "Visit",
hyperlink = list(url = "https://example.com", tooltip = "Go to example.com")
)
# Vector of cells: value and formula cells in one column
cells <- c(
xl_cell_general(value = 1.5),
xl_cell_general(value = "note"),
xl_cell_general(formula = "=A1+A2")
)
# Used in a data frame (length-1 recycles to fill all rows, as with
# xl_formula())
df <- data.frame(x = 1:3)
df$formula_col <- xl_formula("=A1*2") # backward-compatible shorthand
df$cell_col <- xl_cell_general(value = 99L) # all rows get 99
Add a chart to a worksheet
Description
'xl_chart()' builds a chart from one or more [xl_chart_series()] and places it on a sheet, anchored to a cell. Pass one or a list of them as 'xl_sheet(chart = )'.
Placement works exactly as it does for [xl_image()] — 'at', 'scale', 'offset', 'position', 'description' and 'decorative' mean the same things, because libxlsxwriter describes both with the same fields.
Usage
xl_chart(
type,
series,
title = NULL,
title_format = NULL,
title_layout = NULL,
title_overlay = NA,
x_axis = NULL,
y_axis = NULL,
legend = NULL,
data_table = NULL,
plot_area_format = NULL,
plot_area_layout = NULL,
chart_area_format = NULL,
drop_lines = NA,
high_low_lines = NA,
up_down_bars = NA,
hole_size = NA,
rotation = NA,
series_gap = NA,
series_overlap = NA,
show_blanks = NULL,
show_hidden_data = NA,
at = "A1",
scale = 1,
offset = NULL,
position = "move_and_size",
description = NULL,
decorative = FALSE,
style = NA
)
Arguments
type |
The chart type: '"column"', '"bar"', '"line"', '"pie"', '"doughnut"', '"area"', '"scatter"', '"radar"', and the stacked, percent-stacked, smoothed and marker variants. |
series |
One [xl_chart_series()], or a list of them. Every series of a scatter chart must have 'categories', which are its x axis. |
title |
The chart title. A string is always taken literally, so to take the title from a cell give a range spec — ‘list(header = "revenue")' for a column’s header cell, or 'list(rows = 1, cols = 1)' for a data cell. 'FALSE' removes the title Excel would otherwise generate. |
title_format |
An [xl_format()] styling the title text. A title is text, so only the [xl_font()] group applies. |
title_layout |
Where to put the title by hand, as 'c(x, y)' fractions of the chart. Excel places it for you otherwise. |
title_overlay |
Let the title sit over the plot rather than above it. |
x_axis, y_axis |
An [xl_chart_axis()] describing that axis. Pie and doughnut charts have none, and several axis options apply to a value or a category axis only — see [xl_chart_axis()]. |
legend |
An [xl_chart_legend()] moving, styling or removing the legend. |
data_table |
An [xl_chart_table()] printing the plotted numbers in a grid beneath the chart. |
plot_area_format, chart_area_format |
An [xl_format()] styling the plot area — the panel the data is drawn in — and the chart area around it: [xl_border()] for the line, [xl_fill()] for the fill or pattern. |
plot_area_layout |
Where to put the plot area by hand, as 'c(x, y)' or 'c(x, y, width, height)' fractions of the chart. |
drop_lines |
Drop lines from each point to the category axis: 'TRUE', or an [xl_format()] giving the line to draw them with. Line and area charts. |
high_low_lines |
A line joining the highest and lowest series at each category, the same way. Line charts. |
up_down_bars |
Bars between the first and last series at each category: 'TRUE', or 'list(up = , down = )' with an [xl_format()] for either bar. Line charts. |
hole_size |
The size of a doughnut's hole, 10 to 90 percent. |
rotation |
Where a pie or doughnut starts, 0 to 360 degrees clockwise from the top. |
series_gap |
The gap between category groups on a bar or column chart, 0 to 500 percent of a bar's width. |
series_overlap |
How far bars of one category overlap, -100 to 100 percent. 100 stacks them, -100 pushes them apart. |
show_blanks |
What an empty cell does to the plot: leave a '"gap"', plot it as '"zero"', or join across it with '"connected"'. |
|
Plot data from rows and columns that are hidden. Excel leaves them out otherwise. | |
at |
The cell the chart's top-left corner is anchored to. |
scale |
Scale factor: one number for both axes, or 'c(x, y)'. |
offset |
Offset from the anchor cell's corner in pixels, as 'c(x, y)'. |
position |
How the chart behaves when rows and columns change size; see [xl_image()]. |
description |
Alt text, for screen readers. |
decorative |
Mark the chart as decorative, so screen readers skip it. |
style |
Excel's built-in chart style, 1–48. |
Value
An 'xl_chart' object.
What a chart type supports
Excel silently drops options a chart type cannot use, so writexl refuses them instead, naming the types that would work. Pie and doughnut charts have no axes; only a doughnut has a hole; only pie and doughnut rotate; up-down bars and high-low lines are line-only; the series gap and overlap are bar and column only.
See Also
[xl_chart_series], [xl_sheet]
Other images and charts:
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_table(),
xl_chart_trendline(),
xl_chartsheet(),
xl_image()
Examples
xl_chart("column", xl_chart_series(values = list(cols = "revenue")))
xl_chart("pie", xl_chart_series(values = "Data!B2:B5"), title = "Share")
An axis of a chart
Description
'xl_chart_axis()' describes one axis, and is given to [xl_chart()] as 'x_axis' or 'y_axis'.
Several options apply to one kind of axis only, and Excel discards the rest without a word, so writexl refuses them instead. A scatter chart plots numbers against numbers, so both of its axes are **value** axes; every other type has a **category** x axis and a value y axis. (A bar chart is drawn with its categories up the side, but the axes keep their names.) Pie and doughnut charts have no axes at all.
* value axes only — 'min', 'max', 'log_base', 'major_unit', 'minor_unit', 'display_units', 'display_units_visible'; * category axes only — 'position', 'label_align', 'interval_unit', 'interval_tick'.
Usage
xl_chart_axis(
title = NULL,
title_format = NULL,
title_layout = NULL,
label_format = NULL,
num_format = NULL,
line_format = NULL,
visible = NA,
reverse = NA,
min = NA,
max = NA,
log_base = NA,
major_unit = NA,
minor_unit = NA,
display_units = NULL,
display_units_visible = NA,
interval_unit = NA,
interval_tick = NA,
position = NULL,
label_position = NULL,
label_align = NULL,
major_tick = NULL,
minor_tick = NULL,
crossing = NULL,
major_gridlines = NA,
minor_gridlines = NA,
major_gridlines_format = NULL,
minor_gridlines_format = NULL
)
Arguments
title |
The axis title: a string, or a range spec holding one — see [xl_chart_series()] for the spellings, including 'list(header = "revenue")'. |
title_format |
An [xl_format()] styling the axis title. A title is text, so only the [xl_font()] group applies. |
title_layout |
Where to put the axis title by hand, as 'c(x, y)' fractions of the chart, each above 0 and at most 1. Excel places it for you otherwise. |
label_format |
An [xl_format()] styling the tick labels — the [xl_font()] group only. |
num_format |
A number format for the tick labels, as an Excel format string ('"#,##0"') or an [xl_num_format()]. |
line_format |
An [xl_format()] styling the axis line itself: [xl_border()] for the line, [xl_fill()] for the fill behind it. An axis has four parts that can be styled, so none of them is just 'format'. |
visible |
'FALSE' hides the axis. |
reverse |
Draw the axis in the opposite direction. |
min, max |
The axis bounds. Value axes only. |
log_base |
Use a logarithmic scale with this base, 2 or more. Value axes only. |
major_unit, minor_unit |
The spacing between major and minor tick marks. Value axes only. |
display_units |
Scale the labels by '"thousands"', '"millions"', '"billions"' and so on; see Details for the full set. Value axes only. |
display_units_visible |
Whether the caption naming the units — the small rotated "Millions" beside the axis — is drawn. Setting 'display_units' turns it **on**, as Excel does, so this is really for 'FALSE': rescaled labels with no caption. Value axes only. |
interval_unit |
Label one category in every 'n'. Category axes only. |
interval_tick |
Put a tick mark on one category in every 'n'. Category axes only. |
position |
Whether the data sits '"on_tick"' or '"between"' the tick marks. Category axes only. |
label_position |
Where the tick labels go: '"next_to"', '"high"', '"low"', or '"none"' for no labels. |
label_align |
Tick-label alignment: '"center"', '"left"' or '"right"'. Category axes only. |
major_tick, minor_tick |
The tick marks: '"default"', '"none"', '"inside"', '"outside"' or '"crossing"'. |
crossing |
Where the other axis crosses this one: a number, or '"min"' or '"max"' for either end. |
major_gridlines, minor_gridlines |
Show the gridlines. A chart's major y gridlines are on by default and everything else is off. |
major_gridlines_format, minor_gridlines_format |
An [xl_format()] styling the gridlines — [xl_border()] only, since a gridline is a line. |
Details
'display_units' is one of '"none"', '"hundreds"', '"thousands"', '"ten_thousands"', '"hundred_thousands"', '"millions"', '"ten_millions"', '"hundred_millions"', '"billions"' or '"trillions"'.
Value
An 'xl_chart_axis' object.
See Also
[xl_chart], [xl_chart_series]
Other images and charts:
xl_chart(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_table(),
xl_chart_trendline(),
xl_chartsheet(),
xl_image()
Examples
xl_chart_axis(title = "Quarter")
xl_chart_axis(title = "Revenue", min = 0, num_format = "$#,##0",
major_gridlines = FALSE)
Error bars on a chart series
Description
'xl_chart_error_bars()' draws an error bar at each point, and is given to [xl_chart_series()] as 'x_error_bars' or 'y_error_bars'.
Usage
xl_chart_error_bars(
type,
value = NA,
direction = NULL,
endcap = NA,
format = NULL
)
Arguments
type |
How the size of each bar is worked out: '"std_error"' for the standard error, ‘"fixed"' for a constant, '"percentage"' of the point’s own value, or '"std_dev"' for that many standard deviations. |
value |
The constant, the percentage, or the number of standard deviations. '"std_error"' needs none. |
direction |
'"both"', '"plus"' or '"minus"'. |
endcap |
Draw the cap at the end of each bar. On by default. |
format |
An [xl_format()] styling the bars — [xl_border()] only, since an error bar is a line. |
Value
An 'xl_chart_error_bars' object.
See Also
[xl_chart_series]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_table(),
xl_chart_trendline(),
xl_chartsheet(),
xl_image()
Examples
xl_chart_error_bars("percentage", 5)
xl_chart_error_bars("std_dev", 1, direction = "plus", endcap = FALSE)
Data labels on a chart series
Description
'xl_chart_labels()' prints the numbers next to the points that carry them. With no arguments it shows the value of each point, which is Excel's own default.
'xl_chart_label()' describes one label, for 'custom': a label can be given its own text or hidden, one point at a time.
Excel allows different label positions for different chart types, and drops one that does not apply. The table is in libxlsxwriter's header and is enforced here: '"center"' is allowed everywhere, '"right"', '"left"', '"above"' and '"below"' on line and scatter charts, '"inside_base"' on bar and column, '"inside_end"' and '"outside_end"' on bar, column, pie and doughnut, and '"best_fit"' on pie and doughnut.
Usage
xl_chart_labels(
show_value = NA,
show_name = NA,
show_category = NA,
show_percentage = NA,
show_legend_key = NA,
num_format = NULL,
position = NULL,
separator = NULL,
format = NULL,
leader_lines = NA,
custom = NULL
)
xl_chart_label(value = NULL, hide = NA, format = NULL)
Arguments
show_value, show_name, show_category, show_percentage |
What each label holds: the point's value, the series name, the category, and the value as a percentage of the series. Naming any of them means the label holds exactly those, so 'show_percentage = TRUE' alone gives a percentage and nothing else; naming none of them leaves Excel's default, the value. Percentages are meaningful on pie and doughnut charts. |
show_legend_key |
Print the series' legend swatch in each label. |
num_format |
A number format for the labels, as an Excel format string or an [xl_num_format()]. |
position |
Where the label sits relative to its point; see the description for which chart types allow which. |
separator |
What joins the parts of a label when it holds more than one: '"comma"', '"semicolon"', '"period"', '"newline"' or '"space"'. |
format |
An [xl_format()] styling the labels. A label is a shape with text in it, so all of [xl_font()], [xl_border()] and [xl_fill()] apply. |
leader_lines |
Draw a line from a label back to its point. Excel only shows one once the label has been dragged away from the point. |
custom |
A list of [xl_chart_label()]s, one per point in order, giving individual labels their own text, styling, or 'hide = TRUE'. 'NULL' in the list leaves that point's label alone. |
value |
The label's text. A string beginning with '"="' is a formula, so '"=Sheet1!$A$1"' takes the text from a cell. |
hide |
Remove this point's label, leaving the others. |
Value
An 'xl_chart_labels' object.
See Also
[xl_chart_series]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_table(),
xl_chart_trendline(),
xl_chartsheet(),
xl_image()
Examples
xl_chart_labels()
xl_chart_labels(show_category = TRUE, show_percentage = TRUE,
separator = "newline", position = "outside_end")
A chart's legend
Description
'xl_chart_legend()' moves, styles or removes the legend, and can leave individual series out of it.
Usage
xl_chart_legend(
position = NULL,
format = NULL,
layout = NULL,
delete_series = NULL
)
Arguments
position |
Where the legend sits: ‘"right"' (Excel’s default), '"left"', '"top"', '"bottom"', '"top_right"', the '"overlay_*"' variants that let the legend sit over the plot, or '"none"' to remove it. |
format |
An [xl_format()] styling the legend text — the [xl_font()] group only, since libxlsxwriter gives a legend a font and nothing else. |
layout |
Where to put the legend by hand, as 'c(x, y)' or 'c(x, y, width, height)' — fractions of the chart, each above 0 and at most 1. Excel places it for you otherwise. 'at' is a cell everywhere else in writexl, so a chart's own fractions are a 'layout'. |
delete_series |
Series to leave out of the legend, by position: '2' drops the second series' entry while still plotting it. This is how a trendline or a helper series is kept out of the key. |
Value
An 'xl_chart_legend' object.
See Also
[xl_chart]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_table(),
xl_chart_trendline(),
xl_chartsheet(),
xl_image()
Examples
xl_chart_legend(position = "bottom")
xl_chart_legend(position = "none")
xl_chart_legend(delete_series = 2)
A marker on a chart series
Description
'xl_chart_marker()' draws a symbol at each point of a series. Line, scatter and radar charts are where they show; on other types Excel ignores them.
'type = "automatic"' asks Excel for the default marker of that series, and is the one type that cannot be given a size or a format — libxlsxwriter documents that, and Excel drops them, so both are refused here.
Usage
xl_chart_marker(type = NULL, size = NA, format = NULL)
Arguments
type |
The symbol: '"automatic"', '"none"', '"square"', '"diamond"', '"triangle"', '"x"', '"star"', '"short_dash"', '"long_dash"', '"circle"' or '"plus"'. |
size |
The symbol's size in points, 2 to 72. |
format |
An [xl_format()] styling the symbol: [xl_border()] for its outline, [xl_fill()] for its fill or pattern. |
Value
An 'xl_chart_marker' object.
See Also
[xl_chart_series]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_series(),
xl_chart_table(),
xl_chart_trendline(),
xl_chartsheet(),
xl_image()
Examples
xl_chart_marker(type = "circle", size = 8)
xl_chart_marker(type = "none")
A data series within a chart
Description
'xl_chart_series()' names the values a chart plots, and optionally the categories to plot them against and a name for the legend. A series that plots a column is named after that column's header unless told otherwise.
Each range may live on a different sheet from the chart, so it takes an optional 'sheet':
* '"Data!B2:B10"' — an A1 range, sheet-qualified; * ‘list(cols = "revenue")' — resolved against the chart’s own sheet; * 'list(sheet = "Data", cols = "revenue")' — against another sheet; * ‘list(header = "revenue")' — that column’s header cell, which is where a series name usually lives.
A range that selects no data is an error rather than an empty chart.
Usage
xl_chart_series(
values,
categories = NULL,
name = NULL,
format = NULL,
marker = NULL,
labels = NULL,
trendline = NULL,
x_error_bars = NULL,
y_error_bars = NULL,
points = NULL,
smooth = NA,
invert_if_negative = NA
)
Arguments
values |
The range holding the numbers to plot. |
categories |
The range holding the labels to plot them against. Omit for a chart that numbers its points. |
name |
The series name, shown in the legend. Left unset, a series that plots a column takes its name from that column's header cell, which is what Excel does when you chart a column along with its header; 'FALSE' leaves it unnamed. A string is always taken literally — a series may legitimately be called '"Q1!"' — so to take the name from another cell, give a range spec: ‘name = list(header = "cost")' for a different column’s header, or 'name = list(rows = 1, cols = 1)' for a data cell. |
format |
An [xl_format] styling the series — its line and fill. See [xl_chart()] for which format properties a chart can express. |
marker |
An [xl_chart_marker()] drawn at each point. |
labels |
An [xl_chart_labels()] printing the numbers beside the points. |
trendline |
An [xl_chart_trendline()] fitted through the series. |
x_error_bars, y_error_bars |
An [xl_chart_error_bars()] on each point. |
points |
An [xl_format()] per point, as a list, styling individual points — one slice of a pie, one bar of a column chart. 'NULL' in the list leaves that point as it is. |
smooth |
Draw the line smoothed. Line and scatter charts only. |
invert_if_negative |
Fill negative values with the inverse colour. |
Value
An 'xl_chart_series' object.
See Also
[xl_chart]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_table(),
xl_chart_trendline(),
xl_chartsheet(),
xl_image()
Examples
xl_chart_series(values = list(cols = "revenue"))
xl_chart_series(values = "Data!B2:B10", categories = "Data!A2:A10",
name = "2024")
The table of values under a chart
Description
'xl_chart_table()' prints the plotted numbers in a grid beneath the chart, which is Excel's "Data Table" chart element. It is given to [xl_chart()] as 'data_table'.
Naming none of the grid options leaves Excel's own: horizontal, vertical and outline borders drawn, and no legend keys.
Usage
xl_chart_table(
show_keys = NA,
horizontal_border = NA,
vertical_border = NA,
outline_border = NA,
format = NULL
)
Arguments
show_keys |
Print each series' legend swatch in the table. |
horizontal_border, vertical_border, outline_border |
Which of the grid's borders to draw. |
format |
An [xl_format()] styling the table's text — the [xl_font()] group only. |
Value
An 'xl_chart_table' object.
See Also
[xl_chart]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_trendline(),
xl_chartsheet(),
xl_image()
Examples
xl_chart_table()
xl_chart_table(show_keys = TRUE, vertical_border = FALSE)
A trendline on a chart series
Description
'xl_chart_trendline()' fits a line through a series.
Two of Excel's own restrictions are enforced, because it discards these rather than complain: a **moving average** has no forecast, no equation and no R-squared, and an **intercept** applies only to exponential, linear and polynomial fits.
Usage
xl_chart_trendline(
type,
order = NA,
period = NA,
forward = NA,
backward = NA,
intercept = NA,
equation = NA,
r_squared = NA,
name = NULL,
format = NULL
)
Arguments
type |
'"linear"', '"log"', '"poly"', '"power"', '"exp"' or '"average"' for a moving average. |
order |
The order of a polynomial fit, 2 or more. '"poly"' only. |
period |
The number of points a moving average covers, 2 or more. '"average"' only. |
forward, backward |
How far to project the line beyond the data, in categories. |
intercept |
Force the line through this value on the y axis. Exponential, linear and polynomial fits only. |
equation |
Print the fitted equation on the chart. |
r_squared |
Print the R-squared value on the chart. |
name |
The trendline's name in the legend. Excel generates one otherwise. |
format |
An [xl_format()] styling the line — [xl_border()] only, since a trendline is a line. |
Value
An 'xl_chart_trendline' object.
See Also
[xl_chart_series]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_table(),
xl_chartsheet(),
xl_image()
Examples
xl_chart_trendline("linear", equation = TRUE, r_squared = TRUE)
xl_chart_trendline("poly", order = 3)
xl_chart_trendline("average", period = 2)
A sheet holding a single chart
Description
'xl_chartsheet()' is a worksheet-sized chart: a tab of its own holding one chart and no cells. Give it to [write_xlsx()] in place of a data frame.
Because a chartsheet has no cells, every range in the chart's series must name the sheet it plots — 'list(sheet = "Data", cols = "revenue")' or '"Data!B2:B10"'. A bare 'list(cols = )' has nothing to resolve against and is refused.
A chartsheet supports only part of what a worksheet does, and the parts it does not are refused rather than dropped: of [xl_page_setup()] it takes the orientation, paper size, margins and the header and footer; of [xl_sheet_view()] it takes 'active', 'selected', 'visible' and 'first_tab'.
Usage
xl_chartsheet(
chart,
tab_color = NULL,
zoom = NA,
protect = NULL,
page = NULL,
view = NULL
)
Arguments
chart |
The [xl_chart()] to fill the sheet with. |
tab_color |
The colour of the sheet tab. |
zoom |
The zoom level as a percentage, 10 to 400. |
protect |
'TRUE', a password string, or a named list. A chartsheet has no cells, so of Excel's protection options it takes only 'no_content' (let the chart be edited) and 'no_objects' (let the shapes on it be edited); the worksheet options are refused by name. |
page |
An [xl_page_setup()] describing how it prints. |
view |
An [xl_sheet_view()] setting the tab state. |
Value
An 'xl_chartsheet' object.
See Also
[xl_chart], [xl_sheet]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_table(),
xl_chart_trendline(),
xl_image()
Examples
sales <- data.frame(quarter = c("Q1", "Q2"), revenue = c(10, 25))
chart <- xl_chart("column",
xl_chart_series(values = list(sheet = "Data",
cols = "revenue")))
write_xlsx(list(Data = sales, Overview = xl_chartsheet(chart)),
tempfile(fileext = ".xlsx"))
Normalize a color to a libxlsxwriter RGB integer
Description
Converts an R color name (e.g. '"navy"'), a hex string ('"#FF0000"' or '"FF0000"'), or an integer in the range '0x000000'..'0xFFFFFF' into the single '0xRRGGBB' integer that libxlsxwriter expects. Used internally by every 'color'/'background'/'foreground' argument of the formatting constructors, and exported so it can be used directly.
Usage
xl_color(x)
Arguments
x |
A single color: an R color name, a hex string, or an integer. 'NA' returns 'NA_integer_' (an unset color). |
Value
A single integer in '0x000000'..'0xFFFFFF', or 'NA_integer_'.
See Also
Other cell formatting:
is_xl_format(),
xl_format(),
xl_format_groups
Examples
xl_color("red")
xl_color("#0000FF")
xl_color(255L)
Column and row specifications for a worksheet
Description
'xl_col_spec()' and 'xl_row_spec()' describe formatting and geometry for a set of columns or rows within a sheet built by [xl_sheet()]. They are *subclasses* of [xl_format]: they carry the usual formatting groups (so they combine with '+' and the group constructors) plus a target (which columns/rows) and geometry (width/height, hidden, outline level).
Usage
xl_col_spec(
cols,
width = NA,
hidden = NA,
level = NA,
format = NULL,
width_pixels = NA,
collapsed = NA,
na = NA
)
xl_row_spec(
rows,
height = NA,
hidden = NA,
level = NA,
format = NULL,
height_pixels = NA,
collapsed = NA
)
Arguments
cols |
Columns to target: a character vector of column names or a numeric vector of 1-based positions. |
width |
Column width (in Excel character units). |
|
Logical; hide the column/row. | |
level |
Integer outline (grouping) level, 0–7. |
format |
An optional [xl_format] applied to the column/row as its default cell format. Combine groups with '+' (e.g. 'xl_font(bold = TRUE) + xl_fill(background = "yellow")'). |
width_pixels, height_pixels |
The same geometry given in pixels instead. Give one or the other, not both. Excel stores character units and points, so the pixel value is converted on the way in — read back, a width set as 100 pixels is 13.57 character units. |
collapsed |
Logical; draw this column/row as the collapsed summary of the group beside it. Excel does not derive this — the rows or columns of the group itself need 'hidden = TRUE' as well, exactly as clicking the grouping symbol would leave them. |
na |
What to write in this column where a value has none, overriding the workbook's [xl_properties()]'(na = )'. 'NA' (the default) inherits it. Columns are where this usually belongs: a substitute that suits a numeric column rarely suits a date one. |
rows |
Rows to target: a numeric vector of 1-based data-row indices (row 1 is the first data row, ignoring the header). |
height |
Row height (in points). |
Value
An 'xl_col_spec' / 'xl_row_spec' object (also an [xl_format]).
See Also
[xl_sheet], [xl_format]
Other worksheet layout:
xl_outline(),
xl_page_setup(),
xl_sheet(),
xl_sheet_view()
Examples
xl_col_spec("revenue", width = 14, format = xl_num_format("#,##0.00"))
xl_col_spec(c(1, 2), width = 10) + xl_font(bold = TRUE)
xl_col_spec("logo", width_pixels = 100)
xl_row_spec(1, height = 24, format = xl_font(bold = TRUE))
xl_row_spec(1, height_pixels = 40)
Create a cell comment
Description
'xl_comment()' builds a comment (note) that can be attached to a cell via [xl_cell_general()]'s 'comment' argument. The simplest form is just text ('xl_cell_general(value = x, comment = "see note")'); 'xl_comment()' adds options such as the author, initial visibility, box size and position, and styling.
Excel comment boxes support only a **background color** and a **font name/size/family**. These are supplied by reusing the formatting engine via the 'format' argument (e.g. 'xl_font(name = "Arial", size = 10) + xl_fill(background = "lightyellow")'); any other format property (bold, borders, number formats, ...) is not supported by comments and triggers a warning.
Usage
xl_comment(
value,
format = NULL,
author = NA,
visible = NA,
width_pixels = NA,
height_pixels = NA,
x_scale = NA,
y_scale = NA,
start_row = NA,
start_col = NA,
x_offset = NA,
y_offset = NA
)
Arguments
value |
A single string: the comment's text. Anything with an [as.character()] method is accepted, so a cell built for a sheet can be reused here. |
format |
An optional [xl_format]; only its fill background color and font name/size/family are used (see [xl_fill()], [xl_font()]). Other properties are unsupported and warned about. |
author |
Comment author (shown in Excel's status bar). Defaults to the sheet/workbook 'comment_author' when unset (see [xl_sheet()], [xl_properties()]). |
visible |
Initial visibility: 'NA' follows the sheet default (comments are hidden unless 'show_comments' is set), 'TRUE' shows this comment, 'FALSE' hides it. |
width_pixels, height_pixels |
Comment box size in pixels (defaults 128 x 74). |
x_scale, y_scale |
Box scale factors. |
start_row, start_col |
Zero-based anchor cell of the box (by default a comment sits one row up and one column right of its cell). |
x_offset, y_offset |
Pixel offset of the box from its anchor. |
Value
An 'xl_comment' object.
See Also
[xl_cell_general], [xl_format]
Other cell content:
is_xl_comment(),
xl_cell_general(),
xl_formula(),
xl_rich_run(),
xl_rich_string()
Examples
# plain text
xl_comment("Double-check this figure")
# with author and styling reused from the format engine
xl_comment("Estimate", author = "Finance",
format = xl_font(name = "Arial", size = 10) +
xl_fill(background = "lightyellow"))
Format cells according to their contents
Description
Excel's conditional formatting, in four flavours:
* 'xl_cond_cell()' — a rule with a format: comparisons, text matches, time periods, above/below average, top/bottom N, duplicates, blanks, errors, or an arbitrary formula. * 'xl_cond_scale()' — a two- or three-colour scale across the range. * 'xl_cond_bar()' — in-cell data bars. * ‘xl_cond_icons()' — one of Excel’s built-in icon sets.
Pass one or a list of them as 'xl_sheet(conditional = )'.
Usage
xl_cond_cell(
range,
type = NA,
criteria = NA,
value = NULL,
min = NULL,
max = NULL,
format = NULL,
stop_if_true = NA,
multi_range = NA
)
xl_cond_scale(
range,
colors = c("red", "yellow", "green"),
values = NULL,
rule_types = NULL,
stop_if_true = NA,
multi_range = NA
)
xl_cond_bar(
range,
color = NA,
values = NULL,
rule_types = NULL,
solid = NA,
negative_color = NA,
border_color = NA,
negative_border_color = NA,
no_border = NA,
direction = NA,
axis = NA,
axis_color = NA,
bar_only = NA,
stop_if_true = NA,
multi_range = NA
)
xl_cond_icons(
range,
style = "3_traffic_lights",
reverse = NA,
icons_only = NA,
stop_if_true = NA,
multi_range = NA
)
Arguments
range |
The cells the rule applies to: an Excel range string such as '"B2:B100"', a single cell, or a 'list(rows = , cols = )' spec. |
type |
The kind of rule, when it cannot be inferred from 'criteria': '"cell"', '"text"', '"time_period"', '"average"', '"top"', '"bottom"', '"duplicate"', '"unique"', '"blanks"', '"no_blanks"', '"errors"', '"no_errors"' or '"formula"'. |
criteria |
How the rule decides, which depends on 'type': '"=="', '"!="', '">"', '"<"', '">="', '"<="', '"between"', '"not between"' for '"cell"'; '"contains"', '"not contains"', '"begins with"', '"ends with"' for '"text"'; '"yesterday"', '"today"', '"tomorrow"', '"last 7 days"', '"last week"', '"this week"', '"next week"', '"last month"', '"this month"', '"next month"' for '"time_period"'; '"above"', '"below"', '"above or equal"', '"below or equal"' and the '"N std dev above"' / '"below"' variants for '"average"'; and '"percent"' for '"top"' / '"bottom"'. Pairing a criteria with the wrong 'type' is an error — Excel would accept the file and silently ignore the rule. |
value |
What the criteria compares against: a number, a string (for the text criteria), or an '"=..."' formula. For '"top"' / '"bottom"' it is the N. Use 'min' and 'max' for '"between"' / '"not between"'. |
min, max |
The two bounds for '"between"' / '"not between"'. |
format |
The [xl_format] applied to cells that match. |
stop_if_true |
Logical; if this rule matches, skip the later rules on the same cells. |
multi_range |
A further set of ranges the rule also covers, as an Excel multi-range string such as '"B3:K6 B9:K12"'. |
colors |
Two or three colours for the scale, from lowest to highest. Two gives a two-colour scale, three a three-colour scale. |
values |
Optional values marking where each colour sits, in the same order as ‘colors'. Defaults to the range’s minimum, midpoint and maximum. |
rule_types |
How each entry of 'values' is interpreted: '"minimum"', '"maximum"', '"number"', '"percent"', '"percentile"', '"formula"', '"auto_min"' or '"auto_max"'. |
color |
The bar's fill colour. |
solid |
Logical; a solid bar rather than Excel's default gradient. |
negative_color, border_color, negative_border_color, axis_color |
Colours for the negative portion, the bar border, the negative border, and the axis line. |
no_border |
Logical; draw the bar without a border. |
direction |
'"context"' (follow the sheet), '"left to right"' or '"right to left"'. |
axis |
Where the zero axis sits: '"automatic"', '"midpoint"' or '"none"'. |
bar_only |
Logical; show the bar without the cell's value. |
style |
Which built-in icon set: one of '"3_arrows"', '"3_arrows_gray"', '"3_flags"', '"3_traffic_lights"', '"3_traffic_lights_rimmed"', '"3_signs"', '"3_symbols_circled"', '"3_symbols"', '"4_arrows"', '"4_arrows_gray"', '"4_red_to_black"', '"4_ratings"', '"4_traffic_lights"', '"5_arrows"', '"5_arrows_gray"', '"5_ratings"' or ‘"5_quarters"'. These are Excel’s own icons, not images, so nothing is embedded in the file. |
reverse |
Logical; reverse the order the icons are assigned in. |
icons_only |
Logical; show the icon without the cell's value. |
Value
An 'xl_conditional' object.
See Also
[xl_sheet], [xl_format]
Other worksheet features:
xl_filter(),
xl_filter_keep(),
xl_merge(),
xl_table(),
xl_table_column(),
xl_validation()
Examples
xl_cond_cell("B2:B100", criteria = ">", value = 100, format = xl_fill(background = "red"))
xl_cond_cell("C2:C100", type = "text", criteria = "contains", value = "urgent",
format = xl_font(bold = TRUE))
xl_cond_cell("D2:D100", type = "duplicate",
format = xl_fill(background = "yellow"))
xl_cond_scale("C2:C100", colors = c("red", "yellow", "green"))
xl_cond_scale("C2:C100", colors = c("white", "steelblue"))
xl_cond_bar("D2:D100", color = "steelblue")
xl_cond_bar("D2:D100", color = "green", solid = TRUE, bar_only = TRUE)
xl_cond_icons("E2:E100", style = "3_traffic_lights")
xl_cond_icons("E2:E100", style = "5_ratings", icons_only = TRUE)
Filter an autofilter column, hiding the rows that do not match
Description
'xl_filter()' sets the criteria on one autofilter column *and* hides the rows that do not match. Both halves are necessary: Excel stores the criteria and the hidden rows separately and does not apply a filter when a file is opened, so criteria alone produce a sheet that looks filtered but shows every row.
Because writexl decides which rows to hide, it reproduces Excel's own matching rules, which were measured in Excel rather than assumed. Those rules depend on which of two forms the filter takes:
* '"=="' (with no wildcard) and '"blanks"', and any 'list', are written as a **value list**. Excel matches these against the text a cell *displays*, case-insensitively — so '"=="' with '10', with '"10"', or a 'list' of '"10"' all match both the number '10' and the string '"10"'. * every other criteria, including '"=="' with a '*' or '?' in it, is written as a **typed comparison**. If the value is a number the comparison is numeric and a text cell never satisfies it (except '"!="', which a text cell satisfies because it is not that number). If the value is text the comparison is textual, case-insensitive, with '*' and '?' as wildcards, and a number cell never satisfies it.
The consequence worth knowing is that '"=="' with '"10"' keeps the number '10', while '"=="' with '"1*"' keeps nothing on a numeric column: the wildcard changes the form, and so the rule.
Blank means an empty cell or an empty string; '"non-blanks"' is its exact complement. Blanks are excluded by every comparison except '"!="', which keeps them — a blank is not equal to anything. A mixed-type column built with [xl_cell_general()] is matched cell by cell, each by its own type.
Usage
xl_filter(
col,
criteria = NA,
value = NULL,
criteria2 = NA,
value2 = NULL,
and_or = "and",
list = NULL
)
Arguments
col |
The column to filter: a name or a 1-based position. |
criteria |
One of '"=="', '"!="', '">"', '"<"', '">="', '"<="', '"blanks"' or '"non-blanks"'. The four magnitude comparisons need a numeric value; writexl will not guess how Excel orders text. |
value |
The value to compare against. In a text comparison '*' matches any run of characters and '?' any single one. |
criteria2, value2 |
An optional second rule for the same column. |
and_or |
How the two rules combine: '"and"' (default) or '"or"'. |
list |
Instead of a criteria, keep only rows whose value is in this character vector. Matched case-insensitively, as Excel does. |
Value
An 'xl_filter' object.
Limitations
A value list matches displayed text, which writexl can only predict for the General format. Filtering a 'Date' or 'POSIXct' column by '"=="' or 'list' is therefore refused — use a comparison such as '">="'. For the same reason a numeric column carrying a custom number format (say two decimal places, or a currency symbol) may display differently from what writexl compares, so prefer a comparison there too. Columns whose cells hold formulas cannot be filtered at all, since writexl does not know what Excel would compute.
See Also
[xl_sheet], [xl_filter_keep]
Other worksheet features:
xl_conditional,
xl_filter_keep(),
xl_merge(),
xl_table(),
xl_table_column(),
xl_validation()
Examples
xl_filter("qty", ">", 100)
xl_filter("qty", ">", 100, "<", 200) # between, via two rules
xl_filter("fruit", "==", "ap*") # wildcard: typed comparison
xl_filter("fruit", list = c("apple", "banana"))
xl_filter("qty", "==", "10") # value list: matches the
# number 10 and the text "10"
Which rows an Excel autofilter would leave visible
Description
'xl_filter_keep()' answers, for a data frame and a set of [xl_filter()] rules, the question 'xl_sheet(filter =)' has to answer internally: which rows does Excel leave visible? It writes nothing — it is the matching rule on its own, exported because reproducing Excel's filter semantics is hard to get right and useful outside writing a file.
The rules are described in detail under [xl_filter()], and were established by measurement rather than from documentation: a workbook was written with criteria set and no rows hidden, opened in Excel, and Data > Reapply pressed so that Excel computed each match itself.
Usage
xl_filter_keep(data, filter)
Arguments
data |
A data frame whose columns the filters name. |
filter |
One [xl_filter()], or a list of them. Filters on different columns combine with AND, as they do in Excel. |
Value
A logical vector with one element per row of 'data', 'TRUE' where the row stays visible.
Accuracy
This function tracks Excel's *observed* behaviour, so a case found to disagree with Excel is treated as a bug and fixed, which may change the rows it returns. One limitation is known: a filter written as a value list ('"=="' without a wildcard, or 'list') matches the text a cell **displays**, which writexl can only predict for the General format. A numeric column carrying a custom number format may therefore display differently from what is compared here — prefer a comparison such as '">="' on such a column. Dates are refused outright for the same reason. See [xl_filter()].
See Also
[xl_filter], [xl_sheet]
Other worksheet features:
xl_conditional,
xl_filter(),
xl_merge(),
xl_table(),
xl_table_column(),
xl_validation()
Examples
sales <- data.frame(fruit = c("apple", "banana", "cherry"),
qty = c(5, 150, 300))
xl_filter_keep(sales, xl_filter("qty", ">", 100))
sales[xl_filter_keep(sales, xl_filter("fruit", "==", "*a*")), ]
# filters on different columns combine with AND
xl_filter_keep(sales, list(xl_filter("qty", ">", 100),
xl_filter("fruit", "==", "b*")))
Combine cell-formatting groups into a single format
Description
'xl_format()' merges any number of [xl_format] objects (typically the single-group objects returned by [xl_font], [xl_fill], [xl_border], [xl_align], [xl_num_format] and [xl_protection]) into one combined format. The '+' operator does the same for two formats.
Merging is right-biased and works property-by-property: where two formats set the *same* property the later one wins, but properties set by only one side are all preserved. So partial groups accumulate rather than overwrite.
Usage
xl_format(..., quote_prefix = NA, hyperlink = NA)
## S3 method for class 'xl_format'
e1 + e2
Arguments
... |
[xl_format] objects (and/or 'NULL's, which are ignored). May also include the scalar flags 'quote_prefix' and 'hyperlink'. |
quote_prefix |
Logical; treat the cell contents as literal text (as if prefixed with a single quote in Excel). |
hyperlink |
Logical; apply the internal hyperlink style flag (advanced). |
e1, e2 |
[xl_format] objects to combine. |
Value
A combined [xl_format] object.
See Also
[xl_font], [xl_fill], [xl_border], [xl_align], [xl_num_format], [xl_protection], [xl_color]
Other cell formatting:
is_xl_format(),
xl_color(),
xl_format_groups
Examples
xl_format(xl_font(bold = TRUE), xl_border(bottom = "thin"),
xl_num_format("#,##0.00"))
# equivalent, using +
xl_font(bold = TRUE) + xl_border(bottom = "thin") + xl_num_format("#,##0.00")
Cell formatting groups
Description
These constructors build [xl_format] objects, each populating one group of Excel cell-formatting properties. Every property defaults to 'NA', meaning "leave unset"; unset properties are simply not written. Enum-like arguments take lowercase strings and are validated against a fixed set of choices.
Each constructor returns a full 'xl_format', so a single group can be used on its own ('xl_cell_general(1, format = xl_font(bold = TRUE))'), and groups can be combined with '+' (see [xl_format]).
Usage
xl_font(
bold = NA,
italic = NA,
color = NA,
size = NA,
name = NA,
underline = NA,
strikeout = NA,
script = NA,
family = NA,
charset = NA,
outline = NA,
shadow = NA,
condense = NA,
extend = NA,
scheme = NA,
theme = NA,
color_indexed = NA,
font_only = NA
)
xl_fill(background = NA, foreground = NA, pattern = NA, transparency = NA)
xl_border(
all = NA,
left = NA,
right = NA,
top = NA,
bottom = NA,
color = NA,
left_color = NA,
right_color = NA,
top_color = NA,
bottom_color = NA,
diagonal = NA,
diagonal_style = NA,
diagonal_color = NA,
transparency = NA
)
xl_align(
horizontal = NA,
vertical = NA,
wrap = NA,
rotation = NA,
indent = NA,
shrink = NA,
reading_order = NA
)
xl_num_format(format = NA, index = NA)
xl_protection(locked = NA, hidden = NA)
Arguments
bold, italic, strikeout, outline, shadow, condense, extend, font_only |
Logical font flags. |
color, background, foreground, left_color, right_color, top_color, bottom_color, diagonal_color |
A color: an R color name, a hex string, or an integer (see [xl_color]). |
size |
Font size in points (1–409). |
name |
Font name, e.g. '"Calibri"'. |
underline |
One of '"none"', '"single"', '"double"', '"single-accounting"', '"double-accounting"'. |
script |
One of '"super"', '"sub"'. |
family, charset, theme, color_indexed |
Advanced integer font properties (rarely needed). |
scheme |
Font scheme string (advanced). |
pattern |
Fill pattern, e.g. '"solid"', '"light-gray"' (18 choices). When 'background' is supplied and 'pattern' is unset, a '"solid"' pattern is assumed. |
transparency |
Percentage transparency, 0–100. **Charts only**: Excel has no transparency for a cell's fill or border, so this is ignored everywhere except a chart's line and fill (see [xl_chart()]). |
all |
Border style applied to all four sides at once (one of '"none"', '"thin"', '"medium"', '"dashed"', '"dotted"', '"thick"', '"double"', '"hair"', '"medium-dashed"', '"dash-dot"', '"medium-dash-dot"', '"dash-dot-dot"', '"medium-dash-dot-dot"', '"slant-dash-dot"'). |
left, right, top, bottom |
Per-side border styles (override 'all'). |
diagonal |
Diagonal border direction: '"up"', '"down"', '"up-down"'. |
diagonal_style |
Diagonal border style (same choices as 'all'). |
horizontal |
Horizontal alignment: '"left"', '"center"', '"right"', '"fill"', '"justify"', '"center-across"', '"distributed"'. |
vertical |
Vertical alignment: '"top"', '"bottom"', '"center"', '"justify"', '"distributed"'. |
wrap |
Logical; wrap text in the cell. |
rotation |
Text rotation in degrees (-90..90, or 270). |
indent |
Integer indentation level. |
shrink |
Logical; shrink text to fit. |
reading_order |
One of '"default"', '"ltr"', '"rtl"'. |
format |
A number-format string, e.g. '"#,##0.00"', '"0 '"yyyy-mm-dd"'. |
index |
An Excel built-in number-format index (alternative to 'format'). |
locked |
Logical; whether the cell is locked (Excel's default is 'TRUE'). Only takes effect when the worksheet is protected. 'FALSE' unlocks the cell. |
|
Logical; hide the cell's formula. |
Value
An [xl_format] object.
See Also
[xl_format], [xl_color]
Other cell formatting:
is_xl_format(),
xl_color(),
xl_format()
Examples
xl_font(bold = TRUE, color = "navy", size = 12)
xl_fill(background = "#FFF2CC")
xl_border(all = "thin", color = "gray")
xl_align(horizontal = "center", vertical = "top", wrap = TRUE)
xl_num_format("#,##0.00")
xl_protection(locked = FALSE)
Excel Types
Description
* 'xl_formula(x)' — wraps a character vector of Excel formulas (each must start with '"="'). The formulas are written to the xlsx file as-is and are recalculated by Excel on open.
* 'xl_hyperlink(url, name)' — convenience wrapper that builds an Excel '=HYPERLINK(url, name)' **formula** for each element. Because the hyperlink is stored as a formula, it is readable by [readxl::read_xlsx()], which returns the formula text. Display text is controlled by the 'name' argument.
* 'xl_hyperlink_cell(url, value)' — creates a **native cell-level hyperlink** using 'worksheet_write_url_opt()' from libxlsxwriter. The URL is stored as metadata attached to the cell, not in the formula bar. An optional 'value' argument provides the display text shown in the cell. A tooltip and further options can be set by passing a named list to 'xl_cell_general()' directly. **Note:** [readxl::read_xlsx()] cannot read cell-level hyperlinks and returns 'NA' for those cells. Use 'xl_hyperlink()' instead when round-tripping through readxl is required.
Usage
xl_formula(x, format = NULL)
xl_hyperlink(url, value = NULL, format = NULL, name = NULL)
xl_hyperlink_cell(url, value = NULL, format = NULL)
Arguments
x |
character vector to be interpreted as formula |
format |
An optional [xl_format] (or list of 'xl_format', one per element) applied to the cells. See [xl_format]. |
url |
character vector of URLs. Use 'NA' to produce a blank cell. |
value |
character vector (or 'NULL') of display text shown in the cell instead of the URL. When 'NULL' the URL itself is shown. Recycled to the length of 'url', and automatically 'NA' for cells whose URL is 'NA'. The same argument name is used by [xl_hyperlink_cell()] and [xl_cell_general()]. |
name |
**Deprecated.** The former spelling of 'value', kept for backward compatibility. Supplying it warns and points at 'value'; supplying both is an error, since they mean the same thing. 'value' has taken the argument position 'name' used to occupy, so code that passed the display text positionally keeps working unchanged. |
Details
Create special column types to write to a spreadsheet.
See Also
Other cell content:
is_xl_comment(),
xl_cell_general(),
xl_comment(),
xl_rich_run(),
xl_rich_string()
Examples
df <- data.frame(
name = c("UCLA", "Berkeley", "Jeroen"),
founded = c(1919, 1868, 2030),
website = xl_hyperlink(c("http://www.ucla.edu", "http://www.berkeley.edu", NA), "homepage")
)
df$age <- xl_formula('=(YEAR(TODAY()) - INDIRECT("B" & ROW()))')
write_xlsx(df, 'universities.xlsx')
# xl_hyperlink_cell() stores the URL as native cell metadata.
# readxl cannot read these cells, but they display cleanly in Excel.
df2 <- data.frame(
name = c("UCLA", "Berkeley"),
website = xl_hyperlink_cell(c("http://www.ucla.edu", "http://www.berkeley.edu"),
value = "homepage")
)
write_xlsx(df2, 'universities2.xlsx')
# cleanup
unlink(c('universities.xlsx', 'universities2.xlsx'))
Insert an image into a worksheet
Description
'xl_image()' places an image on a sheet, either floating over the cells and anchored to one of them (the default) or, with 'embed = TRUE', inside a cell. Pass one or a list of them as 'xl_sheet(image = )'.
The image may be a file path or a raw vector, which is convenient when a plot has just been written by a graphics device and never touched the disk. PNG, JPEG, GIF and BMP are supported — the formats Excel reads — and the format is detected from the file's own bytes rather than its extension.
Usage
xl_image(
image,
at = "A1",
scale = 1,
offset = NULL,
position = "move_and_size",
description = NULL,
decorative = FALSE,
url = NULL,
tip = NULL,
embed = FALSE,
format = NULL
)
Arguments
image |
The image, in any of four shapes: a path to a PNG, JPEG, GIF or BMP; a raw vector holding one of those encoded; a 'raster' (or anything [grDevices::as.raster()] accepts, such as a colour matrix or an RGB/RGBA array); or a 'nativeRaster'. The last two are what [graphics::rasterImage()] draws, so anything you can plot can be written. |
at |
The cell the image is anchored to, such as '"B2"', or a 'list(rows = , cols = )' spec selecting a single cell. |
scale |
Scale factor: one number for both axes, or 'c(x, y)'. |
offset |
Offset from the anchor cell's top-left corner in pixels, as 'c(x, y)'. |
position |
How the image behaves when rows and columns change size: '"move_and_size"' (the default), '"move_dont_size"', '"dont_move_dont_size"', '"move_and_size_after"', or '"default"' for Excel's own default. Ignored when 'embed = TRUE'. |
description |
Alt text, for screen readers. Excel defaults it to the file name; '""' writes none. |
decorative |
Mark the image as decorative, so screen readers skip it. Excel does not write a description for a decorative image. |
url |
An optional hyperlink the image links to. |
tip |
An optional mouseover tip for 'url'. |
embed |
Place the image inside the cell rather than floating above it. Requires a version of Excel that supports images in cells. |
format |
An [xl_format] for the cell holding an embedded image. Only meaningful with 'embed = TRUE'. |
Value
An 'xl_image' object.
Floating versus embedded
An inserted image floats above the grid: it has a position but occupies no cell, and 'position' decides whether it moves and resizes as rows and columns change. An embedded image ('embed = TRUE') lives *in* a cell and sizes with it, which is the Excel 365 "place in cell" behaviour. Excel versions without that feature show '#VALUE!' in place of an embedded image, so it is worth choosing deliberately.
Caveats inherited from Excel
An image's scaling can shift if it crosses a row whose height changed — for a taller font or wrapped text — so set the height explicitly with [xl_row_spec()] for rows an image spans. BMP is supported only for backward compatibility and must be 24-bit true colour; prefer PNG. SVG is refused, because Excel stores it converted to PNG anyway.
See Also
[xl_sheet]
Other images and charts:
xl_chart(),
xl_chart_axis(),
xl_chart_error_bars(),
xl_chart_labels(),
xl_chart_legend(),
xl_chart_marker(),
xl_chart_series(),
xl_chart_table(),
xl_chart_trendline(),
xl_chartsheet()
Examples
logo <- system.file("help", "figures", "logo.png", package = "writexl")
if (nzchar(logo)) {
xl_image(logo, at = "C2", scale = 0.5)
xl_image(logo, at = "C2", url = "https://example.com", tip = "Home")
}
Merge a range of cells
Description
‘xl_merge()' merges a rectangle of cells into one, as Excel’s "Merge and Centre" does. Pass one or a list of them as 'xl_sheet(merge = )'.
A merged range holds a single value, so 'xl_merge()' carries its own 'value' rather than taking it from the data frame. Merging over cells the data frame filled keeps only the merged value, exactly as merging in Excel discards everything but the top-left value.
Usage
xl_merge(range, value = NULL, format = NULL)
Arguments
range |
The cells to merge: an Excel range string such as '"A1:C1"', or a 'list(rows = , cols = )' spec. It must cover more than one cell — Excel has no single-cell merge. |
value |
The value shown in the merged cell: a string, or anything with an [as.character()] method such as an [xl_rich_string()]. 'NULL' leaves the cell empty. |
format |
An optional [xl_format] applied to the whole merged range. Merged cells usually want 'xl_align(horizontal = "center")'. |
Value
An 'xl_merge' object.
See Also
[xl_sheet], [xl_format]
Other worksheet features:
xl_conditional,
xl_filter(),
xl_filter_keep(),
xl_table(),
xl_table_column(),
xl_validation()
Examples
xl_merge("A1:C1", "Quarterly results",
format = xl_align(horizontal = "center") + xl_font(bold = TRUE))
df <- data.frame(a = 1:3, b = 4:6)
sheet <- xl_sheet(df, merge = xl_merge("A5:B5", "Total",
format = xl_font(bold = TRUE)))
tmp <- write_xlsx(list(Data = sheet))
Control how outline (grouping) symbols are drawn
Description
Grouping itself comes from 'level' in [xl_col_spec()] / [xl_row_spec()]. 'xl_outline()' only changes how the controls are *displayed*, which is rarely needed — the defaults match Excel's own.
Usage
xl_outline(
visible = TRUE,
symbols_below = TRUE,
symbols_right = TRUE,
auto_style = FALSE
)
Arguments
visible |
Show the outline symbols at all. 'FALSE' keeps the grouping (and so the collapsing) but hides the +/- controls. |
symbols_below |
Put the summary row *below* the detail rows, which is Excel's default. 'FALSE' puts it above. |
symbols_right |
Put the summary column to the *right* of the detail columns, Excel's default. 'FALSE' puts it to the left. |
auto_style |
Apply Excel's automatic outline styling to the grouped rows and columns. |
Value
An ‘xl_outline' object, for [xl_sheet()]’s 'outline' argument.
See Also
[xl_sheet], [xl_colrow_spec]
Other worksheet layout:
xl_colrow_spec,
xl_page_setup(),
xl_sheet(),
xl_sheet_view()
Examples
xl_outline(symbols_below = FALSE)
xl_outline(visible = FALSE)
How a worksheet prints
Description
‘xl_page_setup()' collects Excel’s page-layout settings for one worksheet: orientation, paper size, margins, scaling, centring, the print options, and the header and footer. Pass it as 'xl_sheet(page = )'.
None of these affect the cell data — they change only how the sheet prints and how it looks in Excel's page-break preview.
Usage
xl_page_setup(
orientation = NA,
paper = NA,
margins = NULL,
scale = NA,
fit_to = NULL,
center_horizontally = NA,
center_vertically = NA,
header = NA,
footer = NA,
header_margin = NA,
footer_margin = NA,
header_image = NULL,
footer_image = NULL,
page_view = NA,
first_page = NA,
across = NA,
black_and_white = NA,
row_col_headers = NA,
print_area = NULL,
repeat_rows = NA,
repeat_cols = NA,
h_breaks = NULL,
v_breaks = NULL
)
Arguments
orientation |
'"portrait"' or '"landscape"'. |
paper |
Paper size: a name ('"A4"', '"letter"', '"legal"', '"tabloid"', '"ledger"', '"statement"', '"executive"', '"A3"', '"A5"', '"B4"', '"B5"', '"folio"', '"quarto"', '"default"'), or an Excel paper-type integer for the envelope and specialist sizes that have no name here. |
margins |
Page margins in inches: a single number for all four sides, four numbers in the order left, right, top, bottom, or a named vector using any of 'left', 'right', 'top', 'bottom'. |
scale |
Print scaling as a percentage (10–400). Ignored by Excel when 'fit_to' is set. |
fit_to |
Fit the printout to 'c(width, height)' pages. A '0' means "as many pages as needed in that direction", so 'c(width = 1, height = 0)' is Excel's "fit all columns on one page". |
center_horizontally, center_vertically |
Logical; centre the printed output on the page. |
header, footer |
Header and footer text, at most 255 characters, using Excel's own codes: '&L', '&C', '&R' start the left, centre and right sections, '&P' is the page number, '&N' the page count, '&D' the date, '&A' the sheet name, and '&&' a literal ampersand. For example '"&LQ1 report&RPage &P of &N"'. Image placeholders ('&G' / '&[Picture]') are not supported yet and are rejected. |
header_margin, footer_margin |
Header/footer margin in inches (Excel's default is 0.3). Must be greater than 0. |
header_image, footer_image |
Images to place in the header or footer, named by position: 'list(left = , center = , right = )'. Each may be a file path, a raw vector, or an in-memory image, exactly as [xl_image()] accepts. Each image needs a matching '&G' placeholder in the corresponding section of 'header'/'footer' — '"&L&G"' puts one on the left — and the counts must agree. |
page_view |
Logical; open the sheet in Excel's page-layout view rather than normal view. |
first_page |
The page number to start numbering from. |
across |
Logical; print pages left-to-right before top-to-bottom (Excel's "over, then down"). |
black_and_white |
Logical; print without colour. |
row_col_headers |
Logical; print the row numbers and column letters. |
print_area |
The range to print: an Excel range string such as '"A1:F50"', or a 'list(rows = , cols = )' spec naming data rows and columns, as elsewhere in writexl. |
repeat_rows, repeat_cols |
Rows/columns to repeat at the top or left of every printed page. Either a count ('repeat_rows = 1' repeats the first sheet row, which is the header when 'col_names = TRUE') or a range string ('"1:2"', '"A:B"'). Note these count *sheet* rows from 1 with the header included, unlike [xl_row_spec()], which indexes data rows — repeating the header row is the usual reason to use this, and data-row numbering could not name it. |
h_breaks, v_breaks |
Manual page breaks: 1-based sheet positions at which a new page starts, so 'h_breaks = 21' breaks between rows 20 and 21. 'v_breaks' also accepts column letters. Positions must be 2 or greater, and at most 1023 breaks are allowed. Excel ignores manual breaks when 'fit_to' is set, which warns. |
Value
An 'xl_page_setup' object.
See Also
[xl_sheet], [write_xlsx]
Other worksheet layout:
xl_colrow_spec,
xl_outline(),
xl_sheet(),
xl_sheet_view()
Examples
xl_page_setup(orientation = "landscape", paper = "A4",
fit_to = c(width = 1, height = 0))
# margins in inches, and a header with page numbers
xl_page_setup(margins = c(left = 1, right = 1),
header = "&LQuarterly report&RPage &P of &N")
df <- data.frame(x = 1:3)
tmp <- write_xlsx(list(Data = xl_sheet(df, page = xl_page_setup(
orientation = "landscape", header = "&CDraft"
))))
Workbook properties, defaults, and metadata
Description
'xl_properties()' collects everything that applies at the *workbook* level: document metadata, a few native workbook settings, and the formatting defaults that used to be hard-coded. The formatting defaults are ordinary [xl_format] objects, so you can override them (e.g. change the header style or the default date format) simply by passing a different 'xl_format'.
The 'default_format' is cascaded *under* every cell (an emulated workbook-wide default: libxlsxwriter has no native "Normal style" setter, so it is merged beneath each cell/column format). 'header_format' styles the header row and 'hyperlink_format' styles cell hyperlinks; both are also cascaded over 'default_format'.
Usage
xl_properties(
title = NA,
subject = NA,
author = NA,
manager = NA,
company = NA,
category = NA,
keywords = NA,
comments = NA,
status = NA,
hyperlink_base = NA,
created = NA,
na = NA,
custom = NULL,
read_only = FALSE,
window_size = NULL,
names = NULL,
default_format = xl_format(),
header_format = xl_font(bold = TRUE) + xl_align(horizontal = "center"),
hyperlink_format = xl_font(color = "blue", underline = "single"),
date_format = xl_num_format("yyyy-mm-dd"),
datetime_format = .default_datetime_format(),
date_col_width = 20,
datetime_col_width = 20,
header_row_height = 15
)
Arguments
title, subject, author, manager, company, category, keywords, comments, status, hyperlink_base |
Document metadata strings (Excel's "Properties" dialog). |
created |
The workbook's creation timestamp, a 'Date' or 'POSIXct'. Left 'NA' libxlsxwriter stamps the moment the file is written, which is what makes two runs over the same data differ; pinning it makes them byte-identical. |
na |
What to write where a value has none — an 'NA' or 'NaN' in the data, or a cell with nothing in it at all. 'NA' (the default) leaves the cell blank, which is what writexl has always done. Anything else is written in its place, keeping its own type: 'na = "Not available"' writes a string, 'na = 0' a number. A column or an individual cell can override it — see [xl_col_spec()] and [xl_cell_general()]. Note that a non-blank 'na' in a numeric column makes that column mixed, so a reader such as [readxl::read_xlsx()] returns the whole column as character. |
custom |
A named list of custom document properties. Values may be character, integer, numeric, logical, 'Date' or 'POSIXct'. A 'Date' or 'POSIXct' is written as a real datetime property (not as text) and follows the same workbook-wide time zone rule as datetime cells, described below. |
read_only |
Logical; mark the workbook read-only recommended. |
window_size |
Optional integer vector 'c(width, height)' for the workbook window size. |
names |
A named list of workbook-scoped defined names, each a formula string (e.g. 'list(tax = "=0.2")'). |
default_format |
An [xl_format] cascaded under every cell (default: none). |
header_format |
An [xl_format] for the header row (default: bold, centered). |
hyperlink_format |
An [xl_format] for cell hyperlinks (default: blue, underlined), or 'NULL' for no hyperlink styling at all. 'NULL' is the only way to write an unstyled hyperlink: an empty 'xl_format()' leaves the cell with no format, and Excel files written that way fall back to libxlsxwriter's own blue-underlined default. |
date_format, datetime_format |
[xl_format] number formats applied to 'Date' / 'POSIXct' values. |
date_col_width, datetime_col_width |
Default column width for 'Date' / 'POSIXct' columns. |
header_row_height |
Height (in points) of the header row. |
Value
An 'xl_properties' object.
Time zones
Excel has no concept of a time zone. When every 'POSIXct' in the workbook shares one time zone, writexl drops the zone and writes local wall-clock time, and the default 'datetime_format' loses its '" UTC"' suffix so that nothing is mislabelled. When the time zones differ, all datetimes are converted to UTC with a warning. Supplying your own 'datetime_format' overrides the label in either case.
See Also
[xl_workbook], [write_xlsx]
Other workbook settings:
write_xlsx(),
xl_workbook()
Examples
xl_properties(title = "Quarterly report", author = "Finance",
header_format = xl_font(bold = TRUE, color = "white") +
xl_fill(background = "navy"))
One run of a rich (multi-format) string
Description
'xl_rich_run()' is one fragment of an [xl_rich_string()]: a piece of text plus the font it is drawn in.
Usage
xl_rich_run(value, format = NULL)
Arguments
value |
A single non-‘NA', non-empty string: the run’s text. |
format |
An optional [xl_format]. Only its **font** properties apply (see [xl_font()]); a run has no fill, border, alignment or number format, and supplying one warns. ‘NULL' draws the run in the cell’s own font. |
Value
An 'xl_rich_run' object.
See Also
[xl_rich_string], [xl_format]
Other cell content:
is_xl_comment(),
xl_cell_general(),
xl_comment(),
xl_formula(),
xl_rich_string()
Examples
xl_rich_run("bold", xl_font(bold = TRUE))
xl_rich_run("plain")
A cell whose text has several formats
Description
'xl_rich_string()' builds the value of a single cell out of differently formatted runs, so that one cell can read "This is **bold** text". Pass it as the 'value' of [xl_cell_general()].
Excel requires at least two runs: a string with one format is an ordinary character value, so pass it as one.
‘as.character()' returns the cell’s text with the per-run fonts dropped.
Usage
xl_rich_string(...)
is_xl_rich_string(x)
## S3 method for class 'xl_rich_string'
as.character(x, ...)
Arguments
... |
Runs, in order. A bare string is taken as an unformatted run; an [xl_rich_run()] carries its own font. Lists of either are flattened, so runs can be assembled programmatically. |
x |
An object to test. |
Value
An 'xl_rich_string' object: a list of runs.
See Also
[xl_rich_run], [xl_cell_general], [xl_font]
Other cell content:
is_xl_comment(),
xl_cell_general(),
xl_comment(),
xl_formula(),
xl_rich_run()
Examples
xl_rich_string("This is ", xl_rich_run("bold", xl_font(bold = TRUE)), " text")
# in a cell, with a cell-wide format alongside the per-run fonts
xl_cell_general(
value = xl_rich_string("2 H", xl_rich_run("2", xl_font(script = "sub")), "O"),
format = xl_align(horizontal = "center")
)
A worksheet with formatting and layout options
Description
'xl_sheet()' wraps a data frame together with worksheet-level options (column/row formatting and geometry, frozen panes, gridlines, tab color, zoom). Pass it anywhere [write_xlsx()] accepts a data frame; a plain data frame continues to behave exactly as before.
Usage
xl_sheet(
data,
cols = NULL,
rows = NULL,
freeze = NULL,
gridlines = NA,
tab_color = NA,
zoom = NA,
default_row_height = NA,
auto_colwidth = FALSE,
autofilter = FALSE,
protect = FALSE,
comment_author = NA,
show_comments = FALSE,
page = NULL,
view = NULL,
merge = NULL,
validation = NULL,
conditional = NULL,
filter = NULL,
outline = NULL,
ignore_errors = NULL,
table = NULL,
image = NULL,
background_image = NULL,
chart = NULL
)
Arguments
data |
A data frame (the sheet contents). |
cols |
An [xl_col_spec()], or a list of them. |
rows |
An [xl_row_spec()], or a list of them. |
freeze |
Frozen panes: an Excel cell reference such as '"A2"' (freeze the rows above and columns left of that cell), or 'list(row =, col =)' giving the number of rows/columns to freeze. |
gridlines |
Logical; show ('TRUE') or hide ('FALSE') screen gridlines. ‘NA' leaves Excel’s default. |
tab_color |
Sheet tab color (see [xl_color]). |
zoom |
Zoom level as a percentage (10–400). |
default_row_height |
Default height (in points) for rows in the sheet. |
auto_colwidth |
If 'TRUE', size each column to fit its contents (a character-count heuristic, since the xlsx format has no true "AutoFit"). Columns given an explicit width via [xl_col_spec()] are left untouched. |
autofilter |
Add an autofilter (filter dropdowns). 'TRUE' covers the whole used range (header plus data); an Excel range string such as '"A1:D51"' restricts it; 'FALSE' (default) adds none. |
protect |
Protect the worksheet: 'FALSE' (default) leaves it unprotected, 'TRUE' applies the standard protection, and a string sets a password. A named list gives fine-grained control, e.g. 'list(password = "secret", format_cells = TRUE)'; an editing option set to 'TRUE' *allows* that action on the protected sheet. Available option names: 'format_cells', 'format_columns', 'format_rows', 'insert_columns', 'insert_rows', 'insert_hyperlinks', 'delete_columns', 'delete_rows', 'sort', 'autofilter', 'pivot_tables', 'scenarios', 'objects', 'no_select_locked_cells', 'no_select_unlocked_cells'. Cell locking via [xl_protection()] only has an effect on a protected sheet. |
comment_author |
Default author for this sheet's cell comments (a per-comment 'author' overrides it). |
show_comments |
If 'TRUE', all comments on the sheet are initially shown (individual comments can still be forced via 'xl_comment(visible=)'). |
page |
An [xl_page_setup()] describing how the sheet prints (orientation, paper size, margins, scaling, header and footer). Affects printing only, never the cell data. |
view |
An [xl_sheet_view()] describing the sheet's tab state and opening view (active/selected/hidden tab, selection, scroll position, zero display, direction, split panes). |
merge |
One [xl_merge()], or a list of them, merging rectangles of cells into single cells. Merges are applied after the sheet's rows are written, so a merge over cells the data frame filled keeps only the merged text — as merging in Excel does. Any merge turns off the memory-efficient row-streaming mode, since it writes back over rows already emitted. |
validation |
One [xl_validation()], or a list of them, restricting what may be typed into a range — a dropdown, a numeric or date bound, a text length limit or a custom formula. |
conditional |
One conditional format ([xl_cond_cell()], [xl_cond_scale()], [xl_cond_bar()], [xl_cond_icons()]), or a list of them, formatting cells according to their contents. |
filter |
One [xl_filter()], or a list of them, setting autofilter criteria. Each also hides the rows it excludes, because Excel does not apply a filter when a file is opened — criteria on their own produce a sheet that looks filtered but shows every row. Implies 'autofilter = TRUE' over the used range when 'autofilter' is not set separately. |
outline |
An [xl_outline()] controlling how the grouping symbols created by 'level' in [xl_col_spec()] / [xl_row_spec()] are drawn. It changes their display only, never which rows are grouped. |
ignore_errors |
A named list turning off the green error triangle Excel shows in cells it believes are wrong. Each name is an error type and each value a range, e.g. 'list(number_stored_as_text = "A2:A99")'. Types: 'number_stored_as_text', 'eval_error', 'formula_differs', 'formula_range', 'formula_unlocked', 'empty_cell_reference', 'list_data_validation', 'calculated_column', 'two_digit_text_year'. |
table |
One [xl_table()], or a list of them, turning a range into an Excel table — a named, styled block with banded rows, a filter dropdown and an optional total row. Any table turns off the memory-efficient row-streaming mode, which libxlsxwriter refuses to combine with tables. |
image |
One [xl_image()], or a list of them, placing images on the sheet — floating over the cells, or inside a cell with 'embed = TRUE'. |
background_image |
An image tiled behind the sheet's cells, in any shape [xl_image()] accepts. It is a screen backdrop only — Excel never prints it. |
chart |
One [xl_chart()], or a list of them, placed on the sheet and anchored to a cell. A chart's series may plot data from any sheet in the workbook, not only this one. |
Value
An 'xl_sheet' object.
See Also
[xl_col_spec], [xl_row_spec], [write_xlsx]
Other worksheet layout:
xl_colrow_spec,
xl_outline(),
xl_page_setup(),
xl_sheet_view()
Examples
df <- data.frame(name = c("a", "b"), revenue = c(1000.5, 2000.25))
sheet <- xl_sheet(
df,
cols = xl_col_spec("revenue", width = 14, format = xl_num_format("#,##0.00")),
freeze = "A2",
tab_color = "steelblue"
)
tmp <- write_xlsx(list(Data = sheet))
How a worksheet appears when it opens
Description
‘xl_sheet_view()' collects a worksheet’s tab state and opening view: which tab is active, selected or hidden, where the sheet is scrolled and selected, and a few display options. Pass it as 'xl_sheet(view = )'.
None of these affect the cell data.
Usage
xl_sheet_view(
active = NA,
selected = NA,
visible = NA,
first_tab = NA,
selection = NULL,
top_left = NULL,
hide_zero = NA,
right_to_left = NA,
split = NULL
)
Arguments
active |
Logical; make this the tab Excel opens on. At most one sheet in a workbook may be active. |
selected |
Logical; include this tab in the selected group. The active sheet is always selected. |
visible |
Logical; ‘FALSE' hides the sheet’s tab. A hidden sheet cannot be active or selected, the first sheet cannot be hidden unless another is made active, and at least one sheet must stay visible or Excel will not open the file. All four rules are checked before writing. |
first_tab |
Logical; make this the leftmost visible tab in the tab strip. Independent of which sheet is active. |
selection |
The cell or range selected when the sheet opens, as an Excel reference ('"B2"', '"B2:D10"') or a 'list(rows = , cols = )' spec. Excel also uses the order of a selection's corners to mark which cell in it is active; writexl does not expose that, because ranges are normalised by the shared range parser, which rejects an inverted range. |
top_left |
The cell scrolled to the top-left of the window when the sheet opens, as an Excel reference such as '"A5"'. |
hide_zero |
Logical; display zero values as blank cells. |
right_to_left |
Logical; order the columns right to left, for a sheet in a right-to-left language. |
split |
Split the sheet into scrollable panes with a visible, movable divider, given as the cell reference the split sits above and to the left of — '"B3"' splits above row 3 and left of column B. Mutually exclusive with 'xl_sheet(freeze = )', which does the same thing without the divider. libxlsxwriter positions a split by distance, in row-height and column-width units, not by row and column number. writexl converts the cell reference using the sheet's actual row heights and column widths, so the split lands where you asked even after resizing. Pass 'list(vertical = , horizontal = )' to give those units directly. Note that libxlsxwriter derives the pane's scroll anchor back from that distance assuming default row heights, so on a sheet with resized rows or columns the divider is placed correctly but the anchor cell may be a row or two out. |
Value
An 'xl_sheet_view' object.
See Also
[xl_sheet], [xl_page_setup]
Other worksheet layout:
xl_colrow_spec,
xl_outline(),
xl_page_setup(),
xl_sheet()
Examples
xl_sheet_view(active = TRUE, selection = "B2")
xl_sheet_view(visible = FALSE)
df <- data.frame(x = 1:3)
tmp <- write_xlsx(list(
Summary = xl_sheet(df, view = xl_sheet_view(active = TRUE)),
Working = xl_sheet(df, view = xl_sheet_view(visible = FALSE))
))
Add a worksheet table
Description
'xl_table()' turns a range into an Excel table: a named, styled block with banded rows, a filter dropdown in its header, and an optional total row. Pass one or a list of them as 'xl_sheet(table = )'.
Column headers default to the data frame's column names. That is not just a convenience: Excel records a table's column names separately from the header cells and rejects a file where the two disagree, so the default is what makes a table safe to add at all.
Usage
xl_table(
range = NULL,
name = NULL,
style = "medium 9",
header_row = TRUE,
autofilter = TRUE,
banded_rows = TRUE,
banded_columns = FALSE,
first_column = FALSE,
last_column = FALSE,
total_row = FALSE,
columns = NULL
)
Arguments
range |
The cells the table covers, as an Excel range string or a ‘list(rows = , cols = )' spec. Defaults to the sheet’s used range, including the header row and, with 'total_row = TRUE', one row below. |
name |
The table's name. See "Table names". |
style |
The table style: '"none"', or a type and number such as '"medium 9"' (the default), '"light 21"' or '"dark 11"'. Light styles are numbered 0–21, medium 1–28 and dark 1–11. |
header_row |
Show the header row. Turning it off also removes the filter dropdown, as it does in Excel. |
autofilter |
Show the filter dropdown in the header row. |
banded_rows, banded_columns |
Alternating row / column shading. |
first_column, last_column |
Highlight the first / last column. |
total_row |
Add a total row below the data. See "The total row". |
columns |
One [xl_table_column()], or a list of them, overriding individual columns. |
Value
An 'xl_table' object.
Table names
Excel requires table names to be unique across the workbook, and formulas refer to a table by name. 'name = NULL' (the default) has writexl generate a unique name from the sheet name and write it explicitly, so it cannot shift when another table is added elsewhere. Give a string to choose your own; it is validated and checked for collisions. Give 'NA' to write no name at all and let Excel assign 'Table1', 'Table2', ... by insertion order — which makes any formula naming the table fragile, so that combination warns.
The total row
A total row is written by libxlsxwriter below the data, and the sheet's row plan does not know about it: 'auto_colwidth' does not measure it, and an [xl_row_spec()] aimed at that row will fight it. It has no cells of its own until a column gives a 'total' or 'total_label'.
See Also
[xl_table_column], [xl_sheet]
Other worksheet features:
xl_conditional,
xl_filter(),
xl_filter_keep(),
xl_merge(),
xl_table_column(),
xl_validation()
Examples
xl_table(style = "light 9")
xl_table(name = "Sales", total_row = TRUE,
columns = list(xl_table_column("fruit", total_label = "Total"),
xl_table_column("qty", total = "sum")))
Describe a column of a worksheet table
Description
'xl_table_column()' overrides what [xl_table()] does with one column: its header caption, a formula filling the column, what its total-row cell shows, and the formats applied to the header and the data cells.
Only the columns you name need an entry; the rest take the data frame's column name as their header and are left otherwise alone.
Usage
xl_table_column(
col,
header = NULL,
formula = NULL,
total = NULL,
total_label = NULL,
total_value = NULL,
format = NULL,
header_format = NULL
)
Arguments
col |
The column: a name or a 1-based position within the table's range. |
header |
The header caption. Defaults to the data frame's column name — which is also what makes a table safe to add, since Excel rejects a file whose table definition and header cells disagree. |
formula |
A formula filling every data cell of the column, usually with a structured reference such as '"=SUM(Sales[@[Q1]:[Q4]])"'. Because those name the table, see the 'name' argument of [xl_table()]. |
total |
The function shown in this column's total-row cell: one of '"sum"', '"average"', '"count"', '"count_nums"', '"max"', '"min"', '"std_dev"' or '"var"'. Needs 'total_row = TRUE' on the table. |
total_label |
A string for the total-row cell instead of a function — typically '"Total"' under the first column. |
total_value |
The number the total-row cell already holds. Excel recalculates 'total' on open and ignores this, but a reader that does not evaluate formulas — [readxl::read_xlsx()] among them — shows what is cached, which without this is nothing. |
format |
An [xl_format] applied to the column's data cells. |
header_format |
An [xl_format] applied to the column's header cell. |
Value
An 'xl_table_column' object.
See Also
[xl_table], [xl_sheet]
Other worksheet features:
xl_conditional,
xl_filter(),
xl_filter_keep(),
xl_merge(),
xl_table(),
xl_validation()
Examples
xl_table_column("qty", total = "sum")
xl_table_column("fruit", total_label = "Total")
xl_table_column("margin", formula = "=Sales[@revenue] * 0.3")
Restrict what can be typed into a range
Description
'xl_validation()' adds Excel data validation to a range: a dropdown list, a numeric or date bound, a text-length limit, or a custom formula. Pass one or a list of them as 'xl_sheet(validation = )'.
Excel's 17 internal validation types are collapsed into the five 'type' kinds below. Whether a limit is a literal, a cell formula or a date is inferred from what you pass: a string starting with '"="' is a formula, and a 'Date' or 'POSIXct' is a date/time bound.
Usage
xl_validation(
range,
type = "any",
criteria = NA,
value = NULL,
min = NULL,
max = NULL,
list = NULL,
input_title = NA,
input_message = NA,
error_title = NA,
error_message = NA,
error_type = NA,
ignore_blank = NA,
show_input = NA,
show_error = NA,
dropdown = NA
)
Arguments
range |
The cells to validate: an Excel range string such as '"B2:B100"', a single cell, or a 'list(rows = , cols = )' spec. |
type |
The kind of value allowed: '"integer"', '"decimal"', '"date"', '"time"', '"length"' (of the text entered), '"custom"' (any formula that must evaluate 'TRUE'), or '"any"' (no restriction, useful when you only want the input message). Ignored when 'list' is given. |
criteria |
How 'value' (or 'min'/'max') limits the entry: '"between"', '"not between"', '"=="', '"!="', '">"', '"<"', '">="' or '"<="'. Required for the numeric, date, time and length kinds; must not be given for 'list', 'custom' or 'any', which carry their own meaning. Supplying 'min' and 'max' implies '"between"'. |
value |
The single limit the criteria applies to. A number, a 'Date' or 'POSIXct', or a '"=..."' formula. |
min, max |
The two limits for '"between"' / '"not between"'. Supplying both and omitting 'criteria' implies '"between"'. |
list |
A dropdown of allowed values: a character vector of choices, or a single '"=..."' formula naming a range that holds them. The choices are stored joined by commas, and Excel limits that joined string to 255 characters. |
input_title, input_message |
Text shown in a tooltip when the cell is selected. Titles are limited to 32 characters and messages to 255. |
error_title, error_message |
Text shown when an invalid entry is made. Same limits. |
error_type |
What Excel does on an invalid entry: '"stop"' (refuse it), '"warning"' or '"information"' (both allow it through). |
ignore_blank |
Logical; allow an empty cell. 'TRUE' by default, as in Excel. |
show_input, show_error |
Logical; whether the input tooltip and the error alert are shown at all. Both 'TRUE' by default. |
dropdown |
Logical; show the in-cell dropdown arrow for a 'list' validation. 'TRUE' by default. |
Value
An 'xl_validation' object.
See Also
[xl_sheet]
Other worksheet features:
xl_conditional,
xl_filter(),
xl_filter_keep(),
xl_merge(),
xl_table(),
xl_table_column()
Examples
# a dropdown
xl_validation("C2:C100", list = c("open", "high", "close"))
# a numeric bound, with the message Excel shows on a bad entry
xl_validation("B2:B100", type = "integer", min = 1, max = 10,
error_message = "Enter a whole number from 1 to 10")
# a date bound
xl_validation("D2:D100", type = "date", criteria = ">=",
value = as.Date("2024-01-01"))
df <- data.frame(qty = 1:3)
tmp <- write_xlsx(list(Data = xl_sheet(df,
validation = xl_validation("A2:A4", type = "integer", min = 0, max = 99))))
A workbook: sheets plus workbook-level properties
Description
'xl_workbook()' binds one or more sheets (data frames or [xl_sheet]s) to a set of [xl_properties]. It is the single place to attach workbook-level formatting defaults and metadata. When passed to [write_xlsx()], the workbook's 'col_names' and 'format_headers' settings take precedence over ‘write_xlsx()'’s own arguments.
Usage
xl_workbook(
sheets,
properties = xl_properties(),
col_names = TRUE,
format_headers = TRUE
)
Arguments
sheets |
A data frame, an [xl_sheet], or a (named) list of them. |
properties |
An [xl_properties] object. |
col_names |
write column names as the header row at the top of the sheet? |
format_headers |
apply the workbook's header format to that header row?
The default header format is bold and centered; change it with
|
Value
An 'xl_workbook' object.
See Also
[xl_properties], [xl_sheet], [write_xlsx]
Other workbook settings:
write_xlsx(),
xl_properties()
Examples
wb <- xl_workbook(
list(Data = data.frame(x = 1:3)),
properties = xl_properties(title = "Demo", author = "me")
)
tmp <- write_xlsx(wb)