I have a legacy code - some macro for Autocad - and I got it running on Autocad 2015 with enabled VBA. There are some string-related function as Trim, Mid, etc.
And these functions are missing references, VBA can't find their definitions. I can find them manually in object browser, so I use Strings.Trim and it works. How can I avoide adding module name to every call of the function in VBA? Is there something like include String'?
Edited: I got a compile error "Can't find project or library" and here is a screen shot of References window just after this message:
And Microsoft Word Library is selected be default. I double-checked, the path to it is correct.
There is no libraries with MISSING prefix (or just can't see it). Maybe, some of them must be excluded since it is a legacy code, but I am not sure wild guessing will be fine in this case, maybe there is a way to get problem libraries marked?
It is possible one of your references (newer versions of AutoCAD, or more likely Microsoft Word) now has function or method names matching Left, Mid, Trim and so on, that didn't exist before. This will make those function names Ambiguous.
Try selectively removing references to see the effect on those functions, or observe the intelliSense when typing Mid to see if it has a different meaning.
Consider writing wrappers for those string functions. For example, write a Left function that internally calls strings.Left in a module visible to where those functions are used.
While this doesn't solve your problem immediately, it will allow you to minimise changes to the legacy code.
Related
If someone have to carry on working on an Excel VBA project/module after the previous developer left the company, how do they safely change a global variable name?
These global variable names can be problematic if they are misleading, misspelled, look like another variable, don't follow the chosen convention, etc.
Changing them with a Search/Replace is a problem because sometimes it's a word that appears in comments.
Changing them by Copy/Pasting is a problem because it's long and you can miss some, especially if there are a lot of occurrences or if you change it to something similar.
Is there a way to do this safely via the Excel "IDE", or via another tool?
What you need to do here is called a refactoring - you need to make a possibly dangerous change to the code, without affecting its behavior. Do it wrong and the code breaks!
Renaming an identifier that's used in one or more places, is a rename refactoring.
Most modern IDE's have such a feature (and several other refactorings). However the VBE was at the height of its glory well before Visual Studio was the full-featured tool it has become since then - heck, the VBE was Visual Studio (6.0) in 1998!
So you really have two options:
Do the refactoring manually - the IDE's search & replace functionality (Ctrl+H) can be dangerous here, because it treats code as simple text, without semantic understanding: you need to review every single occurrence individually, or risk renaming an identifier that was not referring to the variable you're trying to rename.
Use a 3rd-party tool - I don't know any VBIDE add-ins that understand the code deeply enough to allow safely refactoring VBA code, other than the open-source Rubberduck project, which I've managed since October 2014). This add-in parses your entire project, builds a symbol table, and lets you navigate and, yes, refactor/rename any identifier, automatically updating all call sites.
Note that Rubberduck is a very active open-source project, constantly improving. Parsing VBA is hard, and getting the VBE functionally on par with modern-day IDEs isn't a small undertaking, nor is it easy... but it's fun, and yep, it works.
So I'm having to run someone else's excel app on my PC, and I'm getting "Can't find Project or Library" on standard functions such as date, format, hex, mid, etc.
Some research indicates that if I prefix these functions with "VBA." as in "VBA.Date" then it'll work fine.
Webpages suggest it has to do with my project references on my system, whereas they must be ok on the developer's system. I'm going to be dealing with this for some time from others, and will be distributing these applications to many others, so I need to understand what's wrong with my excel setup that I need to fix, or what needs to be changed in the xls file so that it'll run on a variety of systems. I'd like to avoid making everyone use "VBA." as an explicit reference, but if there's no ideal solution I suppose that's what we'll have to do.
How do I make "VBA." implicit in my project properties/references/etc?
-Adam
I have seen errors on standard functions if there was a reference to a totally different library missing.
In the VBA editor launch the Compile command from the menu and then check the References dialog to see if there is anything missing and if so try to add these libraries.
In general it seems to be good practice to compile the complete VBA code and then saving the document before distribution.
I had the same problem. This worked for me:
In VB go to Tools ยป References
Uncheck the library "Crystal Analysis Common Controls 1.0". Or any library.
Just leave these 5 references:
Visual Basic For Applications (This is the library that defines the VBA language.)
Microsoft Excel Object Library (This defines all of the elements of Excel.)
OLE Automation (This specifies the types for linking and embedding documents and for automation of other applications and the "plumbing" of the COM system that Excel uses to communicate with the outside world.)
Microsoft Office (This defines things that are common to all Office programs such as Command Bars and Command Bar controls.)
Microsoft Forms 2.0 This is required if you are using a User Form. This library defines things like the user form and the controls that you can place on a form.
Then Save.
I have experienced this exact problem and found, on the users machine, one of the libraries I depended on was marked as "MISSING" in the references dialog. In that case it was some office font library that was available in my version of Office 2007, but not on the client desktop.
The error you get is a complete red herring (as pointed out by divo).
Fortunately I wasn't using anything from the library, so I was able to remove it from the XLA references entirely. I guess, an extension of divo' suggested best practice would be for testing to check the XLA on all the target Office versions (not a bad idea in any case).
In my case, it was that the function was AMBIGUOUS as it was defined in the VBA library (present in my references), and also in the Microsoft Office Object Library (also present). I removed the Microsoft Office Object Library, and voila! No need to use the VBA. prefix.
In my case, I could not even open "References" in the Visual Basic window. I even tried reinstalling Office 365 and that didn't work. Finally, I tried disabling macros in the "Trust Center" settings. When I restarted Excel, I got the warning message that macros were disabled, and when I clicked on "enable" I no longer got the error message.
Later I re-enabled all macros in the "Trust Center" settings, and the error message didn't show up!
Hey, if nothing else works for you, try the above; it worked for me! :)
Update:
The issue returned, and this is how I "fixed" it the second time:
I opened my workbook in Excel online (Office 365, in the browser, which doesn't support macros anyway), saved it with a new file name (still using .xlsm file extension), and reopened in the desktop software. It worked.
Even when all references are fine the prefix problem causes compile errors.
What about creating a find and replace sub for all 'built-in VBA functions' in all modules,
like this:
replace text in code module
e.g. "= Date" will be replaced with "= VBA.Date".
e.g. " Date(" will be replaced with " VBA.Date(" .
(excluding "dim t As Date" or "mydate")
All vba functions for find and replace are written here :
vba functions list
For those of you who haven't found any of the other answers work for you.
Try this:
Close out of the file, email it to yourself or if you're at work, paste it from the network drive to your desktop, anything to get it to open in "protected mode".
Now open the file
DON'T CLICK ANY ENABLE EDITING OR THE YELLOW RIBBON
Go to the VBA Editor
Go to Debug - - Compile VBA Project, if "Compile VBA Project" is greyed out, then you may need to click the yellow ribbon one time to enable the content, but DO NOT enable macros.
After you click Compile, save, close out of the file. Reopen it, enable everything and it should be OK. This has worked for me 100% of the time.
In my case I was checking work done on my office computer (with Visio installed) at home (no Visio). Even though VBA appeared to be getting hung up on simple default functions, the problem was that I had references to the Visio libraries still active.
I found references to an AVAYA/CMS programme file? Totally random, this was in MS Access, nothing to do with AVAYA. I do have AVAYA on my PC, and others don't, so this explains why it worked on my machine and not others - but not how Access got linked to AVAYA. Anyway - I just unchecked the reference and that seems to have fixed the problem
I've had this error on and off for around two years in a several XLSM files (which is most annoying as when it occurs there is nothing wrong with the file! - I suspect orphaned Excel processes are part of the problem)
The most efficient solution I had found has been to use Python with oletools
https://github.com/decalage2/oletools/wiki/Install and extract the VBA code all the modules and save in a text file.
Then I simply rename the file to zip file (backup just in case!), open up this zip file and delete the xl/vbaProject.bin file. Rename back to XLSX and should be good to go.
Copy in the saved VBA code (which will need cleaning of line breaks, comments and other stuff. Will also need to add in missing libraries.
This has saved me when other methods haven't.
YMMV.
I'm a complete VBA newbie, having decided to teach myself over a weekend, so forgive the stupid question(s). I'm trying to automate some routine tasks involving generating Word documents or emails from an Excel Spreadsheet. Because there will be multiple software versions involved, I am using late binding to open Word and Outlook. My question is: Where can I find a simple reference telling me what the index numbers are that correspond to the application constants? I have killed a lot of time googling to learn that, for example, the Outlook foldertype for "Contacts" is "10". Maybe someone knows of a web link that could save me countless hours of searching?
Update: http://msdn.microsoft.com/en-us/library/office/gg278936%28v=office.14%29.aspx seems to have some of the information I need, although it's not always intuitive where the information is. For example, if it contains the outlook folder type constants, I haven't found them yet.
See here
Enumeration http://msdn.microsoft.com/en-us/library/office/ff860961(v=office.15).aspx
OlDefaultFolders Enumeration http://msdn.microsoft.com/en-us/library/office/ff861868(v=office.15).aspx
I would recommend to add the relevant object libraries to your project as References during development time. You do this by using the Tools - References Menu in the VBA Editor. This makes developing a lot easier as you can use intellisense while writing the code.
If you need only a few Enums or single Constants in your code the easiest way to get their values is to hit [F2] in in VBA Editor while the object libraries are still referenced. Then search for the constants name and copy its value to your code.
Just using the numeric values of the constants in your code makes the code pretty hard to read. So I would recommend to re-declare all the Enums/Constants you actually use in a module in your own project. That massively improves the readability of your code.
So, instead of just copying the value from the VBA Object Browser, I suggest you copy the name and the value and put it your own code as a constant declaration. For your example of the Outlook contacts folder this will look like this:
Public Const olFolderContacts = 10
You can then use the constant in your procedures as you would do with Early Binding.
Should you work on a larger automation project using many of the constants from any one of the Office Object Libraries, you can download ready-made VBA modules containing all the Office constants from my website. You can then just import the relevant modules into your project and are ready to go.
After you finished the main development work, you remove the linked libraries from your project and declare the relevant object variables As Object instead of the actual type.
Always remember to compile your project not to miss any declaration that does not work late binding.
I have an Excel add-in I wrote in VBA, let's call it MyAddin.xlam.
I have set the project name as MyAddin.
When I open a second project and choose Tools->References..., MyAddIn appears just fine. Everything works. That's great.
But.. for purely aesthetic reasons, I would like the listing to appear as My Addin in the list of References.
Pretty much everything available in the list of potential References has spaces in the name.
But if I try to rename my project to have a space in the name, VBA doesn't allow me to do that.
So, silly as the question may sound, is there any way I can get spaces into the displayed name of my VBA add-in in the "References" list?
I'm perfectly willing to accept the answer "This isn't possible in VBA; you can only put spaces in the reference name if you build the add-in with another language", but I'm wondering if I am missing something simple.
Thanks!
EDIT, Addendum: Essentially, my question is: Is there a way to get the "displayed name" to be different from the project name, which doesn't care about filenaming/object naming restrictions?
Yup you are right. VBA will not let you insert spaces in the Project Name in the Properties window.
If you try to, it will give you an error (see snapshot)
Well No Luck with VB.net as well. I added the space and it converted it to an underscore in Excel. let me test it more and get back to you...
SNAPSHOT
FOLLOWUP
Phew Finally! Yes it is possible in VB.Net. Let me know if you want more details?
You can vary the display name as it appears in the Add-ins window by editing the Title Built-in Document Property, but that doesn't help you with the name in the References window
The VBE won't let you use illegal characters in a project name of module name, but that doesn't mean it can't be done.
For example, the Analysis Toolpak - VBA add-in ATPVBAEN.XLAM has a project name of atpvbaen.xls which includes the supposedly illegal character .
Likewise, the same project has a module called VBA Functions and Subs which includes the illegal (space) character.
But the public procedures in Analysis Toolpak are still callable by using square brackets.
Sub test()
'Run the auto_open macro in Analysis Toolpak
[atpvbaen.xls].[VBA Functions and Subs].auto_open
End Sub
So Microsoft knows how to use illegal characters in project and module names, which is presumably done in the binary or with a special build of VBE.
EDIT
I just edited the binary of a VBA project and was able to put spaces in the VBA project name!
Interestingly, you can't export and then reimport the modules from Analysis Toolpak, as VBE still enforces the naming rules on import. Good luck getting that to work with Source Control.
EDIT: 3 FEB 2017
From the VBA file format spec: [MS-OVBA]
[module name] SHOULD be an identifier... MAY be any string of characters... MUST be less than or equal to 31 characters long.
[project name] SHOULD be an identifier... MAY be any string of characters... MUST be less than or equal to 128 characters long.
So it seems the VBE is imposing the SHOULD rule, but VBA is actually more permissive, if you are able to edit the project binary.
I'm creating a macro in MS Access that imports a CSV file into a table. I'm using the TransferText action to import the CSV string, and I want to allow the user to browse for the file that contains the CSV string.
How do I show the "browse" dialog box to enable the user to choose the file?
See API: Call the standard Windows File Open/Save dialog box. However this requires VBA code.
An alternative (which I would say is second choice to the API call recommended by #Tony Toews and #draice) would be to use the Application.FileDialog object. This has been part of the Office automation library for as long as VBA has been in Access, but in recent versions of Access (starting with either A2002 or A2003, I don't know which), the top-level Access Application has provided a wrapper for this object. Beware, though, that without a reference to the Office automation library, the ENUM values that show up in Intellisense can't be used without a reference (a helpful error message informs you of this and offers to create the reference). In short, if you use it's best to use it as you would any automation object with late binding, with the exception that you don't have to initialize the top-level object with Application.CreateObject, as it's already there for you to use.
EDIT:
#draice asks:
I don't understand the following
statements that you wrote: "the
top-level Access Application has
provided a wrapper for this object"
"it's best to use it as you would any
automation object with late binding"
Tony's API code will work in every version of Windows, and because MS believes in backward compatibility, they will never break this API call in future versions of Windows.
the FileDialog object is not easy to use in VBA unless you add the reference to the Office Automation library. It is better to minimize the number of references in your Access database, because all sorts of things can mess them up and cause your app to break (any missing reference will prevent all VBA code from running). In order to avoid problems from missing references, we use late binding so that the code you write is not dependent on the outside libary.
Microsoft might remove this object from future versions of Access. The FileSearch object is an analogous situation, in that it was introduced in A95/97 as part of the Office Automation library, and then a wrapper around it was created in A2000, but Microsoft removed it in A2007 (and provided no alternative at all). MS could choose to remove the FileDialog object in future versions of Access and then your code would break. But the API call is never going to break.
Answer can be found at http://www.access-programmers.co.uk/forums/showthread.php?p=917371#post917371.