Tehnični članak

HotXLS v Delphiju: preverjanje podatkov, AutoFilter, tabele

Tri zmožnosti v HotXLS si delijo delovni list, a delujejo na povsem različnih objektih, težave pa se začnejo, ko predpostavite, da počnejo podobne stvari. Preverjanje podatkov na obseg pripne pravilo, ki omeji, kaj sme uporabnik vanj vtipkati. AutoFilter na območje pripne shranjeno opredelitev meril in spremeni, katere vrstice pregledovalec pokaže. Tabela obseg ovije v poimenovano, tipizirano strukturo s pasovnim slogom. Ena omejuje vnos, ena beleži pogled, ena vsiljuje shemo. Nobena sama po sebi ne premakne niti ene vrednosti celice, AutoFilter pa ljudi še posebej zavede, ker beseda namiguje na dejanje, hrani pa le opredelitev. Vedeti, katerega objekta se vsak klic dotakne in kdaj se učinek dejansko udejanji, je tisto, kar loči delovni zvezek, ki se v Excelu vede enako kot v vaših testih, od takega, ki tiho odstopa

Diagram treh zmožnosti delovnega lista HotXLS v Delphiju, kjer preverjanje podatkov omeji vnos, AutoFilter hrani opredelitev pogleda, tabela pa vsili shemo
Preverjanje podatkov, AutoFilter in tabele se v HotXLS pripnejo na isti obseg delovnega lista, vsaka pa se udejanji v drugem trenutku — pri tipkanju, ob odprtju datoteke in ob shranjevanju

AutoFilter hrani opredelitev, vrstic ne obreže

AutoFilter v shranjeni datoteki je zapis meril. Skrivanje vrstic se zgodi pozneje, ko Excel delovni zvezek odpre in merila ovrednoti nad podatki. HotXLS ta zapis zvesto zapiše in ne obreže ničesar: vsaka vrstica, ki ste jo filtrirali, je še vedno fizično prisotna v datoteki. Cevovod, ki filter uveljavi, da bi izpustil zavrnjena naročila, in nato delovni zvezek prebere nazaj, bo videl vsa, tudi zavrnjena, koda pa je po API-ju pravilna in po avtorjevem miselnem modelu napačna. Na delovnem listu XLSX SetAutoFilter deklarira filtrirano območje, AddAutoFilterColumn pa merila pripne enemu njegovemu stolpcu. Kadar koda na strežniku potrebuje dejanski izid, za število vrstic v povzetku ali za posredovanje samo ujemajočih se vrstic, knjižnica merila ovrednoti namesto vas, namesto da bi se pretvarjala, da se je datoteka spremenila:

Diagram, ki kaže, kako AutoFilter HotXLS v shranjeni datoteki Excel obdrži vsako vrstico, medtem ko API za predogled v Delphiju ovrednoti, katere vrstice bo Excel pokazal, skupaj z od nič štetim odmikom ID stolpca
Shranjena datoteka obdrži vsako vrstico in beleži le merila, medtem ko Excel vrstice skrije po njihovem ovrednotenju — AddAutoFilterColumn pa stolpce cilja po od nič štetem odmiku znotraj obsega
var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  R, Visible: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    Book.Open('orders.xlsx');
    Sheet := Book.Sheets[0];

    Sheet.SetAutoFilter('A1:E500');
    // ID stolpca 3 = četrti stolpec ZNOTRAJ obsega filtra (odmik od nič)
    Sheet.AddAutoFilterColumn(3, xlsxAfOpGreaterOrEqual, '1000');

    Visible := 0;
    for R := 2 to 500 do
      if Sheet.AutoFilterRowVisible(R) then
        Inc(Visible);
    // Visible se zdaj ujema s tem, kar bo Excel pokazal po odprtju datoteke

    Book.SaveAs('orders-filtered.xlsx');
  finally
    Book.Free;
  end;
end;

AutoFilterRowVisible odgovarja po vrsticah, PreviewAutoFilterRows pa celotno območje prehodi prek povratnega klica, kadar ujemajočo se množico potrebujete v enem prehodu. Obstaja primer, ko nobeden od njiju ni pravi odgovor: če je zahteva, da izključene vrstice v datoteki sploh ne smejo obstajati, torej gre za rez zaradi zasebnosti in ne za pogled, vrstice preprosto izbrišite. Filter je tam napačno orodje, saj ga vsak prejemnik z enim klikom počisti in podatki, ki ste jih hoteli zadržati, so spet na zaslonu

ID stolpca je odmik in ne številka stolpca

Opomba v zgornjem izseku označuje past, ki v tem API-ju stane največ časa za razhroščevanje. AddAutoFilterColumn svoj cilj določi po od nič štetem položaju znotraj obsega filtra in ne po stolpcu delovnega lista. Pri filtru na A1:E500 se sistema oštevilčenja pač razlikujeta za ena, kar je natanko tista vrsta zgrešitve za las, ki prestane hiter test in se sesuje v trenutku, ko kolega filtrira drug stolpec. Pri filtru, ki se začne pri stolpcu C, ID 0 pomeni stolpec C in neujemanje postane hitro očitno. Kadar se obseg filtra izračuna med izvajanjem, ID stolpca izpeljite iz iste spremenljivke, ki je zgradila niz obsega, in nikoli iz konstante za stolpec delovnega lista. Vsak stolpec sprejme drugi pogoj prek preobložitve, ki vzame dva operatorja, dve merili in veznik in/ali, kar zrcali Excelovo pogovorno okno za filter po meri. Fasada XLS isto pokriva s SetAutoFilter in ApplyAutoFilter, katerih parametra za merila in operator sledita starejšim dogovorom v slogu COM ter polje štejeta od 1. Menjava fasad pomeni menjavo izhodišča indeksiranja, zato si mesto klica zasluži opombo, katero od njiju je v igri

Pravila preverjanja so pogodba, pod katero vaši uporabniki urejajo

Med tremi zmožnostmi je preverjanje edino, ki dejavno omejuje prihodnji vnos, in si v delovnih zvezkih, ki gredo ven v izpolnjevanje in se vrnejo v obdelavo, zasluži največ pozornosti pri načrtovanju. Različica s seznamom nosi večino tega dela:

var
  Idx: Integer;
begin
  Idx := Sheet.AddListValidation('C2:C500', 'New,Approved,Blocked');
  Sheet.DataValidations[Idx].SetPrompt('Status',
    'Pick one of the listed states');
  Sheet.DataValidations[Idx].SetError('Invalid status',
    'Type or paste only listed values', xlsxDvErrStop);
  Sheet.DataValidations[Idx].AllowBlank := False;

  // Količine: cela števila, nič ali več
  Sheet.AddWholeNumberValidation('D2:D500', xlsxDvOpGreaterOrEqual, '0');
end;

Poleg seznamov in celih števil ista družina pokriva decimalke, datume, čase, dolžino besedila in prostooblikovne formule prek AddCustomValidation, splošni AddDataValidation pa razkrije celotno matriko tipov in operatorjev za graditelje pravil, ki jih poganja konfiguracija. Slog napake šteje bolj, kot pove njegovo ime. xlsxDvErrStop slab vnos naravnost zavrne; sloga z opozorilom in z informacijo vrednost po enem samem kliku spustita skozi. Izbirajte po stolpcih glede na to, ali koda, ki delovni zvezek bere nazaj, prenese vrednost zunaj pravila. Dve meji sodita v besedilo poziva ali v README, ki ga priložite datoteki. Preverjanje v Excelu varuje tipkanje, lepljenje bloka čez preverjani obseg pa pravilo obide, zato mora vsaka koda, ki podatke bere nazaj, preveriti znova in ne zaupati celicam. In pravilo pokriva dobesedno tisti obseg, ki ste mu ga izročili, kar pomeni, da pripenjanje preverjanja, preden poznate končno število vrstic, pripeti rep pusti nezavarovan. Najprej zapišite podatke, nato pravila pomerite po dejanskem obsegu

Podedovana fasada ponuja iste družine pravil z eno ergonomsko razliko. Ustvarjalci na strani XLS, in sicer AddWholeNumberValidation, AddDecimalValidation, AddDateValidation, AddTimeValidation, AddTextLengthValidation in AddCustomValidation, vrnejo objekt TDataValidation neposredno in ne indeksa, zato se nastavitev poziva in napake veriži na vrnjeni sklic namesto na poizvedbo. Naštevanje operatorjev (xlsDvBetween, xlsDvGreaterThan in ostali) zrcali nabor XLSX, zato se koda za gradnjo pravil med fasadama prenaša brez težav, razen te razlike v slogu vračanja. Besedilo poziva si zasluži prav toliko premisleka kot pravilo. Spustni seznam, ki vnos zavrne s praznim okencem za napako, uporabnike nauči pisati e-pošto oddelku za IT; tak, ki poimenuje dovoljena stanja, jih nauči popraviti celico in iti naprej

En obrat polaritete, ki ga knjižnica prevzame namesto vas

Kdor je kdaj ročno bral XML preverjanja OOXML, je srečal obrnjeni atribut showDropDown: v ISO/IEC 29500 vrednost true pomeni "zatri puščico spustnega seznama", torej nasprotno od tega, kakor se ime bere. HotXLS to interno obrne, zato lastnost ShowDropDown na pravilu preverjanja pomeni, kar pravi, pri čemer true spustni seznam pokaže. Edini način, kako se opeči, je mešanje ravni resnice, torej nastavljanje lastnosti iz kode, medtem ko kolega presoja shranjeni XML in "popravi" atribut, ki se mu zdi obrnjen. Odločite se, ali je za orodja za pregled merodajna lastnost ali surovi XML, in obrat zapišite tam, kjer ta odločitev živi

Tabele obsegu dajo shemo in ime

Tabela delovnega lista, v Excelovem izrazju ListObject, obseg ovije v ime, tipizirane stolpce, pasovni slog in podporo strukturiranim sklicem. To je zmožnost, zaradi katere je generiran delovni zvezek videti dokončan, brž ko ga uporabniki začnejo razvrščati in razširjati. Ustvarjanje je med fasadama simetrično, pri čemer AddTable vzame ime, obseg in seznam stolpcev:

Diagram tabele delovnega lista HotXLS v Delphiju s tipiziranimi stolpci, strukturiranimi sklici, imeni, edinstvenimi v delovnem zvezku, in pastjo pripisovanja pri vrstici s seštevki
Tabela HotXLS svoj obseg ovije v ime, tipizirane stolpce in pasovni slog, vrstica s seštevki pa sedi neposredno pod podatki, prav tam, kjer pristane naiven pripis za zadnjo vrstico
var
  Cols: TStringList;
begin
  Cols := TStringList.Create;
  try
    Cols.CommaText := 'OrderId,Customer,Status,Amount,Owner';
    Sheet.AddTable('Orders', 'A1:E500', Cols);
  finally
    Cols.Free;
  end;
end;

Na strani XLSX nastali objekt tabele razkrije StyleName (vgrajena družina TableStyleMedium2 in njeni sorodniki), preklope za proge in zastavico za vrstico s seštevki, zato je uveljavljanje hišnega sloga prireditev lastnosti in ne ročno oblikovanje. V podedovanih datotekah .xls isti klic zapiše zapise tabele BIFF8, fasada pa ponuja tudi AddPivotTable za povzetne poglede, zgrajene iz vrstičnih, stolpčnih in podatkovnih polj, kar spomni, da "tabele" v starejšem zapisu sežejo dlje od ListObject v OOXML. Tabele poimenujte tako, kot poimenujete poglede v zbirki podatkov. Koda nižje po toku, ki po strukturiranem sklicu bere Orders[Amount], preživi prerazporeditev stolpcev, ki zlomi kodo, vezano na položaj

Dva dogovora vam pozneje prihranita pospravljanje. Excel zahteva, da so imena tabel edinstvena v celotnem delovnem zvezku, zato generator, ki izda en list na regijo, potrebuje shemo, kot je Orders_EMEA, namesto da bi znova uporabil Orders. Podvojitev ob zapisu ne odpove; pokaže se kot pogovorno okno za popravilo, ko uporabnik datoteko odpre, kar je najslabše možno mesto za odkritje. Drugi dogovor zadeva vrstico s seštevki: kadar je vklopljena, sedi neposredno pod podatkovnim obsegom, zato vsaka koda, ki pozneje pripenja po načelu "zadnja uporabljena vrstica plus ena", piše v pas s seštevki namesto za njim. Obseg podatkov spremljajte ločeno od obsega tabele in pripisi bodo pristali tam, kjer pričakujete

Vse tri zmožnosti se v izdelkih za vnos podatkov naravno sestavijo. Tabela določi urejevalno območje, preverjanje omeji stolpce, v katere uporabniki tipkajo, vnaprej nastavljen filter pa prejemniku prihrani prvih nekaj klikov. Obstaja poštena utemeljitev za odpremo z že uveljavljenim filtrom, tako da se delovni zvezek odpre osredotočen na vrstice, ki štejejo, dokler pomnite, da so izključene vrstice še vedno v datoteki in jih radoveden prejemnik lahko razkrije. Kako izide poizvedbe učinkovito spraviti v list, torej zgornja polovica tega cevovoda, je obravnavano v izvozu izidov zbirke podatkov v Excel iz Delphija, delovnim zvezkom, kjer formule povzemajo preverjene podatke, pa koristijo določena imena za stabilne sklice med listi

Preverjanje, filtri in tabele so razlika med odpremo mreže vrednosti in odpremo majhne aplikacije. Celotna referenca za pravila, filtre in tabele je na strani izdelka HotXLS Delphi Component