使用 win32com.client 将 xls 重新保存为 xlsx 时如何 disable/autoanswer 关于 macros/VB 项目的对话框?
How to disable/autoanswer dialog box about macros/VB Project when resaving xls to xlsx with win32com.client?
使用此代码时:
import win32com.client as win32
input_files = os.listdir(parent_dir)
input_files = [parent_dir + i for i in input_files if i.endswith('.xls') and not i.endswith('.xlsx')]
for input_file in input_files:
if not os.path.isfile(input_file.replace('.xls', '.xlsx')):
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(input_file)
wb.SaveAs(input_file + "x", FileFormat=51) # FileFormat = 51 is for .xlsx extension
wb.Close() # FileFormat = 56 is for .xls extension
excel.Application.Quit()
在包含一些 macros/VB 项目的 excel 文件上,消息框经常显示警告,所有 macros/VB 项目都将丢失,我想以某种方式自动回答它,例如,"Yes",或者可能有一些 SaveAs 函数的参数或
的设置
win32.gencache.EnsureDispatch('Excel.Application')?
现在我可以使用 FileFormat=51 将文件重新保存为 xlsm,但出于某些安全原因我不想这样做,我的文件中真的不需要这个 macros/VB 项目。
已尝试 excel.DisplayAlerts = 错误 - 没有帮助。
也在考虑像 pywinauto 这样的东西,但也许它有点过头了,也许还有更优雅的解决方案?
使用
wb.Close(True) #if you need to save .xls file also
或使用
wb.Close(False) # if you not decide to save .xls file
另一方面,它可能打开了其他文件,因此当您使用 excel.Application.Quit()
并且这些文件未保存时,excel 将在关闭前显示确认对话框。
嗯,有趣的是,如果你保存在xlsm中,而不是在xlsx中,Excel不会问包含macros/VB项目的问题,你可以像xlsm一样在openpyxl中打开xlsm,所以, 如何在 xlsm 中重新保存:
def resave_xls_file_as_xlsx_or_xlsm(in_xls_file_path, out_excel_file_type='xlsm'):
excel = win32.gencache.EnsureDispatch('Excel.Application')
wbxls = excel.Workbooks.Open(in_xls_file_path)
in_xls_file_path = in_xls_file_path.replace('/', '\')
out_xlsx_or_xlsm_file_path = in_xls_file_path + out_excel_file_type[-1]
# FileFormat = 51 is for .xlsx extension, 52 for xlsm, no questions about containing VB script for xlsm
if out_excel_file_type == 'xlsm':
excel_file_format = 52
elif out_excel_file_type == 'xlsx':
excel_file_format = 51
else:
excel_file_format = 52 # or do some error corrections:
# print('ERROR, wrong excel file type:', out_excel_file_type)
# return None # sys.exit ('taihen taihen') # raise cthulhu
wbxls.SaveAs(out_xlsx_or_xlsm_file_path, FileFormat=excel_file_format)
wbxls.Close()
excel.Application.Quit()
return out_xlsx_or_xlsm_file_path
此外,有时我们有某种损坏的 xlsx 文件,Excel 开始抱怨它,然后脚本停止,要自动恢复它,您可以使用此代码,注意 xlsx 文件路径,因为例如,此路径在这种情况下不起作用:
resaved_xlsx_on_disk = 'c:/this_wont_work/2.xlsx' # 通常有效,但不适用于 win32.client
corrupted_xlsx_on_disk = 'c:\fyi_if_you_dont_use_two_backslashes_and_use_slashes_in_path_it_will_not_open\1.xlsx'
resaved_xlsx_on_disk = r'c:\you_can_also_use_this.xlsx'
xl = win32.gencache.EnsureDispatch('Excel.Application')
# xl.Visible = True # otherwise excel is hidden (btw if corrupted it anyway show some message, but autoclose it)
wb = xl.Workbooks.Open(corrupted_xlsx_on_disk, CorruptLoad=1)
xl.SendKeys("{Enter}", Wait=1)
xl.DisplayAlerts = 0
wb.SaveAs(resaved_xlsx_on_disk) # You can try wb.Save(), but I can't get it to work :-(
wb.Close()
xl.Application.Quit()
===
更新。 2021 年 8 月 9 日:
考虑到上面的代码,当使用相反的操作 - 将 xlsx 重新保存到 xls 时,经常 windows 发生兼容性检查(另外,如果 Excel 看起来像挂断 - 这可能是因为 window 确实没有获得焦点并隐藏在其他 windows) 之间,tl;dr,excel.DisplayAlerts = False
完成工作,代码示例(我也会检查,也许它适用于不使用此 xlsm 扩展的 xls->xlsx 转换, 如果 xls 包含宏):
import os
import win32com.client
import win32com
# if strange errors on start occures, delete everything from this path
# (maybe dynamic loading from now do this action unnecessary):
print(win32com.__gen_path__)
def resave_xlsx_files_as_xls(files_parent_dir):
input_files = os.listdir(files_parent_dir) # todo: use the glob, Luke!
input_files = [files_parent_dir + i for i in input_files if i.endswith('.xlsx')]
for input_file in input_files:
print(input_file)
if not os.path.isfile(input_file.replace('.xlsx', '.xls')):
excel = win32com.client.dynamic.Dispatch('Excel.Application')
wbxls = excel.Workbooks.Open(input_file)
# wbxls.DoNotPromptForConvert = True # seems that this line has no effect if uncommented
# wbxls.CheckCompatibility = False # seems that this line also has no effect if uncommented
excel.DisplayAlerts = False # this line do the main job - compatibility check window did not shows up!
# AFAIK this library hardly understand normal os.path.join or os.path.sep
input_file = input_file.replace('/', '\')
input_file = input_file.replace('.xlsx', '.xls')
# FileFormat = 51 is for .xlsx extension, 52 for xlsm
excel_file_format = 56
# Compatibility check window will show up here on SaveAs line, you may did not locate it at first, cause it
# usually don't get focus, so it may be hidden somewhere under couple of windows, best
# way to find it - click "-" button on every window until wallpaper shows up, pressing
# hotkeys like Win-D will not help - this command will hide this compatibility check
# window also
wbxls.SaveAs(input_file, FileFormat=excel_file_format)
wbxls.Close() # FileFormat = 56 is for .xls extension
excel.Application.Quit()
else:
print('There is already converted file in folder!')
output_files = os.listdir(files_parent_dir)
output_files = [files_parent_dir + i for i in output_files if i.endswith('.xls')]
return output_files
resave_xlsx_files_as_xls('c:/test/')
使用此代码时:
import win32com.client as win32
input_files = os.listdir(parent_dir)
input_files = [parent_dir + i for i in input_files if i.endswith('.xls') and not i.endswith('.xlsx')]
for input_file in input_files:
if not os.path.isfile(input_file.replace('.xls', '.xlsx')):
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(input_file)
wb.SaveAs(input_file + "x", FileFormat=51) # FileFormat = 51 is for .xlsx extension
wb.Close() # FileFormat = 56 is for .xls extension
excel.Application.Quit()
在包含一些 macros/VB 项目的 excel 文件上,消息框经常显示警告,所有 macros/VB 项目都将丢失,我想以某种方式自动回答它,例如,"Yes",或者可能有一些 SaveAs 函数的参数或
的设置win32.gencache.EnsureDispatch('Excel.Application')?
现在我可以使用 FileFormat=51 将文件重新保存为 xlsm,但出于某些安全原因我不想这样做,我的文件中真的不需要这个 macros/VB 项目。
已尝试 excel.DisplayAlerts = 错误 - 没有帮助。
也在考虑像 pywinauto 这样的东西,但也许它有点过头了,也许还有更优雅的解决方案?
使用
wb.Close(True) #if you need to save .xls file also
或使用
wb.Close(False) # if you not decide to save .xls file
另一方面,它可能打开了其他文件,因此当您使用 excel.Application.Quit()
并且这些文件未保存时,excel 将在关闭前显示确认对话框。
嗯,有趣的是,如果你保存在xlsm中,而不是在xlsx中,Excel不会问包含macros/VB项目的问题,你可以像xlsm一样在openpyxl中打开xlsm,所以, 如何在 xlsm 中重新保存:
def resave_xls_file_as_xlsx_or_xlsm(in_xls_file_path, out_excel_file_type='xlsm'):
excel = win32.gencache.EnsureDispatch('Excel.Application')
wbxls = excel.Workbooks.Open(in_xls_file_path)
in_xls_file_path = in_xls_file_path.replace('/', '\')
out_xlsx_or_xlsm_file_path = in_xls_file_path + out_excel_file_type[-1]
# FileFormat = 51 is for .xlsx extension, 52 for xlsm, no questions about containing VB script for xlsm
if out_excel_file_type == 'xlsm':
excel_file_format = 52
elif out_excel_file_type == 'xlsx':
excel_file_format = 51
else:
excel_file_format = 52 # or do some error corrections:
# print('ERROR, wrong excel file type:', out_excel_file_type)
# return None # sys.exit ('taihen taihen') # raise cthulhu
wbxls.SaveAs(out_xlsx_or_xlsm_file_path, FileFormat=excel_file_format)
wbxls.Close()
excel.Application.Quit()
return out_xlsx_or_xlsm_file_path
此外,有时我们有某种损坏的 xlsx 文件,Excel 开始抱怨它,然后脚本停止,要自动恢复它,您可以使用此代码,注意 xlsx 文件路径,因为例如,此路径在这种情况下不起作用:
resaved_xlsx_on_disk = 'c:/this_wont_work/2.xlsx' # 通常有效,但不适用于 win32.client
corrupted_xlsx_on_disk = 'c:\fyi_if_you_dont_use_two_backslashes_and_use_slashes_in_path_it_will_not_open\1.xlsx'
resaved_xlsx_on_disk = r'c:\you_can_also_use_this.xlsx'
xl = win32.gencache.EnsureDispatch('Excel.Application')
# xl.Visible = True # otherwise excel is hidden (btw if corrupted it anyway show some message, but autoclose it)
wb = xl.Workbooks.Open(corrupted_xlsx_on_disk, CorruptLoad=1)
xl.SendKeys("{Enter}", Wait=1)
xl.DisplayAlerts = 0
wb.SaveAs(resaved_xlsx_on_disk) # You can try wb.Save(), but I can't get it to work :-(
wb.Close()
xl.Application.Quit()
===
更新。 2021 年 8 月 9 日:
考虑到上面的代码,当使用相反的操作 - 将 xlsx 重新保存到 xls 时,经常 windows 发生兼容性检查(另外,如果 Excel 看起来像挂断 - 这可能是因为 window 确实没有获得焦点并隐藏在其他 windows) 之间,tl;dr,excel.DisplayAlerts = False
完成工作,代码示例(我也会检查,也许它适用于不使用此 xlsm 扩展的 xls->xlsx 转换, 如果 xls 包含宏):
import os
import win32com.client
import win32com
# if strange errors on start occures, delete everything from this path
# (maybe dynamic loading from now do this action unnecessary):
print(win32com.__gen_path__)
def resave_xlsx_files_as_xls(files_parent_dir):
input_files = os.listdir(files_parent_dir) # todo: use the glob, Luke!
input_files = [files_parent_dir + i for i in input_files if i.endswith('.xlsx')]
for input_file in input_files:
print(input_file)
if not os.path.isfile(input_file.replace('.xlsx', '.xls')):
excel = win32com.client.dynamic.Dispatch('Excel.Application')
wbxls = excel.Workbooks.Open(input_file)
# wbxls.DoNotPromptForConvert = True # seems that this line has no effect if uncommented
# wbxls.CheckCompatibility = False # seems that this line also has no effect if uncommented
excel.DisplayAlerts = False # this line do the main job - compatibility check window did not shows up!
# AFAIK this library hardly understand normal os.path.join or os.path.sep
input_file = input_file.replace('/', '\')
input_file = input_file.replace('.xlsx', '.xls')
# FileFormat = 51 is for .xlsx extension, 52 for xlsm
excel_file_format = 56
# Compatibility check window will show up here on SaveAs line, you may did not locate it at first, cause it
# usually don't get focus, so it may be hidden somewhere under couple of windows, best
# way to find it - click "-" button on every window until wallpaper shows up, pressing
# hotkeys like Win-D will not help - this command will hide this compatibility check
# window also
wbxls.SaveAs(input_file, FileFormat=excel_file_format)
wbxls.Close() # FileFormat = 56 is for .xls extension
excel.Application.Quit()
else:
print('There is already converted file in folder!')
output_files = os.listdir(files_parent_dir)
output_files = [files_parent_dir + i for i in output_files if i.endswith('.xls')]
return output_files
resave_xlsx_files_as_xls('c:/test/')