ElyTable: an AutoFilter on marked rows keeps the total below out (R2.9)

This commit is contained in:
ZacharyZhang-NY committed 2026-10-09 02:53:55 -04:00
1 parent 69b299f2db
commit d4c5f90c87
4 files changed
+159

No files matched your search

+1
View File
@@ -263,3 +263,4 @@ 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 找字形一律失败。现以“文档自带字体”写字时,从该页字体资源里找到同一字体(`pdf_load_font` 按对象缓存,与文字层的字体同一对象),按文字提取的读法(ToUnicode 或 cid_to_ucs、`pdf_font_cid_to_gid`)倒出 Unicode 到字形号的表,写字只用页面上已有的字形;新字体的 `/ToUnicode` 以这张表重写(MuPDF 按子集的占位表生成的那份会把新字读成乱码)。页面上没有的字仍报缺字。
- 2026-10-09:ElyTable 的自动筛选(R2.9)。内核每次打开筛选列表都把未命名的筛选区向下扩到紧邻的数据行(为接上后来追加的行),分不出选区时就在下方的合计行,合计因此进了列表、随数据一起被隐藏。补丁 `0040-lok-calc-autofilter-keeps-a-marked-block.patch`:LOK 下对跨行的选区开自动筛选时,筛选区记下“选定的行”(不存入文件),此后不再扩展;单格开筛选照旧取整个数据区。已知限制:存后重开的文件不带此记号,其筛选区照内核原样扩展。
+1
View File
@@ -6,6 +6,7 @@ mod analysis;
mod charts;
mod check;
mod commands;
mod filter;
mod format;
mod formula;
mod handouts;
+47
View File
@@ -0,0 +1,47 @@
//! An AutoFilter keeps to the marked block (TABLE-08).
use super::sheet::open_book;
use super::*;
use crate::sheet;
/// A header, three numbers and their total right under them.
const BLOCK: &str = r#"<?xml version="1.0" encoding="UTF-8"?>
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
<office:body><office:spreadsheet><table:table table:name="S">
<table:table-row><table:table-cell><text:p>Name</text:p></table:table-cell></table:table-row>
<table:table-row><table:table-cell office:value-type="float" office:value="1"><text:p>1</text:p></table:table-cell></table:table-row>
<table:table-row><table:table-cell office:value-type="float" office:value="2"><text:p>2</text:p></table:table-cell></table:table-row>
<table:table-row><table:table-cell office:value-type="float" office:value="3"><text:p>3</text:p></table:table-cell></table:table-row>
<table:table-row><table:table-cell office:value-type="float" office:value="6"><text:p>6</text:p></table:table-cell></table:table-row>
</table:table></office:spreadsheet></office:body>
</office:document>"#;
/// The filter entries after an AutoFilter on `marked`.
fn entries_after(marked: &str) -> Vec<String> {
let (_dir, mut worker, doc) = open_book(BLOCK);
worker.run(&doc, "cell.goto", &[marked]).expect("marks the cells");
worker.run(&doc, "data.autofilter", &[]).expect("filters");
let query = sheet::cell_query(sheet::FILTER, 0, 0);
let json = worker.values(&doc, &query).expect("the entries");
sheet::filter_values(&json).expect("parses").entries.into_iter().map(|e| e.text).collect()
}
#[test]
fn an_autofilter_on_a_marked_block_leaves_the_row_below_out() {
if install().is_none() {
eprintln!("SKIP: no pinned LOK build");
return;
}
assert_eq!(entries_after("A1:A4"), ["1", "2", "3"], "the total below stays out");
}
#[test]
fn an_autofilter_on_one_cell_takes_the_data_area() {
if install().is_none() {
eprintln!("SKIP: no pinned LOK build");
return;
}
assert_eq!(entries_after("A1"), ["1", "2", "3", "6"], "the whole column of data");
}
@@ -0,0 +1,110 @@
LOK Calc: an AutoFilter on marked rows keeps to those rows
Each time the filter list opens, GetFilterEntries grows an unnamed
filter range to the data rows right under it (ExtendDataArea and
ExtendBackColorArea), so appended rows join. It cannot tell them from
a totals row that was there when the user marked the block: the
total joined the filter, showed in its list and hid with the data.
Under LOK, an AutoFilter set on a marked block that spans rows keeps
that block: ScDBData remembers it (not saved) and never extends.
diff --git a/sc/inc/dbdata.hxx b/sc/inc/dbdata.hxx
index 6d80216b4..54515b138 100644
--- a/sc/inc/dbdata.hxx
+++ b/sc/inc/dbdata.hxx
@@ -119,6 +119,7 @@ private:
sal_uInt16 nIndex; ///< unique index formulas
bool bAutoFilter; ///< AutoFilter? (not saved)
+ bool bMarkedRows; ///< rows were marked; never extend (not saved)
bool bModified; ///< is set/cleared for/by(?) UpdateReference
::std::vector< OUString > maTableColumnNames; ///< names of table columns
@@ -244,6 +245,9 @@ public:
bool HasAutoFilter() const { return bAutoFilter; }
void SetAutoFilter(bool bSet) { bAutoFilter = bSet; }
+ bool HasMarkedRows() const { return bMarkedRows; }
+ void SetMarkedRows(bool bSet) { bMarkedRows = bSet; }
+
bool IsModified() const { return bModified; }
void SetModified(bool bMod) { bModified = bMod; }
diff --git a/sc/source/core/tool/dbdata.cxx b/sc/source/core/tool/dbdata.cxx
index b1d714c55..e7c5a16c1 100644
--- a/sc/source/core/tool/dbdata.cxx
+++ b/sc/source/core/tool/dbdata.cxx
@@ -75,6 +75,7 @@ ScDBData::ScDBData( const OUString& rName,
bDBSelection(false),
nIndex (0),
bAutoFilter (false),
+ bMarkedRows (false),
bModified (false),
mbTableColumnNamesDirty(true),
nFilteredRowCount(SCSIZE_MAX)
@@ -110,6 +111,7 @@ ScDBData::ScDBData( const ScDBData& rData ) :
bDBSelection (rData.bDBSelection),
nIndex (rData.nIndex),
bAutoFilter (rData.bAutoFilter),
+ bMarkedRows (rData.bMarkedRows),
bModified (rData.bModified),
maTableColumnNames (rData.maTableColumnNames),
maTableColumnAttributes(rData.maTableColumnAttributes),
@@ -146,6 +148,7 @@ ScDBData::ScDBData( const OUString& rName, const ScDBData& rData ) :
bDBSelection (rData.bDBSelection),
nIndex (rData.nIndex),
bAutoFilter (rData.bAutoFilter),
+ bMarkedRows (rData.bMarkedRows),
bModified (rData.bModified),
maTableColumnNames (rData.maTableColumnNames),
maTableColumnAttributes(rData.maTableColumnAttributes),
@@ -192,6 +195,7 @@ ScDBData& ScDBData::operator= (const ScDBData& rData)
bDBSelection = rData.bDBSelection;
nIndex = rData.nIndex;
bAutoFilter = rData.bAutoFilter;
+ bMarkedRows = rData.bMarkedRows;
nFilteredRowCount = rData.nFilteredRowCount;
if (bHeaderRangeDiffers)
@@ -646,6 +650,8 @@ bool ScDBData::UpdateReference(const ScDocument& rDoc, UpdateRefMode eUpdateRefM
void ScDBData::ExtendDataArea(const ScDocument& rDoc)
{
+ if (bMarkedRows)
+ return;
// Extend the DB area to include data rows immediately below.
SCCOL nOldCol1 = nStartCol, nOldCol2 = nEndCol;
SCROW nOldEndRow = nEndRow;
@@ -665,6 +671,8 @@ void ScDBData::ExtendDataArea(const ScDocument& rDoc)
void ScDBData::ExtendBackColorArea(const ScDocument& rDoc)
{
+ if (bMarkedRows)
+ return;
// Extend the DB area to include data rows immediately below.
SCCOL nOldCol1 = nStartCol, nOldCol2 = nEndCol;
SCROW nOldEndRow = nEndRow;
diff --git a/sc/source/ui/view/dbfunc.cxx b/sc/source/ui/view/dbfunc.cxx
index db3d23d86..8140ce4d0 100644
--- a/sc/source/ui/view/dbfunc.cxx
+++ b/sc/source/ui/view/dbfunc.cxx
@@ -18,6 +18,7 @@
*/
#include <scitems.hxx>
+#include <comphelper/lok.hxx>
#include <sfx2/bindings.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
@@ -286,6 +287,11 @@ void ScDBFunc::ToggleAutoFilter()
return;
pDBData->SetByRow( true ); //! undo, retrieve beforehand ??
+ // LOK: marked rows are the range, as in Excel.
+ ScRange aMarked;
+ pDBData->SetMarkedRows(comphelper::LibreOfficeKit::isActive()
+ && rViewData.GetSimpleArea(aMarked) == SC_MARK_SIMPLE
+ && aMarked.aStart.Row() != aMarked.aEnd.Row());
pDBData->GetQueryParam( aParam );
SCCOL nCol;