Die Unit lxOutline bietet engine-neutrale Geometrie und Mutationsplanung für Zeilen- und Spaltengliederungen
Sie speichert nur materialisierte Spannen, erkennt Summenknoten an angrenzenden Übergängen der Gliederungsebene und erzeugt komprimierte Zustandsänderungen für Summe-danach- und Summe-davor-Layouts, ohne für jede Arbeitsblattkoordinate einen Eintrag zu allokieren
Zentrale Typen
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;
Zeilen- und Spaltenindizes sind einsbasiert, Gliederungsebenen sind nicht negativ, und Spannen müssen in streng aufsteigender, sich nicht überlappender Reihenfolge hinzugefügt werden
Angrenzende Spannen mit identischem Level-, Hidden- und Collapsed-Zustand werden automatisch zusammengeführt; ausgelassene Indizes haben implizit Ebene null, sichtbaren Zustand und kein Einklapp-Merkmal
Beide Klassen merken sich ihre Axis ab der Konstruktion, Clear leert einen Plan oder eine Geometrie zur Wiederverwendung, ohne die internen Puffer neu zu allokieren, und SpanCount meldet, wie viele zusammengeführte Spannen die Geometrie derzeit hält
Knotensemantik
| NodeIndex | Die physische Summenzeile oder -spalte, die der Aufrufer abfragt |
| FirstDetailIndex / LastDetailIndex | Der zusammenhängende Detailbereich, dessen Ebene tiefer ist als die des Summenelements |
| SummaryLevel | Die im Summenelement gespeicherte Gliederungsebene oder null, wenn dieses Element nicht materialisiert ist |
| Level | Die vom Knoten dargestellte Gruppenebene, gleich SummaryLevel + 1 |
| SummaryHidden | Der im Summenelement gespeicherte Hidden-Zustand |
| Collapsed | Das im Summenelement gespeicherte explizite Einklapp-Merkmal |
| SummaryAfter | True, wenn die Details vor dem Summenelement liegen, false, wenn sie danach folgen |
Verschachtelte Gruppen bleiben unabhängig, weil jede Abfrage an der ersten angrenzenden Spanne endet, deren Ebene nicht tiefer ist als die des gewählten Summenelements
Eine Lücke beendet ebenfalls den Detailbereich, sodass dünn besetzte Metadaten ungenutzte Koordinaten nicht versehentlich zu einer Gruppe verbinden können
Mutationspläne
Ein Mutationsplan enthält geordnete einsbasierte Bereiche und eine Feldmaske, die angibt, ob jeder Bereich den Hidden-Zustand, den Collapsed-Zustand oder beides ändert; angrenzende gleichwertige Änderungen werden automatisch zusammengeführt
| xocPreserve | Ändert den gewählten Knoten und behält dabei die Einklapp-Merkmale der Nachkommen, was das Standardverhalten für verschachtelte Gruppen ist |
| xocCollapse | Markiert Nachkommenknoten als eingeklappt, wenn sie innerhalb des gewählten Knotens liegen oder unterhalb der angeforderten Anzeigeebene ausgeblendet sind |
| xocExpand | Entfernt die Einklapp-Merkmale von Nachkommenknoten, wenn sie innerhalb des gewählten Knotens liegen oder unterhalb der angeforderten Anzeigeebene ausgeblendet sind |
Das Aufklappen eines übergeordneten Elements mit xocPreserve zeigt unmittelbare Details, während Details zu eingeklappten Kindern verborgen bleiben; das Aufklappen eines Kindes innerhalb eines eingeklappten Vorfahren legt keinen Inhalt über diesen Vorfahren frei
Anzeigeebenen sind einsbasiert: Ebene 1 klappt jede Gruppe der obersten Ebene ein, und jeder höhere Wert legt eine weitere Gliederungsebene offen und setzt zugleich die passenden Grenzknoten-Merkmale
Der Aufbau eines bereits vorhandenen angeforderten Zustands aus der Geometrie ergibt einen leeren Plan, und die Abfrage eines Nicht-Knotens gibt false mit einem leeren Plan zurück
Knotenoperationen lassen den unabhängigen Hidden-Zustand des gewählten Summenelements unverändert, und Anzeigeebenen-Pläne blenden Elemente der Ebene null, die außerhalb einer Gliederungsgruppe ausgeblendet wurden, nicht wieder ein
Arbeitsblattadapter
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 und TXLSXWorksheet legen dieselben drei Methoden offen, sodass Aufrufer einen einsbasierten Zeilen- oder Spaltensummenknoten abfragen oder ändern können, ohne die Geometrie manuell aufzubauen
Der Classic-Adapter liest nur zugewiesene Zeilenblöcke und zugewiesene Spaltenmetadaten, während der XLSX-Adapter seine dünn besetzten Listen für Gliederungsebene, Hidden und Collapsed zusammenführt, bevor er einen komprimierten Mutationsplan in einer einzigen Schreibtransaktion anwendet
OpenDocument-Zeilen- und Spaltengruppen behalten ihren nativen verschachtelten table:display-Zustand; direkte Metadatenbearbeitungen und strukturelle Zeilen- oder Spaltenänderungen projizieren diesen Zustand sicher auf den logischen Summenknoten, und die Konvertierung nach XLSX schreibt das Einklapp-Merkmal auf das XLSX-Summenelement statt auf jedes Gruppenmitglied
Die bestehenden Methoden TXLSXWorksheet.ToggleRowGrouped und ToggleColGrouped bleiben als Kompatibilitätswrapper verfügbar; ihr Argument ist die erste Detailzeile oder -spalte, und der Wrapper löst den richtungssensitiven Summenknoten auf, bevor er ihn umschaltet
Delphi-Beispiel
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;
C++Builder-Beispiel
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;
}
Leistung und Umfang
Die Knotensuche verwendet eine binäre Suche, gefolgt nur von den angrenzenden materialisierten Spannen, die die gewählte Gruppe kreuzt, und leistet damit O(log n + k) Arbeit für n Spannen und k besuchte Spannen
Die Sammel-Mutationsplanung findet jeden materialisierten Knoten mit einem linearen monotonen Stapeldurchlauf, verschmilzt eingeklappte Sichtbarkeitsintervalle und gibt komprimierte Bereichsänderungen aus, ohne ungenutzte Koordinaten zu besuchen
Der Builder akzeptiert die letzte XLSX-Arbeitsblattzeile und behält nur die bereitgestellten Spannen, sodass eine hohe Koordinate keine Allokation oder Suche mit einer Million Einträgen impliziert
Das Regressionsgate der Arbeitsblattadapter führt dieselben 32.768 Knotenabfragen und 2.048 Einklapp- oder Aufklapp-Mutationen über sechs materialisierte Zeileneinträge nahe Zeile 8 und Zeile 1.048.576 aus, verlangt null Zellmaterialisierung und begrenzt die Kosten hoher Koordinaten gegenüber der Basislinie niedriger Koordinaten
TXLSOutlineGeometry schreibt nie direkt Arbeitsmappendaten; Engine-Adapter validieren den zurückgegebenen Plan und wenden ihn an, sodass Geometrieanalyse und Zustandsänderung getrennt bleiben
Siehe auch