Absolutely — here’s a clean, ready-to-paste Google Sheets formula that takes a hex color in cell A1 and outputs HSL.

I’ll give you two versions:

1. One formula per H, S, L (easier to read)

2. One formula that outputs full `hsl(H, S%, L%)` (compact)

---

🎨 1) Individual H, S, L formulas (Google Sheets‑ready)

Assume your hex code is in A1 (e.g., `#7b7b00`).

Hue (H)

=LET(

hex, A1,

r, HEX2DEC(MID(hex,2,2))/255,

g, HEX2DEC(MID(hex,4,2))/255,

b, HEX2DEC(MID(hex,6,2))/255,

max, MAX(r,g,b),

min, MIN(r,g,b),

d, max-min,

h, IF(d=0,0,

IF(max=r, MOD((g-b)/d,6),

IF(max=g, (b-r)/d+2,

(r-g)/d+4))),

ROUND(h*60,1)

)

Saturation (S%)

=LET(

hex, A1,

r, HEX2DEC(MID(hex,2,2))/255,

g, HEX2DEC(MID(hex,4,2))/255,

b, HEX2DEC(MID(hex,6,2))/255,

max, MAX(r,g,b),

min, MIN(r,g,b),

l, (max+min)/2,

d, max-min,

s, IF(d=0,0, d/(1-ABS(2*l-1))),

ROUND(s*100,1)

)

Lightness (L%)

=LET(

hex, A1,

r, HEX2DEC(MID(hex,2,2))/255,

g, HEX2DEC(MID(hex,4,2))/255,

b, HEX2DEC(MID(hex,6,2))/255,

max, MAX(r,g,b),

min, MIN(r,g,b),

l, (max+min)/2,

ROUND(l*100,1)

)

---

🌈 2) One formula that outputs full `hsl(H, S%, L%)`

Paste this into any cell; it reads the hex from A1:

=LET(

hex, A1,

r, HEX2DEC(MID(hex,2,2))/255,

g, HEX2DEC(MID(hex,4,2))/255,

b, HEX2DEC(MID(hex,6,2))/255,

max, MAX(r,g,b),

min, MIN(r,g,b),

d, max-min,

l, (max+min)/2,

h, IF(d=0,0,

IF(max=r, MOD((g-b)/d,6),

IF(max=g, (b-r)/d+2,

(r-g)/d+4)))*60,

s, IF(d=0,0, d/(1-ABS(2*l-1))),

"hsl(" & ROUND(h,1) & ", " & ROUND(s*100,1) & "%, " & ROUND(l*100,1) & "%)"

)

---

Want a version that auto‑detects missing `#`, or outputs HSL in separate columns automatically?

I can tailor it to your workflow — especially if you’re building a color‑coding sheet or a design palette.

Nice—this is already solid. I’ll extend it with the two upgrades you hinted at so it’s more production-ready for your workflow.

---

## ✅ Version 3: Handles missing `#` automatically

This safely normalizes input like `7b7b00` or `#7b7b00`.

```excel

=LET(

hexRaw, A1,

hex, IF(LEFT(hexRaw,1)="#", hexRaw, "#"&hexRaw),

r, HEX2DEC(MID(hex,2,2))/255,

g, HEX2DEC(MID(hex,4,2))/255,

b, HEX2DEC(MID(hex,6,2))/255,

max, MAX(r,g,b),

min, MIN(r,g,b),

d, max-min,

l, (max+min)/2,

h, IF(d=0,0,

IF(max=r, MOD((g-b)/d,6),

IF(max=g, (b-r)/d+2,

(r-g)/d+4)))*60,

s, IF(d=0,0, d/(1-ABS(2*l-1))),

"hsl(" & ROUND(h,1) & ", " & ROUND(s*100,1) & "%, " & ROUND(l*100,1) & "%)"

)

```

---

## ✅ Version 4: Auto-spills H, S, L into 3 columns

This is ideal for palette building or downstream logic (sorting, filtering, thresholds).

```excel

=LET(

hexRaw, A1,

hex, IF(LEFT(hexRaw,1)="#", hexRaw, "#"&hexRaw),

r, HEX2DEC(MID(hex,2,2))/255,

g, HEX2DEC(MID(hex,4,2))/255,

b, HEX2DEC(MID(hex,6,2))/255,

max, MAX(r,g,b),

min, MIN(r,g,b),

d, max-min,

l, (max+min)/2,

h, IF(d=0,0,

IF(max=r, MOD((g-b)/d,6),

IF(max=g, (b-r)/d+2,

(r-g)/d+4)))*60,

s, IF(d=0,0, d/(1-ABS(2*l-1))),

{

ROUND(h,1),

ROUND(s*100,1),

ROUND(l*100,1)

}

)

```

➡️ Output:

- Column 1 → Hue

- Column 2 → Saturation (%)

- Column 3 → Lightness (%)

---

## ✅ Version 5 (Advanced): Works on a whole column (ARRAYFORMULA-style)

Drop this in row 1 (or next to your data), and it processes a full list of hex codes in column A:

```excel

=MAP(A1:A,

LAMBDA(hexRaw,

IF(hexRaw="","",

LET(

hex, IF(LEFT(hexRaw,1)="#", hexRaw, "#"&hexRaw),

r, HEX2DEC(MID(hex,2,2))/255,

g, HEX2DEC(MID(hex,4,2))/255,

b, HEX2DEC(MID(hex,6,2))/255,

max, MAX(r,g,b),

min, MIN(r,g,b),

d, max-min,

l, (max+min)/2,

h, IF(d=0,0,

IF(max=r, MOD((g-b)/d,6),

IF(max=g, (b-r)/d+2,

(r-g)/d+4)))*60,

s, IF(d=0,0, d/(1-ABS(2*l-1))),

"hsl(" & ROUND(h,1) & ", " & ROUND(s*100,1) & "%, " & ROUND(l*100,1) & "%)"

)

)

)

)

```

---

## Small but important edge-case note

- Pure grayscale (like `#777777`) → Saturation correctly returns `0`

- Hue is mathematically undefined in that case → we set it to `0` (standard practice)

---

If you want, I can take this one step further for your color-coded storytelling system:

- map HSL → emotional categories

- normalize palettes across contributors

- or build a “genkiness gradient” scoring system tied to lightness + saturation shifts

Just say the direction.

### ✅ Result

hsl(60, 100%, 24.1%) → `#7A7A00`

---

### 🧠 Quick breakdown

- Hue 60° = yellow

- 100% saturation = fully vivid

- 24.1% lightness = fairly dark → pushes toward an olive/mustard tone

Rounded to nearest integer RGB:

- R ≈ 122

- G ≈ 122

- B = 0

→ Hex: #7A7A00

---

If you want, I can give you the exact reverse formula for Google Sheets too (HSL → HEX) so your system stays fully round-trip consistent.

### ✅ Result

hsl(60, 100%, 24%) → `#7A7A00`

---

### 🔍 Why it’s the same as 24.1%

That tiny 0.1% drop doesn’t change the rounded RGB output:

- R = 122

- G = 122

- B = 0

Hex stays `#7A7A00`

You’d only see a hex change once the lightness shift crosses a rounding boundary (≈ ±0.5 in RGB space).

---

If you want ultra-precise (non-rounded) mapping for your storytelling system, I can give you a version that preserves fractional RGB before hex conversion.

Great catch — this is a real rounding mismatch, not you doing anything wrong.

### ✅ What happened

You started with:

- Hex: `#7B7B00`

→ RGB: (123, 123, 0)

When converted to HSL, that becomes approximately:

- HSL: `hsl(60, 100%, 24.1176%)`

But I gave you:

- `hsl(60, 100%, 24.1%)` (rounded)

---

### ⚠️ Where the mismatch comes from

When you went back:

- You used 24% (or 24.1%)

- But the true value needed to reconstruct `#7B7B00` is:

```

24.1176% (not 24% or even exactly 24.1%)

```

That tiny difference matters because:

- HSL → RGB involves multiplication + rounding to integers (0–255)

- Small decimal shifts can flip:

- 123 → 122 (what happened)

‍ ‍

So you got:

- (122,122,0) → `#7A7A00` instead of `#7B7B00`

---

### 🔬 The key insight

This conversion is not perfectly reversible because:

- HEX = integer RGB (0–255)

- HSL = floating point math

- Rounding happens twice:

1. When converting to HSL (you rounded 24.1176 → 24.1 or 24)

2. When converting back to RGB (floats → integers)

---

### ✅ Exact round-trip values

If you want perfect reversibility, use:

```

#7B7B00 ↔ hsl(60, 100%, 24.1176%)

```

NOT:

- 24%

- 24.1%

---

### 🧠 Rule of thumb for your system

For your color-coded storytelling (this actually matters a lot for consistency):

- ✅ Store HEX as the source of truth

- ✅ Treat HSL as a derived / display format

- ⚠️ Avoid rounding Lightness if you need reversibility

- ✅ Keep at least 4 decimal places for L (and S if needed)

---

### 🧩 Why this matters for your use case

Since you're using hex codes as semantic identifiers:

- `#7B7B00` and `#7A7A00` are different "stories"

- But visually almost identical → dangerous drift

So rounding = identity corruption in your system

---

If you want, I can build you a Google Sheets-safe reversible pipeline where:

- HEX → HSL (high precision)

- HSL → HEX (guaranteed same output)

That would lock your narrative encoding system so nothing silently mutates.