Excel VBA CommandBars - excel

I have an Excel-model used for extracting data via S&P Capital IQ Excel-plugin (COM-Addin). This model has been used for a few years without any issues, but now I am getting an error on this line of code:
Application.CommandBars.FindControl(Tag:="menurefreshdatacell").Execute
I have tried searching around and have found that the CommandBars may have been replaced by the Microsoft Office Fluent user interface. However, I cannot seem to find a solution or example of how this may have changed the piece of code from above.
Been a while since i've been using VBA, so unfortunately I have not been able to solve the issue myself, hope to find some more competent people in here.
Below is the entire piece of code. Which selects a designated area, and presses an "Refresh Selection"-button in the plugin.
Let me know if I have left out anything, thank you very much in advance!
Sub Update_FactSet_formulas()
Application.ScreenUpdating = False
Sheets("Peer group_segments").Select
Range("PG_seg_data").Select
Application.CommandBars.FindControl(Tag:="menurefreshdatacell").Execute
Below is the fomula that is provided by the plugin author, this has not changed for years, and what the above should reflect:
Public Sub RefreshSelection()
Dim Refreshbutton As CommandBarButton
Set Refreshbutton =
Application.CommandBars.FindControl(Tag:="menurefreshdatacell")
Refreshbutton.Execute
End Sub

I found the following worked for me:
Application.Run("CIQKEYS_RefreshSelection")
The function comes from the ciqfunctions library, but you don't have to add the reference for it to work. However, you can add the library by doing the following:
Tools
References
Check ciqfunctions
click OK
To see all of the functions available in the library:
Go to View
Select Object Brow
Check ciqfunctions
from the dropdown menu in the top left corner that likely says "", select ciqfunctions
Under Classes, select IUdf
The functions should appear in the "Members" column
Again, note that for the code to work for me, I didn't need to have the library added to references, I just wanted to outline how to explore the library, should you choose to.
There are also the following refresh functions:
CIQKEYS_RefreshWorkBook
CIQKEYS_RefreshWorkBookRangeV
CIQKEYS_RefreshWorkSheet
CIQKEYS_RefreshWorkSheetRangeV
Hope this works for you!

Related

Excel VBA - programmatically list available event procedures for controls on a userform

Hi! I searched google already but found only 1 page mentioning how to do it in MS Access but not in MS Excel, here:
List an MS Access form's controls with their events.
I know how to list the controls on a userform. What I want to know is how to get to the list of events available to a control in the code editor (just clarifying).
Is there a way to programmatically list all available event procedures for a control on a userform like a command button, so that I can add that list of events to an array/collection/dictionary for other uses.
I can't find the control.properties as mentioned the referred link above since I am working in Excel, where this property is not exposed, I guess.
I wish I could go through a collection of properties/events like "for each oneEvent in oneControl.Events" and I know that it is not possible.
I think there must be an internal list/collection like that because we can go through Object Browser in VBA Editor or write event handler code in the VBA Editor.
Is there a way to access that list/collection (may be through VBIDE.VBProject)?
Many thanks in advance.
Hurrah!
I finally found the answer myself! Well, with a little help from #Tim Williams.
It took me 5 days to research the topic of TLI.
Even when my country, Myanmar, was under siege by an unlawful and awful military coup (on 01FEB2021), I couldn't stop thinking about this TLI issue I am facing, despite having to live through anguish, anger, pain, uncertainty and the feeling of being violated.
Now, I got it solved.
That said, I still don't really understand how the whole TLI thing works.
I think it would take me several years of reading on the subject matter to fully understand its declarations, mechanism, functions and methods.
Anyway, I will share what I found out through reading a lot of webpages and finally getting to the answer using a simple watch window to figure out how to get to the list of event procedure names that are available to a given userform control in VBA.
The following sub was taken from another stackoverflow page about listing the properties of userform object, I got stuck with it because I don't fully understand how the structure of the return data is formatted but that was overcome by looking at the structure using the Watch window in VBA Editor.
Requirement: Reference to TypeLib Information library at C:\Windows\SysWow64\TLBINF32.DLL
Sub listControlEventNames(ByVal o As Object)
Dim t As TLI.TLIApplication
Set t = New TLI.TLIApplication
Dim ti As TLI.TypeInfo
Set ti = t.ClassInfoFromObject(o)
Dim i As Integer
Dim mi As TLI.MemberInfo
For Each mi In ti.DefaultEventInterface.Members
i = i + 1
ActiveSheet.Cells(i, 1).value = mi.Name
Next
End Sub
This sub should be called with a userform control name like:
call listControlEventNames(UserForm1.ToggleButton1)
or
listControlEventNames Userform1.ToggleButton1
Finally, I can swear to God (but I'm a Free Thinker) that I can't really find how to list UserForm Control Events anywhere on the web, let alone a user manual on this library. The many many example code snippets, explanations and discussions that I found on TLI, were, for listing properties of UserForm Controls only.
Anyway, enjoy!

Disable Advanced Filter in Excel 2013

I was wondering if anyone could help me to disable the Advanced Filter option in Excel 2013.
I have used the following to disable all other data ribbon options:
.Protect UserInterfaceOnly:=True
But advanced filter is still able to be selected. With this they can unfilter the data.
The following code used to work in older versions of Excel but I cannot seem to get it to work for Excel 2013:
Application.CommandBars("Worksheet Menu Bar").Controls _
("&Data").Controls("&Filter").Controls("&Advanced Filter...").Enabled = False
If anyone could help me out with this or point me in the right direction then it would be appreciated.
Thanks guys.
Solution Suggested
The approach will be hiding the button from the user interface: the advantage on this solution is that the code is not in VBA (entirely) so, is not that easy for the user to modify it (or know what is going on backstage).
Answer Explanation/Next steps
It's really a deep answer with many steps involved in it so, I'll just post guidance and some useful links, that way you may research about it first.
1. Download Custom UI Editor for Microsoft Office: this helps to modify the user interface for the document.
2. Look for tutorials; start to code there with something basic like adding a tab and a button, (this is a good one)
3. Back to Excel, look for life cycle and custom events, this is a good place to start
4. You'll need to catch the event when the Ribbon is loaded; in that time, you'd need to disable the button, these links (1,2) are useful to show the steps and some example workbooks for it.
5. Locate the ID for the button and disable it (Hint: The idMSO = AdvancedFilterDialog, if you 've followed the previous steps, it will make sense here-).
Further information/Answer Disclaimer
Excel is not a software that can handle security deeply; if you are trying to restrict the user somehow in the original file, you should try other approaches -IG: a copy of a workbook for reference only, while the master one is saved in a sharepoint only modifiable by people authorized for it-.
While FAQ in S.O is strict about referencing to other sites without using a proper reference for it, this is a deep step solution that would take pages to explain even a random example; appealing to the guiding topic, this answer should be ok.

Error with VBA Web Scrape

I spent several hours researching this, couldn't find a solution.
I'm trying to do a relatively simple VBA web scrape on google. I'm currently hung up on inputting text into google's search box. There are three different routes I have seen, all of which cause errors.
One route is the following code
Dim aEXPLORER as InternetExplorer
Set aEXPLORER = New InternetExplorer
Do While aEXPLORER.readyState <> READYSTATE_COMPLETE
Application.StatusBar = "Loading google..."
DoEvents
Loop
At this point, the first route goes like this:
aEXPLORER.Document.Getelementbyid("idhere").value
The problem is after .document my intellisense stops working. If I continue to write the code anyway it errors out.
Route two - add at the top dim aHTML as HTMLDocument
Set aHTML = aEXPLORER.document
aHTML.getElementById("idhere").value
This is marginally more successful as I get to the getelementbyID tag but my intellisense doesn't find a .value anywhere. I have a lot of other options like innertext, etc. But no .value like several people use in tutorials online.
I looked in my object libraries and I don't see a .value in my HTMLDocument library or my InternetExplorer library or my Excel library.
The problem has to be something with declaring a variable or an object or something of that nature. Why don't I ever get to a .value? This first method worked online for three different people showing tutorials, why isn't it working when I do it? How are they getting a Getelementbyid tag without setting up an HTML document at the top? For reference, this popular tutorial uses method one, "http://analystcave.com/web-scraping-tutorial/" about 75% of the way through the tutorial.
Thank you so much for being such helpful people. I'm at the end of my currently very limited rope.
Answer credit goes to Berco!
Problem 1: I was using the wrong ID identifier. Solution 1: Copy and Paste HTML code for each interaction point into VBA, comment it out, and copy/paste the identifier directly from that. This has several other benefits as well.
Problem 2: I was concerned with losing intellisense at .value. Solution 2: Not having intellisense does not mean the code won't work. It just means the code isn't set up with a dim/set. To solve for this one, you have to dim that item as an HTMLInput, which requires the Microsoft HTML Object Library reference to be checked. However, you may still use the .value etc even without intellisense as long as the HTML Object Library reference is checked.
The ID of the googles searchbar is (id="lst-ib"). Try something like:
dim searchbar as object
set searchbar = aEXPLORER.Document.Getelementbyid("lst-ib")
searchbar.value = "I wanna google this"
Answer credit goes to Berco!
Problem 1:
I was using the wrong ID identifier.
Solution 1:
Copy and Paste HTML code for each interaction point into VBA, comment it out, and copy/paste the identifier directly from that. This has several other benefits as well.
Problem 2:
I was concerned with losing intellisense at .value.
Solution 2:
Not having intellisense does not mean the code won't work. It just means the code isn't set up with a dim/set. To solve for this one, you have to dim that item as an HTMLInput, which requires the Microsoft HTML Object Library reference to be checked. However, you may still use the .value etc even without intellisense as long as the HTML Object Library reference is checked.

Where can I find a simple and useful list of VBA objects and methods for a beginner?

I tried pressing f2 to get the VBE thingo open and it just looks like jibberish to me.
I need something nice and simple which gives me a heirachy of what key words to use and where to put the dots so that I can do what I need to do and start learning this lanauge.
h = Worksheets("name_lists").range("g17").Offset(down, 0).Value
I don't know what worksheet is ? Is it a class with object range calling method offset ?
I need some sort of a resource to see what functionality is available but I can't make VBE do what I want.
Can someone please help me.
Thanks.
What you are asking for is at http://msdn.microsoft.com/en-us/library/office/ff194068(v=office.15).aspx. This should help you with documentation about individual objects and their properties/methods.
As for what functionality is available: (just about) everything you can do with the Office suite can be accessed through VBA. A good first step is to record a macro, and then try to follow the generated code. The caveat with that approach is that the recorder LOVES to use .Select and Selection., which is generally bad practice.
And, when you have a specific question you can't figure out, ask it here.

Compile throws a "User-defined type not defined" error but does not go to the offending line of code

Symptoms
This is a symptom specifically when compiling an Excel VBA project. The following error occurs:
User-defined type not defined
However, the code that produces this error is not highlighted by the compiler and so I cannot identify the issue.
What I already know and have tried
This is a "User-defined type not defined" error that I have seen before with simple issues such as naming something As Strig instead of As String. However, this particular error is only popping up during the Debug > Compile VBAProject menu option and when the error message box pops up it does not highlight the line of code that the error is occurring in.
After a lot of research I have found that this bug can be related to missing references and I have ruled this out as I have included all needed references and Toolbox objects.
To ensure I wasn't missing any obvious missing Dim statements I have added Option Explicit to all code pages (forms included) to make sure nothing was missing. The error still shows when running a compile.
There is also this known bug that states the issue has been known to happen because of the VB6 projects using binary compatibility:
Turn off Binary Compatibility and compile the project. Visual Basic
will highlight the line of code that contains the User Defined Type
that is not defined. After resolving the problem, Binary Compatibility
can be turned back on.
I found this article via this Question and Answer, however, I cannot find this option in the standard Excel VBA editor.
Help save mine and others' sanity!
I know from Google searches and other questions that I am not the only one who has had this issue.
I have tried going through the code manually but there are simply too many lines to feasibly do so.
Is there a way of turning off Binary Compatibility in Excel VBA projects? How do people find this offending line of code if they can't debug to what they need to change? Any help would be lovely!
Thank you in advance.
Edit: I have found the offending line of code and so my particular issue is solved The problem is still here after removing that particular line - it was a misspelt control name on a form being referenced in its code. This still does not solve the particular issue of how you would go about finding this offending code was the issue. Are we able to find a good way of finding the offending code when this bug happens so others in the future can avoid this agony?
My solution is not good news but at least it should work.
My case is: I have a .xlsm from a coworker. 1) I open it and click the button: it works fine. 2) I save the file, close excel, open the file again: now it doesn't work anymore. The conclusion is: the code is OK but excel can't manage references correctly. (I've tried removing the re-adding the references without any success)
So the solution is to declare every referenced object as Variant and use CreateObject("Foo.Bar") instead of New Foo.Bar.
For example:
Dim objXML As MSXML2.DOMDocument
Set objXML = New MSXML2.DOMDocument
Replaced by:
Dim objXML As Variant
Set objXML = CreateObject("MSXML2.DOMDocument")
I had exactly the same problem (always seems to occur when I try to implement a Interface onto a userform. Download and install Code Cleaner from here. This is a freeware utility that has saved me on numerous occasions. With your VBA project open, run the "Clean Code..." option. Make sure you check the "backup project" and/or "export all code modules" to safe locations before running the clean. As far as I understand it, this utility exports and then re-imports all modules and classes, which eliminates compiler errors that have crept into the code. Worked like a charm for me! Good luck.
Since it sounds like you've tried many different potentional solutions, you'll probably have to do this the long methodical way now.
Create a new blank workbook. Then piece by piece copy your old workbook into it. Add a reference, write a little bit of code to test it. Ensure it compiles, ensure it runs. Add a sub or function, again, write a little test sub to run it, also ensure it compiles. Repeat this process slowly adding and testing everything.
You can speed this up a bit by first trying larger chunks, then when you find one that triggers the problem, remove it and break it into smaller peices for testing.
Either you will find the offender, or you'll have a new workbook that magically does not have the problem. The latter would be due to some sort of hidden corruption in the workbook file, probably in the binary vbproject part.
Welcome to the world of debugging without debuggers or other helpful tools to do the heavy lifting for you!
Just letting you all know I had this problem too. Rather than the code, the issue lay with what macro a button was calling. (It had been calling the 'createroutes.createroutes' macro, but I had renamed the 'createroutes' module to 'routes'.)
Therefore the problem was fixed by pointing the button to the correct location.
Had a similiar experience, but it was because I had renamed an enum in one of my classes. I exported and re-imported the Classes that had referred to the old enum and the error message disappeared. This suggests it is a caching issue in the VBA environment.
I was able to fix the error by
Completely closing Access
Renaming the database file
Opening the renamed database file in Access.
Accepted various security warnings and prompts.
Not only did I choose to Enable Macros, but also accepted to make the renamed database a Trusted Document.
The previous file had also been marked as a Trusted Document.
Successfully compile the VBA project without error, no changes to code.
After the successful compile, I was able to close Access again, rename it back to the original filename. I had to reply to the same security prompts, but once I opened the VBA project it still compiled without error.
A little history of this case and observations:
I'm posting this answer because my observed symptoms were a little different than others and/or my solution seems unique.
At least during part of the time I experienced the error, my VBA window was showing two extra, "mysterious" projects. Regrettably I did not record the names before I resolved the error. One was something like ACXTOOLS. The modules inside could not be opened.
I think the original problem was indeed due to bad code since I had made major changes to a form before attempting to update its module code. But even after fixing the code the error persisted. I knew the code worked, because the form would load and no errors. As the original post states, the “User-defined type not defined” error would appear but it would not go to any offending line of code.
Prior to finding this error, I ensured all necessary references were added. I compacted and repaired the database more than once. I closed down Access and reopened the file numerous times between various fix attempts. I removed the suspected offending form, but still got the error. I tried other various steps suggested here and on other forums, but nothing fix the problem.
I stumbled upon this fix when I made a backup copy for attempting drastic measures, like deleting one form/module at a time. But upon opening the backup copy, the problem did not reoccur.
I had this problem with an ordinary VB6 program. It turned out that I had omitted a class definition, not a user-defined type. Apparently VB saw something like "Thing.name" and assumed Thing was a UDT. Yes, it's a serious VB6 bug, but you could hardly expect Microsoft to support something they sold sixteen years ago. So what versions of the various products involved are you using? This is only interesting if it occurs with a product that MS supports.
I know this is old, but I had a similar problem and found a fix:
I had the same issue with a module I ported from Excel into Access, in an unrelated UDF I was dimming 'As Range' but ranges don't exist in Access. You may be using a variable type without having the proper reference library turned on.
If you have any non-standard dims google them and see if you're missing the reference to that library under tools.
-E
For future reference -
I had this issue with this piece of code in Microsoft Access with the debugger highlighting the line with the comment:
Option Compare Database
Option Explicit
Dim strSQL As String
Dim rstrSQL As String
Dim strTempPass As String
Private Sub btnForgotPassword_Click()
On Error GoTo ErrorHandler
Dim oApp As Outlook.Application '<---------------------------------Offending line
Dim oMail As MailItem
Set oApp = CreateObject("Outlook.application") 'this is the "instance" of Outlook
Set oMail = oApp.CreateItem(olMailItem) 'this is the actual "email"
I had to select references that were previously unselected. They were
Microsoft Outlook 15.0 Object Library
Microsoft Outlook View Control
For the Scripting.Dictionary type, you can either use late binding (as already pointed out ) with:
Dim Dict as Object
Set Dict = CreateObject("Scripting.Dictionary")
Which works, but you don't get the code auto completion. Or you use early binding, but you need to make sure that VBA can find the Scripting.Dictionary type by adding the reference to the Microsoft Scripting Library via VBA-->Tools-->References--> "Microsoft Scripting Runtime". Then you can use:
Dim Dict as Scripting.Dictionary
Set Dict = New Scripting.Dictionary
... and auto completion will work.
Possible solution, you are trying to work with Powerpoint via Excel VBA and you didn't activate Powerpoint Object Library first.
To do this, in the VBA editor top menu select Tools, References, then scroll down to click the library called Microsoft Powerpoint xx.x Object Library. Office 2007 is library 12, each Office version has a different library. FYI, I've experienced some odd errors and file corruption when I activate the 2007 library but someone tries to open and run this macro using Excel 2003. The old version of Excel doesn't recognize the newer library, which seems to cause problems.
When I had this error in a MS Access database I used the /decompile command line switch along with the Compact/Repair option. Worked for me.
I had removed a reference that I was sure my code no longer used and started getting this error.
Late Binding
This error can occur due to a missing reference. For example when changing from early binding to late binding, by eliminating the reference, some code may remain that references data types specific the the dropped reference.
Try including the reference to see if the problem disappears.
Maybe the error is not a compiler error but a linker error, so the specific line is unknown. Shame on Microsoft!
After years I have discovered one, if not the, answer to the Microsoft bug of the 'User-defined type not defined' error in Excel. I'm running Excel 2010 for Windows.
If you have a UDF named for example 'xyz()', then if you invoke a non-existent entity beginning with that name followed by a period followed by other chars -- e.g., if you try to invoke non-existent range name 'xyz.abc', the stupid app throws that wrong msg., after which it returns you to your sheet.
In my case it was especially unnerving, because I have UDFs named with just one letter, e.g. x(), y(), etc., and I also have range names that include periods--'x.a', 'c.d', etc. Every time I, say, misspelled a range name--for example, 'x.h', the 'User-defined …' error was thrown simply because a UDF named 'x()' existed somewhere in my project.
It took several hrs. to diagnose. Suggestions above to incrementally remove code from your project, or conversely strip all code and incrementally add it back in, were on the right track but they didn't follow thru. It has nothing to do with code per se; it has only to do with the name of the first line of code in each proc, namely the Sub MyProc or Function MyProc line naming the proc. It was when I commented out one of my 1-letter-named UDFs in a completely unrelated part of the project that the bugged error msg. went away, and from there, after another hr. or so, I was able to generalize the rule as stated.
Perhaps the bug also occurs with punctuation characters other than period ('.') But there aren't very many non-alpha chars permitted in a range name; underline ('_') is allowed, but using it in the manner described doesn't seem to throw the bug.
Jim Luedke
I had the same error yesterday: I had two classes, cProgress and cProgressEx, in my project, one of which was no longer used, and when I removed cProgress class I was given this same compilation error.
I managed to fix the error as follows:
Exported all modules, forms and classes to the hard drive
Removed everything from the project
Saved the project
Reimported all modules, forms and classes, removed cProgress class, and compiled.
The error disappeared.
An different problem with the same symptom: I had a class implemented which was not defined. It was wrapped with a #if that I thought should have not allowed the compiler to see it, but not so. Remove the comment out the Implements statement and all is well. I assume importing the definition would also work...
I had the same issue, if you enable Microsoft Scripting Runtime you should be good. You can do so under tools > references > and then check the box for Microsoft Scripting Runtime. This should solve your issue.
A bit late, and not a complete solution either, but for everyone who gets hit by this error without any obvious reason (having all the references defined, etc.) This thread put me on the correct track though. The issue seems to originate from some caching related bug in MS Office VBA Editor.
After making some changes to a project including about 40 forms with code modules plus 40 classes and some global modules in MS Access 2016 the compilation failed.
Commenting out code was obviously not an option, nor did exporting and re-importing all the 80+ files seem reasonable.
Concentrating on what had recently been changed, my suspicions focused on removal of one class module.
Having no better ideas I re-cereated an empty class module with the same name that had previously been removed. And voliá the error was gone!
It was even possible to remove the unused class module again without the error reappearing, until any changes were saved to a form module which previously had contained a WithEvents declaration involving the now removed class.
Not completely sure if WithEvents declaration really is what triggers the error even after the declaration has been removed. And no clues how to actually find out (without having information about the development history) which Form might be the culprit...
But what finally solved the issue was:
In VBE - Copy all code from Form code module
In Access open Form in Design view and set Has Module property to No
Save the project (this removes any code associated with Form)
(Not sure if need to close and re-open Access, but I did it)
Open Form in Design view and set Has Module property back to Yes
In VBE paste back the copied out module code
Save
I had this same problem when I inherited another analyst's workbook. He assigned macros to each button on his worksheet. When I changed the name of the module (not the procedure name), it kicked up this error.
The fix was easy. Have the button run an _OnClick() event procedure in the worksheet and have that procedure explicitly Call MyProcedureName().
I've seen this error too when the code stopped at the line:
Dim myNode As MSXML2.IXMLDOMNode
I found out that I had to add "Microsoft XML, v6.0" via Tools > Preferences.
Then it worked for me.
I don't have an answer as to what is actually wrong or to directly fix it.
I can report that exporting all the code and forms, then importing them into a fresh workbook fixed it for me. All the work was recovered, and nothing more needed to be done to get back to work. Since that works, it seems clear that it must be a bug in Excel, or whatever it is would still be missing in the new version.
I do have a possible clue to how this Excel (2007) bug works. It seems to be associated with the removal of a class module (or two). (But not every class module, every time for some reason.) No code was using any part of the removed modules (or the new imported version would not work either). One module had been cut down to nothing but some comments (in hope of removing anything that could be "missing" later) so that there was no code visibly connecting it to any other part of the project. But the error came up shortly after I removed the code module entirely. The error also stopped when the removed (but exported just in case) modules were returned. So for convenience, this project had been packing two unused code modules to avoid this error.
It appears then, that somehow some element of some departed modules remains in the VBA environment, even if nothing is being used from these (there two in this case) class modules anywhere in the project. Consequently, the debug/compile finds that element, and it is no surprise that something is missing because it is. Since the thing that is missing is nowhere in the project there is nothing to highlight so there is a message only and nothing else happens. That would explain the observed behavior.

Resources