我希望能够从R打开一个excel会话,写入它然后从R关闭excel会话。虽然我可以在同一个函数中完成所有操作,但我试图概括清理代码excel。但是,当我通过传入excel对象从函数调用gc()时,它不会垃圾收集。以下是代码:
opentest<-function() {
excel<-comCreateObject("Excel.Application")
comSetProperty(excel,"Visible",T)
comSetProperty(excel,"DisplayAlerts",FALSE)
comSetProperty(excel, "SheetsInNewWorkbook", 1)
wb <- comGetProperty(excel, "Workbooks")
wb <- comInvoke(wb, "Add")
excel
}
cleanupexcel<-function(excelobj) {
comInvoke(excelobj,"Quit")
rm(excelobj, envir=globalenv())
eapply(env=globalenv(), gc)
}
通过以下函数调用:
excelobj<- opentest()
cleanupexcel(excelobj)
当我调用上面的两个函数时,我仍然可以看到在我的任务管理器中运行的excel会话。但是,如果我从cleanupexcel()返回后调用gc(),它会成功终止excel会话。
关于如何从通用功能成功获取gc或者我在这里遇到其他问题的任何想法?
答案 0 :(得分:2)
这是对您的代码的一个小改动应该有效(我现在在Linux上,所以我无法测试它)。 主要的解决方法是将excel实例包装在一个环境中并返回它。
然后,关闭可以访问实例,然后在调用gc()
之前将其删除(确保不会引用它):
opentest<-function() {
excel<-comCreateObject("Excel.Application")
comSetProperty(excel,"Visible",T)
comSetProperty(excel,"DisplayAlerts",FALSE)
comSetProperty(excel, "SheetsInNewWorkbook", 1)
wb <- comGetProperty(excel, "Workbooks")
wb <- comInvoke(wb, "Add")
# wrap excel in an environment
env <- new.env(parent=emptyenv())
env$instance <- excel
env
}
cleanupexcel<-function(excel) {
comInvoke(excel$instance,"Quit")
rm("instance", envir=excel)
gc()
}
myexcel <- opentest()
cleanupexcel(myexcel)
...请注意,您的旧代码要求将变量命名为“excelobj”,因为您要从cleanupexcel
函数中删除它。那不太好。
好的,有很微妙的问题在起作用,所以这里有一个没有excel的可重现的例子:
opentest<-function() {
excel<-new.env()
reg.finalizer(excel, function(x) { cat("FINALIZING EXCEL!\n") }, FALSE)
# wrap excel in an environment
env <- new.env(parent=emptyenv())
env$instance <- excel
env
}
cleanupexcel<-function(excel) {
cat(excel$instance,"\n")
rm("instance", envir=excel)
gc()
}
myexcel <- opentest()
cleanupexcel(myexcel)
# Prints "FINALIZING EXCEL!"