GetObject error in new version of SolidWorks - vba

I have a user who in 2018 copied a macro from the web. After being upgraded to 2020 the macro can't get past the first line;
Set swApp = GetObject(,"Application.SldWorks")
The error is
Run-time error '429' ActiveX component can't create object
I tried to reset the libraries and have gone through multiple forum posts looking a solution. This post was the closest to my issue.
Below is the full code;
Dim swApp As SldWorks.SldWorks
Public Sub main()
Set swApp = GetObject(,"Application.SldWorks")
Dim ActiveDoc As ModelDoc2
Set ActiveDoc = GetObject(, "Sldworks.Application").ActiveDoc
If Not ActiveDoc Is Nothing Then
If ActiveDoc.GetType = 2 Then
GoTo Traverse
End If
End If
MsgBox ("This macro should be run, with an open assembly as the active document.")
Exit Sub
Traverse:
Dim myModel As ModelDoc2
Set myModel = ActiveDoc
Call Traverse(myModel, myModel.ConfigurationManager.ActiveConfiguration.Name)
MsgBox ("Done")
End Sub

You shouldn't use reserved names like ActiveDoc as a variable name. You don't need to use GetObject on objects that are already directly referenced by the host. You don't need Call anymore.
I only get the error that you see if I use the GetObject command that you have there.
I have tested this code in SolidWorks 2020:
Option Explicit
Dim swApp As Object
Sub main()
Set swApp = Application.SldWorks
Dim thisDoc As ModelDoc2
Set thisDoc = swApp.ActiveDoc
If Not thisDoc Is Nothing Then
If thisDoc.GetType = 2 Then
Dim myModel As ModelDoc2
Set myModel = thisDoc
Traverse myModel, myModel.ConfigurationManager.ActiveConfiguration.Name
MsgBox "Done"
Exit Sub
End If
End If
MsgBox "This macro should be run, with an open assembly as the active document."
End Sub

Related

Run private sub in Visio

I wrote two macros in MS Visio. The first macro hides all layers, the second macro selects a specific layer to be shown. Both macros work fine by themselves, but when I try to run the first macro in the second macro I received a compile error, that the sub cannot be found. Any ideas on how to call the private sub correctly?
First sub, which hides all layers:
Private Sub Deselect_layers()
Dim vsoPage As Visio.Page
Dim vsoShape As Visio.Shape
Dim vsoLayers As Visio.Layers
Dim vsoLayer As Visio.Layer
Set vsoPage = ActivePage
Set vsoLayers = vsoPage.Layers
For Each vsoLayer In vsoLayers
If vsoLayer.CellsC(visLayerVisible).FormulaU = "1" Then
vsoLayer.CellsC(visLayerVisible).FormulaU = "0"
End If
Next
End Sub
Second sub, which shows one specifc layer:
Sub Select18()
Dim vsoPage As Visio.Page
Dim vsoShape As Visio.Shape
Dim vsoLayers As Visio.Layers
Set vsoPage = ActivePage
Set vsoLayers = vsoPage.Layers
RUNMACRO ("SelectLayers.Deselect_layers") <-- Error occurs here
vsoLayers.Item("18").CellsC(visLayerVisible).FormulaU = "1"
End Sub
What I have tried so far:
RUNADDON ("ThisDocument.Deselect_layers")
RUNMACRO ("ThisDocument.Deselect_layers")
Callthis ("ThisDocument.Deselect_layers")
RUNADDON ("ThisDocument.SelectLayers.Deselect_layers")
RUNMACRO ("ThisDocument.SelectLayers.Deselect_layers")
Callthis ("ThisDocument.SelectLayers.Deselect_layers")
No of these commands worked. Any help would be much appriciated!
Try this:
Private Sub Deselect_layers()
Debug.Print "In Deselect_layers()"
End Sub
Sub Select18()
Call Deselect_layers
End Sub

vb console application does not close

I created a vb.net to grab an attribute from AD and create a local variable.
It does that just fine, the problem is that it leaves the console window open with nothing but a flashing cursor. Ideally it would close as soon as it created the variable.
I've tried adding Environment.Exit (0)
Module Module1
Sub Main()
Dim objShell
Dim objUserEnv
Dim objADSysInfo
Dim objUser
objShell = CreateObject("WScript.Shell")
objUserEnv = objShell.Environment("USER")
objADSysInfo = CreateObject("ADSystemInfo")
objUser = GetObject("LDAP://" & objADSysInfo.UserName)
' This will create the variable %ipphone%
objUserEnv("ipphone") = objUser.ipPhone
End Sub
End Module
Any ideas why it's not closing the console?
Ok, Since Environment.Exit(0) is not working and you are within a Console application, Try this, Go to Project > Add Reference > Assemblies > Framework and search for System.Windows.Forms click the check box and then click the Ok after that add this to your code.
Imports System.Windows.Forms
Module Module1
Sub Main()
Dim objShell
Dim objUserEnv
Dim objADSysInfo
Dim objUser
objShell = CreateObject("WScript.Shell")
objUserEnv = objShell.Environment("USER")
objADSysInfo = CreateObject("ADSystemInfo")
objUser = GetObject("LDAP://" & objADSysInfo.UserName)
' This will create the variable %ipphone%
objUserEnv("ipphone") = objUser.ipPhone
Application.Exit()
End Sub
End Module
Another reason that it might not be closing is because it is not completing the task, When I ran your code, It didnt complete and I got this error
Additional information: No mapping between account names and security IDs was done. (Exception from HRESULT: 0x80070534) Since you didn't mention this in your question, Im guessing you didnt get this error?
Try this :
Application.Exit
I think it's cause of the settings of your project, I never had such a matter
Module MyApp
Sub Main()
' Attach the event handler method
AddHandler AppDomain.CurrentDomain.ProcessExit, AddressOf MyApp_ProcessExit
Dim objShell
Dim objUserEnv
Dim objADSysInfo
Dim objUser
objShell = CreateObject("WScript.Shell")
objUserEnv = objShell.Environment("USER")
objADSysInfo = CreateObject("ADSystemInfo")
objUser = GetObject("LDAP://" & objADSysInfo.UserName)
' This will create the variable %ipphone%
objUserEnv("ipphone") = objUser.ipPhone
Environment.Exit(0)
End Sub
Private Sub MyApp_ProcessExit(sender As Object, e As EventArgs)
Console.WriteLine("App Is Exiting...")
End Sub
End Module
Turns out I was just impatient and it does close given enough time.

VBA Macro no longer works when used as a COM Add-In (VB.NET) (Mail Merge function)

I have the below code. Originally, the code was a VBA macro that I built. It ended up working perfectly (sending word doc as an e-mail to a desired range of recipients, iterating through each row). The function begins at the Sub SendIt_Click (very last sub) in the code. The rest is for the add-in. When I click the button in Excel, the MsgBox's work, but the code doesn't send anything. It worked in Excel VBA, but I'm at a loss as to why it isn't working here.
Update: It does open the word doc, just doesn't send e-mail.
Imports Extensibility
Imports System.Runtime.InteropServices
Imports Microsoft.Office.Interop
Imports Microsoft.Office.Core
<GuidAttribute("209AD741-0B95-4931-80CF-4DCE33B761C9"), ProgIdAttribute("MailMerge.Connect")> _
Public Class Connect
Implements Extensibility.IDTExtensibility2
Private applicationObject As Object
Private addInInstance As Object
Dim WithEvents SendIt As CommandBarButton
Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnBeginShutdown
On Error Resume Next
' Notify the user you are shutting down, and delete the button.
MsgBox("MailMerge Add-in is unloading.")
SendIt.Delete()
SendIt = Nothing
End Sub
Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnAddInsUpdate
End Sub
Public Sub OnStartupComplete(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnStartupComplete
Dim oCommandBars As CommandBars
Dim oStandardBar As CommandBar
On Error Resume Next
' Set up a custom button on the "Standard" command bar.
oCommandBars = applicationObject.CommandBars
If oCommandBars Is Nothing Then
' Outlook has the CommandBars collection on the Explorer object.
oCommandBars = applicationObject.ActiveExplorer.CommandBars
End If
oStandardBar = oCommandBars.Item("Standard")
If oStandardBar Is Nothing Then
' Access names its main toolbar Database.
oStandardBar = oCommandBars.Item("Database")
End If
' In case the button was not deleted, use the exiting one.
SendIt = oStandardBar.Controls.Item("My Custom Button")
If SendIt Is Nothing Then
SendIt = oStandardBar.Controls.Add(1)
With SendIt
.Caption = "Send to Mail Group with Outlook"
.Style = MsoButtonStyle.msoButtonCaption
' The following items are optional, but recommended.
' The Tag property lets you quickly find the control
' and helps MSO keep track of it when more than
' one application window is visible. The property is required
' by some Office applications and should be provided.
.Tag = "MailMerge"
' The OnAction property is optional but recommended.
' It should be set to the ProgID of the add-in, so that if
' the add-in is not loaded when a user clicks the button,
' MSO loads the add-in automatically and then raises
' the Click event for the add-in to handle.
.OnAction = "!<MyCOMAddin.Connect>"
.Visible = True
End With
End If
' Display a simple message to show which application you started in.
MsgBox("Started in " & applicationObject.Name & ".")
oStandardBar = Nothing
oCommandBars = Nothing
End Sub
Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnDisconnection
On Error Resume Next
If RemoveMode <> Extensibility.ext_DisconnectMode.ext_dm_HostShutdown Then _
Call OnBeginShutdown(custom)
applicationObject = Nothing
End Sub
Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
MsgBox("On Connection In MailMerge")
applicationObject = application
addInInstance = addInInst
' If you aren't in startup, manually call OnStartupComplete.
If (connectMode <> Extensibility.ext_ConnectMode.ext_cm_Startup) Then _
Call OnStartupComplete(custom)
End Sub
Private Sub SendIt_Click(ByVal Ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean) Handles SendIt.Click
MsgBox("SendIt button was pressed!")
'Dimension variables.
Dim OL As Object, MailSendItem As Object
Dim myxl As Excel.Application
Dim ws As Excel.Worksheet
Dim wd As Word.Application
Dim toRange = InputBox("Input cell range in R1:C1 format.", "Input range", "B3:B4")
Dim subj = InputBox("Input subject.", "Input subject", "TESTING")
wd = CreateObject("Word.Application")
Dim doc As Word.Document
'On Error Resume Next
'Assigns Word file to send
wd = GetObject(, "Word.Application")
If wd Is Nothing Then
wd = CreateObject("Word.Application")
'blnWeOpenedWord = True (MAY NOT NEED THIS)
End If
doc = wd.Documents.Open _
(FileName:="H:\Thought Pieces\Small Cap Liquidity\A Closer Look at Small Cap Liquidity.doc", ReadOnly:=False)
'Set itm = doc.MailEnvelope.Item
'Starts Outlook session
OL = CreateObject("Outlook.Application")
MailSendItem = doc.MailEnvelope.Item
myxl = GetObject(, "Excel.application")
ws = myxl.ActiveSheet
'Creates message
For Each xRecipient In ws.Range(toRange)
With MailSendItem
.Subject = subj
.To = xRecipient
.Cc = xRecipient.Offset(0, 5)
.Attachments.Add("H:\Thought Pieces\Small Cap Liquidity\A Closer Look at Small Cap Liquidity.pdf")
.Send()
End With
doc.Close(SaveChanges:=0)
wd = GetObject(, "Word.Application")
doc = wd.Documents.Open _
(FileName:="H:\Thought Pieces\Small Cap Liquidity\A Closer Look at Small Cap Liquidity.doc", ReadOnly:=False)
MailSendItem = doc.MailEnvelope.Item
myxl.Application.Wait(Now + TimeValue("00:00:20"))
Next xRecipient
'Ends Outlook session
OL = Nothing
End Sub
End Class
At OP's request, what I am doing is just a postmortem summation :)
Whenever in doubt, debug the code yourself. Step through the code but in situations like this when you are testing your code for a VSTO Add-In, I generally put few message boxes in my code so that I know which line is executing and which is not.
Op followed this approach and found two lines which were the culprit.
.To = xRecipient
and
myxl.Application.Wait(Now + TimeValue("00:00:20"))
The first one failed because that field expects a string value. It was sorted using
.To = xRecipient.Value.ToString()
I would recommend doing the same for .CC field as well.
Regarding the other Now + TimeValue("00:00:20") was not being calculated correctly. That is because you have "+" sign. Try doing this in VB.Net
MessageBox.Show(Now + TimeValue("00:00:20"))
The alternative was to use
myxl.Application.Wait(Now.AddSeconds(20))
Hope this helps.

How do I set a macro to launch every time an email arrives in a certain subfolder in outlook 2007?

I have a macro to export relevant field of emails in a subfolder but I need it to automatically run every time I receive a new email. In fact I only want the subject line exported, is there a script which will trigger that macro ('ExportMessagesToExcel') when an email lands in 'M_M_Asia'?
I'm in Outlook 2007.
I'll be forever grateful if anyone can help. Cheers guys.
You should be able to use the Application_NewMail (or NewMailEx) event in ThisOutlookSession module to call your own macro.
Another way is to create a rule that runs a VBA-script, but then you VBA sub needs to handle a MailItem parameter:
Option Explicit
Sub MyVBARule(poMail As MailItem)
End Sub
Or you could add 'ItemAdd' event handler, example here:
Option Explicit
Private Const ASIA_FOLDER_NAME As String = "M_M_Asia"
Private WithEvents m_outlookFolderItems As Outlook.Items
Private Sub Application_Startup()
Initialize_Handler
End Sub
Private Sub m_outlookFolderItems_ItemAdd(ByVal Item As Object)
' You have new mail in folder ASIA_FOLDER_NAME
RunExcelMacro
End Sub
Private Sub Initialize_Handler()
Dim outlookFolder As Outlook.MAPIFolder
Dim defaultInboxFolder As Outlook.MAPIFolder
Dim outlookNameSpace As Outlook.NameSpace
Set outlookNameSpace = Outlook.GetNamespace("MAPI")
Set defaultInboxFolder = outlookNameSpace.GetDefaultFolder(olFolderInbox)
Set outlookFolder = defaultInboxFolder.Folders(ASIA_FOLDER_NAME)
Set m_outlookFolderItems = outlookFolder.Items
End Sub
Public Sub RunExcelMacro()
On Error GoTo RunExcelMacro_Err
Const path As String = "C:\temp\Excel_VBA\"
Const fileName As String = "CallMeFromOutloouk.xlsm"
Const macroName As String = "CallMeFromOutlook"
Dim excelObject As Object
Dim workbookObject As Object
Set excelObject = CreateObject("Excel.Application")
On Error Resume Next
Set workbookObject = excelObject.Workbooks(fileName)
On Error GoTo RunExcelMacro_Err
If workbookObject Is Nothing Then
Set workbookObject = excelObject.Workbooks.Open(path & fileName)
End If
excelObject.Run fileName & "!" & macroName
Exit Sub
RunExcelMacro_Err:
MsgBox Err.Description
End Sub

VBA outlook new mail

I am trying to run a function every time a new mail arrives in outlook. I have been doing some searching but I am unable to find I way to fire code every time an email arrives. Is there a new mail event that I could utilize?
I added a simple MsgBox to it to be able to see if the event is firing but it did not seem to be working. I placed this code in the ThisOutlookSession module. Any adivice? Here is my code.
Public WithEvents myOlApp As Outlook.Application
Sub Initialize_handler()
Set myOlApp = CreateObject("Outlook.Application")
End Sub
Private Sub myOlApp_NewMail()
Dim myExplorers As Outlook.Explorers
Dim myFolder As Outlook.MAPIFolder
Dim x As Integer
Set myExplorers = myOlApp.Explorers
Set myFolder = myOlApp.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
If myExplorers.Count <> 0 Then
For x = 1 To myExplorers.Count
On Error GoTo skipif
If myExplorers.Item(x).CurrentFolder.Name = "Inbox" Then
MsgBox ("Test")
myExplorers.Item(x).Display
myExplorers.Item(x).Activate
Exit Sub
End If
skipif:
Next x
End If
On Error GoTo 0
myFolder.Display
End Sub
Try to put:
Private Sub Application_NewMail()
MsgBox "New mail"
End Sub
In "ThisOutlookSession"
There's a good example on MSDN showing how to display the inbox when a new mail arrives (using Outlook.Explorers). You can probably adapt it pretty readily for your own program.