Code
sub_path <- file.path("output", "officer-sections")
dir.create(sub_path, showWarnings = FALSE, recursive = TRUE)sub_path <- file.path("output", "officer-sections")
dir.create(sub_path, showWarnings = FALSE, recursive = TRUE)By default, the layout options of a Word file (orientation, margins, column organization, headers and footers, etc.) affect all pages of a document.
However, you may need to combine several different layouts within the same document. For example:
To achieve this complex layout, Word provides sections. These are large sets of pages that occupy the highest hierarchical level in document organization, allowing you to define specific layout parameters for distinct parts of your document.
A section is a grouping of blocks (paragraphs and tables) that have a set of properties defining how pages will appear. Section properties store information about:
A section affects preceding paragraphs or tables:
This means when you add a section break, you’re defining the properties for the content that came before the break, not after it.
When creating multiple sections in a document, it is strongly recommended to use the same page_mar() object and same page_size() object for all sections to avoid unwanted page breaks.
Changing page margins or page sizes between sections can cause Word to insert automatic page breaks, even when using type = "continuous". This can result in unwanted blank pages.
Best practice: Create single page_mar() and page_size() objects at the start of your script and reuse them across all prop_section() calls.
Here’s the correct pattern demonstrated in our patient profile reports:
# Define margins and sizes ONCE at the beginning
std_margins <- page_mar(top = 1, bottom = 1, left = 1, right = 1)
portrait_size <- page_size(orient = "portrait")
landscape_size <- page_size(orient = "landscape")
# Reuse these objects in ALL section definitions
sect_portrait <- prop_section(
page_size = portrait_size,
page_margins = std_margins, # Same margins
type = "oddPage"
)
sect_landscape <- prop_section(
page_size = landscape_size,
page_margins = std_margins, # Same margins
type = "oddPage"
)To format content in a section, use the body_end_block_section() function. This function takes a block_section object, which in turn wraps a prop_section object that defines the section properties.
Let’s create a document with a graphic on a landscape page:
library(ggplot2)
gg <- ggplot(data = iris, aes(Sepal.Length, Petal.Length)) +
geom_point()
# Define consistent margins
std_margins <- page_mar(top = 1, bottom = 1, left = 1, right = 1)
# Start document and add graphic
doc_section_1 <- read_docx()
doc_section_1 <- body_add_gg(
x = doc_section_1, value = gg,
width = 9, height = 6,
style = "centered"
)
# Add section break to make previous content landscape
ps <- prop_section(
page_size = page_size(orient = "landscape"),
page_margins = std_margins, # Use consistent margins
type = "continuous"
)
doc_section_1 <- body_end_block_section(
x = doc_section_1,
value = block_section(property = ps)
)Now add more content that will be in the default (portrait) section:
Click to download output/officer-sections/example_landscape_gg.docx.
Section properties are defined with the prop_section() function with these key arguments:
page_size
Page dimensions defined with page_size(). Common uses:
page_size(orient = "portrait") # Default
page_size(orient = "landscape") # For wide tablespage_margins
Page margins defined with page_mar(). Critical: Use the same object across all sections!
std_margins <- page_mar(top = 1, bottom = 1, left = 1, right = 1)type
Section type defining how content is placed relative to the previous section:
"continuous": Begins on the next paragraph (no page break)"nextPage": Begins on the following page"oddPage": Begins on the next odd-numbered page"evenPage": Begins on the next even-numbered page"nextColumn": Begins on the next column"continuous": Most common; keeps content flowing without forced page breaks"oddPage" / "evenPage": Useful for chapters that must start on odd/even pages"nextPage": Simple page break behaviorsection_columns
Column configuration defined with section_columns():
section_columns(widths = c(4, 4)) # Two equal columnsThe standard approach for managing sections uses a sequential bracketing pattern:
Let’s illustrate with a graphic that needs landscape orientation:
# Define consistent properties
std_margins <- page_mar(top = 1, bottom = 1, left = 1, right = 1)
portrait_props <- prop_section(
page_size = page_size(orient = "portrait"),
page_margins = std_margins,
type = "continuous"
)
landscape_props <- prop_section(
page_size = page_size(orient = "landscape"),
page_margins = std_margins, # Same margins!
type = "continuous"
)
doc_section_2 <- read_docx() |>
# 1. Add portrait content
body_add_par("This is a dummy text. It is in the default portrait section.") |>
# 2. Close default section (starts special section)
body_end_block_section(block_section(portrait_props)) |>
# 3. Add landscape content
body_add_gg(value = gg, width = 9, height = 6, style = "centered") |>
# 4. Close landscape section (returns to default)
body_end_block_section(block_section(landscape_props))
print(doc_section_2, target = file.path(sub_path, "example_landscape_gg2.docx"))Click to download output/officer-sections/example_landscape_gg2.docx.
Let’s create a document with a table in landscape, followed by text in two columns (also landscape):
# Consistent margins
std_margins <- page_mar(top = 1, bottom = 1, left = 1, right = 1)
# Landscape, single column
landscape_one_column <- block_section(
prop_section(
page_size = page_size(orient = "landscape"),
page_margins = std_margins,
type = "continuous"
)
)
# Landscape, two columns
landscape_two_columns <- block_section(
prop_section(
page_size = page_size(orient = "landscape"),
page_margins = std_margins, # Same margins!
type = "continuous",
section_columns = section_columns(widths = c(4, 4))
)
)
doc_section_3 <- read_docx() |>
body_add_table(value = head(mtcars), style = "table_template") |>
body_end_block_section(value = landscape_one_column) |>
body_add_par(value = paste(rep(letters, 60), collapse = " ")) |>
body_end_block_section(value = landscape_two_columns)
print(doc_section_3, target = file.path(sub_path, "example_complex_section.docx"))Click to download output/officer-sections/example_complex_section.docx.