Commit Graph
109 Commits
Author SHA1 Message Date
prxnvt b78afc9b3c Merge origin/main (25881a8e) into the Python cells branch
Conflicts: ROADMAP.md and docs/file-format-parity.md only (header lines combined, both sides' rows kept).
2026-11-02 01:29:06 -05:00
Brandon Thomas e361f922d5 Merge PR #3130
# Conflicts:
#	docs/file-format-parity.md
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-11-01 23:08:37 -05:00
Ingmar LübbeandClaude Opus 5.5 e2c523881f Page Layout: Page Setup's page order (Down, then over / Over, then down)
A sheet more than one page wide and tall always printed down, then
over. PrintSettings gains the page order (serde default Down, then
over), pageLayout.pageSetup takes pageOrder, and the pagination numbers
the pages in it, so printing, PDF export, the print preview, Page Break
Preview, Page Layout view and the &P/&N, first-page and odd/even
headers follow the printed sequence. XLSX reads <pageSetup pageOrder>
and writes pageOrder="overThenDown" only, as Excel does.

The Page Setup dialog gets a Page order choice with a small picture of
the order and runs pageLayout.pageSetup, so the order and the margins
are one undo step; the labels are translated where the dialog is, and
the dialog is now in German too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAgnkqJiy3v24Hp25dQLRj
2026-11-02 01:43:14 +01:00
campbellcodyandCodex b6c4500fa7 M7: add data tables beneath charts
Add command and UI controls for chart data tables, shared chart and PDF rendering, and native XLSX persistence. Cover live values, blanks, formatting, alignment, undo/redo, bounds and table flags with regression tests.

Co-Authored-By: Codex <noreply@openai.com>
2026-11-01 15:30:46 -05:00
prxnvt b3a3590db6 Merge main into Python cells as data 2026-11-01 14:03:09 -05:00
prxnvt ec7ee8d4ea Engine: a Python cell that keeps only its value keeps its whole cached result
When a file is opened, a Python cell falls back to keeping only its value in
four cases: its code is missing from the Python part or the part is damaged
(the xlsx reader), its code is too long for a cell, its kept result is
malformed, or its result is past the adoption budget. The first kept the
values the cell spilled as plain values; the others dropped them, so values
the file showed were lost. All of them now follow one rule, through
Sheet::settle_spill: the anchor and every spilled cell keep their cached
values as plain values, with no live spill range; a cell's own content and
format are never overwritten; and the work is bounded by the spilled values
stored, not by the range. The values move from the spill into the cells, so
nothing is copied. The cut-by-budget test is renamed for what it now checks,
the dropped-result test now expects the values kept, and the adoption warning
and the file-format docs say so.
2026-11-01 13:28:19 -05:00
Brandon Thomas e129c072a1 Merge PR #3075
# Conflicts:
#	crates/xlsx/src/read.rs
#	docs/file-format-parity.md
2026-11-01 12:20:06 -05:00
Brandon Thomas bc173ead8f Merge PR #3062
# Conflicts:
#	ROADMAP.md
#	docs/file-format-parity.md
2026-11-01 12:19:55 -05:00
Brandon Thomas 7f1574b573 Merge PR #3052
# Conflicts:
#	docs/file-format-parity.md
2026-11-01 12:19:55 -05:00
prxnvt c03c61fd05 Merge main into Python cells as data 2026-11-01 12:00:09 -05:00
scks1 60a267b4ef #3057: select visible workbook views and normalize tab ratios 2026-11-01 08:06:44 -05:00
Harrison SmithandClaude Opus 5.5 a1e0383056 #2871: unwrap Google Sheets' wrapper only when GridCraft calculates the formula
A formula calling a Google-only function (GOOGLETRANSLATE, QUERY,
ARRAYFORMULA...) opened as #NAME? where the wrapper had shown the cached
value, as Excel does. The XLSX reader now unwraps a cell formula only when
every function inside is known: read_xlsx_with takes the predicate (the
xlsx crate can't depend on the function library) and the engine passes
gridcraft_calc::is_known_function. Unwrapping stays in the reader so shared
formulas are shifted from the unwrapped master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 00:08:40 -06:00
Harrison SmithandClaude Opus 5.5 2c0a00fbae #2871: open Google Sheets' DUMMYFUNCTION export wrapper as the original formula
Google Sheets' XLSX export writes a formula that uses a function it thinks
Excel lacks as IFERROR(__xludf.DUMMYFUNCTION("<formula, quotes doubled>"),
<cached value>). GridCraft showed the wrapper as the formula.

fmla::from_file, which every cell formula read goes through (plain, shared
master and t="array"), now recognises exactly that shape: IFERROR (with or
without _xlfn.) of a single-string __xludf.DUMMYFUNCTION call, any case.
If the string parses, the formula inside replaces the wrapper, as the whole
formula or nested in a larger one (parenthesised unless it is a single
operand). The cell keeps the file's cached value.

Bounded on hostile input: inner text over MAX_FORMULA_LEN is not parsed,
only one level is unwrapped, and a result that no longer parses (nesting
past the parser's limit) keeps the file's formula. Text that doesn't parse
keeps the wrapper.

Saving writes the real formula with Excel's _xlfn. prefixes, as Excel does
with the _xlfn functions it knows. Keeping cached results for functions
GridCraft can't calculate is #2770 and not part of this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 19:19:20 -06:00
Max Murphy 72b1310a5a #2765: CSV and text open detect each column's date order 2026-10-31 16:57:58 +01:00
aiongg 5f7137ca01 docs: tidy agent, contributor and asset docs 2026-10-31 04:17:38 +00:00
Harrison Booth 9587f08253 Merge upstream main into gc-xls-cell-styles 2026-10-30 15:31:49 -05:00
Harrison Booth 9515c29969 CSV export: file.exportCsv values:true writes raw values for automation (#2648)
The default stays Excel's displayed text, byte for byte.
2026-10-26 12:34:18 -05:00
prxnvt 1d7206ebdd Docs: Python cells as data (architecture, file formats, functions, roadmap)
architecture.md gains a Python cells section: the model type, the text
forms and the size limit, the xlsx Python part, calc laying out kept
results as graph nodes, and the limits on open. file-format-parity.md
gains a Python cells table (xlsx as [MS-XLSX] 2.3.10 specifies, the
formula naming its code in the Python part, with cached values and
spills; other formats; GridCraft JSON; the limits on open; and
rich-value object results as not kept). function-parity.md marks the
four Python errors done with their ERROR.TYPE numbers and adds a Python
in cells row (stored, not run). ROADMAP.md records the progress. The
return types are written as "0 or 1" so no table cell holds an
unescaped pipe. architecture.md's "Last updated" label loses the space
inside its bold markers.
2026-10-26 10:18:38 -04:00
Harrison Booth 2c052d03d5 Read cell formatting from .xls files
.xls (Excel 97-2003) import used only each cell's number format. It now
also reads the BIFF8 formatting records (Font, XF, Palette and Style),
so opened sheets keep their fonts, solid and pattern fills, borders
(including diagonals), alignment (rotation, indent, wrap, shrink),
locked and hidden protection, the workbook's custom colour palette, its
Normal font as the default, and its user-defined cell styles.

The decoding lives in a new xls/styles.rs; xls/mod.rs gains the record
arms and the build call. Short or malformed formatting records keep the
fields present and add one warning instead of refusing the workbook.
Tests build the records in code, including truncation and byte mutation.

Also merges origin/main, keeping its dialog-sheet, WINDOW2 and XF
number-format handling; the XF arm now goes through the new styles
module, which covers the number format too.
2026-10-23 16:32:15 -05:00
aiongg d5cdd2ea2b Integration: track t15
# Conflicts:
#	contributors/people.toml
#	crates/engine/src/tests.rs
#	docs/file-format-parity.md
#	docs/localization-parity.md
2026-10-22 03:05:39 +00:00
aiongg 561382cc6d Integration: track t14
# Conflicts:
#	ROADMAP.md
#	contributors/people.toml
#	crates/formula/src/tests.rs
#	docs/file-format-parity.md
#	docs/localization-parity.md
#	docs/ui-parity.md
2026-10-22 03:05:30 +00:00
aiongg ca1cdd4229 Integration: track t13
# Conflicts:
#	ROADMAP.md
#	contributors/people.toml
#	crates/engine/src/cmd/data.rs
#	crates/xlsx/src/tests/mod.rs
#	docs/chart-parity.md
#	docs/file-format-parity.md
#	docs/function-parity.md
#	docs/gaps.md
#	docs/localization-parity.md
#	docs/target-app-parity.md
2026-10-22 03:05:18 +00:00
aiongg 6dda6be2c6 Integration: track t09
# Conflicts:
#	crates/engine/src/tests.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/pt.rs
#	docs/file-format-parity.md
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-22 03:04:21 +00:00
aiongg d3201e7cea Integration: track t08
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/tests.rs
#	docs/file-format-parity.md
#	docs/localization-parity.md
2026-10-22 03:03:55 +00:00
aiongg b0b6409112 Integration: track t03
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/tests/keyboard_shortcuts.rs
#	docs/file-format-parity.md
#	docs/localization-parity.md
#	docs/ui-parity.md
2026-10-22 03:00:13 +00:00
aiongg 857bdae023 Merge PR #1692: XLSX: keep Japanese phonetic runs on open and save
Conflicts:
- crates/model/src/lib.rs, crates/xlsx/src/read.rs, crates/xlsx/src/write.rs: use lists unioned (ShowObjects and the phonetic types)
- docs/file-format-parity.md: main's header and rows kept (#1692 collapsed the three duplicate .xlsx rows; they stay), phonetic-runs text added to each; Last updated 2026-10-20
2026-10-22 02:36:58 +00:00
aiongg 6370fd2254 Merge PR #1693: Charts: series that refer to defined names ([0]!Name) plot their data, and are saved qualified
crates/xlsx/src/tests/mod.rs: kept both mod lines (cellmetadata, chart_book_names)
docs/file-format-parity.md: kept HEAD header line, both change rows
2026-10-22 02:36:34 +00:00
aiongg d97f61748e Merge PR #1946: XLSX: keep cell fonts' charset (Arabic 178) and family on save
crates/xlsx/src/styles.rs: family/charset block ported into the dxf.is_none() branch of font_xml (PR #1225 made it take Option<&DxfStated>)
docs/file-format-parity.md: header Change line keeps both sides' clauses
2026-10-22 02:36:23 +00:00
aiongg 7fd1553a8b Merge PR #1626: Keyboard: Ctrl+6 hides and shows objects, saved as workbookPr showObjects
Conflicts:
- docs/file-format-parity.md: header and the three .xlsx rows keep main's text plus the show-objects entry; both log rows kept
- docs/ui-parity.md: header keeps main's text plus Ctrl+6; both log rows kept
2026-10-22 02:36:15 +00:00
aiongg 7221e11f56 Merge PR #1945: XLSX: keep the theme's per-script fonts (<a:font script="Arab">) on save (stacked on #1740, included)
Conflicts:
- docs/file-format-parity.md: kept main's three .xlsx rows (the PR's docs hunk replaced them with one) and added the theme-font wording to each; header keeps main's change list plus this PR's phrase (updated 2026-10-20)
2026-10-22 02:36:12 +00:00
aiongg d67193f403 Merge PR #1685: #1447: a PivotChart's link names the workbook
docs/file-format-parity.md: header Change line names both pivot fixes; both change log rows kept
2026-10-22 02:36:11 +00:00
aiongg c03d4a881b Merge PR #1570: XLSX: keep dynamic-array cell metadata (cm) on save
ROADMAP.md: kept both progress-log rows
2026-10-22 02:36:04 +00:00
aiongg 44320b393e Merge PR #1648: fix(xlsx): bound repeated column expansion
Conflicts:
- docs/file-format-parity.md: kept main's header and log rows, added this PR's change phrase and row once
2026-10-22 02:35:42 +00:00
aiongg 0118413c77 Merge PR #2080: HTML export: place pictures and charts at their anchors
crates/engine/src/tests.rs: kept both sides' new tests (journal tests from #1230, HTML export tests from the PR).
docs/file-format-parity.md: header Last updated 2026-10-21 with both change clauses; both revision-history rows, newest first.
2026-10-22 02:35:32 +00:00
aiongg 0e298839aa Merge PR #1292: Preserve hyperlinks in PDF export and support PDF in CLI convert
docs/file-format-parity.md: status line combined, change-log rows both kept
2026-10-22 02:35:28 +00:00
aiongg faef39cccc Merge PR #1600: XLSX: keep header and footer pictures on save
Conflicts:
- docs/file-format-parity.md: kept main's header and log rows, added this PR's change phrase and row once
2026-10-22 02:35:26 +00:00
aiongg 013f60a8b6 Merge PR #1514: Fix scalar INDEX/MATCH XLSX export
Conflicts:
- docs/file-format-parity.md: kept main's header and log rows, added this PR's change phrase and row once
2026-10-22 02:34:59 +00:00
aiongg 02640d6626 Merge PR #1495: XLSX: preserve carriage returns in saved text
Conflicts:
- crates/xlsx/src/xml.rs: kept both appended tests (surrogate pairs, carriage returns)
- docs/file-format-parity.md: kept main's header and log rows, added this PR's change phrase and row once
2026-10-22 02:34:51 +00:00
aiongg 02e1828c65 Merge PR #995: XLSX export: a picture shared by several sheets is one media part
Conflicts:
- crates/xlsx/src/tests/mod.rs: both mod lines kept
- docs/file-format-parity.md: header keeps main's change list plus the #985 entry
2026-10-22 02:34:51 +00:00
midasdf e42ebf9311 XLSX: keep a phoneticPr that has no rPh runs, and document the limits
si_body returned as soon as no valid run was written, so a shared string with a
<phoneticPr> and no <rPh> — a shape §18.4.8 allows — lost its properties on
save even though the reader keeps them. The runs and the properties are now
written independently: valid runs as before, then the valid <phoneticPr> when
the workbook has one; with neither, the <si> is exactly the plain t_el output.
property_only_shared_string_survives_open_and_save covers read, save and
reopen, and the si_body damaged-data test now expects the property-only output.

The write-time checks the reader also runs (sb/eb clamped into the UTF-16
length, empty readings skipped, type/alignment filtered through the shared
PHONETIC_KINDS/PHONETIC_ALIGNMENTS) were already in the head; the tests above
pin them, so no further change there.

Docs: the .xlsx row and the revision history now state that the shared string
table holds each text once, so duplicate <si> items with the same text but
different readings keep only the first reading (reported as a warning on open),
and that a <phoneticPr> without runs is kept. Both parity docs' "Last updated"
headers match their 2026-10-20 revision rows; the earlier rows keep their dates.
2026-10-21 22:35:13 +09:00
Gert Pellin a35d241caf XLSX: a note keeps its box's place and size through open and save (#1608)
The reader took only <x:Visible/> from a note's VML shape and vml_xml
wrote every note with a fixed anchor (two columns right of the cell,
four rows tall) and a 108 x 59.25 pt style, so a plain open and save
moved and resized every note box Excel had stored.

Comment gets an optional NoteBox: the <x:Anchor> corners relative to the
note's cell (so the box follows the note when rows or columns move) and
the shape's width and height. The writer puts it back, clamped to the
sheet; notes made here, and boxes equal to the default, keep the
default box.
2026-10-21 09:20:06 +02:00
Eduardo GarciaandClaude Sonnet 5.5 41cb19fd6d Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> 2026-10-20 18:39:49 -03:00
Eduardo GarciaandClaude Sonnet 5.5 eb30ab8f3f Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> 2026-10-20 18:39:49 -03:00
Mirza Bilal feac1679a1 HTML export: place pictures and charts at their anchors
Save as Web Page wrote only the cell table, so pictures and charts on a sheet
were dropped. A sheet that has either now keeps its own geometry and draws them:

- The table gets the sheet's column widths and row heights (`table-layout:fixed`,
  a `<colgroup>`, a height per row); hidden columns and rows take no room and
  merged-cell spans count only visible lines.
- A picture is an `<img>` with a `data:` URI, a chart is inline SVG built from
  the chart crate's drawing primitives (titles, axes, legends and data labels
  included), each absolutely positioned at its anchor cell plus offset.
- Sheets without pictures or charts write byte-identical HTML.

Adds contributors/people.toml entry for bilalmughal.
2026-10-21 01:35:58 +05:00
Mouhand-Kaddo 189eb7ae52 M12.AR14: keep the theme's per-script typefaces (<a:font script="Arab">) on save 2026-10-20 09:21:42 +04:00
midasdf 40803e6aca XLSX: keep Japanese phonetic runs (ふりがな) on open and save
xl/sharedStrings.xml can carry phonetic runs (<rPh sb="0" eb="2"><t>ふりがな</t></rPh>)
and a <phoneticPr> beside a string item. GridCraft read only the text and wrote every
string back as <si><t>…</t></si>, so a plain open + save deleted a Japanese workbook's
furigana.

Both are now read — offsets validated against the base text, runs with bad or missing
offsets, sb >= eb or no reading dropped with a warning, and never used to index — and
kept on the workbook as Workbook::phonetics, one entry per string text. The writer
emits them next to the <si> of the same text. The saved table holds each text once, so
two identical texts cannot keep two different readings: the reader keeps the first and
warns. Strings without phonetic data are written byte for byte as before.

Behaviour reference: ISO/IEC 29500-1 §18.4.6 rPh and §18.4.7 phoneticPr (Microsoft
Learn PhoneticRun/PhoneticProperties). Tests: crates/xlsx/src/tests/phonetic_tests.rs
(round trip, plain string, hostile offsets, shared text, unused data, comments and
inline strings). Docs: file-format-parity.md, localization-parity.md.
2026-10-20 13:39:48 +09:00
midasdf 2c6ffe489c XLSX theme: keep the major/minor ea and cs typefaces through open + save
A theme's <a:fontScheme> carries latin, ea (East Asian) and cs (complex
script) typefaces for each of the major and minor fonts. The model held
only the latin ones and the writer emitted <a:ea typeface=""/> and
<a:cs typeface=""/> unconditionally, so a Japanese workbook's theme fonts
(e.g. 游ゴシック, MS Pゴシック) were silently deleted on open + save.

Theme gains major_font_ea, minor_font_ea, major_font_cs and
minor_font_cs (#[serde(default)], so older GridCraft JSON still loads;
empty means the file did not set one). The XLSX reader and writer
round-trip them escaped, and a theme without them writes exactly the
empty attributes it wrote before.

Rendering and font resolution are unchanged: the UI does not consume ea
yet, and wiring it in is a follow-up.
2026-10-20 13:35:52 +09:00
Eduardo GarciaandClaude Sonnet 5.5 0ca1554642 docs: sheet-name quoting rows in function and file-format parity (#1458)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 17:36:47 -03:00
Mouhand-Kaddo 24b0b5d167 M12.AR15: keep cell fonts' charset and family on save 2026-10-19 21:18:06 +04:00
Mouhand-Kaddo 4faca49836 M12.AR13: read Windows-1256 Arabic CSV and text files as Arabic 2026-10-19 21:18:05 +04:00