HotXLS porovnáva dva zošity prostredníctvom TXLSXWorkbookCompare, ktorý spáruje hárky podľa názvu, prejde obsadené bunky každej dvojice a nahlási, čo sa líši, ako štruktúrovaný zoznam záznamov rozdielov a na požiadanie aj ako jeden čitateľný riadok na rozdiel. Nie je potrebná žiadna inštalácia Excelu a porovnanie beží úplne nad načítaným objektovým modelom v Delphi alebo C++Builder
Táto potreba sa zvyčajne objaví, keď sa niekto prvýkrát opýta, čo sa zmenilo. Finančný zošit sa vráti z revízie, nočný export sa po zmene kódu znovu vygeneruje, alebo dve oddelenia pošlú verzie tej istej šablóny. Otvorenie oboch vedľa seba funguje pri jednom hárku a zlyháva pri dvadsiatich. Porovnávanie súborov bajt po bajte neodpovie vôbec na nič, pretože dve uloženia toho istého zošita sa líšia spôsobmi, o ktoré sa nikto nezaujíma
Čo sa počíta ako rozdiel?
Porovnanie hlási osem druhov rozdielov a táto množina je zámerne malá: pridaný alebo odstránený hárok, pridaná alebo odstránená obsadená bunka, bunka, ktorej hodnota sa zmenila, bunka, ktorej vzorec sa zmenil, a pridaný alebo odstránený zlúčený rozsah. Všetko sa vyjadruje voči ľavému zošitu ako základnej línii, takže pridaná položka existuje iba na pravej strane a odstránená iba na ľavej
Hárky sa spárujú podľa názvu, nie podľa pozície. Zmena poradia hárkov preto neprodukuje žiadne rozdiely, čo je takmer vždy želané správanie: presunutie záložky používateľom nie je zmena dát. Hárok prítomný iba na jednej strane nahlási jeden záznam na úrovni hárka namiesto toho, aby rozvinul každú obsadenú bunku vo vnútri, čím zostáva report dvoch štruktúrne odlišných zošitov čitateľný namiesto toho, aby mal tisíce riadkov
Hodnota alebo vzorec, a ako sa každý porovnáva
Každá bunka prispieva podpisom a pravidlo je jednoduché: bunka nesúca vzorec sa porovnáva podľa textu svojho vzorca s úvodným znamienkom rovnosti, a bunka bez vzorca sa porovnáva podľa svojej hodnoty prevedenej na text. Tento rozdiel je dôležitejší, než sa na prvý pohľad zdá. Dve bunky môžu zobrazovať to isté číslo, pričom jedna je literál a druhá vzorec, a považovať ich za rovnaké by ukrylo presne tú úpravu, ktorú sa v recenzovanom zošite najviac oplatí zachytiť
Znamená to tiež, že vzorec, ktorého text sa nezmenil, nehlási žiadny rozdiel, aj keď sa líši jeho vyrovnávaný výsledok, čo je správne správanie pri porovnávaní autorského obsahu a nesprávne správanie, ak sa snažíte odhaliť odchýlku pri prepočte. Pri druhej otázke oba zošity pred porovnaním prepočítajte, aby hodnoty, ktoré porovnávate, boli tie, ktoré vzorce dnes skutočne produkujú
Spustenie porovnania
Compare prijíma dva načítané zošity a vracia počet nájdených rozdielov. Zoznam rozdielov je potom dostupný podľa indexu, alebo sa dá vypísať do ľubovoľné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 čitateľný riadok na rozdiel
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;
Riadok vytvorený funkciou Report znie ako value changed: Data!A2: 10 -> 99, čo stačí pre recenzenta aj pre commit message. Toto je rozhranie orientované na človeka. Programové rozhranie je samotný záznam rozdielu a práve ten treba použiť, keď porovnanie zásobuje rozhodnutie, nie dokument
Riadenie logiky zo štruktúrovaných rozdielov
Každý rozdiel odhaľuje svoj druh, názov hárka, riadok a stĺpec indexovaný od jedna pri záznamoch na úrovni buniek, referenciu A1 pri záznamoch na úrovni zlúčenia a ľavý a pravý text. Záznamy na úrovni hárka a zlúčenia hlásia riadok aj stĺpec ako nulu, čím ich viete rozlíšiť bez skúmania druhu:
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;
// Politika revízie, ktorá blokuje iba pri úpravách vzorcov
if FormulaEdits > 0 then
raise Exception.CreateFmt(
'%d formula change(s) need sign-off', [FormulaEdits]);
end;
Pred písaním asertov voči výstupu stojí za to poznať dve jeho vlastnosti. Poradie záznamov na úrovni buniek sleduje interné poradie prechodu úložiska buniek, takže testy by mali byť napísané nezávisle od poradia. A podpis vzorca nesie vlastné úvodné znamienko rovnosti, čo znamená, že popisný reťazec zostavený zreťazením môže zobraziť zdvojené ==; keď výsledok riadi logiku, kontrolujte hodnoty polí namiesto parsovania popisného riadka
Kde sa porovnávanie zošitov oplatí
Túto funkciu samostatne odôvodňujú tri prípady použitia. Regresné testovanie generátora zostáv: uchovávajte overený zošit, znovu vygenerujte, porovnajte a pri akomkoľvek neočakávanom rozdiele nechajte zlyhať zostavenie. Revízia zmien: recenzentovi odovzdajte čitateľný report namiesto dvoch súborov. A overenie migrácie: po konverzii dávky starších zošitov porovnajte každý výsledok s jeho zdrojom, aby ste dokázali, že sa nič nestratilo
Tento tretí prípad sa prirodzene spája s priechodmi inventarizácie a auditu opísanými v časti nástroj na audit a konverziu zošitov, kde sa počítanie obsahu zošita deje pred konverziou a porovnanie po nej. Ak sa vaše rozdiely zhlukujú okolo vložených riadkov, pravidlá prepisovania referencií v časti úprava referencií vzorcov pri vkladaní a mazaní vysvetľujú, prečo sa vzorce, ktoré vyzerajú nezmenené, hlásia ako zmenené
Limity, povedané na rovinu
Porovnanie pokrýva hodnoty, vzorce, zlúčenia a prítomnosť hárkov. Neporovnáva formáty čísel, písma, výplne, pravidlá podmieneného formátovania, overenia dát, grafy, obrázky ani definované názvy. Bunka, ktorej hodnota je identická, no formát sa zmenil zo Všeobecný na Mena, nehlási žiadny rozdiel, čo je správne pre porovnanie dát a nedostatočné pre revíziu formátovania
Bunky s dátumovou hodnotou si zaslúžia jedno konkrétne upozornenie: porovnávajú sa podľa svojho prevodu na text, takže zošit uložený v dátumovom systéme 1904 a zošit v systéme 1900 sa môžu porovnávať ako rovnaké alebo odlišné spôsobmi, ktoré vás prekvapia, ak sa podkladové poradové čísla líšia. Pravidlá dátumového systému opisuje časť poradové čísla dátumov a systém 1904. Keď je súčasťou otázky aj vernosť formátovania alebo objektov, skombinujte diff s priechodom auditu, ktorý tieto funkcie počíta na oboch stranách
Porovnávanie zošitov, audit a konverzia bežia na tom istom jadre pre Delphi a C++Builder; kompletný zoznam funkcií nájdete na stránke HotXLS Delphi spreadsheet component