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.)
Related
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!
So, I am using openpyxl and pandas to open an excel file, and write in data. Then, I'm attempting to use pywin32 to open the same file and run a macro to parse the data. But, I'm getting this error when attempting to open the file with pywin32:
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'Open method of Workbooks class failed', 'xlmain11.chm', 0, -2146827284), None)
This is the code I'm using with pywin32:
if os.path.exists(self.excel_parser_location):
# print "Opening Telematics_Messages_Parser.xlsm in Excel"
xl = client.Dispatch("Excel.Application")
xl.Application.visible = True
wb = xl.Workbooks.Open(os.path.abspath(self.excel_parser_location), ReadOnly=1)
And this is the code I'm using to write in the data before using pywin32:
if os.path.exists(csv_path):
data = pd.read_csv(csv_path, error_bad_lines=False)
book = openpyxl.load_workbook(self.excel_parser_location, keep_vba=True)
writer = pd.ExcelWriter(self.excel_parser_location)
writer.book = book
data.to_excel(writer, sheet_name='2 RawData', index=False)
# print 'Writing new data'
book.remove(book['2 RawData'])
# print 'Removing blank sheet'
book_sheet = book['2 RawData1']
book_sheet.title = '2 RawData'
# print 'Renaming sheet'
writer.save()
writer.close()
I've had a similar issue in the past that I resolved by using an older version of pywin32, but that isn't working now. I'm using pywin32 version 223.
Sometimes this error occured when path to file is too long. So you should try this code with file with shorter path
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()
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
I have a block of code that I have used in the past to touch an excel file, run a macro already saved in the workbook, save and close. For example:
import win32com.client
import os
import os.path
file = 'myworkbook.xlsm'
path = 'C:/PATH/'
macro = 'mymacro'
filename = os.path.join(path, file)
xlApp = win32com.client.Dispatch("Excel.Application")
wkbk = xlApp.Workbooks.Open(filename)
runMacro = wkbk.Name + '!' + macro
xlApp.Run(runMacro)
wkbk.Save()
wkbk.Close(1)
xlApp.Quit()
xlApp = None
However, I would now like to use this on a macro that refreshes a data connection, and thus prompts for the password for the SQL database in question. When I try to run this, without worrying about the credentials, I get this error:
com_error: (-2147352567, 'Exception occurred.', (0, u'Microsoft Office
Excel', u"Cannot run the macro 'MYMACRO'. The
macro may not be available in this workbook or all macros may be
disabled.", u'C:\Program Files (x86)\Microsoft
Office\Office12\1033\XLMAIN11.CHM', 0, -2146827284), None)
Is there a way to make this work---i.e. to pass the required credentials from python to excel so that the macro can run?