Google-only functions and portability: what survives an export, and what has to be rewritten
Google Sheets has a large private function library. Some of it is famous —
QUERY, ARRAYFORMULA, IMPORTRANGE — and some of it is
quietly everywhere, like the operator functions ADD, MINUS and
DIVIDE that Sheets writes when it converts certain imported formulas. None of it is in
Excel’s documentation, and none of it is in LibreOffice’s.
The catalog behind this site holds 47 functions that Google documents and neither Microsoft
nor The Document Foundation does. We executed all 47: 189 test cases, in
Google Sheets by Drive import and in LibreOffice Calc on four pinned builds. In LibreOffice,
183 of the 189 cases returned #NAME? outright, and the six that did not
are wrapper artefacts rather than partial support (section 2 below). In Google Sheets, 179 of the 180
assertable cases matched, nine more are deliberate probes with nothing to assert, and the single miss
is a defect in Google’s own documentation rather than in its engine.
The surprise
The absence is not a version gap that a newer LibreOffice will close — it is total, and it
was measured rather than assumed. Each of these functions was written into a workbook under every
spelling LibreOffice could plausibly accept, on all four builds, before any verdict was published.
For the Google service-bound set that meant nine spellings × four builds = 36
combinations, every one of them #NAME?. LibreOffice’s parser also writes
the name back into the converted file lower-cased —
=googlefinance("NASDAQ:GOOG","price") — which is what it does with an identifier
it does not recognise as a function at all.
1. What is actually missing
The Excel column throughout is Microsoft’s documented behaviour as recorded in our test corpus — for these functions there is no Microsoft page at all, so the column simply records that, and we do not run Excel. The Google Sheets column is executed output from the dated Drive-import run of 2026-09-01 unless a row says otherwise. The LibreOffice column is Calc 25.8.7.3, with the same result on 24.2.0.3, 24.8.7.2 and 25.2.0.3 everywhere except the one row that says otherwise.
| Formula | Excel | Google Sheets (executed 2026-09-01) | LibreOffice Calc 25.8.7.3 (executed) |
|---|---|---|---|
| =QUERY(A1:E6,"select A where C > 700",0) | not documented | John, Mike | #NAME? |
| =SUM(QUERY(A1:E6,"select max(C) group by B",0)) | not documented | 2200 | #NAME? |
| =ARRAYFORMULA(A1:C1+A2:C2) | not documented | 11, 22, 33 | #NAME? |
| =SUM(ARRAYFORMULA(LEN(A1:A3))) | not documented | 6 | #NAME? |
| =SPLIT("Alas, poor Yorick"," ") | not documented | Alas, poor Yorick | #NAME? |
| =JOIN(" and-a ",{1,2,"1 2 3 4"}) | not documented | 1 and-a 2 and-a 1 2 3 4 | #NAME? |
| =FLATTEN(B1:B2, A1:A2) | not documented | 2, 4, 1, 3 | #NAME? |
| =SORTN(A2:C6) | not documented | Alice, 100, 90 | #NAME? |
| =COUNTUNIQUE(1,1,2,3,5,8,13) | not documented | 6 | #NAME? |
| =ISBETWEEN(7.9, 1.2, 12.45) | not documented | TRUE | #NAME? |
| =ISEMAIL("noreply@google.com") | not documented | TRUE | #NAME? |
| =ISURL("mailto:someone@example.com") | not documented | TRUE | #NAME? |
| =TEXT(EPOCHTODATE(1655906710,1),"yyyy-mm-dd hh:mm:ss") | not documented | 2022-06-22 14:05:10 | #NAME? |
| =ROUND(MARGINOFERROR(A1:A4,0.95),6) | not documented | 3.528308 | #NAME? |
| =ROUND(AVERAGE.WEIGHTED(2,10,4,15),10) | not documented | 3.2 | #NAME? |
| =ARRAY_CONSTRAIN(A1:C10, 2, 3) | not documented | 1, 2, 3 / 4, 5, 6 | #NAME? |
| =ARRAY_CONSTRAIN(SORT(A1:C10,1,FALSE),2,3) | not documented | 28, 29, 30 / 25, 26, 27 | #VALUE! on 24.8.7.2, 25.2.0.3, 25.8.7.3; #NAME? on 24.2.0.3 |
That last row is the only place in the whole 189 where the four builds disagree, and it is a
useful illustration of how misleading an error code can be. In 24.2 the inner SORT is
also unrecognised, so the whole expression is #NAME?. From 24.8 onward SORT
resolves and produces an array, which the still-unrecognised ARRAY_CONSTRAIN then turns
into #VALUE!. Nothing about ARRAY_CONSTRAIN changed between the builds; the
error code moved because its neighbour got better.
The absence evidence is recorded per function in the test corpus, in one sentence: probed on all
four pinned builds in five storage spellings — plain, _xlfn.,
COM.MICROSOFT., ORG.OPENOFFICE. and _xlfn.ORG.OPENOFFICE.
— and #NAME? under every one of them. That matters because a #NAME?
under the wrong spelling proves nothing at all; our
guide to
storage tokens is about the eight functions where exactly that mistake would have published a
false verdict.
2. The six cases that are not #NAME?, and why they are not support
Five of the 189 cases wrap the Google function in ISNUMBER or ISTEXT,
because the property under test is the result’s type rather than its value. Those
wrappers do not propagate an error — ISNUMBER(#NAME?) is simply
FALSE:
| Formula | Google Sheets (executed 2026-09-01) | LibreOffice Calc 25.8.7.3 (executed) | What the LibreOffice cell means |
|---|---|---|---|
| =ISNUMBER(TO_PERCENT(0.5)) | TRUE | FALSE | wrapper over an unrecognised name |
| =ISTEXT(TO_TEXT(24)) | TRUE | FALSE | wrapper over an unrecognised name |
| =ISNUMBER(TO_DOLLARS(5)) | TRUE | FALSE | wrapper over an unrecognised name |
| =ISTEXT(TO_PURE_NUMBER("abc")) | TRUE | FALSE | wrapper over an unrecognised name |
| =ISTEXT(DOLLAR(5)) | TRUE | TRUE | a control — DOLLAR is a LibreOffice function |
We flag this rather than quietly counting the FALSEs, because it is exactly the shape of mistake
that produces confident wrong compatibility data. A cell that says FALSE looks like an
answer. It is the absence of one.
The TO_* group carries a second caveat of its own that no execution can lift. Google
describes these as formatting functions — TO_PERCENT’s page says the operation
is “equivalent to clicking Format Number Percent from the menu bar” — so what changes
is the cell’s number format, not the number. Our harness reads the computed value back out of a
recalculated .xlsx, which means the formatting half of the documented behaviour is
invisible to it and is asserted nowhere in this corpus.
3. The operator functions: absent, and trivially replaceable
Fourteen of the 47 are function spellings of ordinary operators: ADD,
MINUS, MULTIPLY, DIVIDE, POW, EQ,
NE, GT, GTE, LT, LTE,
UMINUS, UPLUS and UNARY_PERCENT. Every one of their 59 cases is
#NAME? in LibreOffice on all four builds, and every one of them matched in Google
Sheets.
They are also the easiest thing on this page to port, because Google’s own pages define them
as equivalences and our corpus asserts the equivalence rather than the value. ADD’s
page says it is “Equivalent to the + operator”, so the case that runs is
=ADD(A2,A3)-(A2+A3), which must be exactly 0 whatever the engine computes — and in
Sheets it is. Likewise =POW(2,5)-POWER(2,5) is 0, =MULTIPLY(A2,B2)-(A2*B2) is
0, and the six comparison functions are each asserted only against the operator they are documented to
be equivalent to. Rewriting =ADD(a,b) as =a+b is therefore not a guess; it is
what the function is documented to be.
One trap inside that group is Google’s own doing. DIVIDE’s Notes section
says flatly “DIVIDE is equivalent to QUOTIENT”, which contradicts the same page’s
headline definition (DIVIDE = /). They cannot both hold: our executed case
=DIVIDE(7,2)-QUOTIENT(7,2) returned 0.5 in Google Sheets, not 0. If you
port DIVIDE to QUOTIENT on the strength of that sentence you will silently
drop every remainder in the column. Port it to /.
4. Three regex families, three flavours, three sets of names
This is the messiest corner of cross-engine portability and it is worth laying out flat, because the names collide in a way that makes a formula look portable when it is not.
| Name | Whose function it is | Google Sheets (executed) | LibreOffice Calc 25.8.7.3 (executed) |
|---|---|---|---|
| REGEXMATCH(text, regex) | works (2026-09-01) | #NAME? on all four builds | |
| REGEXEXTRACT(text, regex) | Google — and, under the same name and a different argument shape, Microsoft | works (2026-08-31) | #NAME? on all four builds |
| REGEXREPLACE(text, regex, replacement) | Google — same collision | works (2026-08-31) | #NAME? on all four builds |
| REGEXTEST(text, regex) | Microsoft only | #NAME? (2026-08-31) | #NAME? on all four builds |
| REGEX(text, expression, [replacement], [flags|occurrence]) | LibreOffice only | #NAME? (2026-09-01) | works — =REGEX("123456ABCDEF","[:digit:]","Z","g") returns ZZZZZZABCDEF |
Microsoft’s REGEXEXTRACT and REGEXREPLACE take extra arguments that
Google’s same-named functions do not. Our corpus executed the Microsoft forms in Sheets and the
first two arguments carried over — =REGEXEXTRACT(A2,"[A-Z][a-z]+") over
DylanWilliams returned Dylan in Sheets — while the documented
third and fourth arguments did not: =REGEXEXTRACT("2024-08-31","-([0-9]{2})-",2) and
=REGEXREPLACE("a1b2c3","[0-9]","#",-1) both came back #N/A. That is the worst
possible failure mode for a migration: the simple calls survive and look like proof that the whole
family ported, and the calls with options break.
And the dialects differ. Google’s REGEXMATCH page says “Google products use
RE2 for regular expressions. Google Sheets supports RE2 except Unicode character class
matching”. Microsoft’s three pages each say “All regular expressions for this
function… use the PCRE2 ‘flavor’ of regex”. LibreOffice’s
REGEX page says its expression argument uses “ICU regular expressions”. Our
patterns stay inside character classes, quantifiers and anchors, which mean the same thing in all
three, precisely so that a difference we report is a difference about the function and not about
dialect corners — but your patterns almost certainly do not stay inside that fence.
So: a workbook using REGEXTEST or the option arguments of
REGEXEXTRACT does not open and run in LibreOffice. It has to be rewritten to
REGEX, which has a different name, a different argument shape and a different flavour.
5. The service-bound set: nine functions no offline engine can have
GOOGLEFINANCE, GOOGLETRANSLATE, IMPORTDATA,
IMPORTFEED, IMPORTHTML, IMPORTRANGE, IMPORTXML,
SPARKLINE and AI are a category of their own, and the honest handling of them
is different at each end.
In LibreOffice the verdict is ordinary and publishable. All nine were probed with
nine storage spellings on all four builds — 36 combinations per function — and every one
returned #NAME?, with the lower-casing tell described above confirming the parser does not
know the name. “Unsupported in LibreOffice” is a real executed verdict here even though the
returned value is not something any test could assert.
In Google Sheets, seven of the nine carry no verdict at all, by design. They ran, we publish what came back, and we draw no conclusion:
| Formula | Google Sheets returned (executed 2026-09-01) | Why no verdict |
|---|---|---|
| =GOOGLEFINANCE("NASDAQ:GOOG","price") | 335.41 | documented as “delayed by up to 20 minutes” — a quote no test can be held to |
| =GOOGLETRANSLATE("Hello World","en","es") | Hola Mundo | a service’s choice among several correct renderings |
| =IMPORTDATA("https://example.com/data.csv") | #REF! | the call is well formed; only the host is inert |
| =IMPORTFEED("https://example.com/feed.xml") | #REF! | a feed exists in order to change |
| =IMPORTHTML("https://example.com/page.html","table",1) | #REF! | a slice of somebody else’s page |
| =IMPORTRANGE("https://docs.google.com/…","Sheet1!A1") | #REF! | documented as requiring a human to click Allow Access |
| =IMPORTXML("https://example.com/page.html","//a/@href") | #REF! | a document this project does not control |
| =SPARKLINE(A1:A5) | an empty cell | “Creates a miniature chart contained within a single cell” — a picture, not a value |
| =AI("Generate slogan for event in 10 words or less", A2) | its own formula text, returned verbatim | generated text, gated by plan and rationed by quota |
GOOGLEFINANCE and GOOGLETRANSLATE keep an ordinary executed
“supported” verdict — they evaluated and returned a value of the documented kind
— with the values themselves published but not asserted. The other seven are declared
unverdictable and appear in the
Executed, but no verdict drawn table with the reason. The
SPARKLINE blank is the one to be most careful with, and our test file said so in writing
before the run: a chart-in-cell has no cached scalar, so a successful evaluation may read back
as an empty cell, and that blank means “this cell holds a picture” — it must never be
reported as “SPARKLINE returned an empty result”. The AI cell
coming back holding its own formula text is evidence that nothing evaluated it on this account, which
is evidence about the account and not about the function.
What survives, what rewrites, what does not port
Survives with an exact, vendor-documented replacement. The fourteen operator
functions, replaced by their operators. MARGINOFERROR, which our corpus checks against
CONFIDENCE.T directly: =ROUND(MARGINOFERROR(A1:A4,0.95)-CONFIDENCE.T(1-0.95,
STDEV(A1:A4), COUNT(A1:A4)),12) returned 0 in Google Sheets on 2026-09-01, and
CONFIDENCE.T is executed and supported in both engines. TO_PURE_NUMBER and
TO_DATE against N, and TO_DOLLARS against
DOLLAR, in each case with the difference Google’s own Notes state —
DOLLAR outputs text where TO_DOLLARS applies a format to a number.
Rewrites, with an equivalent that exists but is not the same function.
SPLIT has no counterpart in the corpus that is documented as its equal, but
TEXTSPLIT occupies the same ground and we have executed it: it works in LibreOffice
25.8.7.3 only (#NAME? on 24.2.0.3, 24.8.7.2 and 25.2.0.3, executed
2026-07-29) and is #NAME? in Google Sheets (2026-08-29), so it is a target for a
Sheets→LibreOffice move and a dead end in the other direction. JOIN maps onto
TEXTJOIN, which is the healthiest option on this page: executed in both engines and
matching on every case, on all four LibreOffice builds. FLATTEN maps onto
TOCOL, executed and working in Google Sheets and in LibreOffice 25.8.7.3, and
#NAME? on the three older builds. Those three mappings are our authorship, offered as
suggested shapes from the executed availability data above — no vendor documents any of them as
an equivalence, and our corpus asserts none.
Does not port. QUERY is the big one: it embeds a whole separate query
language (the Google Visualization API Query Language, a separate document with its own versioning) and
nothing in Excel or LibreOffice parses it. ARRAYFORMULA is a close second, but for the
opposite reason — it is not a function so much as an evaluation mode, and its work is done in the
other engines by their own implicit array rules, which is a rewrite of the surrounding formula rather
than a substitution. SORTN, ARRAY_CONSTRAIN, ISEMAIL,
ISURL, ISDATE, EPOCHTODATE and COUNTUNIQUE are all
expressible in other functions, but each as a small formula rather than a rename. And the nine
service-bound functions do not port at all in any meaningful sense: an offline engine cannot fetch a
quote, and an engine that produced “es” from a local language table would not thereby be
compatible with the documented service.
One more reason to test rather than read
The single Google Sheets miss in all 189 cases is =ISDATE("1969-20-07"). Google’s
own Formula/Result table publishes TRUE for it, which is only consistent with a
year-day-month reading, and the page says nothing about locale. The live engine returned
FALSE on 2026-09-01. Our test file predicted the shape of this in writing before the
run — if the engine returns FALSE, the page is what will be wrong — and it did. That, and
the DIVIDE/QUOTIENT contradiction in section 3, and
EPOCHTODATE’s off-by-one epoch constant, are collected with their derivations in
when
the documentation is wrong.
Honest limits
The Excel column throughout says “not documented”, which is a statement about Microsoft’s function documentation and nothing more. We do not run Excel, and nothing on this page is a measurement of it.
The Google Sheets column is executed output from dated runs, 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. Most cases here ran
on 2026-09-01; the Microsoft REGEX* trio, IMAGE and
DETECTLANGUAGE ran on 2026-08-31; TEXTSPLIT, TEXTJOIN and
TOCOL ran on 2026-08-29. Sheets’ .xlsx export rounds floats to ten
significant digits, so a full-precision comparison can differ in the readback rather than in the
engine.
The LibreOffice column is executed output from Calc 25.8.7.3, and every case here returned identical
results on 24.2.0.3, 24.8.7.2 and 25.2.0.3 except the ARRAY_CONSTRAIN-over-SORT
row and the TEXTSPLIT/TOCOL availability noted above. Those four builds are
the only ones we tested, so “absent in LibreOffice” means absent in those four and does not
predict a future release.
The spelling probes — five spellings for the Google-documented set, nine for the service-bound set, on every build — are measurements recorded in the test corpus rather than published test cases with verdicts of their own.
Scope. 47 functions and 189 cases is the whole Google-only set as our catalog defines it: documented
by Google, not by Microsoft, not by The Document Foundation. Functions all three vendors document, and
the Excel-only set, are elsewhere on this site. Untested here: QUERY’s error
behaviour (Google’s pages name no error value for it at all, so we assert none), whether a
QUERY result carries a header row (neither page states it), locale-dependent parsing in
ISDATE and TO_DATE, and the formatting half of every TO_*
function. See our methodology for how recalculation is proven rather
than assumed, and the function pages for
QUERY,
ARRAYFORMULA,
SPLIT and
REGEXMATCH for the per-engine support matrices.