HotXLS porovnává dva sešity přes TXLSXWorkbookCompare, který spáruje listy podle názvu, projde vyplněné buňky každé dvojice a nahlásí, co se liší, jako strukturovaný seznam záznamů o rozdílech a na požádání jako jeden čitelný řádek na rozdíl. Není potřeba žádná instalace Excelu a porovnání běží zcela na načteném objektovém modelu v Delphi nebo C++Builder
Potřeba se obvykle objeví ve chvíli, kdy se někdo poprvé zeptá, co se změnilo. Finanční sešit se vrátí z revize, noční export se přegeneruje po změně kódu, nebo dvě oddělení pošlou verze stejné šablony. Otevření obou souborů vedle sebe funguje u jednoho listu a selže u dvaceti. Porovnání souborů bajt po bajtu neodpoví vůbec na nic, protože dvě uložení stejného sešitu se liší způsoby, na kterých nikomu nezáleží
Co se počítá jako rozdíl?
Porovnání hlásí osm druhů a tato množina je záměrně malá: přidaný nebo odebraný list, přidaná nebo odebraná vyplněná buňka, buňka se změněnou hodnotou, buňka se změněným vzorcem a přidaná nebo odebraná sloučená oblast. Vše je vyjádřeno vůči levému sešitu jako výchozímu stavu, takže přidaná položka existuje pouze vpravo a odebraná pouze vlevo
Listy se párují podle názvu, ne podle pozice. Přeuspořádání listů tedy nevytvoří žádné rozdíly, což je téměř vždy chování, které chcete: přetažení karty uživatelem není změna dat. List přítomný jen na jedné straně nahlásí jeden záznam na úrovni listu, místo aby rozepsal každou vyplněnou buňku uvnitř, což udržuje zprávu o dvou strukturálně odlišných sešitech čitelnou místo tisíců řádků dlouhou
Hodnota nebo vzorec, a jak se každý porovnává
Každá buňka přispívá podpisem a pravidlo je jednoduché: buňka nesoucí vzorec se porovnává podle textu vzorce s úvodním rovnítkem, a buňka bez vzorce se porovnává podle své hodnoty převedené na text. Tento rozdíl má větší význam, než se na první pohled zdá. Dvě buňky mohou zobrazovat stejné číslo, přičemž jedna je literál a druhá vzorec, a považovat je za shodné by skrylo přesně tu úpravu, kterou je v revidovaném sešitu nejdůležitější zachytit
Znamená to také, že vzorec, jehož text se nezměnil, nehlásí žádný rozdíl, i když se liší jeho uložený výsledek, což je správné chování pro porovnání autorského obsahu a špatné chování, pokud se snažíte odhalit posun po přepočtu. Pro tuto druhou otázku oba sešity před porovnáním přepočítejte, aby hodnoty, které porovnáváte, byly ty, které vzorce skutečně produkují dnes
Spuštění porovnání
Compare přebírá dva načtené sešity a vrací počet nalezených rozdílů. Seznam rozdílů je pak dostupný podle indexu, nebo jej lze vypsat do libovolného TStrings:
uses
lxHandleX, lxCompare;
var
Left, Right: TXLSXWorkbook;
Cmp: TXLSXWorkbookCompare;
Lines: TStringList;
begin
Left := TXLSXWorkbook.Create;
Right := TXLSXWorkbook.Create;
Cmp := TXLSXWorkbookCompare.Create;
Lines := TStringList.Create;
try
if (Left.Open('baseline.xlsx') <> 1) or
(Right.Open('reviewed.xlsx') <> 1) then
Exit;
if Cmp.Compare(Left, Right) = 0 then
Writeln('workbooks are equivalent')
else
begin
Cmp.Report(Lines); // jeden čitelný řádek na rozdíl
Lines.SaveToFile('workbook-diff.txt');
Writeln(Format('%d difference(s) written', [Cmp.Count]));
end;
finally
Lines.Free;
Cmp.Free;
Right.Free;
Left.Free;
end;
end;
Řádek vytvořený Report vypadá jako value changed: Data!A2: 10 -> 99, což stačí recenzentovi i pro zprávu o commitu. To je stránka určená člověku. Programová stránka je samotný záznam rozdílu, a ten je třeba použít, když porovnání pohání rozhodnutí, ne dokument
Řízení logiky na základě strukturovaných rozdílů
Každý rozdíl vystavuje svůj druh, název listu, řádek a sloupec počítané od jedné u záznamů na úrovni buňky, referenci A1 u záznamů na úrovni sloučení a levý a pravý text. Záznamy na úrovni listu a sloučení hlásí řádek a sloupec jako nulu, což je způsob, jak je rozlišit, aniž byste zkoumali druh:
var
I: Integer;
D: TlxCompareDiff;
FormulaEdits: Integer;
begin
FormulaEdits := 0;
for I := 0 to Cmp.Count - 1 do
begin
D := Cmp.Diff(I);
case D.Kind of
lckFormulaChanged:
begin
Inc(FormulaEdits);
Writeln(Format('%s R%dC%d: %s => %s',
[D.Sheet, D.Row, D.Col, D.LeftText, D.RightText]));
end;
lckSheetAdded, lckSheetRemoved:
Writeln(Format('structure: %s', [D.Describe]));
lckMergeAdded, lckMergeRemoved:
Writeln(Format('layout: %s at %s', [D.Describe, D.Ref]));
end;
end;
// Revizní politika, která blokuje pouze na úpravách vzorců
if FormulaEdits > 0 then
raise Exception.CreateFmt(
'%d formula change(s) need sign-off', [FormulaEdits]);
end;
Dvě vlastnosti výstupu stojí za to znát ještě před psaním assertions proti němu. Pořadí záznamů na úrovni buňky sleduje interní pořadí průchodu úložiště buněk, takže testy by měly být psány nezávisle na pořadí. A podpis vzorce nese vlastní úvodní rovnítko, což znamená, že popisný řetězec sestavený spojováním může zobrazit zdvojené ==; když výsledek pohání logiku, kontrolujte hodnoty polí, ne parsujte popisný řádek
Kde se porovnávání sešitů vyplácí
Tři případy použití samy o sobě funkci ospravedlňují. Regresní testování generátoru sestav: uchovejte znovu ověřený sešit, přegenerujte, porovnejte a nechte sestavení selhat na jakémkoli neočekávaném rozdílu. Revize změn: dejte recenzentovi čitelnou zprávu místo dvou souborů. A ověření migrace: po převodu dávky starších sešitů porovnejte každý výsledek se zdrojem, abyste dokázali, že se nic neztratilo
Tento třetí případ se přirozeně páruje s inventarizačními a auditními průchody popsanými v článku pracoviště auditu a konverze sešitů, kde počítání obsahu sešitu probíhá před konverzí a porovnání probíhá po ní. Pokud se vaše rozdíly soustředí kolem vložených řádků, pravidla přepisování referencí v článku úprava referencí vzorců při vkládání a mazání vysvětlují, proč vzorce, které vypadají nezměněné, hlásí jako změněné
Meze, řečeno otevřeně
Porovnání pokrývá hodnoty, vzorce, sloučení a přítomnost listů. Neporovnává formáty čísel, fonty, výplně, pravidla podmíněného formátování, ověřování dat, grafy, obrázky ani definované názvy. Buňka, jejíž hodnota je identická, ale jejíž formát se změnil z Obecného na Měnu, nehlásí žádný rozdíl, což je správné pro porovnání dat a nedostatečné pro revizi formátování
Buňky s datovou hodnotou si zaslouží jedno konkrétní varování: porovnávají se podle svého textového převodu, takže sešit uložený v systému data 1904 a sešit v systému 1900 se mohou porovnat jako shodné nebo neshodné způsoby, které vás překvapí, pokud se liší podkladová pořadová čísla. Pravidla systému data popisuje článek pořadová čísla dat a systém 1904. Když je součástí otázky formátování nebo věrnost na úrovni objektů, kombinujte porovnání s auditním průchodem, který tyto funkce počítá na každé straně
Porovnávání sešitů, auditování a konverze běží na stejném motoru pro Delphi a C++Builder; kompletní seznam funkcí je na stránce komponenty HotXLS pro tabulky v Delphi