3

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)

上記の 2 つの関数を呼び出しても、タスク マネージャーで実行中の Excel セッションを確認できます。ただし、cleanupexcel() から戻った後に gc() を呼び出すと、Excel セッションが正常に強制終了されます。

ジェネリック関数から正常に gc できる方法についてのアイデアはありますか、それとも他に何か問題がありますか?

4

1 に答える 1

2

これは、動作するはずのコードへの小さな変更です (私は現在 Linux を使用しているため、テストできません)。主な修正は、Excel インスタンスを環境でラップし、代わりにそれを返すことです。

その後、close はインスタンスにアクセスし、それを削除して (インスタンスへの参照が残っていないことを確認して)、次のように呼び出し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。それは素晴らしいことではありません。

OK、非常に微妙な問題が発生しているため、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!"
于 2012-08-28T22:03:51.517 に答える