Reputation: 1275
Often I find that a large proportion of my work consists of summarising data in excel sheets.
I use R to do my calculations and then paste the data to Excel because that's what my organisation uses.
I have not found a good way to do this with multi-headed data.
for example, a typical workflow would look like this:
my_data <- crossing(
year = 2010:2020,
region = LETTERS[1:10],
type = paste("Type ", c("I", "II", "III"))) %>%
mutate(value = runif(n = n()))
my_calculation <- my_data %>%
mutate(
.by = c(year, type),
share = value/sum(value))
my_table <- my_calculation %>%
pivot_wider(names_from = region, values_from = c(value, share))
write.table(my_table, "clipboard", sep = "\t", row.names = FALSE)
this, I would copy to Excel and then manually reformat:
What I am looking for is a package that will help me with handling the multi-headed tables.
I know that there are various packages that can produce multi-headed tables, but they produce HTML output; nothing that can be easily pasted into Excel.
For example, the code below would produce such a multi-headed table, but I don't know a simple way to paste this into an Excel sheet.
ft <- my_table %>% flextable::flextable() %>%
ftExtra::span_header()
If I mark everything and paste to Excel, every cell value, all content will be in the first row.
Upvotes: 0
Views: 46
Reputation: 4147
You could use the flextable object ft
as preparation and then use openxlsx
to print the table directly to Excel. openxlsx
allows you to style your table and directly write data in an excel sheet. This code identifies repeated column values and merges cells accordingly.
if(!require("pacman")) install.packages("pacman")
library("pacman")
p_load(tidyverse, ftExtra, openxlsx, flextable)
my_data <- crossing(
year = 2010:2020,
region = LETTERS[1:10],
type = paste("Type ", c("I", "II", "III"))) %>%
mutate(value = runif(n = n()))
my_calculation <- my_data %>%
mutate(
.by = c(year, type),
share = value/sum(value))
my_table <- my_calculation %>%
pivot_wider(names_from = region, values_from = c(value, share))
# determine multiheaded table
ft <- my_table %>% flextable() %>% span_header()
# crate workbook and sheet
wb <- createWorkbook()
addWorksheet(wb, 1)
header_data <- ft$header$dataset # Extract header structure from ft
writeData(wb, 1, header_data, startRow = 1, colNames = FALSE)
# Detect and merge cells automatically
for (row_idx in 1:nrow(header_data)) {
row <- unlist(header_data[row_idx, ]) # Extract row values
groups <- rle(row) # Identify repeated values
col_positions <- cumsum(c(1, head(groups$lengths, -1))) # Column positions
for (i in seq_along(groups$values)) { # Merge only column cells where labels are repeated
if (groups$lengths[i] > 1) {
mergeCells(wb, 1, cols = col_positions[i]:(col_positions[i] + groups$lengths[i] - 1), rows = row_idx)
}
}
}
# Apply styles
headerStyle <- createStyle(textDecoration = "bold", halign = "center")
addStyle(wb, 1, headerStyle, rows = 1:2, cols = 1:ncol(my_table), gridExpand = TRUE)
# Write main table data below headers
writeData(wb, 1, my_table, startRow = nrow(header_data) + 1, colNames = FALSE)
# Save workbook
saveWorkbook(wb, "Multiheaded_Table.xlsx", overwrite = TRUE)
Upvotes: 0