Python win32com 'Invalid number of parameters' - python

I am trying to use win32com to convert multiple xlsx files into xls using the following code:
import win32com.client
f = r"./input.xlsx"
xl = win32com.client.gencache.EnsureDispatch('Excel.Application')
wb = xl.Workbooks.Open(f)
xl.ActiveWorkbook.SaveAs("./somefile.xls", FileFormat=56)
which is failing with the following error:
Traceback (most recent call last):
File "xlsx_conv.py", line 6, in <module>
xl.ActiveWorkbook.SaveAs("./somefile.xls", FileFormat=56)
File "C:\python27\lib\site-packages\win32com\gen_py\00020813-0000-0000-C000-000000000046x0x1x9.py", line 46413, in SaveAs
, Local, WorkIdentity)
pywintypes.com_error: (-2147352562, 'Invalid number of parameters.', None, None)
Some more details:
I can do other commands to the workbook i.e. wb.Worksheets.Add()and set xl.Visible=True to view the workbook. and even do wb.Save() but can't do a wb.SaveAs()

The COM exception is due to the missing filename argument as f = r"./input.xlsx" cannot be found. Had you used Excel 2013+, you would have received a more precise exception message with slightly different error code:
(-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', "Sorry, we
couldn't find ./input.xlsx. Is it possible it was moved,
renamed or deleted?", 'xlmain11.chm', 0, -2146827284), None)
While your path does work in Python's native context pointing to the directory the called .py script resides, it does not in interfacing with an external API, like Windows COM, as full path is required.
To resolve, consider using Python's built-in os to extract the current directory path of script and concatenate with os.path.join() in the Excel COM method. Also, below uses try/except/finally to properly end the Excel.exe process in background regardless if exception is raised or not.
import os
import win32com.client as win32
cd = os.path.dirname(os.path.abspath(__file__))
try:
f = os.path.join(cd, "input.xlsx")
xl = win32.gencache.EnsureDispatch('Excel.Application')
wb = xl.Workbooks.Open(f)
xl.ActiveWorkbook.SaveAs(os.path.join(cd, "input.xls"), FileFormat=56)
wb.Close(True)
except Exception as e:
print(e)
finally:
wb = None
xl = None

I spent quite a lot of time searching for a proper solution but the only thing I found out is that the script I wrote yesterday today is not working. In addition the same script works on other computers, so I guess this is something broken in the windows/MsExcel/Python environment, but I can't figure out where.
I found a work around to the "SaveAs" problem and it is just to use the "Save" function. Luckily that still works and does not block me from carrying on with my tasks. I hope this help.
import win32com.client as win32
from shutil import copyfile
# you need to define these two:
# src, is the absolute path to the excel file you want to open.
# dst, is the where you want to save as the file.
copyfile(src, dst)
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(PATH_DATASET_XLS)
ws = wb.Worksheets(DATASET_WORKING_SHEET)
# do some stuff
ws.Cells( 1, 'A' ).Value = "hello"
# Saving changes
wb.Save() # <- this is the work around
excel.Application.Quit()

Related

Working with win32com in Python for opening .xslm files

I am using a function I got from another stack overflow article to open some Excel files in python, get all the charts on the first sheet, and save those as png files. I use it as part of a larger code I wrote to iterate through some excel files, change some select values, then get the changed charts.
import win32com.client
import PIL
from PIL import ImageGrab, Image
import os
import sys
def saveExcelGraphAsPNG(inputExcelFilePath, outputPNGImagePath,AC,mg,t):
# Open the excel application using win32com
o = win32com.client.Dispatch("Excel.Application")
# Disable alerts and visibility to the user
o.Visible = 0
o.DisplayAlerts = 0
# Open workbook
wb = o.Workbooks.Open(inputExcelFilePath)
# Extract first sheet
sheet = o.Sheets(1)
for n, shape in enumerate(sheet.Shapes):
# Save shape to clipboard, then save what is in the clipboard to the file
shape.Copy()
image = ImageGrab.grabclipboard()
# Saves the image into the existing png file (overwriting) TODO ***** Have try except?
outputPNGImage = outputPNGImagePath+str(AC)+'_' + str(n) +'_'+str(mg)+'_'+str(t)+ '.png'
image.save(outputPNGImage, 'png')
pass
pass
wb.Close(True)
o.Quit()
Particularly, the excel files i am iterating through are macro-enabled excel files (.xlsm). The function works fine for a few of the files, but then I eventually reach one of them and get the following error I do not get with the other xlsm files:
Traceback (most recent call last):
File "C:\Users\Desktop\Modeling\getGraphs.py", line 100, in <module>
saveExcelGraphAsPNG(preamb+ex_list[imp_nums.index(i)], preamb+outputPNGImagePath,i,mg[imp_nums.index(i)],t)
File "C:\Users\Desktop\Modeling\getGraphs.py", line 49, in saveExcelGraphAsPNG
wb = o.Workbooks.Open(inputExcelFilePath)
File "<COMObject <unknown>>", line 5, in Open
com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'Open method of Workbooks class failed', 'xlmain11.chm', 0, -2146827284), None)
When opening the file after getting this error to check what could have happened, I get a warning that the file has been corrupted and I lose the 2 sheets (out of 4) that primarily employ the macros get deleted when I click to salvage what it can. This is baffeling me because before reaching this file the code works perfectly (and without corrupting) 3 other xlsm files. Any help or clues towards what might be the issue or a fix would be appreciated!
Thanks in advance!

Converting xls to pdf

I'm trying to execute a script to convert a XLS file to a PDF file:
from win32com import client
import win32api
input_file = r"C:\Users\Max12\Desktop\xml\pdfminer\UiPath\attachments\75090058\Status\Verwerking\25063599.xls"
#give your file name with valid path
output_file = r"C:\Users\Max12\Desktop\xml\pdfminer\UiPath\attachments\75090058\Status\Verwerking\test.pdf"
#give valid output file name and path
app = client.DispatchEx("Excel.Application")
app.Interactive = False
app.Visible = False
Workbook = app.Workbooks.Open(input_file)
try:
Workbook.ActiveSheet.ExportAsFixedFormat(0, output_file)
except Exception as e:
print("Failed to convert in PDF format.Please confirm environment meets all the requirements and try again")
print(str(e))
finally:
Workbook.Close()
app.Exit()
However, getting the following error:
File "xls.py", line 9, in <module>
app = client.DispatchEx("Excel.Application")
File "C:\Python38\lib\site-packages\win32com\client\__init__.py", line 113, in DispatchEx
dispatch = pythoncom.CoCreateInstanceEx(clsid, None, clsctx, serverInfo, (pythoncom.IID_IDispatch,))[0]
pywintypes.com_error: (-2147024894, 'The system cannot find the file specified.', None, None)
I've closed Excel.
Please help
This seems to be a problem caused by the fact, that the referenced COM-Interface cannot be found. Normally you have to make sure, that the referenced Office-Tools are installed correctly or that the reference OCS-module is registered correctly.
Maybe you could try to use the pandas lib instead of COM? See enter link description here

Win32Com Save As Variable Name in Python 3.6

I'm trying to loop through .xlsb file types in a folder and convert them to .csv in Python 3+ and Windows 10 and have pieced together the code below with help from SO. I want to save the new .csv as the original .xlsb name but am having issues - I have this so far:
import os
import glob
import win32com.client
path = r'C:\Users\folder\Desktop\Test Binary'
all_files_test = glob.glob(os.path.join(path, "*.xlsb"))
for file in all_files_test:
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = False
doc = excel.Workbooks.Open(file)
doc.SaveAs(Filename="C:\\Users\\folder\\Desktop\\Test Binary\\file.csv",FileFormat = 6) #overwrites file each time, need to substitute 'file'
doc.Close(True)
excel.Quit()
excel.Quit()
Which of course just overwrites each new iteration each time as 'file.csv'. How can I substitute the .xlsb name for each .csv name to SaveAs separate files? Thanks in advance.
Simply use str.replace on file variable to change extension. And consider wrapping in try/except to cleanly release COM objects regardless of error or not.
path = r'C:\Users\folder\Desktop\Test Binary'
all_files_test = glob.glob(os.path.join(path, "*.xlsb"))
for file in all_files_test:
try:
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = False
doc = excel.Workbooks.Open(file)
csv_name = file.replace('.xlsb', '.csv')
doc.SaveAs(Filename = csv_name, FileFormat = 6)
doc.Close(True)
excel.Quit()
except Exception as e:
print(e)
finally:
doc = None
excel = None
And to go one level deeper use combination of os.path.basename and os.path.join:
path = r'C:\Users\folder\Desktop\Test Binary'
...
csv_name = os.path.basename(file).replace('.xlsb', '.csv')
doc.SaveAs(Filename = os.path.join(path, 'Conversion_Files', csv_name), FileFormat = 6)
Parfait's answer is good, but has a few flaws. I have remedied those (that I have noticed) in this answer, and refactored out some context managers to make the logic easier to understand (and hence easier to modify).
It now prints failed files to sys.stdout (to let you recover, Unix-style, by replacing the for loop with repeated input() / f.readline()[:-1] calls), and only opens the Excel COM object once; this should be a lot faster.
I have also added support for recursively performing this match, but this feature requires Python 3.5 or above in order to work.
import os
import glob
import traceback
from contextlib import contextmanager
import win32com.client
from pythoncom import com_error
PATH = r'C:\Users\folder\Desktop\Test Binary'
#contextmanager
def open_excel():
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = False
try:
yield excel
finally:
excel.Quit()
#contextmanager
def open_workbook(excel, filename):
doc = excel.Workbooks.Open(filename)
try:
yield doc
finally:
doc.Close(True)
all_files_test = glob.glob(os.path.join(PATH, "**.xlsb"), recursive=True)
with excel_cm() as excel:
for file in all_files_test:
try:
with open_workbook(file) as doc:
doc.SaveAs(Filename=file[:-4] + 'csv', FileFormat=6)
except com_error as e:
print(file)
traceback.print_exc()

tomcat/CGI and python3 fails to use win32com to open Excel file

I have a PY3 script that uses Win32COM to instantiate a new Excel instance and attempt to open an existing .xlsx file - boiled down, this fails when called via Tomcat/CGI on Windows:
sys.stdout.write("Content-Type: text/html\n\n")
excel = DispatchEx('Excel.Application')
dir = r'C:\temp'
s = 'test.xlsx'
sfile = os.path.join(dir, s)
try:
wbS = excel.Workbooks.Open(sfile)
except pythoncom.com_error as error:
print("exception details: {0}".format(error))
exit(1)
Action fails with:
exception details: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', "Microsoft Excel cannot access the file 'C:\\temp\\test.xlsx'. There are several possible reasons:\n\n• The file name or path does not exist.\n• The file is being used by another program.\n• The workbook you are trying to save has the same name as a currently open workbook.", 'xlmain11.chm', 0, -2146827284), None)
Fails when Tomcat runs either as Administrator or local account, both having Full Control access to the existing file. EnsureDispatch, Dispatch and DispatchEX do not yield success. No other application is accessing/locking the file. Running from within a cmd succeeds, suggesting that something is lost at the CGI level.
(Using COM allows for copying of worksheets between workbooks and other activities not supported by XLSWriter, et.al.)

pywintypes.com_error opening Excel with Python

I have the following script which was immitated from here ( http://pythonexcels.com/python-excel-mini-cookbook/ ):
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open('words.xlsx')
and it returns the following error ( full traceback )
Traceback (most recent call last):
File "", line 1, in
wb = excel.Workbooks.Open('words.xlsx')
File "C:directory\Python35\lib\site-packages\win32com\gen_py\00020813-0000-0000-C000-000000000046x0x1x7\Workbooks.py", line 78, in Open
, Converter, AddToMru, Local, CorruptLoad)
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', "'words.xlsx' could not be found. Check the spelling of the file name, and verify that the file location is correct.\n\nIf you are trying to open the file from your list of most recently used files, make sure that the file has not been renamed, moved, or deleted.", 'xlmain11.chm', 0, -2146827284), None)
When I alternatively use openpyxl's functions to open the workbook there is no issue (referenced this https://automatetheboringstuff.com/chapter12/ ) . The python file and the excel file are in the same folder together. Am I calling something inappropriately?
I am certain that the file is spelled correctly ( words.xlsx ) and that it is in the same folder as the python file.
Any thoughts would be appreciated.
Try this:
import win32com.client as win32
import os
excel = win32.gencache.EnsureDispatch('Excel.Application')
path = os.getcwd().replace('\'','\\') + '\\'
wb = excel.Workbooks.Open(path+'words.xlsx')
Excepted a path error, not module or system error.
'xlmain11.chm' is empty, so don't need this.
Be careful when using escape characters on path-string.
Script and work file are in the same directory!
Hope that helps
Have you tried openpyxl, it's very easy to use, reading and writing excel files is no trouble
from openpyxl import Workbook
And initialize as
wb = Workbook()
ws = wb.active()
And you can start reading and writing right away

Categories