R自定义函数中如何将输入参数作为内部新建tibble的列名
问题背景
编写R自定义函数,调用openxlsx包的writeData方法写入Excel内容时新增标题行,函数参数定义如下:
- tab:待写入的数据集
- headline:带引号的标题文本
- workbook:wb工作簿对象,默认值为全局环境中的wb
- sheetName:目标工作表名称
预期效果是写入的单行标题行直接展示传入的headline参数内容,最初尝试创建单列tibble并将列名设置为传入的headline参数值,编写的代码运行失败,核心诉求是将函数调用时传入的headline字符串参数值,设置为函数内部新建dataframe/tibble的列名,让该单列数据集可用于写入Excel标题行。
原错误代码:
WriteToExcel <- function(tab, headline, workbook=wb, sheetName){ # title: I want this single row to have the input of the argument "headline" So I create a tibble with 1 column with that name headline <- tribble( ~colA, ) %>% rename(headline = colA) openxlsx::writeData(workbook, sheetName, headline, startRow = nrow(readWorkbook("master.xlsx", sheet = sheetName))+1, startCol = 1) openxlsx::saveWorkbook(workbook, "master.xlsx", overwrite = TRUE) } WriteToExcel(tab=data, headline = "Task number three", sheetName = "Sheet 1")
错误原因
原代码存在3个核心问题:
- 列名赋值逻辑错误:
rename(headline = colA)是dplyr的非标准计算语法,会直接把列名改为字面量"headline",不会读取传入的headline参数的实际值 - 构造的数据集无效:创建的tribble没有任何行数据,且后续直接覆盖了同名的
headline参数变量,导致参数值丢失 - 逻辑缺失:函数定义了
tab参数但全程没有调用写入,且读取已有行数时直接读磁盘上的master.xlsx文件,内存中workbook对象的未保存修改无法被读取,计算的起始行位置不准。
修复方案
方法1:按原思路动态设置列名
不需要用tibble和rename的复杂语法,直接用基础R的列名赋值方法即可动态设置列名,构造0行1列的数据集,writeData写入时会自动把列名写在对应位置作为标题,不会额外写入空数据行。
完整修复代码:
WriteToExcel <- function(tab, headline, workbook = wb, sheetName){ # 动态构造标题数据集:1列0行,列名直接赋值为传入的headline参数值 title_df <- data.frame(tmp = character(0)) colnames(title_df) <- headline # 从内存中的workbook对象读取当前工作表已有行数,计算写入起始位置 existing_rows <- nrow(openxlsx::readWorkbook(workbook, sheet = sheetName, colNames = FALSE)) title_start_row <- existing_rows + 1 # 写入标题行,0行数据集仅会写入列名(即标题文本) openxlsx::writeData( wb = workbook, sheet = sheetName, x = title_df, startRow = title_start_row, startCol = 1 ) # 标题行占1行,实际数据集从下一行开始写入 openxlsx::writeData( wb = workbook, sheet = sheetName, x = tab, startRow = title_start_row + 1, startCol = 1 ) # 保存文件 openxlsx::saveWorkbook(workbook, "master.xlsx", overwrite = TRUE) } # 调用示例 WriteToExcel(tab = data, headline = "Task number three", sheetName = "Sheet 1")
方法2:直接写入标题文本(更推荐)
不需要构造带列名的数据集,直接把headline作为字符向量传入writeData即可,写法更简洁,后续也方便给标题设置跨列合并、加粗居中的格式:
# 替换方法1中构造title_df和写入标题的代码即可 openxlsx::writeData( wb = workbook, sheet = sheetName, x = headline, # 直接传入标题字符串 startRow = title_start_row, startCol = 1 )
如果需要做跨列合并居中,可以在写入标题后加一行格式代码:
# 假设tab数据集有ncol(tab)列,合并标题行从第1列到最后1列的单元格 openxlsx::mergeCells(workbook, sheet = sheetName, cols = 1:ncol(tab), rows = title_start_row)
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

