From cc67055cccb3e56dfc737e52dc263b8b03ab2a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 9 Oct 2026 03:43:29 -0400 Subject: [PATCH] ElyTable: a filtered range keeps its rows only for a cell inside it (R2.9) --- agents.md | 2 +- crates/ely-lok/src/client/tests/filter.rs | 60 +++++++++++++++++-- ...0-lok-calc-autofilter-keeps-its-rows.patch | 11 ++-- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/agents.md b/agents.md index 58b4124..cf59679 100644 --- a/agents.md +++ b/agents.md @@ -263,5 +263,5 @@ cargo run -p ely-doc 启动一个应用(ElyDoc 先 cargo build -p ely - 2026-10-09(用户定:“打开方式”里不得出现 LibreOffice):系统会登记磁盘上能找到的 .app、挂载镜像里的 .app 与运行过的包,构建目录里的 `LibreOffice.app` 与测试挂载的官方镜像曾因此成为 xlsx 等的默认程序。现构建后由 `scripts/inert-lo.sh` 去掉其全部文件与 URL 声明、快速查看与聚焦插件,注销它,并在 `engines/` 放 `.metadata_never_index`;Ely 只取其 Frameworks 与 Resources。任何脚本与测试都不挂载 LibreOffice 镜像:LOK 探测用本构建的内核,单测所需的官方内核由 `scripts/extract-official-lo.sh` 以 7zz 解成无包的文件夹。`tests/scripts/lo-unregistered.sh` 以 NSWorkspace 核对 docx、xlsx、pptx、odt、csv 的“打开方式”里没有 LibreOffice。 - 2026-10-09(用户报:ElyTable 点格跳到别处、拖不出选区):Calc 在 `sc_print_twips_msgs` 下以打印 twips(行高原值)报光标、选区与 `.uno:SheetGeometryData`,图块与鼠标却在图块 twips(每行按 `ScViewData::ToPixel` 截成整像素),两者随行号漂移(5000 行处约 140 行)。视图对外一律打印 twips;`LokView::set_geometry` 收下工作表几何后,`sheet::Axis::tile`、`print` 照内核的截断换算(每像素 twips 取图块的像素与 twips 之比),绘制、显示、跳转与冻结都先换成图块 twips,鼠标以图块 twips 发出(`tile_point`),拖动句柄仍为打印 twips;`.uno:` 读回与应用(表头、填充柄)照旧用打印 twips,表头的起点取 `LokView::scrolled_start`。内核读鼠标用的比例原取最后一块图块,worker 现于每次 `setClientVisibleArea` 前以 `setClientZoom` 告知图块比例,点击不再依赖先画过图块。 - 2026-10-09(用户报:ElyPDF 改字报“这种字体画不出 V”):文档自带的子集字体常无可用的 Unicode 表(LibreOffice 导出的子集表为占位,0x00 起逐一对应字形号),按 Unicode 找字形一律失败。现以“文档自带字体”写字时直接用页面上的那个字体对象(`shim/ely_pen.c`;`pdf_load_font` 按对象缓存,与文字层的字体同一对象),以它自己的编码写:按文字提取的读法(ToUnicode,缺项或坏值退回 cid_to_ucs,同 pdf-op-run.c)倒出 Unicode 到编码的表,排版取它的宽度(`pdf_lookup_hmtx`),原有的 ToUnicode 与宽度不动,两个字共用一个字形时各写各的编码(原先按字形号写、重建 ToUnicode,共用字形的字被改写,且 CMap 漏写条目数,PDFKit 读不出字)。删去原文字块后页面资源里可能已无该字体,故按对象号以新名字重新引用。只支持编码即 CID 的字体(简单字体与 Identity-H),其余拒绝并说明;页面上没有的字仍报缺字。排版按同一套宽度量出的框,比较时留 0.01 点的余量(原块宽度即这些宽度之和,浮点误差曾使末字折行)。 -- 2026-10-09:ElyTable 的自动筛选(R2.9)。内核会重新推算未命名的自动筛选区:每次打开筛选列表时向下扩到紧邻的数据行(`ExtendDataArea`、`ExtendBackColorArea`,为接上后来追加的行),命令从单格找到它时按连续数据区重算(`ScDocShell::GetDBData`:应用条件、关闭筛选及其撤销);选区下方紧邻的合计行因此进了列表、随数据一起被隐藏,存后重开的筛选区同样会扩。补丁 `0040-lok-calc-autofilter-keeps-its-rows.patch`:LOK 下已有的自动筛选区保持设定时的行(同 Excel),不再隐式扩展;单格开筛选时仍取整个数据区。代价:紧贴在筛选区下方追加的行不自动并入,需重新选定后再开筛选。 +- 2026-10-09:ElyTable 的自动筛选(R2.9)。内核会重新推算未命名的自动筛选区:每次打开筛选列表时向下扩到紧邻的数据行(`ExtendDataArea`、`ExtendBackColorArea`,为接上后来追加的行),命令从单格找到它时按连续数据区重算(`ScDocShell::GetDBData`:应用条件、关闭筛选及其撤销);选区下方紧邻的合计行因此进了列表、随数据一起被隐藏,存后重开的筛选区同样会扩。补丁 `0040-lok-calc-autofilter-keeps-its-rows.patch`:LOK 下已有的自动筛选区保持设定时的行(同 Excel),不再隐式扩展(光标在区内时;光标在同表另一块数据里即按那一块);单格开筛选时仍取整个数据区。代价:紧贴在筛选区下方追加的行不自动并入,需重新选定后再开筛选。 - 2026-10-09:ElyTree 的差异按文件类型着色(R2.12)。组件库 7f2ac3e:`DiffViewer` 按路径的扩展名判定散文与纯文本(md、markdown、txt、rst、adoc、org、csv、tsv、log 等,无扩展名同),这些文件不按代码着色(原先一律套通用的代码词法,Markdown 的 `#`、引号等被当作代码上色)。同批带入上游的块编辑器跨块选择、浮层滚轮、输入法候选框位置、插入点按设备像素对齐与格式修正。 diff --git a/crates/ely-lok/src/client/tests/filter.rs b/crates/ely-lok/src/client/tests/filter.rs index 353163e..7280e5f 100644 --- a/crates/ely-lok/src/client/tests/filter.rs +++ b/crates/ely-lok/src/client/tests/filter.rs @@ -18,6 +18,33 @@ const BLOCK: &str = r#" "#; +/// Two blocks: A1:A5 as in `BLOCK`, and D1:D3. +const TWO: &str = r#" + + + NameOther + 19 + 210 + 3 + 6 + +"#; + +/// The book saved as flat XML. +fn saved(worker: &mut Worker, doc: &Doc, dir: &std::path::Path) -> String { + let out = dir.join("kept.fods"); + doc.save_as(worker, &crate::file_url(&out), "fods").expect("saves"); + std::fs::read_to_string(&out).expect("the saved book") +} + +/// Whether the row holding `value` is hidden by a filter. +fn hidden(xml: &str, value: &str) -> bool { + let before = &xml[..xml.find(&format!("office:value=\"{value}\"")).expect("the value")]; + before[before.rfind(" Vec { let query = sheet::cell_query(sheet::FILTER, 0, 0); @@ -38,13 +65,9 @@ fn keep_one(worker: &mut Worker, doc: &Doc, dir: &std::path::Path) -> (String, b worker.run(doc, "cell.goto", &["A1"]).expect("A1"); let one = r#"{"column":0,"conditions":[{"op":"values","values":["1"]}]}"#; worker.run(doc, "data.filter", &[one]).expect("keeps 1"); - let out = dir.join("kept.fods"); - doc.save_as(worker, &crate::file_url(&out), "fods").expect("saves"); - let xml = std::fs::read_to_string(&out).expect("the saved book"); + let xml = saved(worker, doc, dir); let range = xml.split("table:target-range-address=\"").nth(1).expect("a filter range"); - let total = &xml[..xml.find("office:value=\"6\"").expect("the total")]; - let row = &total[total.rfind(" = sheet::filter_values(&json).expect("parses").entries.into_iter().map(|e| e.text).collect(); + assert_eq!(entries, ["9", "10"], "an AutoFilter from D1 is D's"); +} diff --git a/patches/libreoffice/0040-lok-calc-autofilter-keeps-its-rows.patch b/patches/libreoffice/0040-lok-calc-autofilter-keeps-its-rows.patch index b6b87ee..3bfc0e8 100644 --- a/patches/libreoffice/0040-lok-calc-autofilter-keeps-its-rows.patch +++ b/patches/libreoffice/0040-lok-calc-autofilter-keeps-its-rows.patch @@ -7,8 +7,8 @@ appended rows join) and whenever a command finds it from a single cell its undo). A totals row right under a marked block joined the filter, showed in its list and hid with the data; a saved range reopened grew the same way. Under LOK the range keeps the rows it was set on, as in -Excel. A single cell still takes the data area when the filter is set. - +Excel, while the cursor is inside it; a cell in another block finds +that block. A single cell still takes the data area when the filter is set. diff --git a/sc/source/core/tool/dbdata.cxx b/sc/source/core/tool/dbdata.cxx index b1d714c55..9a01847ee 100644 --- a/sc/source/core/tool/dbdata.cxx @@ -41,7 +41,7 @@ index b1d714c55..9a01847ee 100644 SCCOL nOldCol1 = nStartCol, nOldCol2 = nEndCol; SCROW nOldEndRow = nEndRow; diff --git a/sc/source/ui/docshell/docsh5.cxx b/sc/source/ui/docshell/docsh5.cxx -index d154597c3..54a2344af 100644 +index d154597c3..5099dbe6f 100644 --- a/sc/source/ui/docshell/docsh5.cxx +++ b/sc/source/ui/docshell/docsh5.cxx @@ -19,6 +19,7 @@ @@ -52,13 +52,14 @@ index d154597c3..54a2344af 100644 #include -@@ -147,7 +148,9 @@ ScDBData* ScDocShell::GetDBData( const ScRange& rMarked, ScGetDBMode eMode, ScGe +@@ -147,7 +148,10 @@ ScDBData* ScDocShell::GetDBData( const ScRange& rMarked, ScGetDBMode eMode, ScGe if (!bSelected) { bUseThis = true; - if ( bIsNoName && (eMode == SC_DB_MAKE || eMode == SC_DB_AUTOFILTER) ) + // LOK: an AutoFilter range keeps its rows, as in Excel. -+ const bool bKeep = comphelper::LibreOfficeKit::isActive() && pData->HasAutoFilter(); ++ const bool bKeep = comphelper::LibreOfficeKit::isActive() && pData->HasAutoFilter() ++ && nCol >= nOldCol1 && nCol <= nOldCol2 && nRow >= nOldRow1 && nRow <= nOldRow2; + if ( bIsNoName && !bKeep && (eMode == SC_DB_MAKE || eMode == SC_DB_AUTOFILTER) ) { // If nothing marked or only one row marked, adapt