ISSUE:
Is there a way to remove missing references (references that have prefix: "MISSING" mentioned before their name) from an Excel workbook using VBA? I have a macro-enabled Excel workbook which I have to share with my colleagues from time to time. The workbook uses a special add-in that utilizes specific references. However, due to a limited number of licenses, not everyone has that add-in installed in their Excel, which is why the references associated with that add-in show up as "MISSING" in their workbooks and throw compilation errors when they try to run any macro. I don't want my collegues to go poking around the developer tab and uncheck the "MISSING" references each time they get the file. Is there a way this can be automated using VBA?
Issue Screenshot
STEPS TAKEN ALREADY:
I already tried the following code but it didn't work.
Option Explicit
Sub References_RemoveMissing()
Dim theRef As Variant, i As Long
For i = ThisWorkbook.VBProject.References.Count To 1 Step -1
Set theRef = ThisWorkbook.VBProject.References.Item(i)
If theRef.IsBroken = True Then
ThisWorkbook.VBProject.References.Remove theRef
End If
Next i
End Sub
When I ran the above code, I got an error on line:
ThisWorkbook.VBProject.References.Remove theRef
The error stated: "Run-time error '-2147319779 (8002801d)': Object library not registered"
Error Screenshot
Before running the above code, I made sure that "Microsoft Visual Basic for Application Extensibility 5.3" is checkmarked/ticked in my MS Excel reference list and placed above the missing references (which I did by increasing its priority).
My excel security settings were also set to "Trust Access To Visual Basic Project".
I looked up on google, this seems to be a pretty old issue. I found a bunch of old links suggesting the same coding solution but none of them seem to work for me.
Excel VBA prevent from importing missing references (didn't work for me)
https://support.microsoft.com/en-us/topic/how-to-check-and-remove-incorrect-project-references-in-the-visual-basic-editor-in-word-7ba187a6-9dfd-1288-8f08-d1f01ea02a3f (didn't work for me)
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/b90ed5cc-6bd1-46b4-bbea-de4a15521b26/detect-and-remove-missing-references-in-vba-code?forum=exceldev (didn't work for me)
POSSIBLE ALTERNATE SOLUTION:
If the missing references cannot be removed using VBA, is it possible to have an external Python-based script embedded within excel VBA that runs and removes the "MISSING" references?
Any help on this would be greatly appreciated! :)
Related
Trying to update a cell in an Excel workbook which is shared (to clarify- it has the 'shared' status ).
However, writing to the workbook using 'openpyxl' library removes the 'shared' status.
I tried looking for solutions online and found nothing helpful. The closest thing was this thread but the zip solution suggested there didn't help. It did not save the changes made into the workbook.
p.s- it goes without saying that using Google Sheets is the better program to use, however sadly it's not a possibility for me.
Thanks in advance :)
We have a rather complicated Excel based VBA Tool that shall be replaced by a proper Database and Python based application step by step.
There will be time of the transition between were the not yet completely ready Python tool and the already existing VBA solution will coexist.
To allow interoperability the Python tool must be able to export the database values into the Excel VBA Tool keeping it intact. Meaning that not only all VBA codes have to work as expected but also Shapes, Special Formats etc, Checkboxes etc. have to work after the export.
Currently a simple:
from openpyxl import load_workbook
wb = load_workbook(r'Tool.xlsm', keep_vba=True)
# Write some data i.e. (not required to destroy the file)
wb["SomeSheet!SomeCell"] = "SomeValue"
wb.save(r"Tool_filled.xlsm")
will destroy the file, i.e. shapes won't work, checkboxes neither. (The resulting file is only 5 MB from originally 8 MB, showing that something went quite wrong).
Is there a way to only modify only the data of an ExcelSheet keeping everything else intact/untouched?
As far I know an Excel Sheet are only zipped .xml files. So it should be possible to edit only the related sheets? Correct?
Is there a more comfortable way as writing everything from scratch to only modify the data of an existing Excel file?
Note: The solution has to work in Linux, so simple remote Excel calls are not an option.
I am trying to read in an 'xls' files in python using pandas. My code basically is a one-liner:
import pandas as pd
df = pd.read_excel(str("/test/test_file.xls"))
This code works for the majority of the files, but there are cases when it fails with the error:
Excessive indirect references in NAME formula
What I tried so far:
Tried changing the stack limit(panic and warning) to as far as 10000 in the Pandas package itself, where the exception was occurring. A recursion limit was encountered, so raised it as far as 125000, which led to my Mac/Python reaching its limit so I am guessing not the right solution.
Used a memory-intensive EMR to see if it can read the file - nope.
Looked at the GitHub repo for XLRD here to raise a bug only to find out it's out of support.
Opened the file, saved it as an xlsx, used the same code to read it into a dataframe. Worked like a charm.
Tried using Spark Excel Library to read in a particular section of the data - this worked too but I need to use pandas.
Googled it only to find out the results would show me the XLRD code where the exception is defined. Not one person has reported it.
Tried using Python2 and Python3 with the latest and older versions of Pandas - no use.
I cannot share the file, but has anyone faced this issue before? Can someone help? All suggestions are welcome!
Try the following:
Open the xls file
Copy/paste all cells as values
Rerun your script
Hard to help further without having access to the file to explain exactly what is happening.
But chances are xlrd is trying to resolve the value of a formula and is exceeding the "STACK_PANIC_LEVEL". Without seeing the formula, very difficult to say more.
xlrd has a method of evaluate_name_formula(). When you try to open a .xls file with xlrd, it will raise an error (as you described) if your file has many user-defined formulas. To try to solve your problem, I think you can delete these user-defined formulas and keep the file free of these formulas. Or you can try to edit xlrd code, and prevent it from raising the Error, which seems much more difficult.
I have a data base of hundreds of submitted forms, every submitted form contains various modules with VBA code in them to process the data.
Each form file name starts with same unique prefix.
All of the forms are saved in our main global directory of documents.
Data from every form is logged into a log file.
VBA code within each forms allow me to change information in the form and send the updated information into the log.
Now because of the office 2019 being introduced, vb scripts in every form made in 2016 version is not working and I have to force change the code in every single form to make it compatible with 2019.
This mass change is not only required due to office version change but also required because I need to update log file with additional information contained within the forms cells which old VBA code does not process.
There are 4 VBA modules in every form file and scripts in every modules needs to be replaced with the new code.
Really don't know where to start, any ideas are much appreciated.
I have no idea what to try.
Expected result is that I have updated/new code for 4 macro modules currently exist in 100's of files which needs to be replaced over the old codes.. of excel files starting with a common unique prefix.
You can use VBA to modify VBA projects. For this, the "Trust access to the VBA project object model" checkbox must be ticked in the Trust Center/Macro Settings.
After that, open the VBA editor. Set a reference to "Microsoft Visual Basic for Applications Extensibility 5.3" (possibly the version is different for you, I don't know).
Now a couple of additional classes become available under the VBIDE library and those can be used to manipulate VBA projects programmatically. (I'm using this feature to export VBA modules for source control.)
There is no easy way to modify the text of the module, but you can try exporting, deleting and re-importing them to see if that already is enough:
Sub Test()
Dim vbcs As VBIDE.VBComponents
Dim vbc As VBIDE.VBComponent
Dim filename As String
Set vbcs = ActiveWorkbook.VBProject.VBComponents
For Each vbc In vbcs
Debug.Print vbc.name
If vbc.name = "The ones you want" Then
filename = GetFilenameFromModule(vbc)
vbc.Export filename
' you could modify the file contents now if needed
vbcs.Remove vbc
vbcs.Import filename
End If
Next vbc
End Sub
Private Function GetFilenameFromModule(vbc As VBIDE.VBComponent) As String
Select Case vbc.Type
Case vbext_ct_ClassModule, vbext_ct_Document:
GetFilenameFromModule = vbc.name & ".cls"
Case vbext_ct_MSForm:
GetFilenameFromModule = vbc.name & ".frm"
Case vbext_ct_StdModule:
GetFilenameFromModule = vbc.name & ".bas"
End Select
End Function
Be sure to check out the properties of the various objects in the debugger or object browser (F2), just to see what's available. I'm not sure how well documented all of that is, but it's versatile and stable.
To work with files in VBA easily, you can set a reference to the "Microsoft Scripting Runtime" library and use the FileSystemObject.
I want to use python to find what the address or coordinates of the currently active or selected cell in an excel spreadsheets currently active sheet.
So far all I've been able to do is the latter. Perhaps I'm just using the wrong words to search. However, this is the first time in two years of writing first VBA and now Python that I haven't been able to just search and find the answer. Even if it took me half a day.
I've crawled through the code at readthedocs (http://openpyxl.readthedocs.org/en/latest/_modules/index.html)
and looked through the openpyxl.cell.cell, openpyxl.worksheet.worksheet, openpyxl.worksheet.views code. The last seemed to have some promise and led me to writing the code below. Still, no joy, and I don't seem to be able to phrase my online searches to be able to pinpoint results that talk about finding the actual active/selected cell. Perhaps this is because openpyxl is really looking at the saved spreadsheet which might not include any data on the last cell to be selected.
I've tried it both in Python 3.4.3 and 2.7.11. Using openpyxl 2.4.0.
Here's the code that got me the closest to my goal. I was running it in Python3.
from openpyxl.worksheet.views import Selection
import openpyxl
wb = openpyxl.load_workbook('example.xlsx')
ws = wb.active
print(wb.get_sheet_names())
print(ws)
print(Selection.activeCell)
Which gives me the below.
['Sheet1', 'Sheet2', 'Sheet3']
<Worksheet "Sheet3">
Values must be of type <class 'str'>
I put in the first two prints just to prove to myself that I'm actually accessing the workbook/sheet.
If I change the last line to:
print(Selection.activeCellId)
I get:
Values must be of type <class 'int'>
I assume this is because these are only for writing not querying. I've toyed with the idea of writing a VBA macro and just running it from python. However, this code will be used with spreadsheets I don't control. By people who aren't necessarily capable of fixing any problems. I don't think I'm capable of writing something good enough to handle any problems that might crop up either.
Any help will be greatly appreciated.
It's difficult to see the purpose of an active cell for a library like openpyxl as it is effectively a GUI artefact. Nevertheless, because openpyxl works hard to implement the OOXML specification it should be possible to read the value stored by the previous application, or write it.
ws.views.sheetView[0].selection[0].activeCell
Consider the win32com library to replicate the Excel VBA property, ActiveCell. Openpyxl might have a limited method for this property while wind32com allows Python to fully utilize the COM libraries of Windows programs including the MS Office Suite (Excel, Word, Access, etc.). You can even manipulate files as a child process as if your were directly writing VBA.
import win32com.client
# OPEN EXCEL APP AND SPREADSHEET
xlApp = win32com.client.Dispatch("Excel.Application")
xlApp.Workbooks.Open('example.xlsx')
xlApp.ActiveWorkbook.Worksheets('Sheet1').Activate
print(xlApp.ActiveCell)
xlApp.ActiveWorkbook.Close(False)
xlApp.Quit
xlApp = None