有没有办法在Excel
我有一个包含宏的Excel文件(Main.xlsm)。 我有一个Python文件(python.py)来生成一个辅助Excel文件(sub.xlsx),我将在Main.xlsm文件的宏中进一步调用它。 这个由python.py运行生成的sub.xlsx文件保存在同一个工作目录中。
现在我想让这个python.py在Main.xlsm宏运行期间执行,然后使用这个xlsx文件。 我基本上想要减少外部执行python.py的步骤。 那是否有命令? 我是VBA的新手。
- 然后保持新的(并远离)VBA :)我希望你找到你需要的。 有趣的问题。
- @ Jean-FranoisFabre感谢您对问题的关注。:p
- 从我的角度来看(也适用于其他专有和繁琐的系统),有时最好1)以CSV格式导出数据2)运行python脚本以便轻松处理数据3)重新导入excel / what所以我们也使用这个 技巧,而不是尝试在子语言中编码:)
- 我使用'网关类'。 所谓的网关,因为它打开了Excel生态系统的丰富世界到Excel VBA Developer exceldevelopmentplatform.blogspot.com/2018/06/
- 我添加了一个完整的答案(使用不同的例子)。
最简单的方法是使用Shell命令运行python解释器
1
|
Shell ('python.exe' & yourScript &'' & arguments)
|
- 谢谢你的回复@Uri。但是一个小问题是它是python或VBA的命令吗?我需要在VBA中执行它。
- 这是一个VBA命令
- @UriGoren yourscript根据这个上下文是Main.xlsm?
- 不,这是你的python脚本文件名
- 您可能还需要使用python解释器的完整路径,以防您没有它PATH
就在这里。我首选的方法是通过xlwings(https://www.xlwings.org/),但也有其他几个选项。 XlWings很棒,因为它是免费的,开源的,易于使用的,具有出色的文档。但是有一些功能限制,因此您必须检查它是否符合您的需求。
- 好主意,有一个upvote。不是XlWings在单个线程中工作吗?
- 据我所知,它确实是单线程的
- 伟大的加载项!不知道这一个,谢谢!有(其他)upvote。
- 我肯定会检查@Gabor。感谢您的答复。
- @Bathsheba最近在xlwings中添加了对线程的支持。
- @Xukrao,谢谢你指出这一点,这是个好消息。
使用VBA运行python脚本有多种方法,具体取决于您是否需要等待执行结束并知道它是否没有错误。
使用Shell,与控制台异步:
1
2 3 |
Public Sub RunPython(file As String, ParamArray args())
Shell'python.exe''' & file &'''' & Join(args,'') End Sub |
使用Shell,无需控制台同步:
1
2 3 |
Public Function RunPython(file As String, ParamArray args())
Shell'pythonw.exe''' & file &'''' & Join(args,'') End Function |
使用WScript.Shell,无需控制台同步和退出代码:
1
2 3 4 5 |
Public Function RunPython(file As String, ParamArray args()) As Long
Dim obj As Object Set obj = CreateObject('WScript.Shell') RunPython = obj.Run('pythonw.exe''' & file &'''' & Join(args,''), 0, True) End Function |
- 优秀 - 如果可以的话,我会更多地投票。
我的博客上有一整个Python月份。我建立了一个模式,我称之为网关类,它是一个支持COM的Python类,如果从命令行运行,它将注册自己,并且一旦使用CreateObject('foo.bar')实例化注册。
这是VBA调用Python类的一个很好的例子,它使用了一些scipy函数
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import numpy as np
import pandas as pd from scipy.stats import skewnorm class PythonSkewedNormal(object): def GeneratePopulation(self, a, sz): def BinnedSkewedNormal(self, a, sz, bins): table = pd.value_counts(bins3, sort=False) table.index = table.index.astype(str) return table.reset_index().values.tolist() if __name__ == '__main__': |
和调用VBA代码
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
Option Explicit
Sub TestPythonSkewedNormal() Dim skewedNormal As Object Dim lSize As Long Dim shtData As Excel.Worksheet Dim vBins 'Stop Dim rngData As Excel.Range rngData.Value2 = vBinnedData 'Stop End Sub |
完整的评论可以在这里的原始博客条目中找到
这里的优点是没有炮击。当它返回的代码时,你知道它已经完成了,炮击一旦检查炮轰进程是否已经结束等等。这个网关类是更好的恕我直言。
- 有趣的提议!但是,如果我错了,请纠正我,但现在你有两个启动进程(python脚本,然后是Excel),对吗?
- @Joel:如果是两个进程,那么与shelling相同。但是,如果位数相同,则将python运行时dll加载到Excel.exe中。如果位数不同那么肯定有两个过程,这是我对该主题的调查exceldevelopmentplatform.blogspot.com/2018/06/
- ModuleNotFoundError:没有名为'win32com'的模块
- @drgs没有名为'xyz'的模块意味着您需要安装'xyz'。