Excel VBA 7.1 comdlg - excel

This is for VBA 7.1 excel's macro. I am trying to export a file to a location and it crashes at this part.
The error I am running into is "Can't find project or library". The reference not found is the "comDlg". I know this is a referencing error. However, I am unsure how to resolve it.
Private Sub cmdBrowse_Click()
comDlg.Filter = "XML Files"
comDlg.DialogTitle = "Save Export File As..."
comDlg.ShowSave
txtExportFile.Text = comDlg.Filename
I had the same issue with a UCase() function call, a simple VBA.UCase() solved it. If you need any more information please let me know. I believe this macro/excel sheet was made on an older version and carried over to a 64bit Windows 10.

You're trying to use VB6 controls that are unsupported in a 64-bit VBA host. Try a 32-bit Excel install, but consider using Application.GetSaveAsFileName/GetOpenFileName for this kind of thing:
Private Sub cmdBrowse_Click()
Dim promptResult As Variant
promptResult = Application.GetSaveAsFilename("file.xml", "XML Files (*.xml),*.xml", 1, "Save Export File As...")
If VarType(promptResult) = vbBoolean Then Exit Sub 'prompt was cancelled
txtExportFile.Text = CStr(promptResult)
End Sub
As for VBA failing to resolve the UCase function, ...wild things happen with broken project references: I'd expect these to just go away once the legacy 32-bit stuff is removed from the project.

Related

Good VBA script fails to run on other computer

I have a very complex excel macro workbook. The VBA code seems to run pretty well on PC's at my location. As soon as I send it to a German colleague it fails to run in unexpected locations of the code.
The last problem I came across is a Runtime error 5 when the code try to modify the Caption of a UserForm (and some text boxes and cmd buttons as well).
Previously we faced with the same issue with SlicerCache(x).ClearManualFilter but somehow I healed itself...
My first thought was to break up the nest With and see which row causes the fail, but it's immediately the first row. I assume it'll do the same for all rows.
I have checked the windows and office settings:
I'm running Win10, English language settings and Hungarian formatting settings. -> Code running well.
My local colleagues run the same system with Hungarian language and formatting. -> Code running well.
The problematic colleague runs Win10 with German language and formatting settings. -> Code fails to run.
We both have the same Reference libraries in VBA editor, none missing. (I assume it's carried by the excel file itself.)
I have Microsoft 365 MSO (16.0.13801.21050) 32-bit, he running 16.013801.21004 32-bit. (I suppose the update scheduled by the IT department.) This portion of code months before my latest office update, so I don't think it's a cause.
The sub called by a CommandButton_Click event, and calls the user form zurueckExport. The form is deisgned so that can called for differnet purposes, so the captions have to be modified according to the needs.
I have ran out of ideas, don't see what and why cause it. Does anybody could give me some help to deal with this issue? I would be very glad.
Public Sub verExport()
With zurueckExport
.Caption = "Version Exportieren zum Creo"
.Label1.Caption = "Welche Version möchten Sie zum Creo exportieren?"
.CommandButtonExportieren.Visible = True
.CommandButtonZurueckladen.Visible = False
.CommandButtonKennlinie.Visible = False
.KennlinieFormat.Visible = False
.Show
End With
End Sub
The captions were too long, that generated the error message on the other computer.
Resolution:
I have added several different labels to the UserForm and modify their visibility instead of overwrite the caption.
Many thanks for #J0eBl4ck for the idea.

Sharepoint and Excel VBA integration failure

I have encountered a problem when trying to retrieve file properties from SharePoint through VBA in Excel. (I can't post the workbook, but the below code should suffice).
The code in question:
Private Sub CheckCheckOutStatus()
Debug.Print Application.Workbooks.CanCheckOut("http://sp.mySharepointDomain.co.uk/myFolderPath/myFile.xlsb")
End Sub
The issue is that on my clients PC this statement always returns false regardless of whether the file is checked out or not (They are able to check out the file manually, so it isn't a file permissions issue).
Upon further investigation, it seems to be that my specific computer is able to get the correct value from this code and none other can. It's also worth mentioning that my client and all the PC's/Users I have tested this with are all on the same shared network and so we should all have the same packages installed.
Through process of elimination we have deduced that it is related to my specific computer (and it doesn't matter who logs into it, its the PC itself) that is able to use this method correctly.
My question is to all the experts out there:
Are there any client side or local packages/installations/permissions that could enable or disable programmatic access to the properties in SharePoint?
Thank you for taking the time to read this, and thanks in advance to any suggestions you might have!
I can't test this because I don't have SharePoint installed, but this looks about right...
Sub test()
Dim docCheckOut As String
docCheckOut = "Filepath&name"
Call UseCheckOut(docCheckOut)
End Sub
Sub UseCheckOut(docCheckOut As String)
' Determine if workbook can be checked out.
If Workbooks.CanCheckOut(docCheckOut) = True Then
Workbooks.CheckOut docCheckOut
Else
MsgBox "Unable to check out this document at this time."
End If
End Sub

How to auto check the 'Microsoft ActiveX Data Objects x.x Library' from the Tools --> References?

We share our Excel Macro - MS Access project with our client.
They don't know to select the 'Microsoft ActiveX Data Objects x.x Library' from the Tools --> References.
Any code to automatically update MS ADO library settings?
Note: In Office we are using MS 2010. I think the client's office is using Micorsoft XP.
I suggest above to use late binding, but you could do something like this (my code exactly as used in PPT 2010, should be easy enough to adapt to Access but I do not ever use access).
You may need to change the ADODBReference constant for use in XP. Or you could add another constant and a logic check to see what Application.Version and load from the appropriate destination path.
Public Const ADODBReference As String = "C:\Program Files (x86)\Common Files\System\ado\msado15.dll"
Sub PPT_AddRefToADODBLibrary()
'Adds a programmatic reference to ADODB library if one doesn't already exist
'ADODBReference is a public const refers to Microsoft ActiveX Data Objects 6.0 Library
If Not PPT_RefExists(ADODBReference, "Microsoft ActiveX Data Objects 6.0 Library") Then
Application.VBE.ActiveVBProject.References.AddFromFile _
ADODBReference
Else:
'Already installed
End If
End Sub
The sub above calls on this custom function, which first iterates the active References
Function PPT_RefExists(refPath As String, refDescrip As String) As Boolean
'Returns true/false if a specified reference exists, based on LIKE comparison
' to reference.description.
Dim ref As Variant
Dim bExists As Boolean
'Assume the reference doesn't exist
bExists = False
For Each ref In Application.VBE.ActiveVBProject.References
If ref.Description Like refDescrip Then
PPT_RefExists = True
Exit Function
End If
Next
PPT_RefExists = bExists
End Function
Trying to simply turn it on with a code like this:
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Program Files (x86)\Common Files\System\ado\msado15.dll"
you may come across three problems: it is already installed, earlier version is installed, the file path is invalid. So my logic is as follows:
Code loops through all refs and checks if ref to Microsoft ActiveX Data Objects 6.0 Library is installed.
If not installed, then it tries to install it with error handling.
If failure will occur, it means that either earlier version i.e. Microsoft ActiveX Data Objects 2.8 is installed (could be checked while looping) or the file path is invalid.
Code:
Sub AddReferenceMicrosoftActiveXDataObjectsLibrary()
Const MyRefPath As String = "C:\Program Files (x86)\Common Files\System\ado\msado15.dll"
Dim ref As Variant
Dim IsInstalled As Boolean: IsInstalled = False
For Each ref In Application.VBE.ActiveVBProject.References
Debug.Print ref.FullPath
If ref.FullPath = MyRefPath Then IsInstalled = True
Next
If IsInstalled = False Then
On Error GoTo err:
Application.VBE.ActiveVBProject.References.AddFromFile MyRefPath
On Error GoTo 0
Debug.Print "Just installed"
Exit Sub
Else
Debug.Print "Already installed"
End If
Exit Sub
err:
MsgBox "Probably earlier version of Microsoft ActiveX Data Objects is already installed or other error occurred"
End Sub
I think late binding is the only way.
I made an Excel-based application for my office, and every time i prepare new version there is about 10% of users I have to visit to add references.
I found out, that since these computers have different Windows versions, for some dll's there is no version which would exist on each computer.
This makes adding references from code more difficult and I do not want to use late binding.
Thats a pity - most of the dll's functionality I use is compatible among all versions.

Cannot add DLL reference with AddFromFile

I am trying to use a COM visible .NET DLL from Excel VBA. I have been successful when registering the DLL using regasm and then manually adding a reference to it via the Tools -> References menu item in the VBA Developer window.
However, I am now trying to register the DLL without using the regasm command so that the Excel file can be used on any computer without registering the DLL. So far this is what I've tried:
Dim JART_Instance As Object
Sub Initialize()
Dim RefPath As String, X As Byte
Const RefName = "JART xxx"
RefPath = Application.ActiveWorkbook.Path & "\JART\JART.dll"
With ActiveWorkbook.VBProject.References
For X = 1 To .Count
If .Item(X).Description Like RefName Then
.Remove .Item(X)
End If
Next
.AddFromFile (RefPath)
End With
End Sub
Sub PostInitialize()
Set JART_Instance = New JART.MainJobControl
End Sub
I have added a reference to "Microsoft Visual Basic for Applications Extensibility 5.3". When I run the above code I get "Run-time error '48': Error in loading DLL". I have loaded this DLL a couple times using regasm. Do I need to do something like change the GUID's used in the project and retry. I've seen code examples where this is supposed to work.
If I reference the tlb file instead of the .dll I do not get the DLL loading error. Instead I get an error whenever I try to use the JART_Instance variable saying that the reference has not been set. Even though PostInitialize gets called directly after Initialize and there is no evidence that any of the code threw an error or failed to run. If I try to put a "Stop" command in the PostInitialize function it tells me that it "Cannot enter break-mode at this time".
Any ideas, thanks.
Excel-DNA has a helper function that does this for Com Addins written on that platform.
It appears to:
load the addin
register it with CoRegisterClassObject
add it's progid to the registry
add it to the registry key HKCU\Software\Microsoft\Office\Excel\Addins
call Application.ComAddins.Update in Excel
remove all the previous registry entries
Unregister the object with CoRevokeClassObject
It would appear that once Excel has loaded the addon, it doesn't unload when the registry entries are removed and CoRevokeClassObject is called. It stays loaded until Excel closes and releases it.
So, it's doable but not easy.
Okay so I've resorted to doing a shell command to register the DLL with regasm. Here is my code:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim strWinCmd As String
Dim retVal As Double
strWinCmd = "cmd.exe %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\regasm.exe /u /codebase /tlb .\JART\JART.dll"
retVal = Shell(strWinCmd, vbHide)
End Sub
Private Sub Workbook_Open()
Dim strWinCmd As String
Dim retVal As Double
strWinCmd = "cmd.exe /c %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\regasm.exe /codebase /tlb """ & Application.ActiveWorkbook.Path & "\JART\JART.dll"""
Call Shell(strWinCmd, vbNormalFocus)
Call Button_Handlers.Sleep(1500)
Call Button_Handlers.Initialize
End Sub
For reference the Button_Handlers.Sleep just calls the system sleep method and Button_Handlers.Initialize does this:
Sub Initialize()
'This JART.MainJobControl is the main class in the JART DLL
Set JART_Instance = New JART.MainJobControl
'Use JART_Instance
End Sub
So basically I'm trying to register the DLL at start-up and un-register it on close. My problem is that when I open this file on a new PC I get an error in Button_Handlers.Initialize. It tells me that I'm trying to use an undefined class (JART.MainJobControl), as if the DLL wasn't referenced. If I try to reopen the file everything works fine???
The way I'm doing this is manually adding the reference to the DLL on a machine that already has it registered with regasm. I then save this excel file and transport it to a machine that hasn't had the DLL registered and try to open it and run it. I think that since the reference is already added to the excel file, alls the code has to do is register it with regasm. Does anyone know why this wouldn't work? Am I not sleeping long enough. I may post this as a separate question.

Change .xla File with MSBuild

I'm trying to create a build script for my current project, which includes an Excel Add-in. The Add-in contains a VBProject with a file modGlobal with a variable version_Number. This number needs to be changed for every build. The exact steps:
Open XLA document with Excel.
Switch to VBEditor mode. (Alt+F11)
Open VBProject, entering a password.
Open modGlobal file.
Change variable's default value to the current date.
Close & save the project.
I'm at a loss for how to automate the process. The best I can come up with is an excel macro or Auto-IT script. I could also write a custom MSBuild task, but that might get... tricky. Does anyone else have any other suggestions?
An alternative way of handling versioning of an XLA file is to use a custom property in Document Properties. You can access and manipulate using COM as described here: http://support.microsoft.com/?kbid=224351.
Advantages of this are:
You can examine the version number without opening the XLA file
You don't need Excel on your build machine - only the DsoFile.dll component
Another alternative would be to store the version number (possibly other configuration data too) on a worksheet in the XLA file. The worksheet would not be visible to users of the XLA. One technique I have used in the past is to store the add-in as an XLS file in source control, then as part of the build process (e.g. in a Post-Build event) run the script below to convert it to an XLA in the output directory. This script could be easily extended to update a version number in a worksheet before saving. In my case I did this because my Excel Add-in used VSTO, and Visual Studio doesn't support XLA files directly.
'
' ConvertToXla.vbs
'
' VBScript to convert an Excel spreadsheet (.xls) into an Excel Add-In (.xla)
'
' The script takes two arguments:
'
' - the name of the input XLS file.
'
' - the name of the output XLA file.
'
Option Explicit
Dim nResult
On Error Resume Next
nResult = DoAction
If Err.Number <> 0 Then
Wscript.Echo Err.Description
Wscript.Quit 1
End If
Wscript.Quit nResult
Private Function DoAction()
Dim sInputFile, sOutputFile
Dim argNum, argCount: argCount = Wscript.Arguments.Count
If argCount < 2 Then
Err.Raise 1, "ConvertToXla.vbs", "Missing argument"
End If
sInputFile = WScript.Arguments(0)
sOutputFile = WScript.Arguments(1)
Dim xlApplication
Set xlApplication = WScript.CreateObject("Excel.Application")
On Error Resume Next
ConvertFileToXla xlApplication, sInputFile, sOutputFile
If Err.Number <> 0 Then
Dim nErrNumber
Dim sErrSource
Dim sErrDescription
nErrNumber = Err.Number
sErrSource = Err.Source
sErrDescription = Err.Description
xlApplication.Quit
Err.Raise nErrNumber, sErrSource, sErrDescription
Else
xlApplication.Quit
End If
End Function
Public Sub ConvertFileToXla(xlApplication, sInputFile, sOutputFile)
Dim xlAddIn
xlAddIn = 18 ' XlFileFormat.xlAddIn
Dim w
Set w = xlApplication.Workbooks.Open(sInputFile,,,,,,,,,True)
w.IsAddIn = True
w.SaveAs sOutputFile, xlAddIn
w.Close False
End Sub
I'm not 100% sure how to do exactly what you have requested. But guessing the goal you have in mind there are a few possibilities.
1) Make part (or all) of your Globals a separate text file that is distributed with the .XLA I would use this for external references such as the version of the rest of your app. Write this at build time and distribute, and read on the load of the XLA.
2) I'm guessing your writing the version of the main component (ie: the non XLA part) of your application. If this is tru why store this in your XLA? Why not have the main part of the app allow certain version of the XLA to work. Version 1.1 of the main app could accept calls from Version 7.1 - 8.9 of the XLA.
3) If you are just looking to update the XLA so it gets included in your version control system or similar (i'm guessing here) maybe just touch the file so it looks like it changed.
If it's the version of the rest of the app that you are controlling i'd just stick it in a text file and distribute that along with the XLA.
You can modify the code in the xla programmatically from within Excel. You will need a reference to the 'Microsoft Visual Basic for Applications Extensibility..' component.
The examples on Chip Pearson's excellent site should get you started.

Resources