Visio: Calculate total length of polyline
11:09 18 Feb 2026

Is it possible to calculate the total length of a Visio polyline using a VBA macro?

I've spent some time trying, admittedly with an AI coding assistant. After an hour or so of testing and debug iterations, we've gotten to a version that calculates the length of a straight line and arc correctly, but fails on polylines. And now I'm kind of going in circles with the assistant, with it crashing periodically. As a result I'm wondering if this is even possible.

Maybe I'm using the wrong term for the type of line I'm interested in. I'm talking about the type of line that's formed by using the straight line tool, and repeatedly starting new segments by clicking on the end of the previous segment, like this:

enter image description here

With the assumption that that is indeed a polyline, the code I've got so far is:

'=====================================================================
' Macro: ShowSelectedShapeLengthV2
' Purpose: Returns the total length of the selected shape(s) and
'          displays it in the current page’s units (mm, cm, in, …)
'=====================================================================
Sub ShowSelectedShapeLengthV2()
    Dim sel As Visio.Selection
    Dim i As Long
    Dim totalLengthIU As Double          ' internal units = inches
    Dim pageUnits As String
    Dim totalLength As Double
    
    Set sel = Application.ActiveWindow.Selection
    
    If sel.Count = 0 Then
        MsgBox "Please select at least one shape.", vbExclamation, "No selection"
        Exit Sub
    End If
    
    '--- sum the length of every selected shape -----------------------
    totalLengthIU = 0#
    For i = 1 To sel.Count
        totalLengthIU = totalLengthIU + GetShapeLength(sel(i))
    Next i
    
    If totalLengthIU = 0 Then
        MsgBox "None of the selected shapes have a measurable outline.", _
               vbExclamation, "No length found"
        Exit Sub
    End If
    
    '--- 1?? Get the **actual** page unit -----------------------------
    pageUnits = GetCurrentPageUnits()
    
    '--- ?? Convert from internal units (inches) to that unit -------
    totalLength = Application.ConvertResult(totalLengthIU, visInches, pageUnits)
    
    '--- 3?? Show the result -----------------------------------------
    MsgBox "Total length of the selected shape(s): " & _
           Format(totalLength, "#,##0.00") & " " & pageUnits, _
           vbInformation, "Shape Length"
End Sub

'ShapeLength
' Returns the length of a single shape in internal units (inches)
'=====================================================================
Private Function GetShapeLength(vsh As Visio.Shape) As Double
    Dim shapeLength As Double
    Dim errNum As Long
    
    '--- A?? Group handling -------------------------------------------
    If vsh.Type = visTypeGroup Then
        Dim mem As Visio.Shape
        For Each mem In vsh.GroupMembers
            shapeLength = shapeLength + GetShapeLength(mem)
        Next mem
        GetShapeLength = shapeLength
        Exit Function
    End If
    
    '--- B?? Try the built-in CurveLength property --------------------
    On Error Resume Next
    shapeLength = vsh.CurveLength               ' internal units (inches)
    errNum = Err.Number
    On Error GoTo 0
    
    If errNum = 0 And shapeLength > 0 Then
        GetShapeLength = shapeLength
        Exit Function
    End If
    
    '--- C?? Plain line (Begin/End cells) -----------------------------
    If vsh.SectionExists(visSectionObject, visExistsLocally) Then
        Dim bX As Double, bY As Double, eX As Double, eY As Double
        
        On Error Resume Next
        bX = vsh.CellsU("BeginX").ResultIU
        bY = vsh.CellsU("BeginY").ResultIU
        eX = vsh.CellsU("EndX").ResultIU
        eY = vsh.CellsU("EndY").ResultIU
        errNum = Err.Number
        On Error GoTo 0
        
        If errNum = 0 Then
            shapeLength = Sqr((eX - bX) ^ 2 + (eY - bY) ^ 2)   ' Euclidean distance
            GetShapeLength = shapeLength
            Exit Function
        End If
    End If
    
    '--- D?? Connectors (same Begin/End cells) ------------------------
    If vsh.Type = visTypeConnector Then
        Dim cBX As Double, cBY As Double, cEX As Double, cEY As Double
        
        On Error Resume Next
        cBX = vsh.CellsU("BeginX").ResultIU
        cBY = vsh.CellsU("BeginY").ResultIU
        cEX = vsh.CellsU("EndX").ResultIU
        cEY = vsh.CellsU("EndY").ResultIU
        errNum = Err.Number
        On Error GoTo 0
        
        If errNum = 0 Then
            shapeLength = Sqr((cEX - cBX) ^ 2 + (cEY - cBY) ^ 2)
            GetShapeLength = shapeLength
            Exit Function
        End If
    End If
    
    '--- E?? No measurable outline ------------------------------------
    GetShapeLength = 0#
End Function

'=====================================================================
' Helper: GetCurrentPageUnits
' Returns a string such as "mm", "cm", "in", "pt", "ft"
'=====================================================================
Private Function GetCurrentPageUnits() As String
    Dim unitStr As String
    
    On Error Resume Next
    ' Try the Units cell on the active page’s ShapeSheet
    unitStr = Application.ActiveWindow.Page.PageSheet.CellsU("Units").ResultStr("")
    On Error GoTo 0
    
    If Len(unitStr) = 0 Then
        ' Fallback – use the document’s default unit (returns a constant)
        Dim defUnit As Long
        On Error Resume Next
        defUnit = Application.ActiveDocument.pageUnits
        On Error GoTo 0
        
        Select Case defUnit
            Case visInches:   unitStr = "in"
            Case visCentimeters: unitStr = "cm"
            Case visMillimeters: unitStr = "mm"
            Case visPoints:   unitStr = "pt"
            Case visFeet:     unitStr = "ft"
            Case Else
                ' If we still have nothing, default to millimetres – the
                ' most common metric unit in Visio drawings.
                unitStr = "mm"
        End Select
    End If
    
    GetCurrentPageUnits = unitStr
End Function

And it gives these results:

enter image description here

visio polyline