Working with win32com in Python for opening .xslm files - python

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!

Related

Python win32com convert from xlsx/xls to xlsm?

I have seen many responses for win32com on how to convert from xlsm to xlsx or xls, but I am trying to do the exact opposite. I tried to mimic the code used to convert xlsm to xlsx but I get an error message. The code I'm using is:
import win32com.client as win32
from win32com import client
from shutil import copyfile
xlApp = client.gencache.EnsureDispatch('Excel.Application')
if file_original[-1] == "x" or file_original[-1] == "s": # If it is xlsx or xls
file_temp = copyfile(file_orig, str(main_folder) + "\\mainfile_duplicated_nomacro.xlsx")
books_temp = xlApp.Workbooks.Open(str(main_folder) + "\\mainfile_duplicated_nomacro.xlsx")
books_temp.SaveAs(Filename = "\\mainfile_duplicated.xlsm" , FileFormat = 52)
books_temp.Close(True)
elif anl_orig[-1] == "m": # If it is xlsm
file_dup = copyfile(file_orig, str(main_folder) + "\\mainfile_duplicated.xlsm")
When I save books_temp, I use FileFormat = 52, which is something I got from here. The error message I get is:
com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel',
"Microsoft Excel cannot access the file 'C:\EDF0B000'. 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)
Where am I going wrong?

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.)

Python win32com 'Invalid number of parameters'

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()

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

Issues with excel file. XLRDError: Unsupported format, or corrupt file: What kind of file is this?

I have a bit of code that works with an xls file. It works for everything I've thrown at it except this one file and I don't know how to properly identify what this one file is. I get the file off of a website I am navigating with Selenium. This particular spreadsheet always downloads as a file type that causes this error.
The full error is:
Traceback (most recent call last):
File "/Users/Meir/Documents/PYTHON/IFG User Update/code/ifg_TPA_update_excel.py", line 44, in <module>
rb = open_workbook((os.path.expanduser("~/Documents/PYTHON/Selenium test/TPA_Example.xls")),formatting_info=True)
File "/usr/local/lib/python2.7/site-packages/xlrd/__init__.py", line 443, in open_workbook
ragged_rows=ragged_rows,
File "/usr/local/lib/python2.7/site-packages/xlrd/book.py", line 94, in open_workbook_xls
biff_version = bk.getbof(XL_WORKBOOK_GLOBALS)
File "/usr/local/lib/python2.7/site-packages/xlrd/book.py", line 1262, in getbof
bof_error('Expected BOF record; found %r' % self.mem[savpos:savpos+8])
File "/usr/local/lib/python2.7/site-packages/xlrd/book.py", line 1256, in bof_error
raise XLRDError('Unsupported format, or corrupt file: ' + msg)
XLRDError: Unsupported format, or corrupt file: Expected BOF record; found '\xff\xfe<\x00S\x00T\x00'
The file I am trying to open displays as an xls file in my finder. However, when I open it, it does not open with the file name as the header but rather displays "Workbook1". When I hit save, it opens the save menu as if I had clicked save as, and defaults to "Workbook1.xlsx". I tried changing my code to open it as an xlsx file, but then it errors out saying it cannot find the file. Whenever I try googling it, I don't know how to phrase it to get a relevant answer.
When I contacted the websites support team asking what kind of file the TPA bulks op sheet is they replied:
The TPA bulk ops is an older version than the rest of the bulk ops, it's due to be rebuilt some time later this year. When downloading the file your best bet is to do a Save As and save it as an older version of .xls, I usually select Microsoft Excel 5.0/95 Workbook, and also format it as text. Formatted that way it should upload without issue.
Any ideas as to how I can open this right from Python?
Currently I am building each part as a separate code and I was going to combine them all together once I get it sorted out. The below is the section of code that will be opening the file and is experiencing the error.
My code:
#!/usr/bin/env python
## Import OS and Modules
import os
import csv
import xlrd
import xlwt
import xlutils
import csv
import collections
## Define Input File from IFG
ifg_user_file = "New_PCs_to_set_up_in_marketing_database_-_4-11-2013.csv"
## Import data
data = [row for row in csv.reader(open (os.path.expanduser("~/Downloads/" + ifg_user_file),'U'))]
## Find number of rows
row_count = sum(1 for row in data)
print row_count
## Set to turn off when reaching the end of data
end_of_data = False
from xlutils.copy import copy # http://pypi.python.org/pypi/xlutils
from xlrd import open_workbook # http://pypi.python.org/pypi/xlrd
from xlwt import easyxf # http://pypi.python.org/pypi/xlwt
##################################################################################
## THE ERROR OCCURS AT THE LINE BELOW
rb = open_workbook((os.path.expanduser("~/Documents/PYTHON/Selenium test/TPA_Example.xls")),formatting_info=True)
r_sheet = rb.sheet_by_index(0) # read only copy to introspect the file
EDIT: I tried to open it with codecs rather than open for diagnostics
rb=codecs.open((os.path.expanduser("~/Documents/PYTHON/Selenium test/TPA_Example.xls")), 'r', encoding='utf16');
print rb;
print rb.readline();
print rb.read(20);
It printed the following result:
<open file '/Users/Meir/Documents/PYTHON/Selenium test/TPA_Example.xls', mode 'rb' at 0x110fe51e0>
<STYLE>
.excel { BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px so
It looks like it is an excel document then. Not sure how to proceed. Is there a universal open an excel document command?

Categories