A table's totals row exported even when the table had no header, or
when its only content was a plain number wrongly declared as a text
label. Excel rejected both cases and repaired the file on open.
Only export a totals row when the table has a header and a column
actually shows a real label or total. Otherwise leave the row as
plain data, matching what Excel itself does when it repairs such a
file.
Signed-off-by: Samuel Mehrbrodt <samuel.mehrbrodt@collabora.com>
Change-Id: I6dc84680780805d8cfe666d681a62a9a907605d2
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/10367
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit cfb01061aec26a218dcd1e4b5cccad395d2a5489)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210453
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
The XLSX export wrote the label as a bare <font> element, so a checkbox
came back with the control default font at 10pt and adjacent labels
overlapped. The label's font name, size and colour, its bold, italic,
underline and strikeout, and its horizontal and vertical alignment are
now written out.
The underline stopped reaching the export altogether when the control
property list started asking for "FontLineStyle", which no control model
has: commit 3187193a61 (tools: rename
FontUnderline to FontLineStyle, 2016-01-29) renamed the VCL enum and
took the UNO property name string along. The same rename hit
sw/source/filter/html/htmlforw.cxx, which is not handled here and needs
a separate fix. A double underline also needs the "fontN" class on the
underline element, which the import compared with a literal "font4",
introduced with no explanation given in commit
04c272eb83 (dr77: #i114128# import legacy
drawing controls, 2010-08-26). N is the index into the workbook font
table, and is treated as one now.
Excel keeps the label font in the VML shape, in the DrawingML run
properties and in a workbook font record, and builds its model from the
DrawingML, while we read the VML and the record it names. Both are
written here so that the two applications show the same document. TODO:
read the label font from the DrawingML run properties, as Excel does.
Signed-off-by: Mike Kaganski <mike.kaganski@collabora.com>
Change-Id: I87259d25a68829f6c1a78179f8e3aa7811a5688f
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/9927
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
(cherry picked from commit ca86699205743f2709f3cd5d412a8a3f0d3fba38)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210334
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
OOXML leaves the @ of =@$I$112# out of the saved text and expresses it
by keeping the cell a plain non-array formula, while an @ over
anything wider keeps its _xlfn.SINGLE. The import didn't put it back,
so the cell showed the row-aligned value while its formula read
=$I$112#, the spelling for a spill.
The @ goes back the way the binary format import already does, and
only for that thinned shape: a non-master cell whose whole formula is
one reference with the operator after it, not even parentheses.
Anywhere wider, injecting an @ would force the operand into an array
and change the result, so (A1)# is left alone.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: Ib8071804eaa805880e20552eeee92665756c5cd7
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/10164
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit 273dbf42009efe6d9f59edf28a4272cfe366196f)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210314
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
OOXML writes @ and # as calls and a reference union as a parenthesised
list, so for each of them we need to know how far the sub-expression
under it reaches. CreateStringFromTokenArray worked that out from the
text it had already written. The problem with this is that every pair
it spliced in shifted all the offsets that were still waiting behind
it, so it kept breaking.
Instead of patching the text, OOXMLRewriter builds a second
token array in the shape OOXML spells out and the writer walks that as
it stands. The call names and the parentheses are ordinary tokens, so
there is nothing to splice and no offsets to keep track of. It is the
same trick RewriteMissing already plays a few lines further up, and it
means the input and the output can be looked at side by side.
The # changes place, from behind its operand to a call in front of it,
so it gets an opcode of its own. _xlfn.ANCHORARRAY spells ocAnchorArray
now, and ocSpill keeps the native postfix spelling with no OOXML one at
all, so the postfix form cannot end up in a file by accident. The
import already rewrote the call back into the postfix operator and now
recognises it by opcode instead of by position. The @ stays
ocSingleValue, it is already in front of its operand so only the
parentheses are new.
The OFFSET() literal argument is swapped for the reference error in
the same pass, instead of the writing loop jumping over tokens.
A unit test drives the rewrite on its own: token array in, token array
out, one case per shape. The shapes that end up with nothing to wrap
are in there too - a lone @, one with a missing argument, and text that
never parsed - since those are the ones where dropping a token is the
only change.
Also drop the dead "@" and "#" rows from the OOXML symbol table, the
rows above them already have _xlfn.SINGLE and _xlfn.ANCHORARRAY.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: I63944fb85b5c4388f304f7d94afd0b4f347d7782
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/10155
Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 4feac84950f5b524d99e277481de50f7b45a8d2f)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210292
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
We have added various workarounds for ScPatternAttr use after free
issues since:
commit 2e1f9da8a6
Date: Sat Dec 23 15:52:06 2023 +0100
Decouple ScPatternAttr from SfxItemPool
separated ScPatternAttr from SfxItemPool.
Prior to that an ScPatternAttr was an SfxPoolItem held in the doc's
SfxItemPool which kept every item alive for the document's whole
lifetime, so any raw const ScPatternAttr* was basically safe.
The various workarounds for the new behaviour were:
commit dca19993a4c732e95b9a47e1abdcaad6efbeebe9
Date: Sat Jan 6 14:40:28 2024 +0100
tdf#159042: crash after changing cell style (if direct formatting done)
commit 19437715eb415fe2c40b8b40dbe04ddca28f9a35
Date: Thu Sep 12 12:06:28 2024 +0100
null pattern deref seen in ScViewData::SetEditEngine
commit e384f2e8de9603ee65a3edc6dcb50b07116ee4fc
Date: Mon Mar 10 14:45:22 2025 +0000
crashtesting: crash on reimport of xlsx output of forum-pl-2758.ods
commit 7999585bd8378f1a8d04ea2a9a93a8e0bf4d8eb6
Date: Fri May 9 08:50:17 2025 +0100
crash on null pattern de-ref
commit 1bf9bbea96
Date: Tue Oct 28 16:53:49 2025 +0300
tdf#169115: sc: fix use-after-free bug in ScDocument::FillInfo
commit 9f366af81478ad218dc2ef2e37423a9ebcc84e73
Date: Sat Apr 25 14:47:02 2026 +0200
ScPatternAttr use-after-free
commit 20fe691a18fb35120d0765dd1519acd6d2986c38
Date: Tue Apr 28 08:33:34 2026 +0200
ScPatternAttr use-after-free (2)
This commit picks the class member fields that are still raw
ScPatternAttr* and converts them to CellAttributeHolder:
ScUsedAreaIterator::pPattern and pFoundPattern
ScInputHandler::pLastPattern
LotAttrCol::ENTRY::pPattAttr
ScPatternCache::Entry::pPattern
The CalcAll() workaround from 9f366af81478 then doesn't seem to be needed(?)
A new compiler plugin catches class member fields of raw type
ScPatternAttr pointer.
Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Change-Id: Ibb9f28b8fcaa5470c7a82eee52900c2d60434e41
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/3163
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Noel Grandin <noel.grandin@collabora.com>
(cherry picked from commit 9c7b6313a29067bf0eef12884fc3ce7efb0374e5)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/209822
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
The tableColumn "name" attribute is an ST_Xstring, so read it with
getXString (like uniqueName next to it) to decode escapes such as
_x000a_ — an Alt+Enter line break in the header. Read with getString it
kept the literal _x000a_, so a defined name referencing the column via a
structured reference (Table[Col]) no longer matched the real newline and
resolved to #NAME?, breaking a data validation list built on that name.
On export the OOXML serializer already escapes the newline ( ), so
the round-trip stays consistent.
Change-Id: I6c51e2259393fafc38f823fb40ce14d28673d8b1
Signed-off-by: Balazs Varga <balazs.varga@collabora.com>
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/9120
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Stephan Bergmann <stephan.bergmann@collabora.com>
(cherry picked from commit f7816a048112157dd603ba9a98dc4f9bf379db97)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/209428
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
...and are used on more than one sheet
Part of bt:
0 0x00007f2273ae44c0 in std::out_of_range::out_of_range(char const*) () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
1 0x00007f2273aaddb6 in std::__throw_out_of_range_fmt(char const*, ...) () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
2 0x00007f225147be88 in std::__sv_check (__size=1, __pos=2, __s=0x7f2250754f39 "basic_string_view::substr") at /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/string_view:75
3 0x00007f225147bdc1 in std::basic_string_view<char16_t, std::char_traits<char16_t> >::substr (this=0x7ffd3afc7078, __pos=2, __n=18446744073709551615)
at /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/string_view:340
4 0x00007f22520f4e5a in ScFormatRangeStyles::GetIndexOfStyleName (this=0x5618ec8485a0, rString=u"t", rPrefix=u"ce", bIsAutoStyle=@0x7ffd3afc72f7: true)
at /home/julien/lo/libreoffice/sc/source/filter/xml/XMLStylesExportHelper.cxx:709
5 0x00007f22521aa673 in ScXMLExport::AddStyleFromCells
(this=0x5618ec0dfc80, xProperties=uno::Reference to (ScCellRangesObj *) 0x5618ec7b5008, xTable=uno::Reference to (ScTableSheetObj *) 0x5618ec81a1d8, nTable=1, pOldName=0x0)
at /home/julien/lo/libreoffice/sc/source/filter/xml/xmlexprt.cxx:2128
6 0x00007f22521aea70 in ScXMLExport::collectAutoStyles (this=0x5618ec0dfc80) at /home/julien/lo/libreoffice/sc/source/filter/xml/xmlexprt.cxx:2560
7 0x00007f22521af8ca in ScXMLExport::ExportAutoStyles_ (this=0x5618ec0dfc80) at /home/julien/lo/libreoffice/sc/source/filter/xml/xmlexprt.cxx:2661
...
I noticed tdf#166939 which is similar and already fixed by Mike Kaganski with faab5ca617
"tdf#166939: Don't pass invalid starting index when creating a view
A style name can be as short as one character; a two-character prefix
can already be too long."
Since we're in a similar case (a one-character style name), let's apply the same way
but for ScFormatRangeStyles::GetIndexOfStyleName which has the extra parameter "bIsAutoStyle".
Change-Id: Ida411dec712bbf39620fd9c2919dc6b0cffe92ba
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/209406
Tested-by: Jenkins
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
nFirstTableCell in both ScHTMLTableStackEntry and ScHTMLLayoutParser has
been turned into size_t because this value was both being converted to
and being compared to elements of type size_t; nRowKey in
ScHTMLLayoutParser::TableOff has been turned into SCROW because this
variable was initialized using two elements of type SCROW
Change-Id: I21edccc663312de75f54b38e95ef4abe49254906
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200921
Tested-by: Jenkins
Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org>
...formulas" and "XLSX: Valid data-validations are not being
exported".
This reverts commits 6b40ebc9e67b165e85212d92c861fc6844d24f42
and c6bcd2f7c467b944765b363e9a900eaa6625ff6f.
Reason:
The original change was introduced to skip exporting certain
formula in data validation checks to XLSX that made the files
invalid for Excel.
But because now some good validations get omitted, and it turns
out Excel itself doesn't do better with the orignal files, either,
let's revert the changes.
Added unit test. (to subsequent_export_test4.cxx, the change in
subsequent_export_test2.cxx comes from the revert)
Change-Id: I89d552853f0119aa4bf3edbc3843edcf00f54a70
Signed-off-by: Aron Budea <aron.budea@collabora.com>
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/7876
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Reviewed-by: Karthik Godha <karthik.godha@collabora.com>
(cherry picked from commit 28b08b853a09b6f7e68bf05eed2f59ed9fcad071)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208754
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
ARRAYTOTEXT returns a cell range or array as one text string,
taking the range and an optional format number.
Format 0 (or omitted) joins the values in row order with ", ".
Format 1 gives an array constant: braces around the array, ","
between columns, ";" between rows, and text quoted with any
inner double quote doubled. Any other format returns #VALUE!.
A number keeps its input-line text, a boolean reads TRUE or
FALSE in the current locale, an empty cell adds nothing, and an
error in a range lists as its error text while a reference to a
single error cell returns that error.
The function is wired up with its name tables, wizard entry,
parameter classification, and OOXML and binary filter mappings.
A self-checking OOXML workbook is verified after import and
after an XLSX and an ODS round trip, each with a recalc, and the
exported files are checked for the ARRAYTOTEXT formula. A ucalc
test covers the locale-dependent boolean text for a value and
a range.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: I0cdd9737a51f402e39cf9a1346f4c5326680fe8f
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/7219
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
(cherry picked from commit f66673d65ee307f17512a4239dd4b52ac189ac20)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208395
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
the string read back from the binary xlsx has an unpaired surrogate,
so toUtf8 asserts when the export tries to convert it.
scrub the invalid utf8 in BiffHelper::readString,the same way the .xls
reader was fixed in:
commit b71a8f85dd1b99a8d879bcf5ddebd185a4354c85
Date: Thu Apr 23 10:28:05 2026 +0200
crashtesting: assert on exporting forum-mso-en4-531883.xls to xlsx
an issue since:
commit 5c841b381fe16634c51121b351c89154a25eb8d9
Date: Tue Mar 17 16:33:19 2026 +0530
XLSX: Truncate external sheet names if the length is > 31
Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Change-Id: I93d6c9a646f6560ee71a8fb13381aa4a161d5238
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/7336
Reviewed-by: Noel Grandin <noel.grandin@collabora.com>
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
(cherry picked from commit 41ede7585d58d0d95d035897f3d14de1bb0956ff)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208296
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
The XLSX f-element stores the spilled-range operator as the
prefix call _xlfn.ANCHORARRAY(<ref>). The compiler did not
know the wrapper, so _xlfn.ANCHORARRAY(C2) + 10 imported as a
name error.
Map _xlfn.ANCHORARRAY to ocSpill in the OOXML symbol table so
the wrapper compiles to the same RPN as <ref>#. A new
liftAnchorArrayToPostfix pass then rewrites the source-order
parse array to <ref># so the cell reads back as <ref># in the
formula bar.
Token-level tests cover the lift on a bare reference and an
arithmetic composition, and a file-import test loads an XLSX
fixture to confirm cells read back as # inside UNIQUE and SUM.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: I687150ac0bb26d02ced9297dc2039c15655d5c0a
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5788
Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
(cherry picked from commit 91e9a978c85458dc5a7c557588da1c402bc43887)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207906
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
The strip walked the array twice with the same parenthesis
depth. Start past the inner open with nDepth = 2 and watch
for depth dropping to 1. If the next token is the outer
close, the inner pair spans the whole argument and is
stripped. Otherwise the parentheses stay.
Expose the helper from formulabuffer.hxx so the new
sc_oox_helpers_test target can drive it directly.
RedundantParenthesesStripperTest covers the strip cases
through the OOXML compiler.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: I6ab95382b7776833b343754cdafb746454739d51
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5652
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
(cherry picked from commit 41557a39d420e45880070b6d942ebfbe32ef8b49)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207873
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
XLSX tags a cell holding =@(expr) with t="array" ref=<self>,
because the OOXML writer evaluates the @ in array context. The
import path honoured the tag and routed such cells through
setMatrixCells, so GetFormula wrapped the imported text in {}
braces. A user-typed =@(F3:F5+0) came back as {=@(F3:F5+0)},
reading as a CSE array even though @ keeps the cell scalar.
When the t="array" range is a single cell and the parse array
starts with @, construct a plain ScFormulaCell instead of
calling setMatrixCells. The @ collapses the operand, so there
is nothing to spill.
testIntersectionOperatorXlsxRoundTrip loads the fixture and
asserts the @-wrapped cells read back as plain formulas, both
on import and after a round trip.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: I05020fa2810a8f2d4f0c9374a9a8afc39e2d9e5e
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5536
Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
(cherry picked from commit 75eda52e374810561261485ed038e70d9e2edab1)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207869
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Add BYCOL(tdf#164508), BYROW(tdf#164509), MAKEARRAY(tdf#164511),
MAP(tdf#164512), REDUCE(tdf#164513), SCAN(tdf#161428) formula
functions, which are usually used together with LAMBDA and are
important for interoperability with other Office suites.
Change-Id: I7eb5a992a113638fdadf0cf61592c082094fb44f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205979
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
The OOXML spec writes =@(expr) as =_xlfn.SINGLE(expr). Calc
emitted the bare @ glyph on save and dropped the wrapper on
load, so =@(F3:F5+0) fell back to a non-array context after a
round trip and lost the authored value.
Map "_xlfn.SINGLE" to ocSingleValue in the OOXML symbol
table. The regular exporter walk now spells ocSingleValue as
"_xlfn.SINGLE" and the import compiler recognises the
wrapper, so a parenthesised operand round-trips with no
further work. A small exporter branch wraps bare and
function-call operands in the wrapper's own parentheses.
OOXML files in the wild put the @ operand inside a redundant
parenthesis pair, _xlfn.SINGLE((expr)). A post-compile pass
on import drops the inner pair so the cell reads back as
=@(expr). The helper takes a trigger-opcode list for reuse.
testSingleOperatorXlsxRoundTrip covers the export path,
testIntersectionOperatorXlsxRoundTrip covers the import strip
from a fixture file.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: I2648da125945295fd8548842aba9c82978d96aa9
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5573
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit 5ac9db1f563bbde01f9e24fc9bbb8c3599eb0c06)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207789
Tested-by: Jenkins
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
When the user types a formula that returns an array (UNIQUE,
TRANSPOSE, a range plus a range, ...) and presses Enter, the
cell now becomes a dynamic-array master. The array result
spills into the empty cells to the right and below the typed
cell. The user no longer has to press Ctrl+Shift+Enter to get
array behaviour.
Formulas loaded from a file and formulas created from a macro
keep their old single-value behaviour, so existing documents
are not affected.
A new per-cell bit, mbAutoDynamicArrayEligible, marks a cell
as allowed to promote. The view code sets it on freshly typed
formulas. The importers and the macro entry path leave it off.
When such a cell first calculates, the formula tokens are
walked in execution order to ask the question: does this
formula produce an array result? If yes, the cell switches to
dynamic-array master mode before the calculation runs, so the
array result is kept and the cells to the right and below get
filled in.
The walk tracks whether the value sitting on the stack at each
step is an array or a scalar:
- Pushing a multi-cell range or an inline matrix puts an
array on the stack.
- An operator like + or * keeps the result an array if any
operand was an array.
- A function known to return an array (UNIQUE, TRANSPOSE,
MMULT, SEQUENCE, ...) puts an array on the stack. Other
functions reduce to a scalar.
- Branching functions like IF, CHOOSE, IFERROR and LET do
not fit this simple model, so the walk gives up and the
cell stays a plain single-cell formula.
A formula that begins with the @ implicit-intersection
operator (=@UNIQUE(...)) opts out of promotion. Cells that
are part of a formula group share a single compiled formula
and stay single-cell so the group is not broken.
Ctrl+Shift+Enter still produces a classic static array master.
The shortcut now routes straight to the matrix-entry code, so
the auto-detect described above does not interfere.
The formula compiler has an optimization that rewrites a
multi-cell range as a single-cell pick when the formula sits
in a single-cell context. For example =A1:A4 typed in row 2
becomes =A2 before evaluation. That is the long-standing
implicit-intersection rule.
For typed input the optimization has to be off, otherwise the
multi-cell range disappears from the formula before the walk
can see it. The optimization stays in place everywhere else,
and the engine still applies implicit intersection at run
time when the cell remains a plain single-cell formula.
XLSX export
XLSX marks a dynamic-array master with cm="1" on the cell.
The exporter used to fall back to "matrix master plus a
dynamic-array function" when the explicit flag was missing.
The fallback is now removed. Every cell that should export as
dynamic carries the flag explicitly, set by the importer or
by the UI entry path.
One trade-off: a Ctrl+Shift+Enter (CSE) array of a dynamic-
array function imported from an XLSX file that has no cm="1"
marker no longer round-trips as dynamic. The cell flag is now
the single source of truth.
Tests
Tests cover the array-intent walk for =MINVERSE(...), ={1;2},
={1;2}+3, ={1;2}+{3;4}, ={1;2}+A1, =ABS({-1;-2}), =A1:A2,
=A2:A5+B2:B5, a long chain of binary additions over the same
range, a range times a scalar, =IF(...) with array branches,
and =SUM(...) over a range as the scalar case.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: Icb4b5e108634cd1529ac829cb34865c56ed8ec02
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/4684
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit c3d67d3ec81621c385744fac7fd7a722084a122f)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207219
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
XLSX marks a dynamic-array master with cm="1" on the cell and a
matching dynamicArrayProperties metadata block. Both import and
export now travel through mbDynamicArrayMaster on the cell.
XLSX import plumbs the flag through the three formula paths.
XML_normal and XML_shared land in applyCellFormulas and
applySharedFormulas through setCellFormula. XML_array lands in
applyArrayFormulas through setCellArrayFormula. Each path sets
mbDynamicArrayMaster on the imported cell or on the matrix master.
XLSX export reads the flag in XclExpFormulaCell::SaveXml to drive
cm="1" and the dynamicArrayProperties block. The legacy pair of a
Ctrl+Shift+Enter (CSE) master that calls a dynamic-array function
stays as a fallback while the importers and the UI entry path are
being wired through.
XLS has no @ encoding and no dynamic-array marker. Save and load
mirror the ODF behaviour:
- The exporter strips ocSingleValue (alongside ocSpaces and
ocWhitespace) in GetNextToken so the BIFF stream stays valid.
The saved formula evaluates to the upper-left value the way XLS
always did.
- The importer walks the just-built RPN of every plain non-array
formula and prepends @ when the formula intends an array. The
resolve runs before the formula cell is constructed, while the
parse array is still mutable. The static helper compiles a
missing RPN on demand so the array-intent walk has the post-fix
order it needs.
- XLS array records keep the legacy CSE behaviour. They have no
dynamic-array encoding, so loading them as static arrays matches
what the file format can express.
Tests cover an XLSX import of Spill.xlsx, an XLSX round trip of the
same file, a direct-XML XLSX export check that the spilled master
at C2 keeps cm="1" and the dynamicArrayProperties metadata block,
and an XLS round trip of =@TRANSPOSE(B1:B4) where the @ reappears
after reload.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: I30318bad4cdb50bbd92240fd71d70df0959a0eda
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/4664
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit 79eda1a177abf9a348dbc67c211b26cabd0cb4c1)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207218
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Steps to reproduce:
1. Create a calc document with a chart in Calc Online.
2. Open an empty calc document in LO desktop.
3. Copy the chart from Calc Online and paste it into the LO Desktop Calc
file ===> Chart is not pasted.
Details of the issues fixed:
1. <img ...> tag is self closing. Code in calc filter expected a closing
img tag. This is now fixed.
2. Add graphic loading logic for embedded images in html like:
<img src="data:image/png;base64,iVBOR.....">
Signed-off-by: Dennis Francis <dennis.francis@collabora.com>
Change-Id: Ib4aef64727da458b014b570f0e22e81bc869226c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/202268
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
(cherry picked from commit dfb400a2eb7574b474e2227dd3c911651543f153)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207719
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
A dxf holds only incremental formatting that is layered on top of an
object's existing format. So an absent border side is left as-is, while
an empty side element (e.g. <left/>) defaults to style="none" and clears
that border. Writing every side unconditionally made a headerRow that
only defines a bottom border also clear the left/right/top borders it
should inherit from the wholeTable element (based on ooxml standard).
(only visible after re-importing into Excel)
Change-Id: Idb703badb7649f7f91d57324295b39f68ec234c1
Signed-off-by: Balazs Varga <balazs.varga@collabora.com>
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5591
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit cc0181aec07f66847b9c5a06cd047d50abc5a70c)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207623
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
XclExpCellBorder only handled the outer box, so the inner vertical and
horizontal dxf lines (e.g. custom table style bands) were dropped on
export - the old "OOXTODO: XML_vertical, XML_horizontal" in SaveXml().
Read them from ATTR_BORDER_INNER and write them out, completing the
roundtrip for the import added in commit
b8a2b55c2c51ee4fe3d6ad29e059d879b645d0c6.
Change-Id: If829545a11529a5ae9a3b154c55aaf89b89bcc46
Signed-off-by: Balazs Varga <balazs.varga@collabora.com>
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5590
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit b2457d3ea6a8f2cfce4d515f40a45329b6dc4514)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207622
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>