在excel中调用R语言程序的尝试 基础篇

目录

一、 绪论. 

(一) 背景.

(二) 使用工具. 

二、 基础实行过程. 

(一) 中介工具的选择. 

(二) 实现中介工具的信息传递. 

(三) 函数化. 

(四) 小结. 

提示:成品请直接看 二(三)的最后,前面的都是思路铺垫。

一、绪论

(一)背景

某日捣鼓excel的VBA编程时,突发奇想,R语言是统计领域的王者,而且开源免费。Excel 是重要的办公软件,商务数据分析的王牌工具,在工作中很重要。在R中有相应的包(package)可以操纵excel表格。那么如果能使用excel调用R中的函数,那岂不是让excel更如虎添翼?

(二)使用工具

使用百度搜索各类文章,包括VBA语法、CMD命令等。安装R语言4.0.5版本,以excel

2019版为例。


二、基础实行过程

(一)中介工具的选择

第一,很多编程语言都可以调用外部程序。由此推断Excel VBA亦可通过调用命令行(CMD)程序运行CMD命令。如在VBA中

Sub test()

    Shell "explorer.exe"

End Sub

其能调用cmd打开文件资源管理器。

第二,很多编程语言的exe文件可以使用CMD方式调用。由此推断可以在CMD中调用R语言内核。

如,在cmd中运行以下代码。

d:

cd "D:\Program Files\R\R4.0.5\bin"

Rscript.exe -e "2+2"

运行结果如下


可以得到R语言的运行结果。

综上,选择CMD为中介,可以实现excel调用R语言功能。

(二)实现中介工具的信息传递

1.  VBA字符串中的引号问题

在VBA字符串里,两个引号成为字符串中的引号。

如运行以下代码。

Sub test()

MsgBox ("e""e")

End Sub

结果如下。


2.  信息传递的调回

若调用R语言后,运行结果不能传递回excel,那么这样的调用毫无意义。

在VBA中运行如下代码。

Sub test()

    DimobjShell As Object, objExec As Object

    SetobjShell = CreateObject("WScript.Shell")


    SetobjExec = objShell.Exec("""D:/ProgramFiles/R/R4.0.5/bin/ Rscript.exe "" -e """ +"2+2" + """")

    DimRscript As String

    Rscript= objExec.stdout.readall()

    MsgBox(Rscript)


    SetobjShell = Nothing

    SetobjExec = Nothing

End Sub

代码的大意是注册一个壳,然后在壳中利用Exec函数调用外部程序,利用stdout.readall方法得到输出。其中,由于路径存在空格,需要在R语言内核路径中使用引号。最后,还将对象清空释放内存。

运行结果如下


至此,调用R语言内核后将信息传回excel得以实现。

(三)函数化

1.   功能目标

目前,应该将该功能实现为能在excel表格中使用的函数,以方便不会VBA的用户。

要实现的使用方式举例如下图:


如图中,在B2单元格调用了Rscript函数,要运行的代码位于B1,而结果也返回到B2。

2.  代码实现

在VBA宏中写入代码,声明该函数如下。

Function Rscript(cmdE As String)

    DimobjShell As Object, objExec As Object

    ss ="""D:/Program Files/R/R4.0.5/bin/Rscript.exe "" -e""" + cmdE + """"

    SetobjShell = CreateObject("WScript.Shell")

    SetobjExec = objShell.Exec(ss)

    Rscript= objExec.stdout.readall()

    SetobjShell = Nothing

    SetobjExec = Nothing

End Function

其中,参数cmdE为要在R语言内核中执行的命令,在内部将完整的调用代码组合为ss,然后利用Exec启动。

运行结果正是前一张图,如下。


3,代码优化

在返回的字符前还有R语言自带的数组标记,优化该函数将其去除,并将结果转为数字,如下。

Function Rscript(cmdE As String)

    DimobjShell As Object, objExec As Object

    ss ="""D:/Program Files/R/R4.0.5/bin/Rscript.exe "" -e""" + cmdE + """"

    'MsgBox(ss)

    SetobjShell = CreateObject("WScript.Shell")

    SetobjExec = objShell.Exec(ss)

    Rscript= objExec.stdout.readall()

    Rscript= Split(Rscript, "]", 2)(1)

    Rscript= Val(Replace(Rscript, " ", ""))

    SetobjShell = Nothing

    SetobjExec = Nothing

End Function

其中,Split函数将字符以]分割,Replace删除空格,Val函数将字符串结果转为Double类型。

运行结果如下。


(四)小结

至此,在excel中调用R语言内核的基础功能版本成型。缺陷在于,只能运行给定的字符串。存在一个明显的优化方向,那便是将excel中的数据列调用R语言内核中的数组机制处理。

你可能感兴趣的:(在excel中调用R语言程序的尝试 基础篇)