Unitatea lxOutline oferă geometrie și planificare de mutații neutră față de motor pentru contururile pe rânduri și coloane
Stochează doar intervalele materializate, recunoaște nodurile de sinteză din tranzițiile adiacente de nivel de contur și creează schimbări de stare comprimate pentru dispunerea cu sinteza după și cu sinteza înainte, fără a aloca o intrare pentru fiecare coordonată a foii de lucru
Tipuri de bază
TXLSOutlineAxis = (xoaRows, xoaColumns);
TXLSOutlineChildMode = (xocPreserve, xocCollapse, xocExpand);
TXLSOutlineMutationPlan = class
constructor Create(AAxis: TXLSOutlineAxis);
procedure Clear;
property Axis: TXLSOutlineAxis;
property Count: Integer;
property Changes[Index: Integer]: TXLSOutlineStateChange;
end;
TXLSOutlineGeometry = class
constructor Create(AAxis: TXLSOutlineAxis;
ASummaryAfter: Boolean);
procedure Clear;
property Axis: TXLSOutlineAxis;
property SpanCount: Integer;
procedure AddSpan(AFirstIndex, ALastIndex, ALevel: Integer;
AHidden, ACollapsed: Boolean);
function TryGetNode(ANodeIndex: Integer;
out ANode: TXLSOutlineNode): Boolean;
function TryBuildNodeCollapsePlan(ANodeIndex: Integer;
ACollapsed: Boolean; AChildMode: TXLSOutlineChildMode;
APlan: TXLSOutlineMutationPlan): Boolean;
procedure BuildDisplayLevelPlan(ADisplayLevel: Integer;
AChildMode: TXLSOutlineChildMode;
APlan: TXLSOutlineMutationPlan);
end;
Indecșii de rând și coloană au indexare de la 1, nivelurile de contur sunt nenegative, iar intervalele trebuie adăugate în ordine strict crescătoare, fără suprapuneri
Intervalele adiacente cu nivel identic și stare ascunsă și restrânsă identică sunt fuzionate automat; indecșii omiși au implicit nivelul zero, stare vizibilă și niciun marcaj de restrângere
Ambele clase își rețin Axis-ul de la construcție, Clear golește un plan sau geometrie pentru reutilizare fără realocarea bufferelor interne, iar SpanCount raportează câte intervale fuzionate conține în prezent geometria
Semantica nodurilor
| NodeIndex | Rândul sau coloana fizică de sinteză interogată de apelant |
| FirstDetailIndex / LastDetailIndex | Intervalul contiguu de detalii al cărui nivel este mai adânc decât elementul de sinteză |
| SummaryLevel | Nivelul de contur stocat pe elementul de sinteză, sau zero când elementul nu este materializat |
| Level | Nivelul de grup reprezentat de nod, egal cu SummaryLevel + 1 |
| SummaryHidden | Starea ascunsă stocată pe elementul de sinteză |
| Collapsed | Marcajul explicit de restrângere stocat pe elementul de sinteză |
| SummaryAfter | True când detaliile preced elementul de sinteză, false când detaliile îl urmează |
Grupurile imbricate rămân independente deoarece fiecare interogare se oprește la primul interval adiacent al cărui nivel nu este mai adânc decât elementul de sinteză selectat
Un gol termină de asemenea intervalul de detalii, astfel încât metadatele rare nu pot lega accidental coordonate nefolosite într-un singur grup
Planuri de mutații
Un plan de mutații conține intervale ordonate cu indexare de la 1 și o mască de câmpuri care indică dacă fiecare interval schimbă starea ascunsă, starea restrânsă sau pe ambele; schimbările adiacente echivalente sunt fuzionate automat
| xocPreserve | Schimbă nodul selectat păstrând marcajele de restrângere ale descendenților, ceea ce este comportamentul implicit al grupurilor imbricate |
| xocCollapse | Marchează nodurile descendenți ca restrânse când se află în interiorul nodului selectat sau sunt ascunse sub nivelul de afișare cerut |
| xocExpand | Șterge marcajele de restrângere ale nodurilor descendenți când se află în interiorul nodului selectat sau sunt ascunse sub nivelul de afișare cerut |
Extinderea unui părinte cu xocPreserve dezvăluie detaliile imediate, în timp ce detaliile aparținând descendenților restrânși rămân ascunse; extinderea unui descendent în interiorul unui strămoș restrâns nu expune conținutul prin acel strămoș
Nivelurile de afișare au indexare de la 1: nivelul 1 restrânge fiecare grup de nivel superior, iar fiecare valoare mai mare dezvăluie un nivel de contur suplimentar, setând totodată marcajele corespunzătoare ale nodului-limită
Construirea aceleiași stări cerute dintr-o geometrie care o conține deja produce un plan gol, iar interogarea unui non-nod returnează false cu un plan gol
Operațiile pe noduri lasă neschimbată starea ascunsă independentă a elementului de sinteză selectat, iar planurile de nivel de afișare nu redeschid elementele de nivel zero care au fost ascunse în afara unui grup de contur
Adaptoare pentru foaia de lucru
function TryGetOutlineNode(AAxis: TXLSOutlineAxis;
ANodeIndex: Integer; out ANode: TXLSOutlineNode): Boolean;
function SetOutlineNodeCollapsed(AAxis: TXLSOutlineAxis;
ANodeIndex: Integer; ACollapsed: Boolean;
AChildMode: TXLSOutlineChildMode = xocPreserve): Boolean;
procedure SetOutlineDisplayLevel(AAxis: TXLSOutlineAxis;
ADisplayLevel: Integer;
AChildMode: TXLSOutlineChildMode = xocPreserve);
TXLSWorksheet și TXLSXWorksheet expun aceleași trei metode, astfel încât apelanții pot interoga sau schimba un nod de sinteză de rând sau coloană cu indexare de la 1 fără a construi manual geometria
Adaptorul clasic citește doar blocurile de rânduri alocate și metadatele de coloană atribuite, în timp ce adaptorul XLSX fuzionează listele sale rare de nivel de contur, stare ascunsă și stare restrânsă înainte de a aplica un singur plan de mutații comprimat într-o singură tranzacție de scriere
Grupurile de rânduri și coloane OpenDocument își păstrează starea nativă imbricată table:display; editările directe de metadate și schimbările structurale de rânduri sau coloane proiectează în siguranță această stare pe nodul logic de sinteză, iar conversia în XLSX scrie marcajul de restrângere pe elementul de sinteză XLSX, nu pe fiecare membru al grupului
Metodele existente TXLSXWorksheet.ToggleRowGrouped și ToggleColGrouped rămân disponibile ca wrapper-e de compatibilitate; argumentul lor este primul rând sau coloană de detalii, iar wrapper-ul rezolvă nodul de sinteză dependent de direcție înainte de a-l comuta
Exemplu Delphi
Geometry := TXLSOutlineGeometry.Create(xoaRows, True);
Plan := TXLSOutlineMutationPlan.Create(xoaRows);
try
Geometry.AddSpan(2, 4, 1, False, False);
Geometry.AddSpan(5, 5, 0, False, False);
if Geometry.TryGetNode(5, Node) then
UseOutlineNode(Node.FirstDetailIndex,
Node.LastDetailIndex, Node.Collapsed);
if Geometry.TryBuildNodeCollapsePlan(5, True,
xocPreserve, Plan) then
ApplyOutlineChanges(Plan);
finally
Plan.Free;
Geometry.Free;
end;
Exemplu C++Builder
Lxoutline::TXLSOutlineGeometry *geometry =
new Lxoutline::TXLSOutlineGeometry(Lxoutline::xoaColumns, false);
try {
geometry->AddSpan(3, 3, 0, false, true);
geometry->AddSpan(4, 7, 1, true, false);
Lxoutline::TXLSOutlineNode node;
if (geometry->TryGetNode(3, node))
UseOutlineNode(node.FirstDetailIndex, node.LastDetailIndex,
node.Collapsed);
}
__finally {
delete geometry;
}
Performanță și scop
Căutarea nodului folosește o căutare binară urmată doar de intervalele materializate adiacente traversată de grupul selectat, oferind un efort O(log n + k) pentru n intervale și k intervale vizitate
Planificarea mutațiilor în masă descoperă fiecare nod materializat cu o trecere liniară pe stivă monotonică, fuzionează intervalele de vizibilitate restrânse și emite schimbări comprimate de interval fără a vizita coordonate nefolosite
Constructorul acceptă ultimul rând al foii de lucru XLSX păstrând doar intervalele furnizate, astfel încât o coordonată mare nu implică o alocare sau o scanare de un milion de intrări
Poarta de regresie a adaptoarelor foii de lucru rulează aceleași 32,768 de interogări de noduri și 2,048 de mutații de restrângere sau extindere peste șase intrări materializate de rânduri în apropierea rândului 8 și a rândului 1,048,576, cere zero materializări de celule și limitează costul coordonatelor mari față de linia de bază a coordonatelor mici
TXLSOutlineGeometry nu scrie niciodată direct datele registrului de lucru; adaptoarele motoarelor validează și aplică planul returnat, permițând analizei geometriei și mutației stării să rămână separate
Consultați și