Techninis straipsnis

Excel struktūrinės lentelių nuorodos Delphi su HotXLS

HotXLS dabar įvertina struktūrines lentelių nuorodas, todėl =SUM(Table1[Amount]) sukuria skaičių, o ne praleidžiamas. Sprendiklis apdoroja Table[Column], Table[[Column]], stulpelių intervalus, tokius kaip Table[[Q1]:[Q4]], ir elemento žymeklius [#Data], [#All], [#Headers] ir [#Totals], spręsdamas kiekvieną pagal darbo knygos lentelės modelį analizavimo metu, kol originalus formulės tekstas tiksliai atkuriamas

Viena forma sąmoningai praleista, ir ji yra ta, su kuria žmonės susiduria pirmiausia. Dabartinės eilutės trumpinys [@Column] nepalaikomas dėl struktūrinės priežasties, kurią verta suprasti, o ne aklai apeiti

Kodėl struktūrinė nuoroda nėra tiesiog diapazonas su draugišku vardu?

Todėl, kad apibrėžtas vardas užšaldo adresą, o lentelės nuoroda ne. Parašykite DataBlock kaip vardą, nurodantį į Sheet1!$A$2:$D$100, ir jis liks tuo stačiakampiu, kol kažkas jį perrašys. Parašykite Sales[Amount], ir tai reiškia „Sales lentelės Amount stulpelis", kokia bebūtų tos lentelės apimtis formulės vertinimo metu. Pridėkite dvidešimt eilučių prie lentelės, ir suma jas apims; nėra nuorodos koreguoti, nes formulėje niekada nebuvo adreso

Ta simbolinė savybė ir yra tiksliai tai, kodėl nuorodos negalima išspręsti eilučių pakeitimu. Sprendiklis turi rasti lentelę pagal vardą darbo knygoje, surasti stulpelį pagal jo antraštės tekstą, nuspręsti, kurias eilutes apima prašomas elemento žymeklis, ir sukurti konkretų stačiakampį. HotXLS tai daro formulės kompiliavimo metu per lentelės modelį, ir būtent todėl formulė, parašyta prieš lentelei augant, vis tiek įvertinama pagal dabartinę lentelės apimtį

Gramatika, kurią sprendžia HotXLS

Palaikoma specifikacijos gramatika apima vieną stačiakampį rezultatą, ir tai verta pasakyti tiksliai, nes Excel dokumentacija pateikia gerokai didesnį paviršių, nei įgyvendina dauguma variklių. HotXLS priima [Col] ir laužtinių skliaustų variantą [[Col]], gryną elemento žymeklį [#Data], [#All], [#Headers] ir [#Totals], sujungtą formą [[#Data],[Col]], intervalą elemento žymeklio viduje kaip [[#Data],[Col1]:[Col2]], ir grynąjį intervalą [Col1]:[Col2]

Tai, ką duoda šis rinkinys, yra kiekviena nuorodos forma, sukurianti vieną tolydų bloką: stulpelį, gretimų stulpelių eilę, tik pagrindinės dalies arba antraštę įtraukiantį bet kurio pjūvį. Nesusiję junginiai ir kelių sričių rezultatai lieka už jo. Kai nuorodos išspręsti nepavyksta, formulė išlaiko ankstesnę praleidimo-be-reikšmės elgseną vietoje spėjimo pakeitimo, todėl neišsprendžiama nuoroda niekada netampa tikėtinu neteisingu skaičiumi

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);
    // ... rašykite antraštės eilutę ir 24 duomenų eilutes ...

    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;

Kodėl dabartinės eilutės forma sąmoningai neįtraukta?

[@Column] ir [#This Row] reiškia „to stulpelio langelis eilutėje, kurioje gyvena ši formulė". Todėl reikšmė priklauso nuo vertinamo langelio padėties, ne tik nuo lentelės. Tai kitokia nuoroda: ne stačiakampis, kurį kompiliatorius gali išspręsti vieną kartą, o kiekvienam langeliui atskiras sprendimas, kurį reikia pakartoti kiekvienai eilutei, kurią užima formulė

HotXLS grąžina False iš lentelės diapazono sprendiklio šioms formoms, o tai jas nukreipia į praleidimo-be-reikšmės kelią. Formulės tekstas išsaugomas ir įrašomas atgal nepakitęs, todėl darbo knyga, naudojanti [@Amount], atsidaro teisingai Excel po atkūrimo per jūsų aplikaciją; trūksta tik HotXLS apskaičiuotos reikšmės. Turint pasirinkimą tarp trūkstamos reikšmės ir reikšmės, apskaičiuotos pagal neteisingą eilutę, trūkstama yra ta, kurią galite aptikti

Praktinis sprendimas mechaniškas: darbo knygoje, kurią generuojate, parašykite lygiavertę A1 stiliaus santykinę nuorodą, kurią Excel taip pat viduje saugo daugeliui lentelės apimties logikos. Darbo knygoje, kurią tiesiog apdorojate, palikite formulę tokią, kokia yra, ir skaitykite kešuotą reikšmę, kurią Excel jau saugojo, o būtent to paprastai nori įkėlimo ir ataskaitos konvejeris

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
      // Įrašų rinkinio stiliaus paieška lentelės kūne, 1 pagrindo eilutės rezultatas
      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;

Kas nutinka, kai lentelė keičia formą

Struktūrinės nuorodos paskelbiamos negaliojančiomis, o ne tyliai perrašomos, kai tai, ką jos vadina, dingsta. Ištrinkite stulpelį, ir formulės, nurodančios tą stulpelį, paskelbiamos negaliojančiomis taip pat, kaip jas paskelbia negaliojančiomis Excel; ištrinkite ar pervardykite lentelę, ir nuorodos į ją apdorojamos taip pat. Tai teisingas elgesys, ir jis atspindi įprastą nuorodos koregavimą, aprašytą straipsnyje apie formulės nuorodos koregavimą įterpiant ir šalinant, kur variklio darbas yra išlaikyti formules sąžiningas, o ne išlaikyti jas atrodančias galiojančias

Eilučių augimas yra priešingas atvejis ir visai nereikalauja koregavimo. Kadangi nuoroda vadina lentelę, o ne stačiakampį, eilučių pridėjimas lentelės ribose praplečia tai, ką apima [#Data], neliečiant nė vienos formulės. Būtent ši savybė daro lenteles vertas naudoti ataskaitos šablone: visų sumų eilutė toliau sumuoja viską, ką sukūrė importas, nesvarbu, kiek eilučių tai galiausiai buvo

Atkūrimo disciplina

HotXLS išlaiko originalų formulės tekstą. Darbo knyga, įkelta su SUM(SalesTable[Amount]), išsaugoma su SUM(SalesTable[Amount]), ne su išspręstu SUM(D2:D25). Tai svarbiau, nei gali atrodyti: naudotojas, atidarantis jūsų rezultatą Excel programoje, tikisi matyti tą formulę, kurią parašė, o išspręstas adresas tyliai paverstų savarankiškai save prižiūrintį modelį trapiu, kuris nustoja apimti naujas eilutes

Dvi susijusios galimybės užbaigia vaizdą. Pačios lentelės apibrėžtys, įskaitant lenteles be antraščių ir lentelės komentarus, atkuriamos per lentelės modelį, aprašytą straipsnyje apie duomenų validaciją, AutoFilter ir Excel lenteles. O kai daug langelių dalijasi vienu šablonu, XLSX juos saugo vieną kartą kaip bendrą formulę, kuri išplečiama ir iš naujo išvedama, kaip aprašyta straipsnyje apie bendros formulės si išplėtimą. Struktūrinės nuorodos bendrose formulėse eina per abu kelius, todėl abu turi veikti, ir jie veikia

HotXLS skaito ir rašo XLS, XLSX ir ODS iš Delphi ir C++Builder be Excel diegimo ir be Office automatizavimo, įvertindamas formules savo pačio varikliu. Lentelės modelis, formulių variklis ir perskaičiavimo API dokumentuoti HotXLS Delphi skaičiuoklių komponento puslapyje