Question: This is how I convert e.g. `RGB(255, 0, 0)` (where red is stored in the least significant byte of a `Long`) to a 6-digit hex string `FF0000`:

```
Function RgbToHex(l As Long) As String
Dim r As Long
Dim g As Long
Dim b As Long
    r = l And ColorConstants.vbRed
    g = (l And ColorConstants.vbGreen) / (2 ^ 8)
    b = (l And ColorConstants.vbBlue) / (2 ^ 16)
    RgbToHex = Right$("0" & Hex(r), 2) _
             & Right$("0" & Hex(g), 2) _
             & Right$("0" & Hex(b), 2)
End Function

```

I'm a bit worried about the string manipulations, but as VB6 lacks `printf`-like formatting, this is the best I could come up with. Can it be improved?

Answer: 
I'll just focus on performance, because that's the fun part.

You're correct to be worried about the string manipulations, so you should obviously try to minimize them. The *other* thing you should be worried about is the division and exponentiation used for bit-twiddling. If all you need to do is swap the byte order of an intrinsic type, you can do it using a CopyMemory API call, a struct, and simple assignments:

```
'Note that this is a VBA declaration (missed the VB6 tag) - adjust accordingly.
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
            (destination As Any, source As Any, ByVal length As LongPtr)

Private Type LongBytes
    Byte1 As Byte
    Byte2 As Byte
    Byte3 As Byte
    Byte4 As Byte
End Type

Public Function SwapEndian(inVal As Long) As Long
    Dim bytes As LongBytes, swapped As LongBytes

    CopyMemory bytes, inVal, 4

    swapped.Byte1 = bytes.Byte4
    swapped.Byte2 = bytes.Byte3
    swapped.Byte3 = bytes.Byte2
    swapped.Byte4 = bytes.Byte1

    Dim retVal As Long
    CopyMemory retVal, swapped, 4
    SwapEndian = retVal
End Function

```

Even *with* the overhead for the API call, this is blazingly fast. It also completely eliminates the need to call `Hex` repeatedly, completely eliminates the need to pad every byte to 2 characters individually, and involves exactly zero math operations.

Once you have the `Long` in the byte order you want, all you need to do is call `Hex$` once (note that it also has a `String` returning variation - kudos on using the one for `Right$`):

```
Public Function RgbToHex2(inVal As Long) As String
    Dim bytes As LongBytes, swapped As LongBytes

    CopyMemory bytes, inVal, 4
    swapped.Byte1 = bytes.Byte3
    swapped.Byte2 = bytes.Byte2
    swapped.Byte3 = bytes.Byte1
    swapped.Byte4 = bytes.Byte4

    Dim retVal As Long
    CopyMemory retVal, swapped, 4

    RgbToHex2 = Right$("0" & Hex$(retVal), 6)    '<--1 call each to Right$ and Hex$
End Function

```

I'd ballpark that it runs about 5 times faster.
Obviously @Comintern knocks out the bit-swapping part, so this answer is more about, well, every other aspect of the code.

---

### Signature

Kudos for proper `PascalCase`!

If the function is meant to be `Public`, it's probably best to specify it as such. I like that it has an explicit return type, but the parameter is implicitly passed by reference, which is potentially confusing since the function is meant to be "pure" and thus, it's really used as a `ByVal` parameter and should be specified as such, too. `l` is a terrible name for it though.

I'd go with this:

```
Public Function RgbToHex(ByVal rgbValue As Long) As String

```

That way none of it is ambiguous or implicit in any way.

---

### Variables and Constant Expressions

It's only 3 of them so it's probably not big of a deal, but I've seen way too many VBA procedures with a page-length wall-of-declarations at the top to skip this: variables should be declared as close as possible to their usage.

This reads more fluently IMO:

```
Dim rValue As Long
rValue = rgbValue And ColorConstants.vbRed

Dim gValue As Long
gValue = (rgbValue And ColorConstants.vbGreen) / (2 ^ 8)

Dim bValue As Long
bValue = (rgbValue And ColorConstants.vbBlue) / (2 ^ 16)

```

I like how `2 ^ 8` and `2 ^ 16` help readability, but not how they need to be computed every time the function is called. Naming them and introducing constants will maintain the readability while avoiding the recalculation:

```
Const gOffSet As Long = 2 ^ 8
Const bOffSet As Long = 2 ^ 16

```

And then:

```
Dim gValue As Long
gValue = (rgbValue And ColorConstants.vbGreen) / gOffSet

Dim bValue As Long
bValue = (rgbValue And ColorConstants.vbBlue) / bOffSet

```

---

### Strings

Kudos for using the string-returning `Right$` function: that avoids an implicit conversion from `Variant` that `Right` would incur.

However `Hex` also has a string-returning little brother; you should prefer `Hex$` over it for the same reason you're using `Right$` over `Right`.

I like how you're using line continuations to line up the function calls, it's very elegant. Sad that it's moot with proper bit swapping :)