Moving a view in a drawing

I have tried making a macro to move many views by the name of the view and specifying a X & Y locating point on the drawing using swView.Position callout. The issue I am having is that it is not correctly moving the view in the specified X & Y location. It only moves in the Y direction. How can I get my view to move in the specified location? Is swView.Position the wrong callout to use?
Thank you in advance for any help!

Sub MoveMultipleViews()
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    Dim swView As SldWorks.View
    Dim viewNames As Variant
    Dim newPositions As Variant
    Dim i As Integer

    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc
    Set swDraw = swModel

    ' Define view names and corresponding new positions (in meters)
    viewNames = Array("Section View K-K", "Drawing View30", "Drawing View25")
    newPositions = Array( _
        Array(4.2, 4.15), _
        Array(4.3, 4.25), _
        Array(4.1, 4.1) _
    )

    For i = 0 To UBound(viewNames)
        Set swView = swDraw.GetFirstView
        Set swView = swView.GetNextView ' Skip sheet view

        Do While Not swView Is Nothing
            If swView.GetName2 = viewNames(i) Then
                swView.Position = newPositions(i)
                Exit Do
            End If
            Set swView = swView.GetNextView
        Loop
    Next i

    swModel.EditRebuild3
    MsgBox "Views moved successfully!"
End Sub

Hi,

Did you RMB on your views > Alignment > break alignment? I guess that is your problem.

If you don’t break the alignment, your positioning will not work because view alignment forces it to follow the parent view and not the x value you want.

From the API docs:

“Any view alignments that might affect this view are handled the same way as if you were using the SOLIDWORKS user interface to draw the view to move it. If it is aligned with another view, it will only be allowed to move along the alignment vector. If it has child views that are aligned with it, those views will also be moved along with this view.”

All views have broken the alignment with other views.

Here is a simple example:

Dim swApp As SldWorks.SldWorks
Dim mDoc As ModelDoc2
Dim dDoc As DrawingDoc
Sub main()
    Set swApp = Application.SldWorks
    Set mDoc = swApp.ActiveDoc
    Dim sheetView As View
    Set dDoc = mDoc
    Set sheetView = dDoc.GetFirstView
    Do While Not sheetView Is Nothing
        Set sheetView = sheetView.GetNextView
        If sheetView Is Nothing Then Exit Sub
        Dim coords(1) As Double
        coords(0) = 0#
        coords(1) = 0#
        sheetView.Position = coords
        mDoc.ForceRebuild3 False
    Loop
End Sub

Before running:

After running:

So if it isn’t working for you, there is something else going on.

1 Like

This code works exactly as shown in the pictures you attached. All views orient to the 0,0 location on my drawing.
Why would my code not work then is my head scratching question. Am I using the array incorrectly for the locating X & Y values?

there is a problem on how you are using your array.
replace the following

            swView.Position = newPositions(i)

by:

            posPair = newPositions(i)
            position(0) = posPair(0)
            position(1) = posPair(1)
            swView.position = position

posPair is defined upfront like this:
Dim posPair As Variant

3 Likes

It’s your array. Arrays in VBA are a little goofy, and I’m no expert on them. To test, I changed your code to build your array in a different way and it works:

Dim swApp As SldWorks.SldWorks
Dim mDoc As ModelDoc2
Dim dDoc As DrawingDoc
Dim xCoords
Dim yCoords
Sub main()
    xCoords = Array(4.2, 4.3, 4.1)
    yCoords = Array(4.15, 4.25, 4.1)
    Dim newPositions(2) As Variant
    Dim i As Integer
    For i = LBound(newPositions) To UBound(newPositions)
        Dim pos(1) As Double
        pos(0) = xCoords(i)
        pos(1) = yCoords(i)
        newPositions(i) = pos
    Next i
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    Dim swView As SldWorks.View
    Dim viewNames As Variant
    
    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc
    Set swDraw = swModel

    ' Define view names and corresponding new positions (in meters)
    viewNames = Array("Section View A-A", "Drawing View1", "Drawing View2")
    
    For i = 0 To UBound(viewNames)
        Set swView = swDraw.GetFirstView
        Set swView = swView.GetNextView ' Skip sheet view

        Do While Not swView Is Nothing
            If swView.GetName2 = viewNames(i) Then
                swView.Position = newPositions(i)
                Exit Do
            End If
            Set swView = swView.GetNextView
        Loop
    Next i

    swModel.EditRebuild3
    MsgBox "Views moved successfully!"
End Sub

2 Likes

Thanks for the solution. I could not figure out a good way to do it without using arrays. I’m no expert at coding, but since you said arrays are a bit goofy, would you suggest another method?

Agreed… Arrays in SW are often a huge pain. Just to add a tiny bit of detail to Jim’s example code, usually (in my experience anyway), any time a SW API call takes an array argument, it has to be specifically declared as an array of that type. The VBA “Array” function creates a Variant array, even if the stuff you put in it is objects, doubles, etc. Specifically declaring the “pos” array as Double is what makes it work. Loading this Double array into a Variant array later is no problem because you actually pull it “out” of the variant array before you pass it to the SW API call.

3 Likes

You definitely still have to use arrays. The API call requires an array as input. You just need to declare the array specifically as a Double instead of using the VBA “Array” function to create it. (see my add-on reply to Jim’s message above)

It gets even worse when you start getting into creating full MathTransform objects from array data. You have to specifically load each element of an array of 16 doubles. :smiley:

2 Likes

Thanks for that explanation @josh ! That helped explain it very well. I would not have been able to figure that out myself.

And thank you for your help with coding @JimSculley :smiley:

@JimSculley @josh Do you happen to know if I would I be limited to the amount of views I can locate using this script?
I am asking because I started to add more views to this macro and it refuses to work now. the error message that I am getting says; Run-time error ‘9’: Subscript out of range.
I have about 20 views I am looking to add to this script

Subscript out of range means you are trying to access element x+1 for an an array that has only x elements. Check your code.

1 Like

I understand now. The newPositions(x) must be defined for the amount of values in the array. hence the count for newPositions(i) in the loop starting with i=0.

Thanks.

The correct answer is already there, but I have a fetish related to Dictionaries in VBA. Here is a version with Drawing View and their coordinates in Dictionaries.

Sub main()
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc

    If swModel Is Nothing Or swModel.GetType <> swDocDRAWING Then
        MsgBox "Active document is not a drawing!", vbExclamation
        Exit Sub
    End If

    Set swDraw = swModel

    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")

    ' Adding views and coordinates (in meters!)
    dict.Add "Section View A-A", Array(4.2, 4.15)
    dict.Add "Drawing View1", Array(4.3, 4.25)
    dict.Add "Drawing View2", Array(4.1, 4.1)

    Dim viewName As Variant
    Dim failedViews As String
    Dim total As Long: total = 0
    Dim failed As Long: failed = 0

    For Each viewName In dict.Keys
        Dim posXY(1) As Double
        posXY(0) = dict(viewName)(0)
        posXY(1) = dict(viewName)(1)

        total = total + 1
        If Not MoveViewByName(swDraw, viewName, posXY) Then
            failedViews = failedViews & vbCrLf & "• " & viewName
            failed = failed + 1
        End If
    Next

    swModel.EditRebuild3

    If failed = 0 Then
        MsgBox "All views moved successfully (" & total & ")."
    Else
        MsgBox "Some views were not moved (" & failed & " of " & total & "):" & failedViews, vbExclamation
    End If
End Sub

Function MoveViewByName(swDraw As SldWorks.DrawingDoc, ByVal viewName As String, posXY() As Double) As Boolean
    Dim swView As SldWorks.View
    Set swView = swDraw.GetFirstView
    Set swView = swView.GetNextView ' skip sheet

    Do While Not swView Is Nothing
        If swView.GetName2 = viewName Then
            swView.Position = posXY
            MoveViewByName = True
            Exit Function
        End If
        Set swView = swView.GetNextView
    Loop

    MoveViewByName = False ' not found
End Function
2 Likes