目录
一、 绪论.
(一) 背景.
(二) 使用工具.
二、 基础实行过程.
(一) 中介工具的选择.
(二) 实现中介工具的信息传递.
(三) 函数化.
(四) 小结.
提示:成品请直接看 二(三)的最后,前面的都是思路铺垫。
某日捣鼓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"
运行结果如下
![](https://img.haomeiwen.com/i6481653/322eba6116848033.png)
可以得到R语言的运行结果。
综上,选择CMD为中介,可以实现excel调用R语言功能。
1. VBA字符串中的引号问题
在VBA字符串里,两个引号成为字符串中的引号。
如运行以下代码。
Sub test()
MsgBox ("e""e")
End Sub
结果如下。
![](https://img.haomeiwen.com/i6481653/dc0625165203b109.png)
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语言内核路径中使用引号。最后,还将对象清空释放内存。
运行结果如下
![](https://img.haomeiwen.com/i6481653/a035efbd5cea1dd5.png)
至此,调用R语言内核后将信息传回excel得以实现。
1. 功能目标
目前,应该将该功能实现为能在excel表格中使用的函数,以方便不会VBA的用户。
要实现的使用方式举例如下图:
![](https://img.haomeiwen.com/i6481653/26305ad1c244a665.png)
如图中,在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启动。
运行结果正是前一张图,如下。
![](https://img.haomeiwen.com/i6481653/100111efc8ac4887.png)
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类型。
运行结果如下。
![](https://img.haomeiwen.com/i6481653/84d58070340dd05d.png)
至此,在excel中调用R语言内核的基础功能版本成型。缺陷在于,只能运行给定的字符串。存在一个明显的优化方向,那便是将excel中的数据列调用R语言内核中的数组机制处理。
网友评论