Rexcel是通過COM,而我介紹的方案是基于http協(xié)議,原理很簡單,就是在R里設(shè)置一個http服務(wù)器,用VBA構(gòu)建R代碼或格式化數(shù)據(jù),從Excel向R發(fā)送數(shù)據(jù)、代碼,計算完畢返回結(jié)果,以VBA處理返回結(jié)果。Rexcel難安裝,且也需要學(xué)習(xí)一些使用技術(shù),對于實際應(yīng)用而言,很多情況下未必有這個基于http協(xié)議的方法易用。強調(diào)一點,這里介紹的,是一個策略或方案,不是一個單一的辦法,實現(xiàn)這個方案的技術(shù)不僅下述一種。
這個方案的難點在于R語言一端的server,見以下腳本,別看這個腳本沒幾行,為了攢起這個玩意,還真耗了不少搜索。
library(Rook)
library(R.utils)
setRefClass(
'FooBar',
methods = list(
? ? call = function(env) {
? ? result <- captureOutput(source(textConnection(rawToChar(env[['rook.input']]read())))value)
? ?? ?? ?list(
? ?? ?? ?? ? status = 200L,
? ?? ?? ?? ? body = paste(result,collapse="\n")
? ?? ?? ?? ???)
? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ???)
? ?? ?? ?? ? )
s<-Rhttpdnew()sstar(listen='127.0.0.1',port='11269')
sadd(name="response",app=getRefClass('FooBar')new())
幾點說明:
1. 以上腳本可以實現(xiàn)的功能是:運行客戶端發(fā)的R代碼,捕捉輸出,以文本格式返回客戶端。這樣就實現(xiàn)了以Excel為前端,以R為后端的效果。不過,不能返回圖像。
2. 為什么選基于http的通信方式?Excel一端用WinHttpRequest發(fā)請求很容易,且可以與一個打開的R session反復(fù)通信;Clipboard我也試過,也很容易實現(xiàn),但不知為什么容易出莫名其妙的故障;管道也試過,也不難,但在Windows下,很難實現(xiàn)一直守著一個打開的R session。
3. 本文介紹的以R為后端的通信方案僅可用作本地工具,不適合做網(wǎng)絡(luò)應(yīng)用開發(fā),要想做開發(fā),就必須用Shiny之類的了。
4. 上文中的腳本要求Rook包。R里能用來做server的工具不多,Rook是比較簡易高效的一個,Linux和Windows下都沒問題,還有個更小更快的httpuv,Linux下很好用,Windows下似乎總會導(dǎo)致R崩潰。
5. 向Rook服務(wù)器發(fā)送請求的長度上限為64kb,這個長度能做的事情還是不少的。
6. 上述代碼中最為來之不易的是最長的那句,尤其是“env[['rook.input']]$read()”這部分,其功能是獲得http請求中的原始input,Rook的官方說明里并沒有給出說明,我是從其他包的源碼中找到的這種方法。
7. 客戶端以以下 VBA代碼為例:
Private Sub CommandButton1_Click()
Dim REQ As New WinHttpRequest '引用Microsoft WinHTTP Services
REQ.Open "POST", "http://127.0.0.1:11269/custom/response/" '注意url后半段中的路徑
REQ.Send ("citation()")
Debug.Print REQ.ResponseText
End Sub
8. 基于這個方案,可以利用R編程的優(yōu)勢,把一些復(fù)雜的計算過程或者Excel中沒有的功能做成宏,提高效率。
上面強調(diào)過了,以http通信連接Excel與R只是一個策略而已,具體實現(xiàn)方法很多,再如用Python或Node.js等做一個數(shù)據(jù)中轉(zhuǎn)用的服務(wù)器,在Excel做格式化數(shù)據(jù)的宏,實現(xiàn)在Excel中選取數(shù)據(jù),將數(shù)據(jù)以文本方式發(fā)至中轉(zhuǎn)服務(wù)器,R端從服務(wù)器讀入數(shù)據(jù),省去建立數(shù)據(jù)文件的麻煩。








暫無數(shù)據(jù)