Jump to content

VBA Macro Runs but does not execute actions


Argo

Recommended Posts

Hi All,

 

I've finally started coding up my own VBA macro that batch creates drawings and attaches Xref, Sets Layer States etc.

 

The issue i'm finding though is that if I run the script after turning the computer on and not running autocad everything runs fine and the script executes everything it needs to and sends commands to AutoCAD.

 

If I then decide I want to change a value and the same instance of autocad is open (the one the macro originally created) everything works fine. But if I close AutoCAD and reopen it, or have already had a instance of AutoCAD open (seperate to to one the macro originally created) the script runs but nothing happens. If i close the excel file and reopen. The macro will run

 

Here is my code

 

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub XrefAttach2Dwg()
Dim XrefRng As Range, XrefPathRng As Range, cell As Range, cxrefname As String, Xrefpaste As Range, cellx As Range, Alive As String, checkcellRange As Range, Checkcellval As String, fileName As String, pctCompl As Single, inRng As Range, n, myworkbook, cellxval As String, CurrentDWG As String, sleeptime As Integer, Tidy As Integer

Dim TempLoc As String
Dim LayName As Range
Dim acadApp As Object
TempLoc = "File Path/Drawing.dwt"

Set XrefRng = Range("Xref_Attach_Range")
Set XrefLookup = Range("Xref_Lookup")
Set inRng = Application.Range("Table4[DWG Path]")
Set wS1 = Worksheets("Send AutoCAD Commands")
Set XrefPathRng = Range("Xref_Paths")
Set outCell = wS1.Range("E18") 'change to be first cell of output range
Set inlay = Application.Range("Table4[Layout]") 'set copy location of layout name
Set outlay = wS1.Range("F16") 'set paste location of layout name
i = 0
Startcolumn = "F"
Endcolumn = "N"
n = 0
Currrow = 18
Application.ScreenUpdating = False
Checkcellval = Worksheets("Project builder").Range("F6").Value

'------------Checking if XRef's Exist-------------------
For Each checkcell In XrefPathRng
Checkcellval = checkcell.Value
'MsgBox checkcell.Address
If Checkcellval = "" Then
 GoTo SkipCell
 Else
 End If
If Dir(Checkcellval) <> "" Then

 'MsgBox "File exists."
Else
  MsgBox ("The following Xref does not exist:" & vbNewLine & Checkcellval & vbNewLine & "Please check the file and try again")
  Exit Sub
End If
i = 1 + i
SkipCell:
Next checkcell
'-------End Checking Xrefs---------------

If MsgBox("Excel and AutoCAD will not be accessible during the operation Are you sure you would like to continue?", vbYesNo) = vbNo Then Exit Sub
Worksheets("Project Builder").Range("F19").Select


'-------------Creating Drawing--------------------
For Each incell In inRng
'incell.Select
'MsgBox incell
   CurrentDWG = incell.Offset(0, -11).Value
   Set LayName = Worksheets("Project Builder").Cells(incell.Row, 1)
       If Dir(incell.Value) <> "" Then
         Tidy = 1
           GoTo DWGExist
        Else
           
   [b]On Error Resume Next
   Set acadApp = GetObject(, "AutoCAD.Application")
   If Err Then
       Err.Clear
       Set acadApp = CreateObject("AutoCAD.Application")
       acadApp.Visible = True
   End If[/b]
  ' Set acadApp = GetObject(, "AutoCAD.Application")
  ' acadApp.Visible = True
   'If acadApp Is Nothing Then
   'Sleep (3000)
       'Set acadApp = CreateObject("AutoCAD.Application")
       'acadApp.Visible = True
       'Alive = "Yes"
   'Else
   'Alive = "No"
    'End If
       
   'Check (again) if there is an AutoCAD object.
   If acadApp Is Nothing Then
       MsgBox "Sorry, it was impossible to start AutoCAD!", vbCritical, "AutoCAD Error"
       Exit Sub
   End If
               AutoCAD.Application.Documents.Open TempLoc
               AutoCAD.Application.ActiveDocument.SendCommand ("LAYOUT" & vbCr & "R" & vbCr & "000" & vbCr & LayName & vbCr) 'renames the layout from default "000" to the name stored in LayName
               AutoCAD.Application.ActiveDocument.SaveAs incell.Value, AcSaveAsType.ac2007_dwg 'Saves the drawing to the incell value in a 2007  DWG format
        UserForm1.DWG.Caption = "Created" & CurrentDWG 'Updates the progress indicator to display drawing created
       End If



'Progress Bar Code Start

pctCompl = (n / (Range("Table4[DWG Path]").Count)) * 100

   progress pctCompl
   progressDWG CurrentDWG
'Progress Bar Code Ends
   'End If
'--------Searching XrefRange For Instances of "Yes"---------------
Sheets("Project Builder").Select
Currrow = Currrow + 1
Set Currrange = Range(Startcolumn & Currrow & ":" & Endcolumn & Currrow)

For Each cell In Currrange
'cell.Select
Sheets("Project Builder").Select
If cell.Value = "Yes" Then
sleeptime = 2000
cxrefname = Cells(17, cell.Column).Value
'MsgBox cxrefname & " " & ActiveCell.Address 'Use for Testing Variable Value

Else
sleeptime = 100
cxrefname = "No Xref to Attach"
End If

'--------once it finds an instance of yes search for Xref particulars-------------
Sheets("Project Builder").Select
For Each cellx In XrefLookup
cellxval = cellx.Value
   If cellxval = cxrefname Then
   Set Xrefpaste = cellx.Offset(0, 1)
   fileName = Replace(Dir(Xrefpaste), ".dwg", "")
AutoCAD.Application.ActiveDocument.ActiveSpace = acModelSpace
AutoCAD.Application.ActiveDocument.SendCommand ("FILEDIA" & vbCr & "0" & vbCr & "-Xref" & vbCr & "o" & vbCr & Xrefpaste & vbCr & "0,0" & vbCr & "1" & vbCr & "1" & vbCr & "0" & vbCr & "FILEDIA" & vbCr & "1" & vbCr) 'Attaches Xref into Drawing
AutoCAD.Application.ActiveDocument.SendCommand ("FILEDIA" & vbCr & "0" & vbCr & "-rename" & vbCr & "b" & vbCr & fileName & vbCr & cxrefname & vbCr & "FILEDIA" & vbCr & "1" & vbCr) 'Renames Xref from default name to that specified in Project builder

UserForm1.DWG.Caption = "Attaching Xrefs to " & CurrentDWG 'Updates Progress Indicator to display that Xrefs are currently being attached to Drawings

Else
   End If

Next cellx
'--------End searching for xref particulars------------

Next cell

AutoCAD.Application.ActiveDocument.SendCommand ("FILEDIA" & vbCr & "0" & vbCr & "FILEDIA" & vbCr & "1" & vbCr & "COMMANDLINE" & vbCr) 'Quick Saves Drawing
AutoCAD.Application.ActiveDocument.Save
AutoCAD.Application.ActiveDocument.Close 'Closes AutoCAD
Sleep (sleeptime)
n = n + 1
Tidy = 0
DWGExist:
Next incell

'----------------End Searching XrefRange For Instances of "Yes"----------------
If Tidy = 0 Then
Sheets("Send AutoCAD Commands").Range("C13:O73").ClearContents
AutoCAD.Application.ActiveDocument.SendCommand ("FILEDIA" & vbCr & "1" & vbCr & "COMMANDLINE" & vbCr)

If Alive = "Yes" Then
AutoCAD.Application.Quit

End If

Else
End If
[b]acadApp.Quit
Set acadApp = Nothing[/b]
Application.ScreenUpdating = True

pctCompl = 100
UserForm1.Bar.Width = 246.5
progress pctCompl
   MsgBox "The project has been built. " & vbNewLine & n & " Drawing(s) were created.", vbInformation, "Done"
End Sub


I'm assuming the script runs because the on error resume next allows it to, however it doesn't do anything because the process isn't killed?

Edited by Argo
Link to comment
Share on other sites

Just to add some comments I actually think I may be dealing with an orphaned acad.exe process. What's the best way to deal with closing off these objects.

Link to comment
Share on other sites

It might have to do with

- your use of

AutoCAD.Application.ActiveDocument

reference, which would always stick to the first AutoCAD session ever opened and available at the time your VBA macro first starts

so that should that session get closed that reference in your code would throw an error (some "remote server not existent or not available", or "error automation" or stuff like that)

- your simultaneous use (and let aside as well) of "acadApp" variable

 

add to this that "GetObject()" method always returns the first instance of AutoCAD in the Windows Running Object Table available

 

so, to (hopefully) thoroughly understand the implications of what above and (even more hopefully!) learn how to handle it, lets' try this:

- close all of your AutoCAD sessions and Excel workbook that holds your macro too

- open AutoCAD session #1 and set "Drawing1" as its active document name

- open AutoCAD session #2 and set "Drawing2" as its active document name

- open Excel and its VBA IDE and type in this simple macro

Sub test_AcadSessions()
Dim okStop As Boolean
Dim acadApp As Object
Do While Not okStop
   Set acadApp = GetObject(, "AutoCAD.Application") 'Get a running instance of the class AutoCAD.Application
   acadApp.ZoomExtents

   MsgBox ("AutoCAD.Application.ActiveDocument.Name: " & vbCrLf & AutoCAD.Application.ActiveDocument.Name)
   MsgBox ("acadapp.ActiveDocument.Name: " & vbCrLf & acadApp.ActiveDocument.Name)

   okStop = MsgBox("Stop?", vbYesNo) = vbYes

   acadApp.ZoomExtents

   Set acadApp = Nothing
Loop

End Sub

 

- run that Macro:

1) you'll get

"AutoCAD.Application.ActiveDocument.Name: Drawing1.dwg"

 

2) press OK

 

you'll get

"acadapp.ActiveDocument.Name: Drawing1.dwg"

 

3) press OK

 

4) at the message box asking

"Stop?"

- don't press any button on the message box

- open a new AutoCAD session #3 and have its active document named after "Drawing3"

- switch to AutoCAD session #1 and close it

- finally go back to message box and press "NO"

 

you'll get an error message thrown from

acadApp.ZoomExtents

since "acadApp" variable is still referencing to what it was last set by

Set acadApp = GetObject(, "AutoCAD.Application")

statement and thus pointing at the first AutoCAD session available at that moment, i.e. that session #1 you just closed right under its nose!

 

5) skip that statement (just drag the yellow arrow to the following one) and press F5 to make the macro go on

the macro will silently (no error) process the

Set acadApp = GetObject(, "AutoCAD.Application")

statement that will have "acadApp" variable pointing at session #2, it being the first available AutoCAD session "now" (as opposed to "ever")

 

you'll get an error message again!

this time it's thrown from

MsgBox ("AutoCAD.Application.ActiveDocument.Name: " & AutoCAD.Application.ActiveDocument.Name)

since "AutoCAD.Application" reference is still pointing at that first AutoCAD session available "ever" (as opposed to "now"), i.e. the first available at the moment your macro started (session #1 you closed at step 4) and it would always do that until you stop/finish the macro and close its workbook!

 

6) skip that statement, press F5 and make the macro go on

you'll get

"acadapp.ActiveDocument.Name: Drawing2.dwg"

thus no error. and that's because acadApp variable has been reset to point at session #2 (as explained at the beginning of step 5)

 

7) press "OK"

 

eight) at the message box asking

"Stop?"

- don't press any button on the message box

- switch to AutoCAD session #2 and close it

- finally go back to message box and press "NO"

 

well, by now you should know what to expect

you'll get an error message thrown from

acadApp.ZoomExtents

since "acadApp" variable is still referencing to AutoCAD session #2 it was last set to and you just closed right under its nose, once again! (same mechanism of step 4)

 

9) skip the statement throwing the error (you already know it, it's the "acadApp.ZoomExtents" one) and press F5 to make the macro go on

the macro will silently process the

Set acadApp = GetObject(, "AutoCAD.Application")

statement that will now have "acadApp" variable pointing at session #3, it being the first (and the only) available AutoCAD session "now"

 

and, yes, you'll get an error message thrown from that nasty

MsgBox ("AutoCAD.Application.ActiveDocument.Name: " & AutoCAD.Application.ActiveDocument.Name)

since "AutoCAD.Application" reference is still pointing at the first AutoCAD session available "ever" (i.e. the long dead but still in our hearts session #1)

 

10) skip that statement, press F5 and make the macro go on

of course you'll get

"acadapp.ActiveDocument.Name: Drawing3.dwg"

well,bottom line?

always set and use an "acadApp" by

Set acadApp = GetObject(, "AutoCAD.Application")

reference instead of using an "AutoCAD.Application." one

 

when you 're finished with an autocad session, quit it and set its reference (acadApp) either to nothing or to another AutoCAD session

 

once you quit an AutoCAD session you'll never be able to reference it (of course!) again and if your acaApp variable was pointing at that session then you must reset it with either a GetObject() method (which will get the first available session at that moment - "now") or a CreateObject() method (which will start a brand new AutoCAD session)

 

 

hope this will help

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...