Tehnični članak

Strukturirana sklicevanja Excel v Delphiju s HotXLS

HotXLS zdaj ovrednoti strukturirana sklicevanja na tabele, tako da =SUM(Table1[Amount]) ustvari število namesto da bi bilo preskočeno. Razreševalnik obravnava Table[Column], Table[[Column]], razpone stolpcev, kot je Table[[Q1]:[Q4]], in specifikatorje postavk [#Data], [#All], [#Headers] in [#Totals], pri čemer vsakega razreši glede na tabelni model delovnega zvezka v trenutku razčlenjevanja, medtem ko se izvirno besedilo formule vrne dobesedno nespremenjeno

Ena oblika namerno manjka, in prav to je tista, na katero ljudje naletijo najprej. Bližnjica trenutne vrstice [@Column] ni podprta, iz strukturnega razloga, ki ga velja razumeti in ne zgolj obiti

Zakaj strukturirano sklicevanje ni le obseg s prijaznim imenom?

Ker definirano ime zamrzne naslov, strukturirano sklicevanje pa ne. Zapišite DataBlock kot ime, ki kaže na Sheet1!$A$2:$D$100, in ostane ta pravokotnik, dokler ga nekaj ne prepiše. Zapišite Sales[Amount] in pomeni "stolpec Amount tabele Sales", karkoli je obseg te tabele v trenutku ovrednotenja. Dodajte tabeli dvajset vrstic in vsota jih pokrije; ni sklica za prilagoditev, ker v formuli od začetka ni bilo naslova

Prav ta simbolna narava je razlog, da sklicevanja ni mogoče razrešiti z zamenjavo niza. Razreševalnik mora tabelo poiskati po imenu v delovnem zvezku, poiskati stolpec po besedilu njegove glave, odločiti, katere vrstice pokriva zahtevani specifikator postavke, in ustvariti konkreten pravokotnik. HotXLS to opravi med prevajanjem formule prek tabelnega modela, zato se formula, napisana pred rastjo tabele, še vedno ovrednoti glede na trenutni obseg tabele

Slovnica, ki jo HotXLS razrešuje

Podprta slovnica specifikatorjev pokriva en sam pravokoten rezultat in jo velja natančno navesti, ker dokumentacija Excela predstavi veliko večjo površino, kot jo izvaja večina pogonov. HotXLS sprejme [Col] in različico z oklepaji [[Col]], gole specifikatorje postavk [#Data], [#All], [#Headers] in [#Totals], kombinirano obliko [[#Data],[Col]], razpon znotraj specifikatorja postavke kot [[#Data],[Col1]:[Col2]] in navaden razpon [Col1]:[Col2]

Kar vam ta nabor da, je vsaka oblika sklicevanja, ki ustvari en sklenjen blok: stolpec, niz sosednjih stolpcev, rezino telesa ali rezino, ki vključuje glavo, katerega koli od njiju. Nesosednje unije in rezultati z več območji so izven tega. Kadar sklica ni mogoče razrešiti, formula ohrani prejšnje vedenje preskoči-brez-vrednosti namesto da bi nadomestila ugibanje, tako da nerešljivo sklicevanje nikoli ne postane verjetno napačno število

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Cols: TStringList;
begin
  Book := TXLSXWorkbook.Create;
  Cols := TStringList.Create;
  try
    Sheet := Book.Sheets.Add('Sales');
    Cols.Add('Region');
    Cols.Add('Q1');
    Cols.Add('Q2');
    Cols.Add('Amount');
    Sheet.Tables.Add('SalesTable', 'A1:D25', Cols);
    // ... zapišite vrstico glave in 24 vrstic podatkov ...

    Sheet.Cells[27, 4].Formula := 'SUM(SalesTable[Amount])';
    Sheet.Cells[28, 4].Formula := 'SUM(SalesTable[[Q1]:[Q2]])';
    Sheet.Cells[29, 4].Formula := 'COUNTA(SalesTable[[#Data],[Region]])';
    Sheet.Cells[30, 4].Formula := 'ROWS(SalesTable[#All])';

    Book.Recalculate;
    Book.SaveAs('sales.xlsx');
  finally
    Cols.Free;
    Book.Free;
  end;
end;

Zakaj je oblika trenutne vrstice namerno izključena?

[@Column] in [#This Row] pomenita "celica tega stolpca v vrstici, v kateri živi ta formula". Vrednost je torej odvisna od položaja celice, ki ovrednoti, ne le od tabele. To je drugačna vrsta sklicevanja: ne pravokotnik, ki bi ga prevajalnik razrešil enkrat, temveč razreševanje na posamezno celico, ki ga je treba ponoviti za vsako vrstico, ki jo formula zaseda

HotXLS za te oblike iz razreševalnika obsegov tabele vrne False, kar jih usmeri na pot preskoči-brez-vrednosti. Besedilo formule je ohranjeno in zapisano nazaj nespremenjeno, tako da se delovni zvezek, ki uporablja [@Amount], po povratni pretvorbi skozi vašo aplikacijo v Excelu odpre pravilno; manjka le vrednost, ki jo je izračunal HotXLS. Glede na izbiro med manjkajočo vrednostjo in vrednostjo, izračunano za napačno vrstico, je odsotnost tista, ki jo lahko zaznate

Praktična obhodna rešitev je mehanska: v delovnem zvezku, ki ga ustvarjate sami, zapišite enakovreden relativen sklic v slogu A1, kar je tako ali tako tisto, kar Excel interno shrani za velik del logike v obsegu tabele. V delovnem zvezku, ki ga zgolj obdelujete, pustite formulo pri miru in preberite predpomnjeno vrednost, ki jo je Excel že shranil, kar si običajno želi cevovod za nalaganje in poročanje

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Table: TXLSXTable;
  Row: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    if Book.Open('sales.xlsx') <> 1 then Exit;
    Sheet := Book.Sheets[1];

    Table := Sheet.Tables.FindByName('SalesTable');
    if Table <> nil then
    begin
      // Iskanje v slogu podatkovnega niza po telesu tabele, rezultat vrstice od 1 naprej
      Row := Table.FindFirst(Sheet, 'Region', 'EMEA');
      while Row > 0 do
      begin
        Log(VarToStr(Sheet.Cells[Row, 4].Value));
        Row := Table.FindNext(Sheet, 'Region', 'EMEA', Row);
      end;
    end;
  finally
    Book.Free;
  end;
end;

Kaj se zgodi, ko tabela spremeni obliko

Strukturirana sklicevanja so ob izginotju tega, kar poimenujejo, razveljavljena in ne tiho preusmerjena. Izbrišite stolpec in formule, ki se sklicujejo nanj, so razveljavljene tako, kot jih razveljavi Excel; izbris ali preimenovanje tabele obravnava enako. To je pravilno vedenje in zrcali običajno prilagajanje sklicev, opisano v prilagajanju formulskih sklicev ob vstavljanju in brisanju, kjer je naloga pogona ohraniti formule poštene in ne le videti veljavne

Rast vrstic je nasproten primer in ne potrebuje nobene prilagoditve. Ker sklicevanje poimenuje tabelo in ne pravokotnik, dodajanje vrstic znotraj obsega tabele razširi to, kar pokriva [#Data], ne da bi se dotaknilo ene same formule. To je lastnost, zaradi katere se tabele splača uporabljati v predlogi poročila: vrstica seštevka še naprej sešteva vse, kar je uvoz ustvaril, ne glede na to, koliko vrstic je to na koncu bilo

Disciplina povratne pretvorbe

HotXLS ohrani izvirno besedilo formule. Delovni zvezek, naložen s SUM(SalesTable[Amount]), je shranjen s SUM(SalesTable[Amount]), ne z razrešenim SUM(D2:D25). To je pomembnejše, kot se morda zdi: uporabnik, ki odpre vaš izhod v Excelu, pričakuje, da vidi formulo, ki jo je napisal, razrešen naslov pa bi tiho pretvoril model, ki se vzdržuje sam, v krhkega, ki preneha pokrivati nove vrstice

Sliko dopolnita dve povezani zmožnosti. Same definicije tabel, vključno s tabelami brez glave in komentarji na posamezno tabelo, se povratno pretvorijo skozi tabelni model, opisan v preverjanju podatkov, samodejnem filtru in tabelah Excel. In kadar si veliko celic deli en vzorec, XLSX to shrani enkrat kot skupno formulo, ki je razširjena in ponovno izdana, kot je obravnavano v razširitvi si skupnih formul. Strukturirana sklicevanja znotraj skupnih formul gredo skozi obe poti, zato se morata obe obnašati pravilno, in se tudi obnašata

HotXLS bere in zapisuje XLS, XLSX in ODS iz Delphija in C++Builderja brez namestitve Excela in brez avtomatizacije Officea, formule pa ovrednoti v lastnem pogonu. Tabelni model, formulski pogon in API za ponovni izračun so dokumentirani na strani izdelka HotXLS