LENB counts 2 bytes per CJK character everywhere — the docs say 1 outside DBCS locales
LENB is supposed to count bytes where LEN counts characters. For
"Phoenix, AZ" they are both 11 and nobody thinks about it. The whole point of the
function is what happens with Japanese, Chinese or Korean text, where a character is not a byte
— and that is exactly where the documented rule and the executed behaviour part company.
We ran =LENB("日本") — two CJK characters, no spaces, nothing else. LibreOffice
Calc 25.8.7.3 returned 4. Google Sheets returned 4.
Microsoft’s documented rule, applied to the locale our harness runs under, gives
2.
The surprise
This is one of the few pages on this site where both engines we execute diverge from the
documented answer, and they diverge to the same number. Microsoft’s archived LEN/LENB page
says, verbatim: “LENB counts 2 bytes per character only when a DBCS language is set as the
default language. Otherwise LENB behaves the same as LEN, counting 1 byte per character.”
Our harness VM’s default language is en_US.UTF-8, which is not a DBCS language, so
the documented answer here is 2. Both engines returned 4 — two bytes per character, as though a
DBCS language were always in force. All four LibreOffice builds we tested (24.2.0.3, 24.8.7.2,
25.2.0.3 and 25.8.7.3) returned 4.
4 is not the UTF-8 byte count
It is worth being precise about which wrong answer this is, because “LENB counts raw bytes” is the natural guess and it does not fit the measurement.
The string 日本 encodes as 6 bytes in UTF-8 (three per character) and
4 bytes in UTF-16 (two per character). Neither engine returned 6. Both returned 4. So
what is being counted is not the storage the file actually uses — both LibreOffice and Google
Sheets store text as UTF-8 — but two bytes per character, which is the DBCS rule applied
unconditionally rather than only under a DBCS default language.
That matters for a migration because it changes what the number means. A LENB result
of 4 is not a promise about how many bytes anything occupies anywhere; it is a character count
multiplied by two for the characters an engine considers wide. If you are sizing a database column, a
fixed-width export record or an API payload against real UTF-8 bytes, LENB is not
measuring the thing you think it is measuring in any of the three engines.
Executed: the LENB corpus
All six LENB cases, run as written. The Excel column is Microsoft’s documented
behaviour as recorded in our test corpus — we do not run Excel. The Google Sheets column is
executed output from the dated Drive-import run of 2026-08-31. The LibreOffice column is Calc
25.8.7.3, with 24.2.0.3, 24.8.7.2 and 25.2.0.3 returning the identical value on every row.
| Formula | Excel (documented, non-DBCS default language) | Google Sheets (executed 2026-08-31) | LibreOffice Calc 25.8.7.3 (executed) |
|---|---|---|---|
| =LENB("Phoenix, AZ") | 11 | 11 | 11 |
| =LENB("") | 0 | 0 | 0 |
| =LENB(" One ") | 8 | 8 | 8 |
| =LENB(1234) | 4 | 4 | 4 |
| =LENB("日本") | 2 | 4 | 4 |
| =LENB(1/0) | #DIV/0! | #DIV/0! | #DIV/0! |
Five of the six rows agree everywhere, and they are the rows where the DBCS rule cannot change the
answer: every character in "Phoenix, AZ", " One " and the coerced number
1234 is single-byte under either reading, an empty string has no bytes under either, and
an error argument propagates before LENB ever sees a character. The single CJK row is the
whole divergence.
Two smaller things the table settles. Spaces count — leading and trailing — so
" One " is 8 and not 3, in both engines as documented. And a numeric argument is
converted to its text form first, so =LENB(1234) is 4 rather than an error or a byte
width of the underlying double.
For context on whether this batch of text functions is broadly trustworthy: T, the
other text function executed in the same 2026-08-31 run, matched the documented result on all six of
its cases in both engines — including the two that catch a naive implementation,
=T(19) and =T(TRUE), which both correctly returned empty text rather than
"19" or "TRUE". The LENB divergence is a specific finding, not
noise from a bad run.
Microsoft has deprecated LENB
There is a second reason not to build on this function, and it is on the help page itself. The current live LEN/LENB article states that the LENB function is deprecated, and it has dropped the DBCS explanation entirely — the “2 bytes per character only when a DBCS language is set as the default language” wording that our test case is measured against now survives only in the archived version of the page.
So the documented behaviour this page compares against is documentation Microsoft has retired. That
cuts both ways honestly: it means our Excel column for the CJK row rests on an archived rule rather
than a current one, and it means a workbook whose logic depends on LENB is depending on a
function its own vendor has stopped explaining. Both are reasons to migrate away from it rather than
to reason carefully about it.
What this means for a CJK migration
The risk depends on the locale the workbook was built under, not on the workbook.
This is the unusual part. If the original Excel file was authored and run under a Japanese, Simplified
Chinese, Traditional Chinese or Korean default language, then under the documented rule Excel counted
2 bytes per CJK character — the same 4 that LibreOffice and Google Sheets returned for us. Those
workbooks migrate without a change in value. If the original ran under a non-DBCS default language
such as en-US, the documented rule gives 1 byte per character, and every
LENB over CJK text doubles on migration. The formula is identical in both cases;
only the machine it used to run on differs.
The failure is silent and directional. A doubled byte count does not error. It
overstates width, so the typical symptoms are a validation rule that starts rejecting valid input, a
“field too long” flag that fires on rows that were fine yesterday, a truncation
LEFT/MID that cuts short, or a padding calculation that pads to the wrong
width in a fixed-width export.
Find the exposure by searching for the B-suffix family. LENB is the
one we executed, but Excel ships a whole set of byte-oriented twins — LEFTB,
RIGHTB, MIDB, FINDB, SEARCHB,
REPLACEB — that carry the same DBCS wording. None of those has a case in our
corpus, so we make no claim at all about how any engine implements them; we mention them because a
workbook that uses one usually uses several, and they are what you should be grepping for.
Prefer LEN unless you genuinely need bytes. Most real uses of
LENB in the wild are counting characters for a display or a validation and reaching for
the byte version out of habit or copied code. LEN is portable, current, and means one
thing everywhere.
If you genuinely need UTF-8 bytes, compute them. No engine’s
LENB gave us the UTF-8 byte count in this test, so a workbook that needs real byte
budgets has to build the number rather than ask for it — typically by classifying characters and
weighting them. We have no executed case for such a construction and are not going to publish one as
though we had; the point is only that LENB is not it.
Honest limits
The Excel column is Microsoft’s documented behaviour as recorded in our test corpus, and for
the CJK row that documentation is the archived LEN/LENB page — the current page has removed the
DBCS rule and marks the function deprecated. We do not run Excel, and no value in that column is a
measurement. In particular we cannot tell you what a real Excel returns for =LENB("日本")
under any locale; we can only tell you what its documentation said it would.
The locale question cuts into our own results too, and this is the biggest caveat on the page. Our
LibreOffice runs happen on a VM whose default language is en_US.UTF-8, which is what makes
the documented answer 2 rather than 4 for that row. We did not re-run the corpus under a DBCS default
language, so we cannot say whether LibreOffice’s answer would change if we did — only that
under a non-DBCS default it returns 4 where the documented rule says 1 byte per character. For Google
Sheets the document and account locale are Google’s to decide and we did not control them, so
treat the Sheets 4 as “what the Drive-import run returned” and not as a locale-controlled
experiment.
Scope. This is one probe, on one two-character string, in one function. LENB is the
only B-suffix function in our corpus, and our LEN cases are all ASCII, so we have no
executed value for =LEN("日本") to sit beside the LENB one. Mixed
ASCII-and-CJK strings, emoji and other astral-plane characters, combining marks, and non-CJK
non-ASCII text are all untested here.
The Google Sheets column is executed output from a dated run, because Sheets has no version number
to pin: a formula-only .xlsx carrying no cached results goes to Google Drive, is recalculated by
Google’s engine, and comes back as .xlsx for readback, with a deterministic
=1111+2222 canary in every sheet proving the recalculation happened. These six cases ran
on 2026-08-31. See our methodology for how recalculation is proven
rather than assumed, and the function pages for LENB,
LEN and T for the per-engine
support matrices.