Retrieve Excel Workbook Connection Properties - python

I am attempting to grab the "Command Text" from the Connection Property window in an Excel file using python. However, I cannot find the object that contains this information. In the below picture I would like to retrieve the highlighted EXEC sp_FooBar as a string:
I am able to retrieve the Connection names with:
import odbc
import win32com.client
file = r'PATH_TO_FILE'
xl = win32com.client.DispatchEx('Excel.Application')
wb = xl.workbooks.open(file)
for x in wb.connections:
print(x)
But I'm not sure how to use the <COMObject <unknown>> object further to grab the command text. I'm thinking win32com may have something, but can't seem to crack the code.

You can get the CommandText property from a OLEDBConnectioninstance like this:
import odbc
import win32com.client
file = r'PATH_TO_FILE'
xl = win32com.client.DispatchEx('Excel.Application')
wb = xl.workbooks.open(file)
for x in wb.Connections:
print(x.OLEDBConnection.CommandText)
xl.Application.Quit()

Related

Python's win32com not closing?

I'm trying to close an Excel sheet that I have open using win32com, but the following code doesn't work:
from win32com import DispatchEx
xlApp = client.DispatchEx("Excel.Application")
books = xlApp.Workbooks.Open(str(main_folder) + "\\Original.xlsm")
ws = books.Worksheets["Sheet 1"]
ws.Visible = 1
ws.ExportAsFixedFormat(0, str(main_folder) + "\\Duplicated")
ws.Close()
I get the following error:
"AttributeError: .Close"
How should I solve this?
If you want to close the workook, you can do:
from win32com import DispatchEx
xlApp = client.DispatchEx("Excel.Application")
books = xlApp.Workbooks.Open(str(main_folder) + "\\Original.xlsm")
ws = books.Worksheets["Sheet 1"]
ws.Visible = 1
ws.ExportAsFixedFormat(0, str(main_folder) + "\\Duplicated")
books.Close() # changed line, use books instead of ws.
You can also see xlwings if you have lots of things to do with Excel.
Please use the below command to close the excel application.
xlApp.Quit()

How to extract OLE objects from Excel table using Python?

I would like to use Python to extract OLE-objects from an Excel table into the Windows clipboard.
This post didn't help further since it is for VBA.
And this post is still unanswered.
Assuming the given Excel table (with ChemDraw or ChemSketch OLE objects):
There are some Python modules which can handle Excel files, e.g. openpyxl, xlrd.
The module win32clipboard can put data into the clipboard.
My Problems:
I don't see how to get the embedded OLE object to the clipboard. Probably, openpyxl and xlrd together with win32clipboard are not suited for this?
There is a Python module oletools which maybe can do it but I don't understand how it works.
https://pypi.org/project/oletools/
From this page:
oleobj: to extract embedded objects from OLE files.
This seems to be exactly what I am looking for, however, I couldn't find any MCVEs. And unfortunately, the documentation of oleobj is basically reduced to: "read the source code and find out yourself". I would be grateful for hints and assistance.
My code so far:
### trying to extract OLE objects from Excel table into clipboard
from openpyxl import load_workbook
import win32clipboard as clpbd
def set_clipboard(data):
clpbd.OpenClipboard()
clpbd.EmptyClipboard()
clpbd.SetClipboardText(data) # I'm aware, this is only for text, is there anything for OLEs?
clpbd.CloseClipboard()
def print_clipboard():
clpbd.OpenClipboard()
data = clpbd.GetClipboardData()
clpbd.CloseClipboard()
print(data)
wb = load_workbook(filename = 'tbChemOLE.xlsx')
ws = wb.active
myName = ws['A3'].value # result: napthalene
myImage = ws['B3'].value # result: None
myObject = ws['C3'].value # result: None
set_clipboard(myName)
print_clipboard() # result: Naphtalene
# set_clipboard(myImage) # crash, because myImage is None
print_clipboard()
# set_clipboard(myObject) # crash, because myObject is None
print_clipboard()
wb.close()
### end of code
I built a python module to do exactly this check it out over here. https://pypi.org/project/AttachmentsExtractor/ also the module can be run on any os.
after installing the library use the following code snippet:
from AttachmentsExtractor import extractor
abs_path_to_file='Please provide absolute path here '
path_to_destination_directory = 'Please provide path of the directory where the extracted attachments should be stored'
extractor.extract(abs_path_to_file,path_to_destination_directory) # returns true if one or more attachments are found else returns false.
In the meantime I found this post, where the OP actually didn't want the OLE objects on the clipboard, but for me it is fine. Actually, no need for openpyxl or xlrd, but win32com.client is required.
I can get all OLE objects, however, they are indexed (probably) in the sequence of their addition.
So I need to create a dictionary with the row index as key and a set of OLE object index of and name as value.
Code:
### copy OLE object in certain cell to clipboard
import win32com.client as win32
import win32clipboard
excel = win32.gencache.EnsureDispatch('Excel.Application')
ffname = r'C:\Test\tbChemOLE.xlsx'
wb = excel.Workbooks.Open(ffname)
ws = wb.Worksheets.Item(1)
objs = ws.OLEObjects()
def get_all_OLEs():
oleNo_dict = {} # dictionary for all OLE objects
for i in range(1,len(objs)+1): # loop all OLE objects
obj = objs.Item(i)
myRow = obj.TopLeftCell.Row # row of OLE object
myName = ws.Cells(myRow,1).Value # corresponding name
oleNo_dict[myRow] = (i, myName)
return oleNo_dict
def get_OLE(row):
try:
objs[oleNo_dict[row][0]].Copy()
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData(0xC004) # Binary access
win32clipboard.CloseClipboard()
except Exception as e:
print(e)
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.CloseClipboard()
return oleNo_dict[row]
# and OLE is on clipboard if found
oleNo_dict = get_all_OLEs()
row = 4
myMolecule = get_OLE(row)
print(myMolecule[1], "OLE object is now on the clipboard.")
wb.Close()
excel.Application.Quit()
### end of code
Result:
Anthracene OLE object is now on the clipboard.

Can excel CSV files be injected with macros?

I am trying to inject my csv files with a macro that automatically fits the column widths in excel but nothing is happening. I am using a code from a previous post (Use Python to Inject Macros into Spreadsheets). But here is the code
import os
import sys
# Import System libraries
import glob
import random
import re
#sys.coinit_flags = 0 # comtypes.COINIT_MULTITHREADED
# USE COMTYPES OR WIN32COM
#import comtypes
#from comtypes.client import CreateObject
# USE COMTYPES OR WIN32COM
import win32com
from win32com.client import Dispatch
desktop = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
x = r'C:\This\is\the\path'
scripts_dir = x
conv_scripts_dir = x
strcode = \
'''
sub test()
Column.Autofit
end sub
'''
#com_instance = CreateObject("Excel.Application", dynamic = True) # USING COMTYPES
com_instance = Dispatch("Excel.Application") # USING WIN32COM
com_instance.Visible = True#False
com_instance.DisplayAlerts = True#False
for script_file in glob.glob(os.path.join(scripts_dir, '*.csv')):
print("Processing: %s" % scr ipt_file)
# do the operation in background without actually opening Excel
(file_path, file_name) = os.path.split(script_file)
objworkbook = com_instance.Workbooks.Open(script_file)
xlmodule = objworkbook.VBProject.VBComponents.Add(1)
xlmodule.CodeModule.AddFromString(strcode.strip())
objworkbook.SaveAs(os.path.join(conv_scripts_dir, file_name))
com_instance.Quit()
This code actually opens the a file in excel, executes a macro, and then closes the excel window. Why doesn't the macro work from the python command line, but does work inside excel?
Exactly. There is not formats, whatsoever, in a CSV. It's like trying to add formatting to a Text file. You can't do that. You can convert CSV files to XLSM files (Excel Macro) or XLSB (Binary).
Sub CSVtoXLSB2()
Dim wb As Workbook
Dim CSVPath As String
Dim sProcessFile As String
CSVPath = "C:\your_path_here\"
sProcessFile = Dir(CSVPath & "*.csv")
Do Until sProcessFile = "" ' Loop until no file found.
Set wb = Application.Workbooks.Open(CSVPath & sProcessFile)
wb.SaveAs CSVPath & Split(wb.Name, ".")(0) & ".xlsb", FileFormat _
:=50, Password:="", WriteResPassword:="", ReadOnlyRecommended:=False, _
CreateBackup:=False
wb.Close
sProcessFile = Dir() ' Get next entry.
Loop
Set wb = Nothing
End Sub
Now, if you want to copy a Module from one Workbook to another, follow the steps listed below:
Copying a module from one workbook to another
Open both the workbook that contains the macro you want to copy, and the workbook where you want to copy it.
On the Developer tab, click Visual Basic to open the Visual Basic Editor.
In the Visual Basic Editor, on the View menu, click Project Explorer Project Explorer button image, or press CTRL+R.
In the Project Explorer pane, drag the module containing the macro you want to copy to the destination workbook. In this case, we're copying Module1 from Book2.xlsm to Book1.xlsm.
VBA Project Explorer
Module1 copied from Book2.xlsm
Copy of Module1 copied to Book1.xlsm

Connecting from Python to Excel 2016(365) and perform tasks

I have a problem connecting to Excel API in windows 10. I use Office365 and with it Excel2016. My goal is: to download CSV file from a client FTPS Server, merge it with the existing files,perfom some action on it(with pandas) and then load the whole data into excel and do reporting with it... Up to the point of loading it into Excel everything is fine.I managed to do all steps automatically with Python (sorry if my code looks a little cluttered - I am new to Python)
import subprocess
import os
import ftplib
import fnmatch
import sys
from ftplib import FTP_TLS
from win32com.client import Dispatch
import pandas as pd
filematch = '*.csv'
target_dir = 'cannot tell you the path :-) '
def loginftps(servername,user,passwort):
ftps = FTP_TLS(servername)
ftps.login(user=user,passwd=passwort)
ftps.prot_p()
ftps.cwd('/changes to some directory')
for filename in ftps.nlst(filematch):
target_file_name = os.path.join(target_dir,os.path.basename(filename))
with open(target_file_name,'wb') as fhandle:
ftps.retrbinary('RETR %s' %filename, fhandle.write)
def openExcelApplication():
xl = Dispatch("Excel.Application")
xl.Visible = True # otherwise excel is hidden
def mergeallFilestoOneFile():
subprocess.call(['prepareData_executable.bat'])
def deletezerorows():
rohdaten = pd.read_csv("merged.csv",engine="python",index_col=False,encoding='Latin-1',delimiter=";", quoting = 3)
rohdaten = rohdaten.convert_objects(convert_numeric=True)
rohdaten = rohdaten[rohdaten.UN_PY > 0]
del rohdaten['deletes something']
del rohdaten['deletes something']
rohdaten.to_csv('merged_angepasst.csv',index=False,sep=";")
def rohdatenExcelAuswertung():
csvdaten = pd.csv_read("merged.csv")
servername = input("please enter FTPS serveradress:")
user = input("Loginname:")
passwort = input("Password:")
loginftps(servername,user,passwort)
mergeallFilestoOneFile()
deletezerorows()
And here I am stuck somehow,.. I did extensive google research but somehow nobody has ever tried to perform Excel tasks from within Python??
I found this stackoverflow discussion: Opening/running Excel file from python but I somehow cannot figure out where my Excel-Application is stored to run code mentioned in this thread.
What I have is an Excel-Workbook which has a data connection to my CSV file. I want Python to open MS-Excel, refresh data connection and refresh a PivoTable & then save and close the file.
Has anybody here ever tried to to something similar and can provide some code to get me started?
Thanks
A small snippet of code that should work for opening an excel file, updating linked data, saving it, and finally closing it:
from win32com.client import Dispatch
xl = Dispatch("Excel.Application")
xl.Workbooks.Open(Filename='C:\\Users\\Xukrao\\Desktop\\workbook.xlsx', UpdateLinks=3)
xl.ActiveWorkbook.Close(SaveChanges=True)
xl.Quit()

Python to excel, openpyxl and file format not valid

The following is a simple snippet to open a .xlsm file, write a few values to it with python, and save it.
import openpyxl
from openpyxl import load_workbook
def toExcel():
wb = load_workbook(filename="C:\\Users\\Mark\\Documents\\Test.xlsm")
ws = wb.worksheets[0]
ws.cell(row=1, column=1).value = 'foo'
ws['A2'] = 'bar'
wb.save("C:\\Users\\Mark\\Documents\\Test1.xlsm")
toExcel()
While the file opens and saves, it mentions file format not valid / corrupt and cannot open. If the .xlsm is removed from the wb.save, it will save and open after selecting excel with Open With. Why is the file format not valid as is?
From here: https://openpyxl.readthedocs.io/en/default/tutorial.html#saving-to-a-file
Note
The following will fail:
>>> wb = load_workbook('document.xlsx')
>>> # Need to save with the extension *.xlsx
>>> wb.save('new_document.xlsm')
>>> # MS Excel can't open the document
>>>
>>> # or
>>>
>>> # Need specify attribute keep_vba=True
>>> wb = load_workbook('document.xlsm')
>>> wb.save('new_document.xlsm')
>>> # MS Excel can't open the document
>>>
>>> # or
>>>
>>> wb = load_workbook('document.xltm', keep_vba=True)
>>> # If us need template document, then we need specify extension as *.xltm.
>>> # If us need document, then we need specify attribute as_template=False.
>>> wb.save('new_document.xlsm', as_template=True)
>>> # MS Excel can't open the document
I found this post because I was trying to create a .xlsm file from scratch using openpyxl. I figured out that I was getting this error because when you load the workbook you need to have keep_vba=True as the second parameter passed to the load_workbook function.
So this is what your load_workbook function should look like:
wb = load_workbook(filename="C:\\Users\\Mark\\Documents\\Test.xlsm", keep_vba=True)
As a side note, here is my post that talks about creating a .xlsm file from scratch using openpyxl.

Categories