运行 Excel 从 R 到 RDCOMClient 的宏,错误 -2147418111
Running Excel macros from R through RDCOMClient, error -2147418111
objective是用OpenXLSX将数据添加到一个现有的excel文件,然后运行宏在同一个Excel文件中使用RDCOMClient,保存在方式,来自 R 脚本。
Excel 宏对数据加载后必须发生的枢轴 table 过滤器和折叠点进行更改。
这个小问题的重现没有问题:
library(openxlsx)
library(RDCOMClient)
ds <- cars
tmpl <- './templates/templatetest.xlsm'
datatab <- 'data'
datarng <- 'pdata'
fn <- paste0("./WAR/", "test1.xlsm")
wb <- loadWorkbook(tmpl)
writeData(wb, datatab, ds)
saveWorkbook(wb, fn, overwrite = TRUE)
rm(wb)
# note this doesn't reveal the full actual UNC path
fn <- paste0("./WAR/",
"test1.xlsm")
xlApp <- COMCreate("Excel.Application")
xlWbk <- xlApp$Workbooks()$Open(fn)
# run macros
xlApp$Run("clear_pt_filters")
xlApp$Run("CollapsePivotFields")
xlApp$Run("toggle_alcItems")
# Close the workbook and quit the app:
xlWbk$Close(TRUE)
xlApp$Quit()
# Release resources:
rm(xlWks, xlWbk, xlApp)
gc()
但是,当 运行 投入生产时,我在第一个宏行出现错误:
xlApp$运行("clear_pt_filters")
Error in .COM(x, name, ...) : Cannot locate 0 name(s) Run in COM
object (status = -2147418111)
我怀疑这是由于加载 1-2 MB 文件的时间导致的,而 R 没有发出 RDCOMClient 已准备好宏 运行 请求的信号。
我通过简单地从相同的宏行开始再次 运行 再次运行脚本来手动解决这个问题。最后,错误只是阻止了完全自动化,电子表格的结果完全符合预期。
编辑:如果我逐行执行 'production' 版本,则没有错误。
我的问题是 1) 错误的原因是什么,以及 2) 我该如何解决自动化中的问题?
谢谢。
我认为问题在于 saveWorkbook() 函数旨在以 xlsx 格式保存并且可能不会在工作簿中保留宏信息。可能更好的方法是完全使用 RDCOMClient 来处理它。可能通过这样的方法。
library(openxlsx)
library(RDCOMClient)
ds <- cars
tmpl <- './templates/templatetest.xlsm'
newfile <- './templates/templatetestNEW.xlsm'
# Create Excel instance
xlApp <- COMCreate("Excel.Application")
# Open workbook template
xlWB <- xlApp$Workbooks()$Open(tmpl)
# Select the "data" Sheet
xlSheet <- xlWB$Sheets("data")
# Create a dataframe from headers
headers <- t(as.data.frame(colnames(ds)))
# Set range for headers
rng <- xlSheet$Range(xlSheet$Cells(1, 1),xlSheet$Cells(1, ncol(headers)))
# Insert headers
rng[["Value"]] <- asCOMArray(headers)
# Set range for data values
rng <- xlSheet$Range(xlSheet$Cells(2, 1),xlSheet$Cells(nrow(ds)+1, ncol(ds)))
# Add data to Excel sheet
rng[["Value"]] <- asCOMArray(ds)
# Save Workbook
xlWB$SaveAs(gsub("/","\\",newfile))
# run macros
xlApp$Run("clear_pt_filters")
xlApp$Run("CollapsePivotFields")
xlApp$Run("toggle_alcItems")
# Close the workbook and quit the app:
xlWbk$Close(TRUE)
xlApp$Quit()
# Release resources:
rm(xlWks, xlWbk, xlApp)
gc()
我发现我使用的最简单的解决方案是使用 Sys.sleep() 插入一秒钟的停顿。
Sys.sleep(1)
所以,它看起来像这样,从上面编辑:
xlApp <- COMCreate("Excel.Application")
xlWbk <- xlApp$Workbooks()$Open(fn)
# run macros
Sys.sleep(1)
xlApp$Run("clear_pt_filters")
xlApp$Run("CollapsePivotFields")
xlApp$Run("toggle_alcItems")
# Close the workbook and quit the app:
xlWbk$Close(TRUE)
xlApp$Quit()
# Release resources:
rm(xlWbk, xlApp)
gc()
归功于
objective是用OpenXLSX将数据添加到一个现有的excel文件,然后运行宏在同一个Excel文件中使用RDCOMClient,保存在方式,来自 R 脚本。
Excel 宏对数据加载后必须发生的枢轴 table 过滤器和折叠点进行更改。
这个小问题的重现没有问题:
library(openxlsx)
library(RDCOMClient)
ds <- cars
tmpl <- './templates/templatetest.xlsm'
datatab <- 'data'
datarng <- 'pdata'
fn <- paste0("./WAR/", "test1.xlsm")
wb <- loadWorkbook(tmpl)
writeData(wb, datatab, ds)
saveWorkbook(wb, fn, overwrite = TRUE)
rm(wb)
# note this doesn't reveal the full actual UNC path
fn <- paste0("./WAR/",
"test1.xlsm")
xlApp <- COMCreate("Excel.Application")
xlWbk <- xlApp$Workbooks()$Open(fn)
# run macros
xlApp$Run("clear_pt_filters")
xlApp$Run("CollapsePivotFields")
xlApp$Run("toggle_alcItems")
# Close the workbook and quit the app:
xlWbk$Close(TRUE)
xlApp$Quit()
# Release resources:
rm(xlWks, xlWbk, xlApp)
gc()
但是,当 运行 投入生产时,我在第一个宏行出现错误:
xlApp$运行("clear_pt_filters")
Error in .COM(x, name, ...) : Cannot locate 0 name(s) Run in COM object (status = -2147418111)
我怀疑这是由于加载 1-2 MB 文件的时间导致的,而 R 没有发出 RDCOMClient 已准备好宏 运行 请求的信号。
我通过简单地从相同的宏行开始再次 运行 再次运行脚本来手动解决这个问题。最后,错误只是阻止了完全自动化,电子表格的结果完全符合预期。
编辑:如果我逐行执行 'production' 版本,则没有错误。
我的问题是 1) 错误的原因是什么,以及 2) 我该如何解决自动化中的问题?
谢谢。
我认为问题在于 saveWorkbook() 函数旨在以 xlsx 格式保存并且可能不会在工作簿中保留宏信息。可能更好的方法是完全使用 RDCOMClient 来处理它。可能通过这样的方法。
library(openxlsx)
library(RDCOMClient)
ds <- cars
tmpl <- './templates/templatetest.xlsm'
newfile <- './templates/templatetestNEW.xlsm'
# Create Excel instance
xlApp <- COMCreate("Excel.Application")
# Open workbook template
xlWB <- xlApp$Workbooks()$Open(tmpl)
# Select the "data" Sheet
xlSheet <- xlWB$Sheets("data")
# Create a dataframe from headers
headers <- t(as.data.frame(colnames(ds)))
# Set range for headers
rng <- xlSheet$Range(xlSheet$Cells(1, 1),xlSheet$Cells(1, ncol(headers)))
# Insert headers
rng[["Value"]] <- asCOMArray(headers)
# Set range for data values
rng <- xlSheet$Range(xlSheet$Cells(2, 1),xlSheet$Cells(nrow(ds)+1, ncol(ds)))
# Add data to Excel sheet
rng[["Value"]] <- asCOMArray(ds)
# Save Workbook
xlWB$SaveAs(gsub("/","\\",newfile))
# run macros
xlApp$Run("clear_pt_filters")
xlApp$Run("CollapsePivotFields")
xlApp$Run("toggle_alcItems")
# Close the workbook and quit the app:
xlWbk$Close(TRUE)
xlApp$Quit()
# Release resources:
rm(xlWks, xlWbk, xlApp)
gc()
我发现我使用的最简单的解决方案是使用 Sys.sleep() 插入一秒钟的停顿。
Sys.sleep(1)
所以,它看起来像这样,从上面编辑:
xlApp <- COMCreate("Excel.Application")
xlWbk <- xlApp$Workbooks()$Open(fn)
# run macros
Sys.sleep(1)
xlApp$Run("clear_pt_filters")
xlApp$Run("CollapsePivotFields")
xlApp$Run("toggle_alcItems")
# Close the workbook and quit the app:
xlWbk$Close(TRUE)
xlApp$Quit()
# Release resources:
rm(xlWbk, xlApp)
gc()
归功于