这是我的故事:
首先,我正在使用Windows7。我有一个xlsx文件,正在尝试将其注入宏;我不想将宏保存在文件中,我只想在工作表上运行宏(文件中只有一个工作表)。这是我的代码:
import sys
from os.path import join
from os import chdir
from os import getcwd
from glob import iglob
from logging import error
from logging import exception
from win32com.client import Dispatch
sys.coinit_flags = 0
com_instance = Dispatch('Excel.Application')
# do the operation in background without actually opening Excel
com_instance.Visible = False
com_instance.DisplayAlerts = False
str_code = \
'''
Sub macro()
Set ws = ThisWorkbook.ActiveSheet
With ws
LastRow = .Range("A" & Rows.Count).End(xlUp).Row
.Range(.Cells(1, 1), .Cells(LastRow, 1)).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
.Range("A1").FormulaR1C1 = "record_id"
Dim rng As Range: Set rng = Application.Range("A2:A5")
Dim i As Integer
For i = 1 To rng.Rows.Count
rng.Cells(RowIndex:=i, ColumnIndex:="A").FormulaR1C1 = i
Next
Range("A2:A5").AutoFill Destination:=Range(.Cells(2, 1), .Cells(LastRow, 1))
End With
End Sub
'''
try:
for fname in iglob(join(destination, file_name)):
print('Injecting %s with macro' % file_name)
wb = com_instance.Workbooks.Open(fname)
xlmodule = wb.VBProject.VBComponents.Add(1)
xlmodule.CodeModule.AddFromString(str_code.strip())
com_instance.Application.Run('macro')
wb.SaveAs(join(destination, file_name))
com_instance.ActiveWorkBook.Close()
com_instance.Quit()
# except Exception as e:
except Exception as e:
error(e)
exception(e)
print('Injection failed')
com_instance.Quit()
pass
else:
print('Injected %s with macro' % file_name)
return
该宏应该打开xlsx文件,在最开始处插入一个新的空白列-该列的行数与先前存在的“ A”列的非空白填充范围内的行数相同,然后填充该新列。换句话说,我想移动现有的“ A”列,以便将新内容放置在“ A”列中。我要在此列中放置的内容是,对于第一行,标题为“ record_id”,然后将从1开始的连续整数放置在该列的其余单元格中,直到到达最后一行。我的宏VBA代码-上面的str_code-在我打开excel,按alt-F11,将模块插入工作表中并单击“运行”时有效,但是在我调用python代码时无法正常运行。当我调用我的python代码时,excel会正确打开,因此我的行
Dispatch('Excel.Application')
正常运行。而且,
com_instance.Visible = False
com_instance.DisplayAlerts = False
正常工作,因为没有弹出excel窗口并且没有警报显示。问题出在口译员遇到时
com_instance.Application.Run('macro')
这时,如果我将鼠标悬停在任务栏中的excel图标上,则excel从Visual Basic应用程序中打开了一个警报-按下alt-F11时会弹出GUI-并为我提供了结束VBA的选择执行或尝试对其进行调试。明确地说,
Run-time error '1004':
Auto-fill method of Range Class Failed
因为它给了我机会,所以我知道这行代码的确会导致工作表运行指定的行,因为上述警告是在“手动”运行宏时出现的。我知道问题出在我的VBA代码中
Range("A2:A5").AutoFill Destination:=Range(.Cells(2, 1), .Cells(LastRow, 1))
但是,如果我复制该行,则将其复制,然后将其粘贴到预先存在的相同行之上即可。从视觉上看
Range("A2:A5").AutoFill Destination:=Range(.Cells(2, 1), .Cells(LastRow, 1))
然后我有
Range("A2:A5").AutoFill Destination:=Range(.Cells(2, 1), .Cells(LastRow, 1))
Range("A2:A5").AutoFill Destination:=Range(.Cells(2, 1), .Cells(LastRow, 1))
如果我删除底线,然后单击运行。宏正确执行,然后我的代码继续到我的glob生成器提供的下一个项目,然后遇到相同的问题。
我正在使用此代码的300个文件,因此手动调试所有300个文件效率低下。
我的记录器记录到错误是这样的
(-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2146788248), None)
使用
import win32api
win32api.FormatMessage(-2147352567)
win32api.FormatMessage(-2146788248)
告诉我错误是
'Exception occurred' (which was very helpful -_-)
pywintypes.error: (317, 'FormatMessageW', 'The system cannot find message text for message number 0x%1 in the message file for %2.')
我无法弄清楚问题出在哪里;我花了太长时间搜索互联网并阅读堆栈溢出,github等论坛,并且坦率地说,我不理解后一个错误。我需要帮助使上面的代码正确运行。预先感谢。