是的,loadWorkbook() 的问题在于它不允许您使用 writeDate 函数“写入”数据,但会保留样式。相反,readWorkbook() 允许您将数据写入任何其他工作表,但不保留样式。因此,您需要将 loadWorkbook 中的样式(和适用的行/列)与 readWorkbook 中的可写数据结合起来。假设我有以下各种样式的 wb:
library(openxlsx)
#Create original file with various formats
wb <- createWorkbook()
big_font <- createStyle(fontSize = 20)
red_font <- createStyle(fontColour = "red")
border_cell <- createStyle(borderStyle = "thick", borderColour ="purple", border = "TopBottomLeftRight")
bold_blue_big <- createStyle(fontColour = "blue", fontSize = 25, textDecoration = "bold")
addWorksheet(wb, sheetName = "format")
writeData(wb, sheet = "format", mtcars)
addStyle(wb, sheet = "format", rows = 1:5, cols = 1:3, style = big_font, gridExpand = TRUE)
addStyle(wb, sheet = "format", rows = 6:7, cols = 1:3, style = red_font, gridExpand = TRUE)
addStyle(wb, sheet = "format", rows = 8:15, cols = 1:3, style = border_cell, gridExpand = TRUE)
addStyle(wb, sheet = "format", rows = 14:20, cols = 1:3, style = bold_blue_big, gridExpand = TRUE, stack = TRUE)
openXL(wb)
saveWorkbook(wb, "path/format.xlsx", overwrite = TRUE)
getStyles(wb)[[2]]
> getStyles(wb)[[2]]
A custom cell style.
Cell formatting: GENERAL
Font colour: #FF0000
wb 已设置样式,第二个样式是颜色#FF0000 或红色
如果loadWorkbook读入刚刚写好的wb的xlsx文件,会保留样式
#Preserves styles
format_wb <- loadWorkbook("path/format.xlsx")
getStyles(format_wb)[[2]] #returns styles
> getStyles(format_wb)[[2]]
A custom cell style.
Cell formatting: GENERAL
Font name: Calibri
Font size: 11
Font colour: #FF0000
但在使用 readWorkwook 时不会。我们仍然希望将这些可写数据添加到新的合并中
#Loses styles but writable data
write_wb <- readWorkbook("path/format.xlsx")
getStyles(write_wb) #returns no styles
基本上需要一个专门的函数来组合来自这两个方面的信息。如果仅要复制少数几种样式或特定样式,则需要对其进行修改,否则-如果完全复制所有格式:
这个函数有几个输入,但它基本上有:
- 样式来源的格式化工作簿,
- 应用样式的工作簿,
- 工作簿的工作表名称,
- 和 5. 以及是否应添加行/列。这适用于当您希望从 wb1 中为单元格 A1:J25 保留精确格式但例如将 wb1 内容添加到 wb2 并希望在 A150:J175 处格式化 wb1.data 时。如果不应对行/列进行调整,则这些默认值将设置为 0
format_wb$styleObjects 打印样式以及找到该样式的行和列。从那里开始,它只是在您对 format_wb 中的所有样式进行排序时,为每一行 (these_rows) 和 col (these_cols) 提取不同的值。通过使用 getStyles 引用样式来添加样式,并将其应用于 these_rows 和 these_cols。如果不是从第一行和第一列开始(即添加行和列),则参数 addrow 和 addcol 需要从默认值 0 更改
#Function ----
apply_old_format <-
function(format_wb, new_wb, sheetname, addrow = 0, addcol = 0){
for(i in seq_along(format_wb$styleObjects)){
these_rows <- unique(format_wb$styleObjects[[i]]$rows)
these_cols <- unique(format_wb$styleObjects[[i]]$cols)
addStyle(new_wb, sheet = sheetname,
style = getStyles(format_wb)[[i]],
rows = addrow + (these_rows),
cols = addcol + (these_cols),
gridExpand = TRUE, stack = TRUE)
}
}
现在我们可以创建一个新的工作簿,它将结合现有数据集(在本例中为 iris),并附加在 原始 wb 中格式化并作为 加载的 mtcars 数据集format_wb 的样式,并读入可写为 write_wb。
示例在第一张纸上有长数据,在第二张纸上有宽数据,具体取决于附加第二个数据集的位置
#Create merged product
new_wb <- createWorkbook()
addWorksheet(new_wb, sheetName = "iris_cars_long")
addWorksheet(new_wb, sheetName = "iris_cars_wide")
writeData(new_wb, sheet = "iris_cars_long", iris, colNames = TRUE)
writeData(new_wb, sheet = "iris_cars_long", write_wb, startRow = 152, startCol = 1)
apply_old_format(format_wb = format_wb, new_wb = new_wb, sheetname = "iris_cars_long") #adds to top part of iris data
apply_old_format(format_wb = format_wb, new_wb = new_wb, sheetname = "iris_cars_long", addrow = dim(iris)[1] +1) #adds to cars using dimension of data if it is not known, just used as demo can otherwise enter number
writeData(new_wb, sheet = "iris_cars_wide", iris, colNames = TRUE)
writeData(new_wb, sheet = "iris_cars_wide", write_wb, startRow = 1, startCol = length(iris) + 2) #for if you don't know exact length just for demo
apply_old_format(format_wb = format_wb, new_wb = new_wb, sheetname = "iris_cars_wide", addcol = length(iris) +1)
openXL(new_wb)