从python运行excel宏

从python运行excel宏,python,excel,python-3.x,vba,Python,Excel,Python 3.x,Vba,我使用以下代码从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('ma

我使用以下代码从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文件,只会看到一个灰色窗口:

你知道为什么会这样吗?另外,如何向代码中添加一些内容,以便在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
Sub-LoopFilesInFolder()
将wb1设置为工作簿
将wb2设置为工作簿
将路径设置为字符串
将文件设置为字符串
作为字符串的Dim扩展名
将myFileName设置为字符串
Application.ScreenUpdating=False
Application.DisplayAlerts=False
设置wb1=ActiveWorkbook
path=ActiveWorkbook.path&“\csvs\”
扩展名=“*.csv”
file=Dir(路径和扩展名)
文件“”时执行此操作
设置wb2=工作簿.打开(文件名:=路径和文件)
wb2.激活
'此部分是针对avail heads文件的,基本上它只是打开它并将信息复制到模板中
如果wb2.Name=“avail\u heads.csv”,则
范围(“A1”)。选择
范围(选择,选择。结束(xlDown))。选择
范围(选择,选择。结束(xlToRight))。选择
选择,复制
wb1.激活
工作表(“原始数据”).Range(“B88”).Paste特殊XLPaste值
如果结束
'此部分用于预测文件,基本上它只是打开它并将信息复制到模板中
如果wb2.Name=“forecast.csv”,则
范围(“A1”)。选择
范围(选择,选择。结束(xlDown))。选择
范围(选择,选择。结束(xlToRight))。选择
选择,复制
wb1.激活
工作表(“原始数据”).Range(“B74”).Paste特殊XLPaste值
如果结束
“此部分用于收入文件,基本上它只是打开它并将信息复制到模板中
如果wb2.Name=“income volume.csv”,则
范围(“A1”)。选择
范围(选择,选择。结束(xlDown))。选择
范围(选择,选择。结束(xlToRight))。选择
选择,复制
wb1.激活
工作表(“原始数据”).Range(“B3”).Paste特殊XLPaste值
如果结束
'此部分用于传出卷文件,基本上它只是打开它并将信息复制到模板
如果wb2.Name=“outgoing_volume.csv”,则
范围(“A1”)。选择
范围(选择,选择。结束(xlDown))。选择
范围(选择,选择。结束(xlToRight))。选择
选择,复制
wb1.激活
工作表(“原始数据”).Range(“B36”).Paste特殊XLPaste值
如果结束
'此部分用于所需的heads文件,基本上它只是打开它并将信息复制到模板中
如果wb2.Name=“required_heads.csv”,则
范围(“A1”)。选择
范围(选择,选择。结束(xlDown))。选择
范围(选择,选择。结束(xlToRight))。选择
选择,复制
wb1.激活
工作表(“原始数据”).Range(“B102”).Paste特殊XLPaste值
如果结束
wb2.关闭
file=Dir
环
'myFileName=ActiveWorkbook.path&“\forecast\u for\u w”&格式(现在为“ww”)+1
myFileName=ActiveWorkbook.path&“\yoda\u forecast”
ActiveWorkbook.SaveAs文件名:=myFileName,文件格式:=xlWorkbookNormal
“MsgBox”完成
Application.DisplayAlerts=True
端接头

分派后,您需要将可见性设置为True:

xl = win32com.client.Dispatch("Excel.Application")
xl.Application.Visible = True
此外,调用宏不需要
此工作簿

xl.Application.Run("LoopFilesInFolder")
要再次关闭工作簿,需要将其分配给变量:

wb = xl.Workbooks.Open(Filename=name, ReadOnly=1)
wb.Close(SaveChanges=False)
我写这个软件包是为了让事情变得更简单:

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
运行宏还没有实现,但有一个解决方案。同时,您可以通过执行以下操作来解决此问题:


分派后,需要将可见性设置为True:

xl = win32com.client.Dispatch("Excel.Application")
xl.Application.Visible = True
此外,调用宏不需要
此工作簿

xl.Application.Run("LoopFilesInFolder")
要再次关闭工作簿,需要将其分配给变量:

wb = xl.Workbooks.Open(Filename=name, ReadOnly=1)
wb.Close(SaveChanges=False)
我写这个软件包是为了让事情变得更简单:

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
运行宏还没有实现,但有一个解决方案。同时,您可以通过执行以下操作来解决此问题:


我在《赏金》杂志上写这篇文章已经快一个星期了,我真的不知道有多少人以前有过这个问题。经过一个多星期的努力,我多次考虑跳出办公室的窗户,我终于明白了问题所在

我刚刚补充说,问题不在python(某种程度上),而主要在VBA代码上

Application.ScreenUpdating = True
最后,问题就解决了。不确定是excel错误导致宏完成时不更新,还是python错误导致宏完成后不允许屏幕更新。然而,在这样做之后,现在一切都很好


谢谢

我在《赏金》杂志上发表这篇文章已经将近一个星期了,我真的不知道以前有多少人有过这个问题。经过一个多星期的努力,我多次考虑跳出办公室的窗户,我终于明白了问题所在

我刚刚补充说,问题不在python(某种程度上),而主要在VBA代码上

Application.ScreenUpdating = True
最后,问题就解决了。不确定是excel错误导致宏完成时不更新,还是python错误导致宏完成后不允许屏幕更新。然而,在这样做之后,现在一切都很好


谢谢

嗨!我试图添加
xl.Application.Visible=True
,但一直遇到同样的问题。为了摆脱灰色sc