Python: Open Excel Workbook using Win32 COM Api - python

I'm using the following code to open and display a workbook within Excel:
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open('my_sheet.xlsm')
ws = wb.Worksheets('blaaaa')
excel.Visible = True
When the File 'my_sheet.xlsm' is already opened, Excel asks me whether I want to re-open it without saving.
How could I check in advance whether the workbook is already opened up and in case it is, just bring it to the front?
EDIT: Found out by now:
if excel.Workbooks.Count > 0:
for i in range(1, excel.Workbooks.Count+1):
if excel.Workbooks.Item(i).Name is 'my_sheet.xlsm':
wb = excel.Workbooks.Item(i)
break
And one more question: My worksheet contains some headers where I enabled some filtering. So when the filters are set, and when I open the Workbook from Python, it sometimes asks me to enter a unique name to save the filter. Why is that? This is the dialogue:
EDIT Ok here it says (in german language) that the latter problem is a known bug in 2007 and 2010 files: https://social.msdn.microsoft.com/Forums/de-DE/3dce9f06-2262-4e22-a8ff-5c0d83166e73/excel-api-interne-namen and it seems to exist if you open Excel-Files programmatically. Don't know whether there is a workaround.

While you found a solution, consider using try/except/finally block. Currently your code will leave the Excel.exe process running in background (check Task Manager if using Windows) even if you close the visible worksheet. As an aside, in Python or any other language like VBA, any external API such as this COM interface should always be released cleanly during application code.
Below solution uses a defined function, openWorkbook() to go two potential routes: 1) first attempts to relaunch specified workbook assuming it is opened and 2) if it is not currently opened launches a new workbook object of that location. The last nested try/except is used in case the Workbooks.Open() method fails such as incorrect file name.
import win32com.client as win32
def openWorkbook(xlapp, xlfile):
try:
xlwb = xlapp.Workbooks(xlfile)
except Exception as e:
try:
xlwb = xlapp.Workbooks.Open(xlfile)
except Exception as e:
print(e)
xlwb = None
return(xlwb)
try:
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = openWorkbook(excel, 'my_sheet.xlsm')
ws = wb.Worksheets('blaaaa')
excel.Visible = True
except Exception as e:
print(e)
finally:
# RELEASES RESOURCES
ws = None
wb = None
excel = None

Related

Run Excel macro from different Excel file

I know there already are many questions regarding this topic, but I couldn't figure out a solution that works out for me.
I want to run an Excel macro stored in an 'xlsm' file, but I need to run it on a different Excel file ('xlsx').
Whenever I try the code below, I get an error message saying that the macro wasn't found, so I suppose the problem has to do with the pathing.
This is what I have:
import win32com.client
import os
try:
excel = win32com.client.Dispatch('Excel.Application')
excel_path = r'C:\Users\martin\Desktop\testing_excel.xlsx'
workbook = excel.Workbooks.Open(excel_path, ReadOnly=1)
excel.Application.Run("'macro_testing.xlsm'!local_macro")
workbook.Save()
excel.Quit()
print('Macro run succesfully')
except Exception as e:
print(e)
excel.Quit()
The 'xlsm' file with the macro is named 'macro_testing.xlsm', and the macro name is 'local_macro'.
Thanks in advance!
When I have to do similar, I store the macro in a command book (.xlsm) - or even .xlam that is called from the command book (which is .xlsm) and it then opens, manipulates, saves and closes .xlsx as appropriate.
If you try to run it from within an .xlsx, you'll never be able to save the code that has done the run, not exactly advisable for repetitive workflows.
So,
macro_testing.xlsm could have another sub which would be something like:
sub runExternal()
with Sheets("Sheet1").
extPath = cells(1,2)
extBook = cells(2,2)
'Declaring the path & workbook to use within the master workbook's "Sheet1"
workbooks.open(extPath & extBook) ReadOnly:False
call local_macro()
application.displayalerts = false 'Just in case there are any GUI prompts
workbooks(extBook).close saveChanges:=True
application.displayalerts = true
end sub
For anybody there who was experiencing the same problem I had, what I finally did was open the two Excel files, like this:
import os
excel_path = os.path.abspath('Excel_to_run_macro.xlsx')
if os.path.exists(excel_path):
xl = win32com.client.Dispatch('Excel.Application')
xl.Workbooks.Open(os.path.abspath('Excel_with_macro.xlsm'), ReadOnly=1)
workbook = xl.Workbooks.Open(excel_path, ReadOnly=1)
xl.Application.Run("'Excel_with_macro.xlsm'!Macro_name")
workbook.Save()
xl.Application.Quit()
del xl

How to ignore "Enable Editing" in excel after writing data using openpyxl

I am using a Excel template which have 6 tabs (All unprotected) and writing the data on each worksheet using openpyxl module.
Once the excel file is created and when tried to open the generated file, its not showing all data untill and unless I click "Enable editing" pop up.
Is there any attribute to disable in openpyxl.
This sounds like Windows has quarantined files received over a network. As this is done when the files are received, there is no way to avoid this when creating the files.
I solved this for me.
I found the answer here:
https://codereview.stackexchange.com/questions/240136/python-script-for-refreshing-and-preprocessing-data-in-excel-report-files
I only used the refresh function and it basically opened the excel file, click/refreshed, and closed/saved. You see an Excel file appear briefly on the screen. I'll insert this in a loop to go through all the files I am creating. It might take a little while to run hundreds, but much faster than open-click-save.
Here is all the code I used:
import win32com.client as win32
def refresh(directory, file_name):
xlapp = win32.DispatchEx('Excel.Application')
xlapp.DisplayAlerts = False
xlapp.Visible = True
xlbook = xlapp.Workbooks.Open(directory + '\\' + file_name)
xlbook.RefreshAll()
xlbook.Save()
xlbook.Close()
xlapp.Quit()
return()

Can't detect if the excel file is open without prompting user to save file / cancel

Using Iron Python I need to first determine if the excel file is already open and then if it is open, access it. if its not open then open it. problem: in my try statement when I try to open the workbook if its already open instead of failing the try it completes it instead and prompts the user to save / cancel the open file in excel. I want it to fail the try if the excel file is already open not prompt the user.
I use the Marshal Interopt lib to access the open file and that works well
UserExcelFile = os.path.join(userdirectory, 'podi.xlsx')
try:
workbook = excel.Workbooks.Open(UserExcelFile)
except:
print "Looks like it was already open"
return
workbook = excel.ActiveWorkbook
ws = excel.ActiveSheet
If the file is already open "workbook = excel.ActiveWorkbook" works perfect to edit the already open excel file.
I don't think your try except statement is going to catch an exception here. The line below will open the same file again even if it is already open.
workbook = excel.Workbooks.Open(UserExcelFile)
You should check if the file is already open yourself. Suggestions on how it can be done can be found here on stack: Python: Open Excel Workbook using Win32 COM Api
I finally got this working to where it will check using interop if the excel file is already open, if its not, it will open and start.. if it is already open then it just starts editing the open workbook. This is only a big deal for me because its Iron Python and the Win32 COM Api will not work with Iron.
if ex.Workbooks.Open(UserExcelFile) == True:
ExtAPI.Log.WriteMessage("excel file already open")
workbook = excel.ActiveWorkbook
ex = workbook
ws = excel.ActiveSheet
else:
workbook = ex.Workbooks.Open(UserExcelFile)
ws = workbook.Worksheets[1]

Open excel safe mode win32com - python 2.7

I am running a program using python with would open a macro enabled excel file that uses COM objects to capture the real time data from an application. I frequently end up in an Excel crash error (occurs when i run the job more than two or three times). I went through web and found that this might be due to add ins that are installed to my excel file, I followed the instructions to remove the add ins from excel but still have the problem. I am using win32com to open the excel file and here is the code that I am using. I am new to python, please share your comments to improve this code and fix this issue.
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(excel, r'C:\\pynow_futu.xlsm')
win32api.Sleep(5000)
ws = wb.Worksheets('fut')
excel.Visible = True
excel.DisplayAlerts = False
for wb in excel.Workbooks:
ws = wb.Worksheets('fut')
if wb.Name == 'pynow_futu.xlsm':
print("WB:", str(wb.Name))
wb.DoNotPromptForConvert = True
wb.CheckCompatibility = False
filename = "C:\\futu.csv"
win32api.Sleep(2000)
wb.SaveAs(filename,FileFormat=24, ConflictResolution=2)
win32api.Sleep(1000)
wb.Close(True)
The excel file got crashed because few child process from the previous run was still active and it stops from opening the new file thus it crash. Fixed it by killing the child process

Python / Excel : Turn off Office Excel Compatibility Checker Programmatically

A file which has data I need to access is being generated in xlsx format yet I need it to be in xls format for my purpose.
I'm able to use win32com.client to open the file however the save cannot fully complete due to Compatibility Checker dialog pop up which notifies you of loss of formatting/features by going from a xlsx --> xls format.
Here's the code which currently doesn't allow me to save the file as execution hangs waiting for the dialog to close, any help would be much appreciated:
excel = win32com.client.Dispatch('Excel.Application')
excel.DisplayAlerts = False
in_file = u"C:\\Path\\to\\infile\\infile.xlsx"
out_file = u"C:\\Path\\to\\outfile\\outfile.xls"
wb = excel.Workbooks.Open(in_file)
wb.CheckCompatibility = False
wb.DoNotPromptForConvert = True
wb.SaveAs(out_file, FileFormat=56) #Execution hangs here
wb.Close()
excel.Quit()
I've seen other similar posts which mention the methods and attributes I've already set in this script. I've also modified my the registry value to ShowCompatDialog = 0.
MSDN says on Workbook.DoNotPromptForConvert property:
"true to prompt the user to convert the workbook; otherwise, false".
Write in your code:
wb.DoNotPromptForConvert = False
UPDATE: Solved this issue using this Excel Add-In
For reference: Changing the registry value was working however the values were being reset daily on the internal network which I develop in. Without being able to edit the registry values myself b/c I don't possess the admin rights to do so, the above solution was the only thing that ended up solving my problem.

Categories