R - Autofit Excel column width

I had the same issues as above, but was working with a list of data frames. Using the tidyverse, I modified Rick's answer to account for that. I also didn't want column widths wider than 75. This still didn't fix the date issue described above. I didn't want the timestamp to show with my dates and I found you can set the options for how dates are formatted in Excel. So for that I used options("openxlsx.datetimeFormat" = "mm/dd/yyyy"). More info on formatting here

myList <- list(A = data.frame(ID = c("AAA", "AAA"), 
                          Test = c(1, 1), 
                          Value = 1:2), 
           B = data.frame(ID = c("BBB", "BBB", "BBB"), 
                          Test = c(1, 3, 5), 
                          Value = 1:3),
           C = data.frame(Test = c(1, 3, 5), 
                          Value = 1:3))

data_cols <- myList %>%
  map(~ 1:ncol(.), .depth = 2)

width_vec <- myList %>% 
  map(~ summarise_all(., funs(max(nchar(as.character(.)))), na.rm = TRUE), .depth = 2) %>% 
  map(~ unlist(., use.names = FALSE), .depth = 2) %>% 
  map(~ . + 2, .depth = 2)
width_vec_header <- map(myList, ~ nchar(names(.)) + 2, .depth = 2) 
max_vec <- map2(width_vec, width_vec_header, ~ pmin(75, pmax(.x, .y, 0)), .depth = 2)
pwalk(list(names(myList), data_cols, max_vec), ~ setColWidths(wb, ..1, ..2, widths = ..3))

Ok, I got it after another extensive search in the documentation. It seems very few people actually use this from the dearth of solutions online...

setColWidths(WB, Sheet, cols = 1:ncol(DF), widths = "auto")

However, this still does not give the desired result, the date column is still a bit short and shows ########; while the column headers are not fitting as well (as they are formatted bold).

EDIT:

Finally, chose to add c(7.5, 10, "auto", ...) replacing just "auto", it is not totally dynamic, but solves the issue for now. Hope to see better answers.


Using XLConnect...

setColumnWidths(WB, Sheet, column = 1:ncol(DF), width = -1)

Reference: https://cran.r-project.org/web/packages/XLConnect/XLConnect.pdf


Given that widths = "auto" did not work as you hoped, a more generalized answer to assign the widths based on the lengthiest value + 2 (to handle emboldening):

width_vec <- apply(DF, 2, function(x) max(nchar(as.character(x)) + 2, na.rm = TRUE)) setColWidths(WB, Sheet, cols = 1:ncol(DF), widths = width_vec)

And to assign the width based on the column headers:

width_vec_header <- nchar(colnames(DF)) + 2
setColWidths(WB, Sheet, cols = 1:ncol(DF), widths = width_vec_header)

And to assign the width based on the lengthiest string per column, whether the header or the cells in the body, use the "parallel" maximum function (like a vectorized maximum function):
width_vec <- apply(DF, 2, function(x) max(nchar(as.character(x)) + 2, na.rm = TRUE))
width_vec_header <- nchar(colnames(DF)) + 2
max_vec_header <- pmax(width_vec, width_vec_header)
setColWidths(WB, Sheet, cols = 1:ncol(DF), widths = max_vec_header )