【问题标题】:openxlsx: How to copy a workbook worksheet (or its formatted data) into a different worksheet?openxlsx:如何将工作簿工作表(或其格式化数据)复制到不同的工作表中?
【发布时间】:2022-07-22 10:41:17
【问题描述】:

我想从一个 Excel 文件中加载一个工作簿/工作表,该文件具有无法使用 openxlsx 应用的复杂格式(即一些文本为斜体而一些不是斜体的单元格),然后附加格式化数据来自现有工作表底部的该工作表。

我知道cloneWorksheet() 将复制整个工作表,但我特别想将数据从一个工作表添加到另一个现有工作表中。

wb <- createWorkbook()
sheet <- addWorksheet(wb = wb, sheetName = "sheet")

writeData(wb, sheet, mydata) #assume mydata is a data frame

wb2 <- loadWorkbook("myfile.xlsx")

writeData(wb = wb, sheet = sheet, x = wb2, startRow = ncol(mydata) + 1) #I know this doesn't work

对于最后一行,我想从 wb2 的工作表中获取格式化数据,并将其添加到 wb 工作表中的现有数据之后。

【问题讨论】:

    标签: r openxlsx


    【解决方案1】:

    是的,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
    

    基本上需要一个专门的函数来组合来自这两个方面的信息。如果仅要复制少数几种样式或特定样式,则需要对其进行修改,否则-如果完全复制所有格式:

    这个函数有几个输入,但它基本上有:

    1. 样式来源的格式化工作簿,
    2. 应用样式的工作簿,
    3. 工作簿的工作表名称,
    4. 和 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)
    

    【讨论】:

      猜你喜欢
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      • 1970-01-01
      相关资源
      最近更新 更多