This package contains a large set of library routines I have built over the years to do many things related to numbers. These routines run in VB6 as well as 32 or 64-bit VBA. As you know, there are often multiple ways of solving a problem. I have been building these utilities for 20+ years and I often work on speed, accuracy and functionality for all of them. If you have any procedures that you think are better than those I have in this package please let me know so I can upgrade the library.

A lot of the routines use normal VB code. For some I have used RtlMoveMemory (many of you use an alias of CopyMemory for this Windows API function) to facilitate things like shifting bits, copying to other data types (e.g., getting the top byte of a Long variable into a Byte) etc.

In general I have found that I do not include an entire module but rather use specific ones you need in my code.

The package consists of 9 modules and is there are no dependencies. Most of the subs and functions are self-explanatory but each is briefly discussed below. BTW, if you use any of this in Excel as User Defined Functions, you can greatly improve the time lag in the workbook by putting the Application.Volatile False at the top of whatever function(s) are using in the spreadsheet.

At the end of this document are instructions for running the sample code.

mBaseConversions

This module allows for conversion between regular numbers, hexadecimal and binary.

This module makes use of a variable I call UVar which represents an unsigned Currency which allows us to use all 64 bits of the number. If you are using 64-bit VBA then you can also think of UVar as an unsigned LongLong (also 64 bits). A UVar can be a Byte, Integer, Long, Currency, Single, Double, Decimal (part of a Variant) and a LongLong (64-bit only).

What you submit to this function (and the others in this module) are treated as unsigned values. As you know, VB uses the top bit of scalar variables to designate the sign. We ignore that and treat the topmost bit as just another bit. For example, the hex value of -1 as a Long is &HFFFF (i.e., all bits are set). BTW, you cant avoid the top bit being used for the sign. It would be tempting to think you can take and integer value of -1 and use the function to convert it to a Long that the full 16 bits would go to the Long. Unfortunately, VB doesnt do that. Instead, VB converts the Integer -1 to a Long -1 (all 32 bits in the Long are set whereas only 16 bits were set in the Integer. For normal use this is okay but when we want to use all of the bits in hex or binary, this is a problem. Other than a Byte, VB doesnt have any unsigned variables so thats what we deal with here.

One interesting thing occurs with the Currency variable. Even though it is an integer type variable, it has a decimal component. VB does this by taking the value given it an multiplying by 10,000 and then it uses the lower bits to do the fractional part. Internally it is just a 64-bit value and the multiplying and dividing by 10,000 is done when a value is assigned or the conversion function CCur is used. We treat a Currency value as an unsigned 64-bit value. If you have a regular Currency variable and you want to feed it to UVar2Hex or UVar2Bin then you should first divide it by 10,000. Likewise, if you use Hex2UVar or Bin2UVar and you want to use the return Currency value for other calculations you should multiply it by 10,000.

If you use this in 64-bit Office you have access to a signed 64-bit variable called a LongLong that does not have the 10,000 factor that the Currency data type has. The only thing to watch out for is that it is a signed variable (i.e., the topmost of the 64 bits is the sign bit).

UVar can also be a Single, Double or a Decimal value but note that when you use UVar2Hex or UVar2Bin with a negative number it gets converted to a signed value. For example, if you have a Double variable with a value of -1, when it gets converted it will become an integer (Currency or LongLong) with a value of -1. If thats what you wanted thats fine but just know that with anything other than a Byte data type, you have to be aware that VB messes around with the topmost bit. It would be nice if VB had unsigned variables but it doesnt so this is why I created this set or procedures.

Return a hex string from the UVar. The return will have no leading zeroes (e.g., Feeding it a Long value of 10000000& returns 98 9680 and not 0098 9680). You can determine whether to group the return characters, and if so, how much (the example in the previous was based on the default grouping of 4 characters).Function UVar2Hex

The function specifies the input variable is a Variant but you can use whatever data type you want without first converting it to a variant (I believe VB does that internally).

Convert a hex string (up to 16 characters (64-bit)) into an unsigned value. You can specify a data type or take the default which is to determine the data type from the size of the value. For example, if you pass F as the hex string, you could specify for it to be returned as a byte, integer, long, etc. but if you go with the default it will be returned as a byte inside the variant.Function Hex2UVar

Converts an unsigned variable into its binary equivalent (as a string). For a Byte, Integer, Long, Currency, LongLong, Single, Double or Decimal returns the string representation of the binary number (base 2). Since the routine uses an unsigned value, if you use a Currency then it should first be divided by 10,000 (or as part of the call) to use all of the bits.Function UVar2Bin

There is an optional parameter named RndType (optional) determines the size of the return number (higher bits are discarded from return). For example, if you pass an integer with a value of 111, this function will return 00000000 01101111 but if you set RndType to 1 to indicate a Byte, the function will return 01101111. You can specify what character (or none at all) to sue as the leading character. For example, if you specify no leading character, the return from the previous example will be 1101111. Finally, you can set the grouping. The previous examples use a grouping of 8 characters. If you specify 0 there is no grouping and the string is returned without any spacing characters.

- Returns the variable related to the binary string of up to 64 characters (1s and 0s). Must specify the variant variable type in "VarType" (vbByte, vbInteger, vbLong, vbCurrency or vbLongLong) and the return is adjusted for the type of variable. If you do not specify this value then the function determines it from the length of the input binary string (1-8 byte, 9-16 integer, 17-32 long, 33-64 currency or longlong).Function Bin2UVar

- Converts a hex string into its binary counterpart. As discussed above, you can also specify the leading character (defaults to 0) or you can not have leading zeroes by specifying . You can also set the grouping of binary characters in the return (default 8 characters which is 1 byte).Function Hex2Bin

- Converts a binary string of up to 64 characters (all 0's and 1's) into a hex string.Function Bin2Hex

Module mBaseConversions1

The previous module has very flexible routines for converting between base 10, hexadecimal and binary numbers. If you want type-specific solutions that have fewer frills, the following conversions could be used.

Returns the hexadecimal representation of a Byte with optional leading 0s.Byte2Hex

Converts an Integer into a Hex.Int2Hex

Converts an unsigned Long to a Currency.Long2Curr

Returns an unsigned Currency with the Long in the low order bytes.Long2UCurr

Converts a Long into a binary string. Same functionality as Bin2Hex in module mBaseConversions but uses different logic & has a different name to avoid duplicate names in the same project.Long2Bin1

Converts a Long variable into a Hex string.Long2Hex

Converts a Currency into a hex string.Curr2Hex

Converts a Currency into a binary string.Curr2Bin

- An unsigned Currency (if it is a normal Currency, it should be divided by 10,000). This function converts this unsigned Currency into a Hex string.UCurr2Hex

Converts a binary string into a Byte.Bin2Byte

Converts a binary string into an unsigned integer (uses last 16 bits).Bin2Int

Converts a binary string into a Long.Bin2Long

Converts a binary string into a Currency. Unlike Bin2UVar, this one returns the Currency without using the last 4 bits (i.e. not divided by 10,000).Bin2Curr

Converts a binary string into the unsigned Currency.Bin2UCurr

Converts a binary string into its hex equivalent. Same functionality as Bin2Hex in module mBaseConversions but uses different logic & has a different name to avoid duplicate names in the same project.Bin2Hex1

Converts a hex string into a Currency.Hex2Curr

Converts a Double into its hex equivalent.Double2Hex

If you are using 64-bit VBA you also have the following procedures:

Converts an unsigned Long into an unsigned LongLong.Long2LL

Converts an unsigned LongLong into its Hex equivalent.LLToHex

Converts a binary string into an unsigned LongLong (string, max 62 chars)Bin2LL

Converts a hex String (up to 15 characters) into an unsigned LongLong.Hex2LL

Converts an unsigned LongLong into hex.LL2Hex

Converts an unsigned LongLong into a binary string.LL2Bin

Module mDataTypeConversions

This module works with sub-parts of variables. For example, one function takes all 4 bytes of a Long and puts them into 4 Byte variables.

Puts 2 Bytes into the 2 bytes of an Integer.Bytes2Int

Puts 4 Bytes into one Long.Bytes2Long

Combines 8 Bytes into a Currency (not multiplied by 10,000).Bytes2UCurr

Puts the 2 bytes of an Integer into 2 Bytes.Int2Bytes

Puts 2 Integers into a Long.Ints2Long

Combines 4 Integers into a Currency (not multiplied by 10,000).Ints2UCurr

- Returns the low byte (least significant byte) of "Integer1"Int2LoByte

- Returns the high byte (most significant byte) of "Integer1"Int2HiByte

- Puts the specified byte (1=least significant byte, 4=most significant byte from a Long into a Byte.Long2Byte

Puts the 4 bytes of a Long into 4 Bytes.Long2Bytes

Puts the two integers making up the most and least significant words of a Long into 2 Integers.Long2Ints

- Takes a long (unsigned but contained in a signed long) like from an API call & returns it in a U64 (NOT multiplied by 10,000). Note the top 4 bytes of the U64 value will always be 0 by definition.LongToUCurr

Combines 2 Words into a Currency (not multiplied by 10,000).Longs2UCurr

- Returns the low integer (least significant word) of a Long into an Integer.Long2LoWord

- Returns the high integer (most significant word) of a Long into an Integer.Long2HiWord

Puts a Long into the low 4 bytes of a Currency (hi bits are 0).Long2CurrLo

- Takes a Currency that VB has already multiplied by 10000. Existing fractional part is discarded.Curr2UCurr

Puts the 8 bytes of a Currency (not divided by 10,000) into 8 Bytes.UCurr2Bytes

Puts the 8 bytes of a Currency (not divided by 10,000) into 4 Integers.UCurr2Ints

Puts the 8 bytes of a Currency (not divided by 10,000) into 2 Longs.UCurr2Longs

Puts the selected byte of a Currency into a Byte.UCurr2Byte

Puts the selected word of a Currency into an Integer.UCurr2Int

- Returns the low long (least significant long) of a Currency.UCurr2LoLong

- Returns the high long (most significant long) of a Currency.UCurr2HiLong

- Takes a 64-bit value that VB has NOT multiplied by 10,000 and does that to the number (for display & non-bit calculations).UCurrToCurr

If you are using 64-bit VBA you also have the following procedures:

Puts the 8 bytes of a LongLong into 8 Bytes.LL2Bytes

Puts the 8 bytes of a LongLong into 4 Integers.LL2Ints

Puts the 8 bytes of a LongLong into 2 Longs.LL2Longs

Puts 8 Bytes into a LongLong.Bytes2LL

Ints2LL Combines 4 Integers into a LongLong.

Combines 2 Longs into a LongLong.Longs2LL

Puts the 4 bytes of a Long into the low 4 bits of a LongLong (hi 4 bytes are 0d).Long2LLLo

- Puts the specified byte (1=least significant byte, 8=most significant byte out of a LongLong into a Byte.LL2Byte

- Puts the specified integer (1=least significant integer, 4=most significant integer out of a LongLong into an Integer.LL2Int

- Puts the low long (least significant long) of a LongLong into a Long.LL2LoLong

Puts the most significant 4 bytes of a LongLong into a Long.LL2HiLong

Numbers.zip

{Continued in next post}