保留格式的情况下,将R中的内容写入Excel模板

32
我有一个R中的数据框想要写入Excel(或CSV)并以漂亮的格式输出(例如带有边框、表格标题,不从单元格A1开始)。

目前我使用write.table函数将我的数据框写入CSV文件,然后将数据复制并粘贴到Excel文档中,其中我已经准备好了格式为模板的表格。

当只有一个数据框时,这不是什么大问题,但现在我想为多个数据框执行此操作,并在Excel中跨多个选项卡中显示这些数据。

是否有一种方法可以自动将我的数据框复制到现有Excel电子表格中的特定单元格,并正确设置所有格式?


1
CSV文件仅限文本格式,不支持任何格式设置。你可以使用R (D)COM从R中写入和格式化Excel文件。 - Joshua Ulrich
4
@joran 这个问题包含一个重要部分:保留原始模板的格式。去试试看吧... - Joris Meys
@JorisMeys 是的,?setStyleAction - joran
10
@joran 我知道(请看我的回答)。但是,如果我必须对每个可以通过浏览相当多的手册页面来回答的问题进行投票否决,那么剩下的问题就不会太多了。这是一个完全有效的问题。在使用XLConnect一段时间后,我才发现该功能。它没有在文档中说明,并且很少有帮助页面链接到该特定信息。 - Joris Meys
3个回答

25

正如Joran所说,您可以使用XLConnect软件包。 请仔细阅读该软件包的文档指南,以确切了解其可行性。

通常情况下,使用XLConnect会覆盖单元格样式,除非您使用“none”作为样式操作来设置样式动作。

setStyleAction(wb,XLC$"STYLE_ACTION.NONE")

为了让您走上正确的道路,这是一个简单的例子:

require(XLConnect)
wb <- loadWorkbook("test.xlsx", create=TRUE)
setStyleAction(wb,XLC$"STYLE_ACTION.NONE")

Data <- data.frame(
  a = 1:10,
  b = letters[1:10]
)

writeWorksheet(wb,Data,"aSheet",startRow=1,startCol=1,header=TRUE)

saveWorkbook(wb)

之前

在此输入图片描述

之后

在此输入图片描述


编辑:如 Dirk Eddelbuettel 所指出,您也可以使用 xlsx 包达到相同的效果。我个人使用 XLConnect,因为它可以处理 xls 和 xlsx 文件,并且比我用来处理 EXCEL 文件的任何旧包都要稳定得多。我还没有使用过 xlsx 包。您可以查看CRAN 数据导入/导出页面了解可用选项。


3
顺便提一下,“xslx”包也可以做到这一点。 - Dirk Eddelbuettel
谢谢Joris,非常感谢! - user1165199
7
我们如何在使用xlsx包时实现这个功能呢?我没有找到任何可以保存整个工作表格式的函数,你能帮忙翻译一下吗?请注意保持原文意思不变,并尽量简洁易懂。 - name_masked
4
我已经进行了一些从R.xlsx文件的写作,并且更喜欢openxlsx包而不是xlsx。我的理由是我经常遇到操作系统(64位)难以轻松与rjavaxlsx的依赖项)配合使用的问题。openxlx不需要rJava,这在当时使我的生活变得更加容易。 - Steven
openxlsx在99%的情况下都表现良好,但我使用的一些第三方程序拒绝打开openxlsx生成的xlsx文件,并声称无法读取Excel文档。如果我打开Excel文件,然后保存并重试,它总是能够正常工作。有人知道如何解决这个问题吗? - Michael Cantrall
@DirkEddelbuettel,如何在xlsx包中实现? - pajonk

2

一些用户询问如何使用 xlsx 包进行操作。

STHDA 上有一个非常好的、广泛的 xlsx 包使用示例。

它包括单元格格式化、多个工作表的工作簿、如何添加图形等示例。


1

这里有一个基于openxlsx的函数,您可以在其中指定包含样式的工作簿(from_wb)和工作表名称/位置(from_sheet),以及要传输样式的工作簿(to_wb)和工作表名称/位置(to_sheet):

注意:我还使用了purrrglue软件包,但这可以用基本R重新编写。

copyStyle <- function(from_wb, to_wb, from_sheet, to_sheet) {
  # check for workbook objects
  if (!(inherits(from_wb, "Workbook") && inherits(to_wb, "Workbook"))) { 
    stop("from_wb and to_wb must be Workbook objects.")
    }
  
  # get all sheet names from workbooks
  from_sheets <- from_wb$sheet_names
  to_sheets <- to_wb$sheet_names

  # convert sheets from numeric to sheet name. wb$styleObjects uses sheet name
  if (is.numeric(from_sheet)) {
      from_sheet <- from_wb$getSheetName(from_sheet)
  }
  
  if (is.numeric(to_sheet)) { 
      to_sheet <- to_wb$getSheetName(to_sheet)
  }

  # if sheet name given check that it exists
  if (is.character(from_sheet) && !from_sheet %in% from_sheets) {
    stop(glue::glue("{from_sheet} was not found in from_wb"))
  }
  
  if (is.character(to_sheet) && !to_sheet %in% to_sheets) {
    stop(glue::glue("{to_sheet} was not found in to_wb"))
  }
  
  # get from_wb sheet styles
  from_styles <- purrr::keep(from_wb$styleObjects, ~ .x$sheet == from_sheet)

  # add styles to to_wb
  purrr::walk(from_styles, ~ openxlsx::addStyle(to_wb, 
                                                to_sheet, 
                                                .x$style, 
                                                rows = .x$rows, 
                                                cols = .x$cols))
  return(to_wb)
}

使用方法

library(openxlsx)

wb <- loadWorkbook("getStyle.xlsx")

new_wb <- write.xlsx(head(iris), "transfer_style.xlsx")
# can give sheet name or index
copyStyle(from_wb = wb, to_wb = new_wb, from_sheet = "Sheet1", to_sheet = 1)

# must save workbook after copying style
saveWorkbook(new_wb, "transfer_style.xlsx", overwrite = T)

输入

getStyles.xlsx 是一个本地的 Excel 工作簿,其中包含多个工作表上的多个样式:

getStyles.xlsx

输出

transfer_styles.xlsx:

transfer_styles.xlsx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接