Get code from module in Excel - python

I have a number of workbooks that have Macros which point to a particular SQL server using a connection string embedded in the code. We've migrated to a new SQL server so I need to go through these and alter the connection string to look at the new server in each of the Macros that explicitly mentions it.
Currently I'm able to list all of the modules in the workbook, however I'm unable to get the code from each module, just the name and type number.
for vbc in wb.VBProject.VBComponents:
print(vbc.Name + ": " + str(vbc.Type) + "\n" + str(vbc.CodeModule))
What property stores the code so that I can find and replace the server name? I've had a look through the VBA and pywin32 docs but can't find anything.

Got it- there's a Lines method in the CodeModule object that allows you to take a selection based on a starting and ending line. Using this in conjunction with the CountOfLines property allows you to get the whole thing.
for vbc in wb.VBProject.VBComponents:
print(vbc.Name + ":\n" + vbc.CodeModule.Lines(1, vbc.CodeModule.CountOfLines))
It's worth noting as well that the first line is line 1, not line 0 as that caught me out. The following will error vbc.CodeModule.Lines(0, vbc.CodeModule.CountOfLines - 1) because the index 0 is out of range.

Method Lines of property CodeModule has the signature
Function Lines(ByVal first as Integer, ByVal count as Integer) as String
first is in range 1...CodeModule.CountOfLines,
index of the first row of the code section, you want to
retrieve
count is in range 1...CodeModule.CountOfLines-first+1,
number of lines of the section
The return value is a concatenation of the code lines of the section with separator vbNewLine.

Related

why does openpyxl keeps changing "normal" formula into an array formula

So I have a table with the following formula
=SUMPRODUCT((IFERROR(INDEX(Tabela2[start],MATCH(((Tabela1[type]=J3) * Tabela1[id]),Tabela2[id],0))>=$I$1;0)*1))
which just count the number of entries that happen after a certain date and are of a certain type
however when I run my script which uses openpyxl to update the main table , it adds curly brackets to the previous formula which makes it return the wrong values. I can fix it by just enter it normally without control+shift+center but it is kind of annoying having to fix it every time I update it
I also made the following script that just opens and saves the files and it also adds curly brackets to the formula. Can someone tell me what am I doing wrong.
from openpyxl import load_workbook
ficheiro = 'Livro1.xlsx'
workbook = load_workbook(filename=ficheiro)
workbook.save(filename="test1 -test.xlsx")
"...it adds curly brackets to the formula. Can someone tell me what am I doing wrong."
It's Excel's dynamic array function added with Office 365 compatibility and certain cross-platform updates. It assumes the formula is an array and forces curly braces ("{", "}") unless one uses an implicit intersection operator ("#"). The down side is that older versions of Excel don't recognize either operator and will cause string variables (lookup, parse, filter, concatenate "&") to crash in VBA code.
There is no way to prevent excel from doing that, but this may be a useful workaround.
This code removes the implicit intersection after inserting the '#' operator to force turning off the dynamic array function while executing VBA. This cycles thru each worksheet and returns to the original sheet. Comment out the formula list to suit particular use of the formulas causing difficulty. The second macro changes type of replace function used depending on version VBA by testing if it recognizes newer array constructs. The trick is to use a precompile identifier (#) to process newer code that the retro editor will not allow but also in which the newer formulas won't work without.
Sub DelOperand
Scheat = ActiveSheet.Name
Sheets(1).Select
For Count = 1 To Worksheets.Count
'Remove forced special character'
Run FormulaFix("Cell")
Run FormulaFix("Column")
Run FormulaFix("FilterXML")
Run FormulaFix("FormulaText")
'Run FormulaFix("Frequency")'
'Run FormulaFix("Growth")'
Run FormulaFix("Hyperlink")
Run FormulaFix("If")
Run FormulaFix("Index")
Run FormulaFix("Indirect")
Run FormulaFix("IsFormula")
'Run FormulaFix("LinEst")'
'Run FormulaFix("LogEst")'
'Run FormulaFix("MInverse")'
'Run FormulaFix("MMult")'
'Run FormulaFix("Mode.MULT")'
'Run FormulaFix("Munit")'
Run FormulaFix("Offset")
Run FormulaFix("Row")
Run FormulaFix("Transpose")
'Run FormulaFix("Trend")'
If Count = Worksheets.Count Then Exit For
ActiveSheet.Next.Select
Next
Sheets(Scheat).Select
Err.Clear
End Sub
Function FormulaFix(ByRef Whatzit)
'Credit: Stephen L. Rush'
Dim WhatNow
Dim ErrNum As Integer
On Error Resume Next
WhatNow = "#" & Whatzit
If Application.Evaluate("=XLOOKUP(1,{1,2,3},{3,2,1})") Then
#If Not Err = 0 Then
Cells.Replace What:=WhatNow, Replacement:=Whatzit, LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
#Else
Cells.Replace What:=WhatNow, Replacement:=Whatzit, LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
#End If
End If
Next
On Error GoTo 0
End Function

Getting exception "openpyxl.utils.exceptions.IllegalCharacterError"

I am extracting data from an Oracle 11g Database using python and writing it to an Excel file. During extraction, I'm using a python list of tuples (each tuple indicates each row in dataset) and the openpyxl module to write the data into Excel. It's working fine for some datasets but for some, it's throwing the exception:
openpyxl.utils.exceptions.IllegalCharacterError
This is the solution I've already tried:
Openpyxl.utils.exceptions.IllegalcharacterError
Here is my Code:
for i in range(0,len(list)):
for j in range(0,len(header)):
worksheet_ntn.cell(row = i+2, column = j+1).value = list[i][j]
Here is the error message:
raise IllegalCharacterError
openpyxl.utils.exceptions.IllegalCharacterError
I did get this error because of some hex charactres in some of my strings.
'Suport\x1f_01'
The encode\decode solutions mess with the accente words too
So...
i resolve this with repr()
value = repr(value)
That give a safe representation, with quotation marks
And then i remove the first and last charactres
value = repr(value)[1:-1]
Now you can safe insert value on your cell
The exception tells you everything you need to know: you must replace the characters that cause the exception. This can be done using re.sub() but, seeing as only you can decide what you want to replace them with — spaces, empty strings, etc. — only you can do this.

Selenium - How to add integer variable in xpath using python

Im new with selenium/python and that my problem:
I have a simple site with a couple of news.
I try to write script that iterates over all news, open each one, do something and goes back to all other news
All news have same xpath, difference only with last symbol - i try to put this symbol as variable and loop over all news, with increment my variable after every visited news:
x = len(driver.find_elements_by_class_name('cards-news-event'))
print (x)
for i in range(x):
driver.find_element_by_xpath('/html/body/div[1]/div[1]/div/div/div/div[2]/div/div[3]/div/div[1]/div/**a["'+i+'"]**').click()
do something
i = i+1
Python return error: "Except type "str", got "int" instead. Google it couple of hours but really can't deal with it
Very appreciate for any help
You are trying to add a string and a int which is is why the exception. Use str(i) instead of i
xpath_string = '/html/body/div[1]/div[1]/div/div/div/div[2]/div/div[3]/div/div[1]/div/**a[{0}]**'.format(str(i))
driver.find_element_by_xpath(xpath_string).click()
In the above the {0} is replaced with str(i). You can use .format to substitute multiple variables in a string by providing them as positional values, it is more elegant and easy to use that using + to concatenate strings.
refer: http://thepythonguru.com/python-string-formatting/

Generate customer ID's with Python 2.7

In the program I am writing I need to generate a customer ID for every new client that gets registered into the system.
I want the list to start at 0001 and each new client ID is the next consecutive number from the last one registered (for example if the last registered client ID is 0234 the new registered ID needs to be 0235).
First, you generate a number then append zeros to that number. This works:
n = 500
for i in range(1, n):
print "0" * (4 - len(str(i))) + str(i)
I am hoping you have a basic background in python, I'm making it a crude way, I'm sure there are more sophisticated approaches, but this should do for now.
To start with:
Make a file that stores values alone, say store. (Initial value 0001)
In your main script, read store's contents and feed them to a variable, say n.
An elegant way of generating client IDs in the format you specified would be print "%04d" %(n+1) - %04d specifies the 4 digit format you requested and n is the variable that stores your previous ID issued.
And last, overwrite the contents of store to the incremented value.
Remember to close() the file and you are all set!
For more information you can refer to the python documentation on string formatting.

xlwt can't parse IF statement in formula

i'm trying to write a formula to a series of cells by building the string. for instance i want to display the word "true" in a cell if the corresponding cell in column G contains the word "monkey" in it.
for rowi in range(totalRows):
thisRow = str(rowi)
functionString = r'IF(ISNUMBER(SEARCH("monkey",G'+thisRow+')),("true")
this will produce the string "IF(ISNUMBER(SEARCH("monkey",G1)),("true")" -- if i then pass that to xlwt.Formula...
ws.write(rowi+1, 0, xlwt.Formula(functionString))
i get this error...
File "C:\Python27\Lib\site-packages\xlwt\ExcelFormula.py", line 22, in __init__
raise ExcelFormulaParser.FormulaParseException, "can't parse formula " + s
xlwt.ExcelFormulaParser.FormulaParseException: can't parse formula IF(ISNUMBER(SEARCH("bitmap",G2)),("true")
is it possible to use this type of function with xlwt?
Ignoring the impossibility that you typed in monkey and G1 whereas the error message mentions bitmap and G2 ...
I suggest that you fire up Excel, select a cell, type = and paste your formula ... what happens? This check is always advisable before going public, and is available even if your internet connection is broken.
Notes:
(1) the parentheses around "true" are redundant
(2) simpler: ISNUMBER(SEARCH("bitmap",G2))
(3) Are you really expecting that a user will open the resulting XLS file and type text into column G?

Categories