|
|
Joined: Dec 1999
Posts: 30,867
Master Elite Member
|
FUNCTION Num_ToHuman( _
BYVAL Num AS EXT, _
OPTIONAL BYVAL Units AS STRING, _
OPTIONAL BYVAL Suffixes AS STRING, _
OPTIONAL BYVAL Format AS STRING, _
OPTIONAL BYREF Metric AS LONG, _
OPTIONAL BYVAL SD AS LONG, _
OPTIONAL BYVAL SuffixPrefix AS STRING, _
OPTIONAL BYVAL Flags AS STRING _
) AS STRING
'Purpose
' Used to format a number for easier human reading by appending a value specifier to the value if it is large.
' Example: 234000000 becomes "234M".
'Parameters
' Num (QUAD) = The number we're formatting.
' Units (Optional STRING) = This is a string that is appended to the returned value.
' In order to facilitate singular units, this string may contain 2 separate values delimited by a comma.
' The first string is used is used for singular return values. The second is used for plural return values.
' For example: "gram,grams" would return "1 gram" or "1.1 grams".
' Default: "" (zero-length)
' Suffixes (Optional STRING) = A list of suffixes to use.
' This can be defined in 1 of 3 ways (following is the order of presidence):
' - A predefined value.
' - A list of single characters (a simple string).
' - A comma-delimited list of strings.
' If this is a predefine value, it represents a predefined character list or a predefined
' comma-delimited list. If the first character of this value is "@", then it is interpreted
' as a predefined value.
' Valid Values:
' "@SI" (Ess-Eye) The System of International Units standard using multiple characters.
' This defaults to: "kilo,mega,giga,tera,peta,exa,zetta,yotta"
' "@SI1" (Ess-Eye-One) The System of International Units standard using single characters.
' This defaults to: "kMGTPEZY" (Note the "k" is intentionally small.)
' "@IEC" The International Electrotechnical Commission standard using long values.
' This defaults to: "kibi,mibi,gibi,tebi,pebi,exbi,zebi,yobi"
' "@IEC2" International Electrotechnical Commission standard using 2-character values.
' This defaults to: "Ki,Mi,Gi,Ti,Pi,Ei,Zi,Yi"
' "@JEDEC" Joint Electron Devices Engineering Council standard using long values.
' This defaults to: "kilo,mega,giga,tera,peta,exa,zetta,yotta"
' "@JEDEC1" Joint Electron Devices Engineering Council standard using single-character values.
' This defaults to: "KMGTPEZY"
' "@k" Common usage with small letters.
' This defaults to: "kmgtpezy"
' "@KB" Common usage with Bytes
' This defaults to: "KB,MB,GB,TB,PB,EB,ZB,YB"
' "@Kb" Common usage with Bits
' This defaults to: "Kb,Mb,Gb,Tb,Pb,Eb,Zb,Yb"
' "@kb" Common usage with Bits, lower case.
' This defaults to: "kb,mb,gb,tb,pb,eb,zb,yb"
' "@kB" Common usage with Bytes, lower case.
' This defaults to: "kB,mB,gB,tB,pB,eB,zB,yB"
' Other If the string (beginning with "@") does not equal a predefined value, then it
' is used as-is, and is considered a character list.
' If this is a list of single characters and does not contain a comma, then each character represents a unit of measure.
' Each subsequent character is used for each increasing unit of measure.
' Example: "KMGTPEZY"
' If this is a comma-delimited list (it contains 1 or more commas), each substring represents a unit of measure.
' If this value contains at least 1 comma, then it is interpreted as a comma-delimited list.
' Each subsequent string is used for each increasing unit of measure.
' Example: "kilo,mega,giga,tera,peta,exa,zetta,yotta"
' Default if zero-length: "@JEDEC1"
' Format (Optional STRING) = A format string used to format the returned number.
' This is used directly in the FORMAT$(fmt&) parameter, so see it for usage.
' Default: "#,"
' Metric (Optional LONG) =
' If this value is positive:
' This is maximum number of digits allowed to the left of the decimal point.
' The unit of measurement is automatically determined.
' This value does not include added commas. For example, if this value is 4 then you may have a return
' value of "1,000" even through there are 5 characters. Of couse, this assumes that the specified Format
' includes commas, which it does by default.
' If you wish to use a value < 3, then make sure you specify a format (Format) that displays digits after the decimal.
' In order for accurate rounding to occur, you should have at least this many digits after the decimal:
' (3 - MaxWholeDigits), otherwise, you may end up inadvertently rounding some values too low or to zero.
' In short, allow at least 3 digits to be displayed total, inclusing all before and after the decimal point.
' If this value is negative:
' This is a code representing the unit of measurement that the returned value will be displayed in.
' Valid Values:
' 0 Actual value
' -1 Kilo
' -2 Mega
' -3 Giga
' -4 Tera
' -5 Peta
' -6 Exa
' -7 Zetta
' -8 Yotta
' Default if < -8: 3
' Default: 3
' SD (Optional LONG) = The standard divisor used for humanizing values.
' If 0, this value defaults to 1024 (Binary divisor).
' If -1, this value defaults to 1000 (Decimal divisor).
' If any other value, the absolute value of the value specified is used.
' Default: 0 (zero)
' SuffixPrefix (Optional STRING) = This string is inserted just before the suffix.
' This string is only displayed if a suffix is displayed.
' This behavior allows the conditional insertion of strings. See examples below for specific applications.
' Default: "" (zero-length)
' Flags (Optional STRING) = Contains a list of behavior flags.
' Valid Flags:
' -NoNum Suppresses the number. Only the suffix is returned.
' -NoSuffix Suppresses the suffix. Only the number is returned.
' Default: "" (zero-length string)
'Return (STRING)
' Returns the specified number (Num) formatted.
' Returns a zero-length string if:
' - Both flags NoNum and NoSuffix are specified in Flags.
'Examples
' Simple usage:
' Num_ToHuman(23) returns "23"
' Num_ToHuman(2348373) returns "2M"
' Display units:
' Num_ToHuman(1, "tons") returns "1tons"
' Num_ToHuman(2348373, "tons") returns "2Mtons"
' Display units with singular option:
' Num_ToHuman(1, "ton,tons") returns "1ton"
' Num_ToHuman(2348373, "ton,tons") returns "2Mtons"
' Display units with singular option and spacing:
' Num_ToHuman(1, " ton, tons") returns "1 ton"
' Num_ToHuman(2348373, " ton, tons") returns "2M tons"
' Use a predefined suffix:
' Num_ToHuman(1, "", "@JEDEC") returns "1"
' Num_ToHuman(2348373, "", "@JEDEC") returns "2mega"
' Use a predefined suffix with singular and plural units:
' Num_ToHuman(1, "ton,tons", "@JEDEC") returns "1ton"
' Num_ToHuman(2348373, "ton,tons", "@JEDEC") returns "2megatons"
' Use the format parameter to separate the number and the suffix/units with a space:
' Num_ToHuman(1, "ton,tons", "@JEDEC", "# ") returns "1 ton"
' Num_ToHuman(2348373, "ton,tons", "@JEDEC", "# ") returns "2 megatons"
' Increase the resolution by adding 2 decimal places by changing the Format parameter:
' Num_ToHuman(1, "ton,tons", "@JEDEC", "#.00 ") returns "1.01 ton"
' Num_ToHuman(2348373, "ton,tons", "@JEDEC", "#.00 ") returns "2.24 megatons"
' Pad the resulting number by modifying the Format parameter:
' Num_ToHuman(1, "ton,tons", "@JEDEC", "00#.00 ") returns "001.01 ton"
' Num_ToHuman(2348373, "ton,tons", "@JEDEC", "00#.00 ") returns "002.24 megatons"
' Define the number of digits allowed before the decimal point:
' Num_ToHuman(1, "ton,tons", "@JEDEC", "# ", 4) returns "1 ton"
' Num_ToHuman(2348373, "ton,tons", "@JEDEC", "# ", 4) returns "2293 kilotons"
' Add commas:
' Num_ToHuman(1, "ton,tons", "@JEDEC", "# ", 4) returns "1 ton"
' Num_ToHuman(2348373, "ton,tons", "@JEDEC", "#, ", 4) returns "2,293 kilotons"
' Allow even more digits before the decimal point:
' Num_ToHuman(2348373, "ton,tons", "@JEDEC", "#, ", 7) returns "2,348,373 kilotons"
' Change the standard divisor to metric format (1000) by specifying -1:
' Num_ToHuman(2348373, "ton,tons", "@JEDEC", "#, ", 0, -1) returns "2.348 megatons"
' Display a prefix on the suffix. This prefix is only displayed if a suffix is displayed:
' Num_ToHuman(1.01, "ton,tons", "@JEDEC", "#,00 ", 0, 0, "-") returns "1.01 tons"
' Num_ToHuman(2348373, "ton,tons", "@JEDEC", "#,00 ", 0, 0, "-") returns "2.24 -megatons"
' Display the number, not the suffix:
' Num_ToHuman(2348373, "", "", "#,.00 ", 0, 0, "", "-NoSuffix") returns "2.24"
' Display the suffix, not the number:
' Num_ToHuman(2348373, "", "", "#,.00 ", 0, 0, "", "-NoNum") returns "M"
' Define our own suffixes:
' Num_ToHuman(2348373, "", " KILO, MEGA, GIGA") returns "2 MEGA"
' Define our own suffixes and units:
' Num_ToHuman(1, "watt,watts", "KILO,MEGA,GIGA") returns "1watt"
' Num_ToHuman(2348373, "watt,watts", "KILO,MEGA,GIGA") returns "2MEGAwatts"
' Define our own suffixes and units and use the Format parameter to insert a space:
' Num_ToHuman(1, "watt,watts", "KILO,MEGA,GIGA", "# ") returns "1 watt"
' Num_ToHuman(2348373, "watt,watts", "KILO,MEGA,GIGA", "# ") returns "2 MEGAwatts"
'Version History
' 1.0 2010.03.18 Tested by Russ Tanner on PB/CC 5.04.
DIM SuffixList(0 TO 8) AS STRING 'List of suffixes we're using.
LOCAL sNum AS STRING 'Return buffer.
LOCAL sSuffix AS STRING 'Return buffer.
LOCAL Range AS LONG 'Buffer for UOM range we're going to use.
LOCAL i AS LONG 'Index pointer.
LOCAL c AS LONG 'Iterator.
LOCAL pMetric AS LONG 'Parameter buffer.
LOCAL pUnit AS STRING 'Parameter buffer for singular units.
LOCAL pUnits AS STRING 'Parameter buffer for plural units.
'Default Parameter: Format.
Format = IIF$(LEN(Format) = 0, "#,", Format)
'Default Parameter: Metric
pMetric = IIF&(ISMISSING(Metric), 3, Metric) 'Default to 3 if missing.
pMetric = IIF&(pMetric < -8, 3, pMetric) 'Default to 3 if out of range (< -8).
'Default Parameter: Units
i = INSTR(Units, ",")
IF i > 0 THEN 'Units contains a comma. Parse singular and plural.
pUnit = LEFT$(Units, i - 1)
pUnits = MID$(Units, i + 1)
ELSE
pUnit = Units
pUnits = Units
END IF
'Initialize Parameter: Suffixes.
'Default if zero-length.
IF LEN(Suffixes) = 0 THEN Suffixes = "@JEDEC1"
'Predefined Value. Convert into standardized value.
IF LEFT$(Suffixes, 1) = "@" THEN
Suffixes = SWITCH$( _
Suffixes = "@SI", "kilo,mega,giga,tera,peta,exa,zetta,yotta", _
Suffixes = "@SI1", "kMGTPEZY", _
Suffixes = "@IEC", "kibi,mibi,gibi,tebi,pebi,exbi,zebi,yobi", _
Suffixes = "@IEC2", "Ki,Mi,Gi,Ti,Pi,Ei,Zi,Yi", _
Suffixes = "@JEDEC", "kilo,mega,giga,tera,peta,exa,zetta,yotta", _
Suffixes = "@JEDEC1", "KMGTPEZY", _
Suffixes = "@k", "kmgtpezy", _
Suffixes = "@KB", "KB,MB,GB,TB,PB,EB,ZB,YB", _
Suffixes = "@Kb", "Kb,Mb,Gb,Tb,Pb,Eb,Zb,Yb", _
Suffixes = "@kb", "kb,mb,gb,tb,pb,eb,zb,yb", _
Suffixes = "@kB", "kB,mB,gB,tB,pB,eB,zB,yB", _
ISTRUE 1, Suffixes _
)
END IF
'Convert Suffixes to an array.
IF INSTR(Suffixes, ",") > 0 THEN 'Suffixes is a comma-delimited list.
FOR c = 1 TO 8
i = INSTR(Suffixes, ",")
SuffixList(c) = IIF$(i > 0, LEFT$(Suffixes, i - 1), Suffixes) 'Parse the element. If no comma, use it all.
Suffixes = IIF$(i > 0, MID$(Suffixes, i + 1), "") 'Cut the element.
NEXT c
ELSE 'Suffixes is a character-list.
FOR c = 1 TO 8
SuffixList(c) = MID$(Suffixes, c, 1) 'Parse the element.
NEXT c
END IF
'Determine the standard divisor we're going to use.
SD = SWITCH&(SD = 0,1024, SD = -1,1000, ISTRUE 1,ABS(SD)) 'Last element is a catch-all.
'If Metric is > 0, automatically determine which range to use.
IF pMetric > 0 THEN
FOR Range = 0 TO 8
IF LEN(FORMAT$(ABS(Num/SD^Range), "#")) <= pMetric THEN EXIT FOR 'Max characters before decimal (not including minus).
NEXT i
'If Metric is <= 0, then force the Range.
ELSE
Range = ABS(pMetric)
END IF
'Calculate the return values...
'If using actual range (Range = 0), then make no conversions.
sNum = IIF$(Range = 0, FORMAT$(Num, Format), FORMAT$(Num/SD^Range, Format))
'If a suffix is undefined for the required range, default the suffix to "".
sSuffix = IIF$(Range <= UBOUND(SuffixList), SuffixList(Range), "")
FUNCTION = IIF$(ISTRUE INSTR(Flags, "-NoNum"), "", sNum) + IIF$(Range > 0, SuffixPrefix, "") + IIF$(ISTRUE INSTR(Flags, "-NoSuffix"), "", sSuffix) + IIF$(VAL(sNum) = 1, pUnit, pUnits)
END FUNCTION
|
|
|
|
|