The SolidWorks API speaks one language for lengths: meters. Not millimeters. Not inches. Meters, always, regardless of what your document’s unit system displays.
This sounds like something you’d learn in the first chapter of any SolidWorks API tutorial, and it is — yet it causes more silent macro failures than any other single issue. The problem is not that developers don’t know about it. The problem is that it bites you in a second way you didn’t expect, in a context you were already confident about.
The Basic Trap
When you record a SolidWorks macro in VBA and then try to modify the hardcoded dimension values, the first thing you notice is that the recorded values look strange:
' Recorded macro: sets a dimension to 25mm
Dim myDim As Object
Set myDim = swDoc.Parameter("D1@Sketch1")
myDim.SystemValue = 0.025
That 0.025 is 25 millimeters expressed in meters. If your document is set to millimeters and you “correct” the macro to use 25, you just set that dimension to 25 meters.
The recorded macro is correct. Your intuition is wrong.
IDimension.SystemValue (and its newer replacement IDimension.GetSystemValue3 / IDimension.SetSystemValue3) always operates in meters. The display unit is irrelevant to the API — it is a presentation concern only.
The same applies to:
- Sketch geometry coordinates —
ISketchManager.CreateLine(x1, y1, z1, x2, y2, z2)expects all six values in meters CreateCircleByRadius(x, y, z, r)— radius in metersCreateArcByRadius(cx, cy, cz, startX, startY, startZ, r)— meters throughout- Model transform inputs —
MathTransformtranslation components are in meters - View display bounding box queries — return values in meters
- Sheet metal
ISheetMetalFolder.SetBendDeduction()andIBend.BendAnglesetters
Where the “I Knew That” Fails You
Experienced VBA developers often know about the meters requirement for sketch operations. They get caught in the second trap: reading values back.
' Get the current value of a dimension
Dim currentValue As Double
currentValue = swDim.GetSystemValue3(swInConfigurationOpts_e.swThisConfiguration, Nothing)
' Now display it or use it in a formula
MsgBox "Current value: " & currentValue ' Shows 0.025, not 25
If you use GetSystemValue3 to read a value and then pass it somewhere that expects display units — say, writing it into a text box, feeding it to an equation string, or comparing it against a user-typed number — you get a value 1000× smaller than expected for mm documents, or ~39.37× smaller for inch documents.
The two most common places this causes silent corruption:
Reading a dimension to copy it elsewhere — you read
0.025and write that into a different document whose system was expecting millimeters, so you get0.025mm(essentially zero in practice).Comparing against a tolerance threshold —
If currentValue > 50 Thenwill never trigger for a 50mm feature becausecurrentValueis0.05.
The Correct Conversion Pattern
The standard approach uses IModelDoc2.GetUnits(0) to query the document’s length unit and build a conversion factor:
Function GetLengthConversionFactor(swDoc As SldWorks.ModelDoc2) As Double
Dim unitType As Long
unitType = swDoc.GetUnits(0) ' 0 = length unit index
Select Case unitType
Case swLengthUnit_e.swMETER
GetLengthConversionFactor = 1.0
Case swLengthUnit_e.swMM
GetLengthConversionFactor = 0.001 ' 1mm = 0.001m
Case swLengthUnit_e.swCM
GetLengthConversionFactor = 0.01 ' 1cm = 0.01m
Case swLengthUnit_e.swINCHES
GetLengthConversionFactor = 0.0254 ' 1in = 0.0254m
Case swLengthUnit_e.swFEET
GetLengthConversionFactor = 0.3048 ' 1ft = 0.3048m
Case Else
GetLengthConversionFactor = 0.001 ' Fallback to mm
End Select
End Function
Usage:
Dim convFactor As Double
convFactor = GetLengthConversionFactor(swDoc)
' Set dimension to 25 (in document units)
swDim.SetSystemValue3 25 * convFactor, swInConfigurationOpts_e.swThisConfiguration, Nothing
' Read dimension, convert to display units
Dim displayValue As Double
displayValue = swDim.GetSystemValue3(...) / convFactor
MsgBox "Value: " & displayValue & " (document units)"
The conversion factor converts from display units to meters on write, and from meters to display units on read. You multiply on write, divide on read.
Angles follow the same pattern but use a fixed conversion — radians always, multiply degrees by π/180 = 0.017453293.
The Equation Manager Exception
Here the rule inverts. IEquationMgr and the equation string format use display units, not meters:
' This sets an equation using display units (e.g., mm if document is mm)
swEqnMgr.Add2 -1, "\"MyGlobal\" = 25", True
If your document is in millimeters, that 25 means 25mm. If you instead write 0.025 thinking you’re in API-land, you get an equation that evaluates to 0.025mm — a near-zero value.
The rule of thumb: anything touching COM interop geometry directly (dimensions, sketches, transforms, sheet metal calculations) uses meters. Anything working through the UI equation layer uses display units. Mix them up and you get values that are off by three orders of magnitude.
Sheet Metal: Bend Deduction and K-Factor
Bend deductions are lengths — they follow the meters rule:
' ISheetMetalFolder methods
Dim folder As SheetMetalFolder
folder.SetBendDeduction 0.0002 ' 0.2mm in meters
' Reading back:
Dim bd As Double
bd = folder.GetBendDeduction() ' Returns meters
Dim bdInMM As Double
bdInMM = bd / convFactor ' Convert to display units
K-factor is dimensionless, so it needs no conversion — it is always a ratio between 0 and 1.
Bend allowance (IBend.GetBendAllowance) and bend radius (IBend.GetBendRadius) both return meters. If you are writing a macro that reads bend parameters to populate a custom property or a BOM template, you almost certainly need to convert.
The failure mode here is particularly insidious because the values are small and plausible. A bend deduction of 0.0002 looks like a reasonable decimal in isolation. Only when you check the part and find the flat pattern is 0.2mm shorter than expected instead of 0.2mm shorter does the unit error surface.
The Macro Portability Problem
Unit traps compound when you share macros across teams. A macro written for a millimeter-standard shop will produce catastrophically wrong results when run in an inch-standard shop — or more commonly, will produce subtly wrong results that only appear when parts go to fabrication.
The correct pattern for shared macros:
- Never hardcode dimension values in meters — always write them as
<display_value> * convFactor - Expose user inputs in display units — if you show a dialog asking for a dimension, present and accept mm or inches depending on
GetUnits(0), convert internally before passing to the API - Log the unit system at the start of every macro run — makes debugging unit-related support tickets much faster
A helper module that gets loaded by all macros in your standard library and provides a ToMeters(value) / FromMeters(value) pair eliminates the error surface almost entirely.
C# and the Same Problem
The meters rule applies identically in C# COM interop add-ins. The types are different (SldWorks.IDimension, SldWorks.IModelDoc2) but the behavior is the same. The main difference is that in C# you lose the VBA Variant fallback — type-mismatched units cause dimension-setting failures that are easier to detect at runtime.
For in-process vs standalone add-in architectures, unit conversion belongs in a shared utility layer, not scattered across each feature’s implementation. When automating drawing creation with macros, dimensions created on drawing views have the same unit requirement as model dimensions.
Debugging Checklist
When a macro produces geometry that is the wrong size:
- Check the ratio — is the error exactly ×1000, ×0.001, ×25.4, or ×0.0394? Those are unit conversion factors.
- Add a print statement for
swDoc.GetUnits(0)at startup — confirm the unit system is what you expect. - Check for hardcoded values — any numeric literal used as a length is a potential trap.
- Check equation strings separately — if you touch
IEquationMgr, those values are in display units; everything else is meters. - Validate against a known dimension — read back a dimension you know (say, a 100mm reference) and print
swDim.GetSystemValue3(). It should return0.1. If not, your document is not in the unit system you assumed.
If you are exporting DXF flat patterns and the output geometry is scaled incorrectly relative to the source part, the same diagnosis applies — though tools like CadShift handle the unit normalization internally so the exported DXF matches the part regardless of which unit system the document was authored in.
The meters rule is not a quirk. It is a deliberate API design decision that keeps the kernel coordinate system consistent regardless of what individual documents display. Once you internalize it and build the conversion pattern into your standard library, it stops being a trap and becomes predictable infrastructure.