VBA Macro Arguments

Written by Rod Wing.

MicroStation VBA allows for supplying arguments in a macro call, most other VBA implementations including the Microsoft Office apps to do not support this feature. The arguments are stored as a single string in the application’s KeyinArguments property. Multiple arguments must be parsed by the program prior to use.

Using arguments to call a macro allows for much more flexibility, such as allowing for variable inputs for use in a Batch Process script. The following macro illustrates how arguments can be parsed. In the case of this macro all of the arguments must be separated by spaces.

vba run MacroWithArguments arg1 arg2 arg3

Sub MacroWithArguments()
Dim strArgs() As String
Dim i As Long
Dim iStart As Long
Dim iEnd As Long
If Len(KeyinArguments) > 0 Then
'
' Arguments separated by spaces
'
strArgs = Split(KeyinArguments, " ")
iStart = LBound(strArgs)
iEnd = UBound(strArgs)
For i = iStart To iEnd
Debug.Print strArgs(i)
Next
End If
End Sub

 

Here is an example of how this could be put to use. This PlaceCell macro will open a userform if no arguments are supplied. It also allows the arguments to be supplied in any order by using the command switches (-n, -s, -a, etc.)

 

Usage: vba run PlaceCell -n<cellName> -s<cellScale> -a<cellAngle> -x<xValue> -y<yValue> -z<zValue>

Sub PlaceCell()
Dim strArgs() As String
Dim i As Long
Dim iStart As Long
Dim iEnd As Long
Dim cellName As String
Dim cellScale As String
Dim cellAngle As String
Dim strSwitch As String
Dim x As String
Dim y As String
Dim z As String

 

'
' Set default values for arguments not supplied
'
cellName = ActiveSettings.cellName
cellScale = cStr(ActiveSettings.Scale.x)
cellAngle = cStr(Degrees(ActiveSettings.Angle))
x = "0"
y = "0"
z = "0"

 

If Len(KeyinArguments) = 0 Then
'
' No arguments - show user form
'
UserForm1.Show
Else
'
' Arguments supplied - run in batch mode
'
strArgs = Split(KeyinArguments, " ")
iStart = LBound(strArgs)
iEnd = UBound(strArgs)
For i = iStart To iEnd
strSwitch = Left$(strArgs(i), 2)
Select Case strSwitch
Case "-n"
cellName = Mid$(strArgs(i), 3)
Case "-s"
cellScale = Mid$(strArgs(i), 3)
Case "-a"
cellAngle = Mid$(strArgs(i), 3)
Case "-x"
x = Mid$(strArgs(i), 3)
Case "-y"
y = Mid$(strArgs(i), 3)
Case "-z"
z = Mid$(strArgs(i), 3)
End Select
Next

With CadInputQueue
.SendKeyin "active cell " & cellName
.SendKeyin "active scale " & cellScale
.SendKeyin "active angle " & cellAngle
.SendKeyin "place cell icon"
.SendDataPoint Point3dFromXYZ(CDbl(x), CDbl(y), CDbl(z))
End With
End If
End Sub
Rod Wing

Rod Wing

Rod joined EnvisionCAD in March 2007 and has nearly three decades of experience working in the CADD industry. He led the IT evaluations of Bentley InRoads and AutoDesk Civil 3D at Wisconsin DOT in their overall CAiCE replacement evaluation. He also led the MicroStation V7 to V8 upgrade effort at Wisconsin DOT which included updating not only the CADD standards to accommodate the changes in the file format but also updating legacy MDL and macros to work in the new environment. Rod received a Bachelor of Science degree from the University of Wisconsin in Cartography and a Master of Science in Geographic and Cartographic Sciences from George Mason University. Rod has extensive experience in CADD as well as the areas of GIS, cartography, plotting, scanning, raster editing/manipulation, publishing, and file/data translations. In all of these areas, he has produced custom tools and developed workflows to enhance productivity between diverse sets of applications. He instructs MicroStation classes ranging from fundamentals to advanced applications.

Tags:

7 comments on “VBA Macro Arguments

  1. Basti Reply

    I am really new in VBA in microstation. I cannot see any forum which discuss about cells already inserted to change in a different scale. for example “SectionTag” that’s been inserted in 1:50 scale and need to be re-scale to 1:75.. Could anyone please help me on this.. Thank you very much

  2. Rod Wing Rod Wing Reply

    The method required to change the scale will be determined by you use of annotation scale. If you have placed the cells using annotation scale the VBA code would be to simply change the model’s annotation scale property like this….

    Sub ChangeAnnotationScale(NewScale As Double)
    ActiveModelReference.GetSheetDefinition.AnnotationScaleFactor = NewScale
    End Sub

    If the cells were not placed using annotation scale then you must calculate the scale difference, iterate through each cell, and modify its scale. Something like this…

    Sub ChangeCellScale(OldScale As Double, NewScale As Double)
    Dim elCell As CellElement
    Dim dScale As Double
    Dim ee As ElementEnumerator
    Dim es As ElementScanCriteria
    Dim elArray() As Element
    Dim i As Long
    Dim iStart As Long
    Dim iEnd As Long

    ‘Calculate change in scale
    dScale = NewScale / OldScale

    ‘Scan for all cells
    Set es = New ElementScanCriteria
    With es
    .ExcludeAllTypes
    .IncludeType msdElementTypeCellHeader
    End With

    Set ee = ActiveModelReference.Scan(es)

    elArray = ee.BuildArrayFromContents
    iStart = LBound(elArray)
    iEnd = UBound(elArray)

    ‘ iterate through all the cells and change the scale
    For i = iStart To iEnd
    Set elCell = elArray(i).AsCellElement
    elCell.ScaleUniform elCell.Origin, dScale
    elCell.Rewrite
    Next
    End Sub

    I hope this answers your question.
    Rod

  3. kimbra Reply

    hey i need same above coding for autocad vba for designing a connecting rod!! plss help

  4. Al Reply

    Rod,

    My problem is determining the OldScale. In my case the same scale has been placed in different models at different scales. I don’t want to manually determine the existing scale for each cell.

    How can I do this with VBA?

    Thanks,
    Al

  5. Rod Wing Rod Wing Reply

    Al

    The VBA CellElement object has a Scale property that can be queried to get the scale of the cell. An example of how that might be used is shown below.

    Sub test()
    PrintCellScales “DTREE”
    End Sub

    Sub PrintCellScales(cellName As String)
    Dim ee As ElementEnumerator
    Dim es As ElementScanCriteria

    Set es = New ElementScanCriteria


    ‘ Set scan criteria to only find cells with
    ‘ supplied cellName

    With es
    .ExcludeAllTypes
    .IncludeType msdElementTypeCellHeader
    .IncludeOnlyCell cellName
    End With

    Set ee = ActiveModelReference.Scan(es)

    Do While ee.MoveNext
    Debug.Print “Cell Name: ” & ee.Current.AsCellElement.Name
    Debug.Print vbTab & “X Scale: ” & CStr(ee.Current.AsCellElement.Scale.X)
    Debug.Print vbTab & “Y Scale: ” & CStr(ee.Current.AsCellElement.Scale.Y)
    Debug.Print vbTab & “Z Scale: ” & CStr(ee.Current.AsCellElement.Scale.Z)
    Loop
    End Sub

Leave a Reply

Your email address will not be published. Required fields are marked *