Delete a Module in Outlook Project - vba

Can I delete an Outlook VBA Module?
I have tried the below code:
Dim vbMod As Object
Set vbMod = Application.VBE.ActiveVBProject.VBComponents
vbMod.Remove VBComponent:=vbMod.Item("Module2")
But getting an error:
438 Error, Object doesn't support this property or method
Can this be done with Outlook VBA and are there any References to be included?

Try this.
You will need to add a reference to Microsoft Visual Basic for Applications Extensibility 5.3.
Public Sub DeleteModule(ByVal ModuleName As String)
On Error GoTo Trap
Dim VBAEditor As VBIDE.VBE
Dim objProject As VBIDE.VBProject
Dim objComponent As VBIDE.VBComponent
Set VBAEditor = Application.VBE
Set objProject = VBAEditor.ActiveVBProject
For Each objComponent In objProject.VBComponents
If objComponent.Name = ModuleName Then
objComponent.Collection.Remove objComponent
End If
Next
Leave:
On Error GoTo 0
Exit Sub
Trap:
MsgBox Err.Description, vbCritical
Resume Leave
End Sub
To test it:
Sub Test()
DeleteModule "ModuleName"
End Sub

The answer to your answer is no, we can't delete or even access programmatically the VBIDE; it is correct that you can add reference to Microsoft Visual Basic for Applications Extensibility 5.3, but to no avail.
If you try this at Word or Excel, this is the output:
But, when you try this at Outlook, VBE is not exposed:
Here is a confirmation. Maybe in older Outlook versions, less safer, you could do that, but at least since Outlook 2002, it is not possible.

Related

Excel-VBA show Warning if Addon is not Installed

I am using an Excel 2013 file, which was updated by me to use PowerQuery for easier Data imports.
It already uses VBA Macros and i would like to include a Warning/MsgBox with a link to download PowerQuery, if it is not already installed.
How would i check for the existence of PowerQuery on the host System?
Adapting the code by Rory at the link i provided you would have something like the following. Note: You could use Rory's additional code to handle 2016 version or earlier ensuring if present is installed.
As you can't use a hyperlink direct i have adapted the Wiktor Stribiżew's code here that allows the user to click OK to go to the download site after getting msgbox saying not installed.
Option Explicit
Private Sub IsPowerQueryAvailable()
Dim downloadlink As String
downloadlink = "https://www.microsoft.com/en-gb/download/details.aspx?id=39379"
Dim bAvailable As Boolean
If Application.Version >= 16 Then
bAvailable = True
Else
On Error Resume Next
bAvailable = Application.COMAddIns("Microsoft.Mashup.Client.Excel").Connect
On Error GoTo 0
If Not bAvailable Then DownloadPowerQuery downloadlink
End If
End Sub
Private Sub DownloadPowerQuery(downloadlink As String)
Dim objShell As Object
Dim Message As String
Dim Wscript As Object
Set objShell = CreateObject("Wscript.Shell")
Message = MsgBox("Would you like to download PowerQuery?", vbYesNo, "Powerquery not available")
If Message = vbYes Then
objShell.Run (downloadlink)
Else
Wscript.Quit
End If
End Sub

Call outlook macro from code

I get an error when I run the InvokeMember method below. The error is UNKNOWN NAME. I have checked the spelling and it is correct. In Outlook I have Enable Macros in the trust center. Is there anything I might be missing to get this working? Thanks
VB code:
olApp.GetType().InvokeMember("Run", Reflection.BindingFlags.Default Or
Reflection.BindingFlags.InvokeMember,
Nothing, olApp, New Object() {"nameOfMacro"})
Research
Well, it seems InvokeMember will not work. The answer is to make the code as you would in the macro and run that. Example:
Private Sub MoveAttachmentToFolder()
Dim olNs = olApp.GetNamespace("MAPI")
Dim subFolderA = olNs.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Parent.Folders("subFolderA")
Dim subFolderB = olNs.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).Parent.Folders("subFolderB")
For Each mi As Outlook.MailItem In subFolderA.Items
If mi.Attachments.Count = 1 Then
'remember interops use 1 based arrays not zero
Dim fileName As String = "some path" & mi.Attachments(1).FileName
mi.Attachments(1).SaveAsFile(fileName)
mi.Move(subFolderB)
End If
Next
End Sub

Excel VBA On Error handling with User-Defined Type

this is an example sub to programatically install a type library for API. Why is the error handling routine failing? I attempted to follow the try...except...finally strategy I am familiar with from Python.
Sub CopyViewLayout():
'TRY:
On Error GoTo addReference
Dim App As femap.model
'COMPILE ERROR: USER TYPE NOT DEFINED
ResumeSub:
Dim App As femap.model
Set App = GetObject(, "femap.model")
Dim rc As Variant
Dim feView As femap.View
Set feView = App.feView
rc = feView.Get(0)
Exit Sub
'EXCEPT:
addReference:
Dim vbaEditor As VBIDE.VBE
Dim vbProj As VBIDE.VBProject
Dim checkRef As VBIDE.Reference
Dim filepath As String
Set vbaEditor = Application.VBE
Set vbProj = ActiveWorkbook.VBProject
filepath = "C:\apps\FEMAPv11\"
On Error GoTo Failure
vbProj.References.AddFromFile (filepath & "femap.tlb")
Set vbProj = Nothing
Set vbaEditor = Nothing
GoTo ResumeSub
'FINALLY
Failure:
MsgBox ("couldn't find type library, exiting sub")
End Sub
EDIT
I broke out this section from main because Error handling is just ridiculous in VBA... A better approach for me was to implement a finite-state-machine using Booleans.
answer
Sub refcheck()
Dim i As Long
Dim FEMAP_GUID As String
FEMAP_GUID = "{08F336B3-E668-11D4-9441-001083FFF11C}"
With ActiveWorkbook.VBProject.references
For i = 1 To .Count
If .Item(i).GUID = FEMAP_GUID Then
Exit For
Else
'note: filepath is determined using Dir() elsewhere...
.AddFromFile (filepath & "femap.tlb")
Exit For
End If
Next
End With
End Sub
Error handling only handles runtime errors; not compile time errors. Use
Dim App as Object
And make sure you only Dim App once in your code.
By using As Object, you can late bind any object to it. You lose Intellisense while youre coding thought.
Like Dick mentioned, use Late Binding but that alone is not enough. You will have to use it with proper Error Handling.
For example
Dim App As Object
On Error Resume Next
Set App = GetObject(, "femap.model")
On Error GoTo 0
If App Is Nothing Then
MsgBox "Please check if femap is installed"
Exit Sub
End If
'
'~~> Rest of the code
'
If you are sure that it is installed then you are getting the error because the relevant library is not referenced. For that I would recommend having a look at How to add a reference programmatically
I would however still suggest that you take the Late Binding route.

How to access certain mailitem properties/methods in a Visual Studio Outlook Add-In?

I'm developing an Outlook (2010) add-in using Visual Studio 2013 (Targeting .NET 4).
Certain Outlook properties/methods seem to be unavailable.
The following code works from Outlook VBA.
Public Sub OutlookTest()
'Dim oApp As New Outlook.Application (NOT NEEDED FOR OUTLOOK VBA)
Dim oExp As Outlook.Explorer
Dim oSel As Outlook.Selection ' You need a selection object for getting the selection.
Dim oItem As Object ' You don't know the type yet.
Set oExp = Application.ActiveExplorer 'Get the ActiveExplorer.
Set oSel = oExp.Selection ' Get the selection.
For i = 1 To oSel.Count ' Loop through all the currently .selected items
Set oItem = oSel.Item(i) ' Get a selected item.
Call DisplayInfo(oItem) ' Display information about it.
Next i
End Sub
Private Sub DisplayInfo(oItem As Object)
Dim strMessageClass As String
Dim oMailItem As Outlook.MailItem
' You need the message class to determine the type.
strMessageClass = oItem.MessageClass
If (strMessageClass = "IPM.Note") Then ' Mail Entry.
Set oMailItem = oItem
MsgBox oMailItem.Subject
MsgBox oMailItem.EntryID
MsgBox oMailItem.HTMLBody
oMailItem.SaveAs "C:\Users\u001tb7\Desktop\New folder\testOL.msg", olMSG
Else
MsgBox "Pick something else"
End If
End Sub
When I try near identical code from Visual Studio in an add-in:
Private Sub butSettings_Click(sender As Object, e As RibbonControlEventArgs) Handles butSettings.Click
Dim oApp As New Outlook.Application
Dim oExp As Outlook.Explorer
Dim oSel As Outlook.Selection ' You need a selection object for getting the selection.
Dim oItem As Object ' You don't know the type yet.
oExp = oApp.ActiveExplorer ' Get the ActiveExplorer.
oSel = oExp.Selection ' Get the selection.
For i = 1 To oSel.Count ' Loop through all the currently .selected items
oItem = oSel.Item(i) ' Get a selected item.
DisplayInfo(oItem) ' Display information about it.
Next i
End Sub
Sub DisplayInfo(oItem As Object)
Dim strMessageClass As String
Dim oMailItem As Outlook.MailItem
' You need the message class to determine the type.
strMessageClass = oItem.MessageClass
If (strMessageClass = "IPM.Note") Then ' Mail Entry.
oMailItem = oItem
MsgBox(oMailItem.Subject)
MsgBox(oMailItem.EntryID)
MsgBox(oMailItem.HTMLBody) '<---FAILS
oMailItem.SaveAs("C:\Users\u001tb7\Desktop\New folder\testVS.msg", Outlook.OlSaveAsType.olMSG) '<---ALSO FAILS
Else
MsgBox("Pick something else")
End If
End Sub
I get an error on MailItem.HTMLBody and MailItem.SaveAs but NOT MailItem.Subject or .EntryID.
This makes me suspect it's something to do with the security, as I think properties like .HTMLBody are 'protected', but .EntryID and .Subject are not.
The error is the generic COM exception not giving me any detail:
An exception of type 'System.Runtime.InteropServices.COMException' occurred in MsgSave.dll but was not handled in user code
Additional information: Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))
Is there any way to get Outlook to 'trust' my VS code (for eventual distribution)? Or is there something else amiss?
EDIT: Thanks to both below!
Instead of:
Dim oApp As New Outlook.Application
Use:
Dim oApp as Outlook.Application = Globals.ThisAddIn.Application
Do not use New Outlook.Application in an Outlook addin - you get Outlook.Application object for free when your addin starts up.
certain outlook properties/methods seem to be unavailable
What properties are you talking about? Could you be more specific?
As Dmitry suggested, you need to use the Application property provided by VSTO. In that case you will avoid security prompts or exceptions. Typically you get such issue when you try to automate Outlook from a standalone application. The Application object provided by VSTO is trusted and doesn't generate exceptions for secured properties or methods (for example, MailItem.Send). You can read more about that in the Outlook "Object Model Guard" Security Issues for Developers article.

Excel VBA Reference load issue

I've been attempting to add a reference to a specific DLL, and after several attempts I've found a bit of code that actually works. However when I attempt it with the DLL that is supposed to work in Excel, it gives me an error and refuses to load.
I've tested this code with a few DLLs that came with Excel/Windows, and I've had no issues.. Was wondering if perhaps there is some 'install' process I need to go through with new DLLs or something of that sort.
Runtime-error '48'
Error in loading DLL
Code:
Sub AddReference()
Dim VBAEditor As VBIDE.VBE
Dim vbProj As VBIDE.VBProject
Dim chkRef As Reference
Dim BoolExists As Boolean
Set VBAEditor = Application.VBE
Set vbProj = ActiveWorkbook.VBProject
'~~> Check if "Microsoft VBScript Regular Expressions 5.5" is already added
For Each chkRef In vbProj.References
If chkRef.Name = "VBScript_RegExp_55" Then
BoolExists = True
GoTo CleanUp
End If
Next
vbProj.References.AddFromFile "C:\WINDOWS\system32\HIDDEN.dll"
CleanUp:
If BoolExists = True Then
MsgBox "Reference already exists"
Else
MsgBox "Reference Added Successfully"
End If
Set vbProj = Nothing
Set VBAEditor = Nothing
End Sub
Usually this kind of problems are related to conflicting bit versions of Office and the DLL you are loading.
Try to load the correct version of the DLL.