ElyTable: an AutoFilter on marked rows keeps the total below out (R2.9)
This commit is contained in:
4 files changed
+159
No files matched your search
@@ -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 下对跨行的选区开自动筛选时,筛选区记下“选定的行”(不存入文件),此后不再扩展;单格开筛选照旧取整个数据区。已知限制:存后重开的文件不带此记号,其筛选区照内核原样扩展。
|
||||
@@ -6,6 +6,7 @@ mod analysis;
|
||||
mod charts;
|
||||
mod check;
|
||||
mod commands;
|
||||
mod filter;
|
||||
mod format;
|
||||
mod formula;
|
||||
mod handouts;
|
||||
|
||||
@@ -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;
|
||||
Reference in new issue
Block a user