运行 excel 来自 python 的宏
Running excel macro from python
我正在使用以下代码 运行 来自 Python 的 Excel 宏:
import pymysql
import datetime
import csv
import math
import os
import glob
import sys
import win32com.client
import numpy
from tkinter import *
from tkinter import ttk
import tkinter.messagebox
def run_macro():
print('macro')
#this if is here because if an executable is created, __file__ doesn't work
if getattr(sys, 'frozen', False):
name = (os.path.dirname(sys.executable) + '\Forecast template.xlsm')
else:
name = str(os.path.dirname(os.path.realpath(__file__)) + '\Forecast template.xlsm')
print(name)
#this part runs the macro from excel
if os.path.exists(name):
xl=win32com.client.Dispatch("Excel.Application")
xl.Workbooks.Open(Filename=name, ReadOnly=1)
xl.Application.Run("ThisWorkbook.LoopFilesInFolder")
xl.Application.Quit() # Comment this out if your excel script closes
del xl
print('File refreshed!')
我似乎遇到了一些问题,在 运行 之后,我去打开任何 excel 文件,我只得到一个灰色的 window:
知道为什么会这样吗?另外,如何在代码中添加一些内容以在 Excel 中打开一个文件? (不是为了获取信息,而是为了在 Excel 中打开该文件)
额外的问题:如何让它不关闭所有打开的 Excel 文件?
编辑:我刚刚检查了宏,工作正常,问题似乎来自于我 运行 代码。
新编辑:
这是宏中的代码:
Sub LoopFilesInFolder()
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim path As String
Dim file As String
Dim extension As String
Dim myFileName As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set wb1 = ActiveWorkbook
path = ActiveWorkbook.path & "\csvs\"
extension = "*.csv"
file = Dir(path & extension)
Do While file <> ""
Set wb2 = Workbooks.Open(Filename:=path & file)
wb2.Activate
'this section is for the avail heads file, basically it just opens it and copies the info to the template
If wb2.Name = "avail_heads.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B88").PasteSpecial xlPasteValues
End If
'this section is for the forecast file, basically it just opens it and copies the info to the template
If wb2.Name = "forecast.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B74").PasteSpecial xlPasteValues
End If
'this section is for the income file, basically it just opens it and copies the info to the template
If wb2.Name = "income volume.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B3").PasteSpecial xlPasteValues
End If
'this section is for the outgoing volume file, basically it just opens it and copies the info to the template
If wb2.Name = "outgoing_volume.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B36").PasteSpecial xlPasteValues
End If
'this section is for the required heads file, basically it just opens it and copies the info to the template
If wb2.Name = "required_heads.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B102").PasteSpecial xlPasteValues
End If
wb2.Close
file = Dir
Loop
'myFileName = ActiveWorkbook.path & "\forecast_for_w" & Format(Now, "ww") + 1
myFileName = ActiveWorkbook.path & "\yoda_forecast"
ActiveWorkbook.SaveAs Filename:=myFileName, FileFormat:=xlWorkbookNormal
'MsgBox "Done!"
Application.DisplayAlerts = True
End Sub
发送后需要将Visibility设置为True:
xl = win32com.client.Dispatch("Excel.Application")
xl.Application.Visible = True
此外,调用宏应该不需要 ThisWorkbook
:
xl.Application.Run("LoopFilesInFolder")
为了能够再次关闭工作簿,您需要将其分配给一个变量:
wb = xl.Workbooks.Open(Filename=name, ReadOnly=1)
wb.Close(SaveChanges=False)
我写了包 xlwings 让事情变得更简单:
from xlwings import Workbook, Range
wb = Workbook(r'C:\path\to\workbook.xlsx') # open a workbook if not open yet
Range('A1').value = 123 # Write a value to cell A1
wb.close() # close the workbook again
运行 一个宏尚未实现,但有一个 issue 开放。同时,您可以通过执行(按照上面的说明)来解决此问题:
wb.xl_app.Run("macro_name")
我已经有将近一周的赏金了,我真的不知道以前有多少人遇到过这个问题。折腾了一个多星期,多次考虑跳出办公室window,我想通了问题出在哪里。
问题不在 python(某种程度上),但主要在 VBA 代码上,我刚刚添加了
Application.ScreenUpdating = True
在最后,问题停止了。不确定是 excel 宏完成后不更新的错误,还是宏完成后不允许屏幕更新的 python 错误。不过现在一切都好了。
谢谢!!
运行ning Excel 来自 Python
的宏
来自python的运行一个Excel宏,你几乎什么都不需要。在完成这项工作的脚本下面。从 Excel 内的宏更新数据的优点是您可以立即看到结果。您不必先保存或关闭工作簿。我用这个方法来更新实时股票报价。它快速且稳定。
这只是一个示例,但您可以使用 Excel.
中的宏执行任何操作
from os import system, path
import win32com.client as win32
from time import sleep
def isWorkbookOpen(xlPath, xlFileName):
SeachXl = xlPath + "~$" + xlFileName
if path.exists(SeachXl):
return True
else:
return False
def xlRunMacro(macroLink):
PathFile = macroLink[0]
xlMacro = macroLink[1]
isLinkReady = False
# Create the link with the open existing workbook
win32.pythoncom.CoInitialize()
xl = win32.Dispatch("Excel.Application")
try:
wb = win32.GetObject(PathFile)
isLinkReady = True
except:
NoteToAdd = 'Can not create the link with ' + PathFile
print(NoteToAdd)
if isLinkReady:
# If the link with the workbook exist, then run the Excel macro
try:
xl.Application.Run(xlMacro)
except:
NoteToAdd = 'Running Excel Macro ' + xlMacro + ' failed !!!'
print(NoteToAdd)
del xl
def mainProgam(macroSettings):
FullMacroLink = []
PathFile = macroSettings[0] + macroSettings[1]
FullMacroLink.append(PathFile)
FullModuleSubrout = macroSettings[1] + '!' + macroSettings[2] + '.' + macroSettings[3]
FullMacroLink.append(FullModuleSubrout)
if isWorkbookOpen(macroSettings[0], macroSettings[1]) == False:
# If the workbook is not open, Open workbook first.
system(f'start excel.exe "{PathFile}"')
# Give some time to start up Excel
sleep(2)
xlRunMacro(FullMacroLink)
def main():
macroSettings = []
# The settings below will execute the macro example
xlPath = r'C:\test\' # Change add your needs
macroSettings.append(xlPath)
workbookName = 'Example.xlsm' # Change add your needs
macroSettings.append(workbookName)
xlModule = "Updates" # Change add your needs
macroSettings.append(xlModule)
xlSubroutine = "UpdateCurrentTime" # Change add your needs
macroSettings.append(xlSubroutine)
mainProgam(macroSettings)
if __name__ == "__main__":
main()
exit()
VBA Excel 宏
Option Explicit
Sub UpdateCurrentTime()
Dim sht As Worksheet
Set sht = ThisWorkbook.Sheets("Current-Time")
With sht
sht.Cells(2, 1).Value = Format(Now(), "hh:mm:ss")
End With
End Sub
您也可以将它用作动态模块。在您的 python 项目中将上述模块另存为 RunExcelMacro.py。仅使用以下行后:
from RunExcelMacro import mainProgam
mainProgram(macroSettings)
它将完成工作,成功...
我正在使用以下代码 运行 来自 Python 的 Excel 宏:
import pymysql
import datetime
import csv
import math
import os
import glob
import sys
import win32com.client
import numpy
from tkinter import *
from tkinter import ttk
import tkinter.messagebox
def run_macro():
print('macro')
#this if is here because if an executable is created, __file__ doesn't work
if getattr(sys, 'frozen', False):
name = (os.path.dirname(sys.executable) + '\Forecast template.xlsm')
else:
name = str(os.path.dirname(os.path.realpath(__file__)) + '\Forecast template.xlsm')
print(name)
#this part runs the macro from excel
if os.path.exists(name):
xl=win32com.client.Dispatch("Excel.Application")
xl.Workbooks.Open(Filename=name, ReadOnly=1)
xl.Application.Run("ThisWorkbook.LoopFilesInFolder")
xl.Application.Quit() # Comment this out if your excel script closes
del xl
print('File refreshed!')
我似乎遇到了一些问题,在 运行 之后,我去打开任何 excel 文件,我只得到一个灰色的 window:
知道为什么会这样吗?另外,如何在代码中添加一些内容以在 Excel 中打开一个文件? (不是为了获取信息,而是为了在 Excel 中打开该文件)
额外的问题:如何让它不关闭所有打开的 Excel 文件?
编辑:我刚刚检查了宏,工作正常,问题似乎来自于我 运行 代码。
新编辑:
这是宏中的代码:
Sub LoopFilesInFolder()
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim path As String
Dim file As String
Dim extension As String
Dim myFileName As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set wb1 = ActiveWorkbook
path = ActiveWorkbook.path & "\csvs\"
extension = "*.csv"
file = Dir(path & extension)
Do While file <> ""
Set wb2 = Workbooks.Open(Filename:=path & file)
wb2.Activate
'this section is for the avail heads file, basically it just opens it and copies the info to the template
If wb2.Name = "avail_heads.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B88").PasteSpecial xlPasteValues
End If
'this section is for the forecast file, basically it just opens it and copies the info to the template
If wb2.Name = "forecast.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B74").PasteSpecial xlPasteValues
End If
'this section is for the income file, basically it just opens it and copies the info to the template
If wb2.Name = "income volume.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B3").PasteSpecial xlPasteValues
End If
'this section is for the outgoing volume file, basically it just opens it and copies the info to the template
If wb2.Name = "outgoing_volume.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B36").PasteSpecial xlPasteValues
End If
'this section is for the required heads file, basically it just opens it and copies the info to the template
If wb2.Name = "required_heads.csv" Then
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
wb1.Activate
Worksheets("raw data").Range("B102").PasteSpecial xlPasteValues
End If
wb2.Close
file = Dir
Loop
'myFileName = ActiveWorkbook.path & "\forecast_for_w" & Format(Now, "ww") + 1
myFileName = ActiveWorkbook.path & "\yoda_forecast"
ActiveWorkbook.SaveAs Filename:=myFileName, FileFormat:=xlWorkbookNormal
'MsgBox "Done!"
Application.DisplayAlerts = True
End Sub
发送后需要将Visibility设置为True:
xl = win32com.client.Dispatch("Excel.Application")
xl.Application.Visible = True
此外,调用宏应该不需要 ThisWorkbook
:
xl.Application.Run("LoopFilesInFolder")
为了能够再次关闭工作簿,您需要将其分配给一个变量:
wb = xl.Workbooks.Open(Filename=name, ReadOnly=1)
wb.Close(SaveChanges=False)
我写了包 xlwings 让事情变得更简单:
from xlwings import Workbook, Range
wb = Workbook(r'C:\path\to\workbook.xlsx') # open a workbook if not open yet
Range('A1').value = 123 # Write a value to cell A1
wb.close() # close the workbook again
运行 一个宏尚未实现,但有一个 issue 开放。同时,您可以通过执行(按照上面的说明)来解决此问题:
wb.xl_app.Run("macro_name")
我已经有将近一周的赏金了,我真的不知道以前有多少人遇到过这个问题。折腾了一个多星期,多次考虑跳出办公室window,我想通了问题出在哪里。
问题不在 python(某种程度上),但主要在 VBA 代码上,我刚刚添加了
Application.ScreenUpdating = True
在最后,问题停止了。不确定是 excel 宏完成后不更新的错误,还是宏完成后不允许屏幕更新的 python 错误。不过现在一切都好了。
谢谢!!
运行ning Excel 来自 Python
的宏来自python的运行一个Excel宏,你几乎什么都不需要。在完成这项工作的脚本下面。从 Excel 内的宏更新数据的优点是您可以立即看到结果。您不必先保存或关闭工作簿。我用这个方法来更新实时股票报价。它快速且稳定。 这只是一个示例,但您可以使用 Excel.
中的宏执行任何操作from os import system, path
import win32com.client as win32
from time import sleep
def isWorkbookOpen(xlPath, xlFileName):
SeachXl = xlPath + "~$" + xlFileName
if path.exists(SeachXl):
return True
else:
return False
def xlRunMacro(macroLink):
PathFile = macroLink[0]
xlMacro = macroLink[1]
isLinkReady = False
# Create the link with the open existing workbook
win32.pythoncom.CoInitialize()
xl = win32.Dispatch("Excel.Application")
try:
wb = win32.GetObject(PathFile)
isLinkReady = True
except:
NoteToAdd = 'Can not create the link with ' + PathFile
print(NoteToAdd)
if isLinkReady:
# If the link with the workbook exist, then run the Excel macro
try:
xl.Application.Run(xlMacro)
except:
NoteToAdd = 'Running Excel Macro ' + xlMacro + ' failed !!!'
print(NoteToAdd)
del xl
def mainProgam(macroSettings):
FullMacroLink = []
PathFile = macroSettings[0] + macroSettings[1]
FullMacroLink.append(PathFile)
FullModuleSubrout = macroSettings[1] + '!' + macroSettings[2] + '.' + macroSettings[3]
FullMacroLink.append(FullModuleSubrout)
if isWorkbookOpen(macroSettings[0], macroSettings[1]) == False:
# If the workbook is not open, Open workbook first.
system(f'start excel.exe "{PathFile}"')
# Give some time to start up Excel
sleep(2)
xlRunMacro(FullMacroLink)
def main():
macroSettings = []
# The settings below will execute the macro example
xlPath = r'C:\test\' # Change add your needs
macroSettings.append(xlPath)
workbookName = 'Example.xlsm' # Change add your needs
macroSettings.append(workbookName)
xlModule = "Updates" # Change add your needs
macroSettings.append(xlModule)
xlSubroutine = "UpdateCurrentTime" # Change add your needs
macroSettings.append(xlSubroutine)
mainProgam(macroSettings)
if __name__ == "__main__":
main()
exit()
VBA Excel 宏
Option Explicit
Sub UpdateCurrentTime()
Dim sht As Worksheet
Set sht = ThisWorkbook.Sheets("Current-Time")
With sht
sht.Cells(2, 1).Value = Format(Now(), "hh:mm:ss")
End With
End Sub
您也可以将它用作动态模块。在您的 python 项目中将上述模块另存为 RunExcelMacro.py。仅使用以下行后:
from RunExcelMacro import mainProgam
mainProgram(macroSettings)
它将完成工作,成功...