Display Value in Engineering Notation

November 26, 2020

As all electrical engineers, I work with a large range of numbers for various components – from 22 pF capacitors (22* 1e-12) to 2 MΩ resistors (2* 1e+6). To make the work a little easier, we tend to use Engineering Notation. This ensures the SI prefixes are multiples of three. Just try quickly adding 4 deciFarad to 7 centiFarads and the problem shows itself (answer is 400 mF plus 70 mF = 470 mF).

As handy as MS Excel can be, it does not have a native way to display results in engineering notation. So I had to write a VBA function.

Inside any cell, just pass the value to this function along with the number of significant digits to display and any unit (such as W, L, A, etc.) and it will be appended to the displayed value. If you don’t want a unit, then pass an empty string (“”).

Example raw input and displayed values.

Cell contentsDisplayed Value
=EngSI(0.1234, 2, “V”)120 mV
=EngSI(12345, 3, “W”)12.4 kW
=EngSI(299792458, 3, “m/s”)300 Mm/s

Below is the source code for the Excel VBA function.

' Function to convert value to Engineering notation.
'   Handles positive and negative numbers 
'     from 10e-24 to 10e+24.
'
'       value: input value
'   sigDigits: number of significant digits.  
'                (i.e. 123 with 2 digits => 120)
'        unit: SI units (i.e. W, m, L)
'
'   Returns: String (i.e. "33.3 W", "124 kW", "-6 uW")

Function EngSI(value, sigDigits, unit)
    Dim i As Integer
    Dim s As String
    
    ' Add multiplier to add reducing roundoff underflow.
    '  If increase number of significant digits beyond 3,
    '    then will need to reduce this value.
    value = value * 1.0005
    
    ' Get number of decimals to move decimal point to normalize numbers.
    '   We must use absolute value since we use log later.
    '   Sign is retained and will fix itself later.
    Dim logVal As Double
    logVal = Log(Abs(value)) / Log(10#)
    
    ' Int function will truncate value but will change negative numbers
    '  to next lower int.
    '   Int(99.2) = 99, Int(-99.2) = -100
    Dim logInt As Double
    logInt = Int(logVal)
    
    ' Create normalized value (+/- 1.xxx) and round to number of
    '  significant digits.
    Dim normValue As Double
    normValue = Round(value / (10 ^ logInt), sigDigits - 1)

    ' Create SI scale:
    '   [..., -2:micro, -1:milli, 0:no prefix, 1:kilo, 2:mega, ...]
    ' Create EngSI - value is 1.00 to 999.0 followed by SI scale prefix.
    Dim siScale As Double
    If value >= 1 Then
        ' Determine SI units for numbers greater than or equal zero.
        If (logInt Mod 3) > 0 Then
            siScale = (logInt - 1) \ 3
            EngSI = normValue * 10 ^ (logInt - siScale * 3)
        Else
            siScale = logInt \ 3
            EngSI = normValue * 10 ^ (logInt - siScale * 3)
        End If
    Else
        ' Determine SI units for numbers less than zero.
        If Abs(logInt Mod 3) > 0 Then
            logInt = logInt - 3
            siScale = logInt \ 3
            EngSI = normValue * 10 ^ (logInt - siScale * 3 + 3)
        Else
            siScale = logInt \ 3
            EngSI = normValue * 10 ^ (logInt - siScale * 3)
        End If
    End If
    
    ' SI Prefixes from 10^-24 to 10^24
    Dim prefixes As String
    prefixes = "yzafpnum kMGTPEZY"
    
    s = ""
    If siScale <> 0 Then
        s = Mid(prefixes, siScale + 9, 1)
    End If

    EngSI = CStr(EngSI) + " " + s + unit
    
End Function