Release excel workbook after write operations through a script - python

I am using a python script to write data into the excel workbook. Now, I want to release the pointer. I dont want to close the workbook because of some other reasons. I just want to release the pointer. I searched on google but no answer. Can anyone please help?
from win32com.client import Dispatch
xl = Dispatch('Excel.Application')
xl.ScreenUpdating = True # performance
xl.Visible = 1
xl.DisplayAlerts = True
wbs = xl.Workbooks
return xl, wbs
Then i am using wb to refer to workbook's different sheets.
wb = xl.Workbooks.open(filename)

Variables will be released as they go out of scope. In the example below, the variable xl is released when the get_workbook function is exited. If you need to explicitly remove a variable, use the del statement.
from win32com.client import Dispatch
def get_workbook(path):
xl = Dispatch('Excel.Application')
xl.Visible = 1
return xl.Workbooks.open(path)
wb = get_workbook(r'c:\temp\test.xlsx')
sheet = wb.Worksheets.Item(1)
sheet.Range('A1').Value2 = 'test'
del wb, sheet

Related

How to make an URL 'clickable' in Excel with Python? [duplicate]

I am using win32com to modify an Excel spreadsheet (Both read and edit at the same time) I know there are other modules out there that can do one or the other but for the application I am doing I need it read and processed at the same time.
The final step is to create some hyperlinks off of a path name. Here is an Example of what I have so far:
import win32com.client
excel = r'I:\Custom_Scripts\Personal\Hyperlinks\HyperlinkTest.xlsx'
xlApp = win32com.client.Dispatch("Excel.Application")
workbook = xlApp.Workbooks.Open(excel)
worksheet = workbook.Worksheets("Sheet1")
for xlRow in xrange(1, 10, 1):
a = worksheet.Range("A%s"%(xlRow)).Value
if a == None:
break
print a
workbook.Close()
I found some code for reading Hyperlinks using win32com:
sheet.Range("A8").Hyperlinks.Item(1).Address
but not how to set hyperlinks
Can someone assist me?
Borrowing heavily from this question, as I couldn't find anything on SO to link to as a duplicate...
This code will create a Hyperlink in cells A1:A9
import win32com.client
excel = r'I:\Custom_Scripts\Personal\Hyperlinks\HyperlinkTest.xlsx'
xlApp = win32com.client.Dispatch("Excel.Application")
workbook = xlApp.Workbooks.Open(excel)
worksheet = workbook.Worksheets("Sheet1")
for xlRow in xrange(1, 10, 1):
worksheet.Hyperlinks.Add(Anchor = worksheet.Range('A{}'.format(xlRow)),
Address="http://www.microsoft.com",
ScreenTip="Microsoft Web Site",
TextToDisplay="Microsoft")
workbook.Save()
workbook.Close()
And here is a link to the Microsoft Documentation for the Hyperlinks.Add() method.

update links using win32com where excel is linked with multiple sources

I am using win32com.client to open Excel with
excel = win32com.client.Dispatch("Excel.Application")
workbook = excel.Workbooks.Open(filename,UpdateLinks=False, ReadOnly=True)
Sometimes this generates an alert with the following text:
"This workbook contains one or more links that cannot be
updated." & options are: "Continue", and "Edit Links").
This stops the script until I handle the dialogue box manually which is not preferred.
I want to continue as if "Continue" had been
clicked, or to suppress the whole dialogue box, I can't find a way to do this.
Searching the Stackoverflow forums, I've seen the following suggestions:
excel.DisplayAlerts = False
excel.AskToUpdateLinks = False
I've tried each of these (immediately after the excel variable is
assigned) and neither has the desired effect, separately or together.
As suggested in other forums I have also tried to open excel & save & then again reopen with python, which is also not working.
wb = xlApp.Workbooks.Open(Path to file,UpdateLinks = False)
ws = wb.Worksheets('XYZ')
wb.Close(SaveChanges=1)
excel.Visible = False
excel.ScreenUpdating = False
excel.DisplayAlerts = False
excel.AskToUpdateLinks = False
wb = xlApp.Workbooks.Open(Path to file)
ws = wb.Worksheets('XYZ')
Does anyone know a solution that works? anything will do either break link or continue.
Thank you in advance
excel.AskToUpdateLinks = False
As far as I know, the above turns off the prompt and automatically update external links as a file is open. Try use below:
excel = win32com.client.Dispatch("Excel.Application")
excel.DisplayAlerts = False
workbook = excel.Workbooks.Open(Path to file,UpdateLinks=0)

dynamically read and/or overwrite an excel file with python without the overwrite alert appearing

For some reason the following code runs fine but the file overwrite alert keeps coming up even though I have set xl.EnableEvents = False, the code won't execute further unless I manually click the overwrite file popup. Does anyone know how to fix this?
The code opens an excel file which contains a string which allows the excel file to connect to the bloomberg api, I used this solution here to get this to work. As long as the file is open for enough time the data is pulled into the file and then saves and exits. It takes around ~35 seconds to get the data and the pandas table starts displaying the content I'm requesting
The problem is the popups! - I need to see when the string '#N/A Requesting Data...' is no longer in the file and can't see a way to do it without periodically saving the file. A solution that allows me to see the file contents dynamically without having to save would be great.
The solution here didn't work for me to stop the popups, I could probably make a new file each time and then delete them all at the end but this seems a bit clunky. This question extends this problem here if anyone wants to see the code and the problem in a more full context.
WB = 'C:/path/to/my/file.xlsx'
location = "EGLL"
def run_VWA(WB, location):
"""open the excel file, allow enough time to pull the data, then close and save"""
bb = 'C:/blp/API/Office Tools/BloombergUI.xla'
xl=win32com.client.DispatchEx("Excel.Application")
xl.Workbooks.Open(bb)
xl.AddIns("Bloomberg Excel Tools").Installed = True
wb = xl.Workbooks.Open(Filename=WB) #opens workbook in readonly mode.
xl.Visible = False
xl.EnableEvents = False
xl.DisplayAlerts = False
total=0
colstring='#N/A Requesting Data...'
while total < 40:
wb.Save()
df = df_from_excel(WB, location)
if colstring not in df:
break
time.sleep(3)
total+=3
wb.Close(SaveChanges=1)
xl.DisplayAlerts = True
xl.Quit()
#Cleanup the com reference.
del xl
return
Any help with this is much appreciated, I have very limited experience with the win32com library.
After a good few hours digging I've found how to solve this dynamically without the need for saving the file each iteration. If anyone else comes up against this problem most of the solution was found here. Many thanks assylias for some useful pointers.
def run_VWA(WB, location):
"""open the excel file, allow enough time to pull the data, then close and save"""
bb = 'C:/blp/API/Office Tools/BloombergUI.xla'
xl=win32com.client.DispatchEx("Excel.Application")
xl.Workbooks.Open(bb)
xl.AddIns("Bloomberg Excel Tools").Installed = True
wb = xl.Workbooks.Open(Filename=WB) #opens workbook in readonly mode.
xl.Visible = False
xl.EnableEvents = False
xl.DisplayAlerts = False
count=0
while True:
readData = wb.Worksheets(location)
allData = readData.UsedRange
if allData.Rows.Count > 1 or allData.Columns.Count > 1:
print('rows: {}'.format(allData.Rows.Count))
print('cols: {}'.format(allData.Columns.Count))
break
print(wb)
print(count)
time.sleep(3)
count+=3
wb.Close(SaveChanges=1)
xl.DisplayAlerts = True
xl.Quit()
#Cleanup the com reference.
del xl
return

How to check if a large Excel file is protected as quickly as possible?

How to check if excel file is protected with password the fastest way (without trying to open it and placing an exception)?
Updated:
from zipfile import *
from openpyxl import load_workbook
filename = 'Z:\\path_to_file\\qwerty.xlsm' # protected one
try:
wb = load_workbook(filename, data_only=True, read_only=True)
except (BadZipfile) as error:
print(is_zipfile(filename))
A problem is that I got False as an output, thus I cannot get rid of the exception and replace it with is_zipfile() condition.
Solution using the openpyxl library:
import openpyxl
wb = openpyxl.load_workbook(PATH_TO_FILE)
if wb.security.lockStructure == None:
# no password, act accordingly
...
else:
# password, act accordingly
...
You can do this using the protection._password property of a sheet:
wb = openpyxl.load_workbook("C:\\Users\\...\\Downloads\\some_workbook.xlsx")
print(wb.worksheets[0].protection._password)
You can do this for whatever sheet you would like, based off the worksheets in the workbook.
If there is no password, the value is None. Otherwise, it returns the hashed password.
So, you can create a method to check this:
def password_protected(sheet):
if sheet.protection._password is None:
return False
return True
The same method applies for the whole workbook, the property is just workbook.protection._workbook_password.
When trying to open a password protected workbook with openpyxl, this indeed gives a error zipfile.BadZipFile so a workaround would be to use:
import zipfile
zipfile.is_zipfile("workbook.xlsx")

Accessing UpdateLinks() in COM Object using Python

I am working on automating an Excel file which is linked to certain .csv files.
Those .csv files are created from a SAS Code which is run every Quarter.
The files created are timestamped accordingly for example XYZ_201603.csv and XYZ_201606.csv and so on.
I need to update the links on my Excel File so that it automatically changes the link to the file from next quarter. I am trying to do this using Python win32com.client and my code looks like
from win32com import Dispatch
xl_app = Dispatch("Excel.Application")
xl_app.Visible = True
xl_app.DisplayAlerts = False
wb = xl_app.workbooks.open(r"C:\Users\XYZ\Desktop\Test\Summary.xlsx")
xl_app.AskToUpdateLinks = False
try:
wb.UpdateLink(Name=r"C:\Users\XYZ\Desktop\Test\XYZ_201606.csv")
except Exception as e:
print(e)
finally:
wb.Close(True)
wb = None
return True
xl_app.Quit()
xl = None
Whenever I run this, I get the following error
(-2147352567,'Exception occured.',(0,'Microsoft Excel','UpdateLink method of
Workbook class failed','xlmain11.chm',0,-2146827284),None)
Can Somebody tell me what is going wrong here. Also, incase I have multiple links, how do I tell which link needs to be changed to what? Can I pass a dictionary of directories of updated datasets
The code and the approach has been taken from this answer on Stack Overflow
Update Links in for Excel Spreadsheet Using Python
If you review the Microsoft Documentation, it seems that the UpdateLink method can be called without any parameters. Therefore this program should work:
import win32com.client as win32
xl_app = win32.gencache.EnsureDispatch("Excel.Application")
xl_app.Visible = True
xl_app.DisplayAlerts = False
wb = xl_app.workbooks.open(r"C:\Users\XYZ\Desktop\Test\Summary.xlsx")
wb.UpdateLink()
wb.Save()
wb.Close()
xl_app.Quit()
I'm not sure if my solution solves your issue, but I had the same problem and I used LinkSources() and ChangeLink() instead
newSource = r"C:\Users\XYZ\Desktop\Test\XYZ_201606.csv"
oldSource = wb.LinkSources()
wb.ChangeLink(Name = oldSource[0], NewName = newSource, Type = 1)
Hope it helps!

Categories