分享

有没有办法在Excel

 F2967527 2021-10-19

我有一个包含宏的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很棒,因为它是免费的,开源的,易于使用的,具有出色的文档。但是有一些功能限制,因此您必须检查它是否符合您的需求。

  • 好主意,有一个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):
    _reg_clsid_ ='{1583241D-27EA-4A01-ACFB-4905810F6B98}'
    _reg_progid_ = 'SciPyInVBA.PythonSkewedNormal'
    _public_methods_ = ['GeneratePopulation', 'BinnedSkewedNormal']

    def GeneratePopulation(self, a, sz):
        # https://docs./doc/numpy-1.15.1/reference/generated/numpy.random.seed.html
        np.random.seed(10)
        # https://docs./doc/scipy-0.19.1/reference/generated/scipy.stats.skewnorm.html
        return skewnorm.rvs(a, size=sz).tolist()

    def BinnedSkewedNormal(self, a, sz, bins):
        # https://docs./doc/numpy-1.15.1/reference/generated/numpy.random.seed.html
        np.random.seed(10)
        # https://docs./doc/scipy-0.19.1/reference/generated/scipy.stats.skewnorm.html
        pop = skewnorm.rvs(a, size=sz)
        bins2 = np.array(bins)
        bins3 = pd.cut(pop, bins2)

        table = pd.value_counts(bins3, sort=False)

        table.index = table.index.astype(str)

        return table.reset_index().values.tolist()

if __name__ == '__main__':
    print('Registering COM server...')
    import win32com.server.register
    win32com.server.register.UseCommandLine(PythonSkewedNormal)

和调用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
    Set skewedNormal = CreateObject('SciPyInVBA.PythonSkewedNormal')

    Dim lSize As Long
    lSize = 100

    Dim shtData As Excel.Worksheet
    Set shtData = ThisWorkbook.Worksheets.Item('Sheet3') '<--- change sheet to your circumstances
    shtData.Cells.Clear

    Dim vBins
    vBins = Array(-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5)

    '
Stop
    Dim vBinnedData
    vBinnedData = skewedNormal.BinnedSkewedNormal(-5, lSize, vBins)

    Dim rngData As Excel.Range
    Set rngData = shtData.Cells(2, 1).Resize(UBound(vBins) - LBound(vBins), 2)

    rngData.Value2 = vBinnedData

    'Stop

End Sub

完整的评论可以在这里的原始博客条目中找到

这里的优点是没有炮击。当它返回的代码时,你知道它已经完成了,炮击一旦检查炮轰进程是否已经结束等等。这个网关类是更好的恕我直言。

  • 有趣的提议!但是,如果我错了,请纠正我,但现在你有两个启动进程(python脚本,然后是Excel),对吗?
  • @Joel:如果是两个进程,那么与shelling相同。但是,如果位数相同,则将python运行时dll加载到Excel.exe中。如果位数不同那么肯定有两个过程,这是我对该主题的调查exceldevelopmentplatform.blogspot.com/2018/06/
  • ModuleNotFoundError:没有名为'win32com'的模块
  • @drgs没有名为'xyz'的模块意味着您需要安装'xyz'。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多