HotXLS įvertina Excel LAMBDA kaip tikrą pirmos klasės funkcijos reikšmę. Apibrėžtas vardas, kurio RefersTo tekstas yra LAMBDA, gali būti iškviestas pagal vardą kaip =MyFunc(5), uždarinys, susietas LET viduje, gali būti iškviestas kaip =LET(f, LAMBDA(x, x*2), f(21)), o leksinė aplinka, pagauta apibrėžimo metu, keliauja kartu su uždariniu. Formulės tekstas tiksliai atkuriamas darbo knygoje
Tai yra funkcija, kuri atskiria formulių variklį nuo formulių analizatoriaus. Viskas prieš LAMBDA galėjo būti įvertinta apeinant reikšmių medį. LAMBDA reikalauja sričių dėklo, ir turint sričių dėklą, visa naudotojo sukurtos skaičiuoklės logikos klasė pradeda veikti jūsų Delphi aplikacijoje, o ne tik Excel programoje
Kodėl dauguma ne Excel variklių sustoja ties LAMBDA raktažodžiu?
Todėl, kad klasikinis skaičiuoklės vertintojas turi lygiai vieną reikšmių rūšį: skaičių, eilutę, loginę reikšmę, klaidą, arba nuorodą į langelius, laikančius tas reikšmes. Nėra kur padėti funkciją. Kai Excel 365 pristatė LAMBDA, jis pridėjo reikšmės tipą, nešantį parametrų vardus, kūno išraišką ir susiejimus, matomus ten, kur ji buvo parašyta. Variklis be šio tipo gali analizuoti LAMBDA(x, x*2) ir saugoti tekstą, tačiau tuo momentu, kai langelis bando ją iškviesti, nėra ko iškviesti
HotXLS įgyvendina trūkstamą dalį kaip uždarinio reikšmę ir vykdymo laiko sričių dėklą. Uždarinio iškvietimas pastumia jo pagautą aplinką, tada pastumia argumentų reikšmes po parametrų vardais, įvertina kūną ir sutrumpina dėklą atgal iki žymos. Ta tvarka svarbi, ir kitas skyrius paaiškina kodėl
Trys būdai, kaip iškviečiama LAMBDA
HotXLS išsprendžia iškvietimą nežinomam funkcijos vardui per tris kelius, bandomus paeiliui, o žinojimas, kuris iš jų suveikia, paaiškina daugumą netikėtumų. Pirma, vardas, susietas dabartinėje LET arba LAMBDA srityje: jei f yra vietinis susiejimas, laikantis uždarinį, f(21) jį pritaiko. Antra, darbo knygos apibrėžtas vardas, kurio formulės tekstas prasideda LAMBDA: MyFunc(5) sukompiliuoja to vardo kūną ir jį pritaiko. Trečia, klasikinis naudotojo funkcijos apdorojiklis, nepakitęs, viskam, ko pirmi du keliai nepretenduoja
Vietinis susiejimas, laikantis kažką kito nei uždarinį, nėra iškviečiamas. Susiekite f su skaičiumi 3, tada parašykite f(21), ir gausite reikšmės klaidą, o ne bandymą daugybai. Tai griežčiau, nei elgtųsi dinaminė kalba, ir sąmoningai taip: rašybos klaida, paverčianti funkcijos iškvietimą atsitiktine nuoroda, yra tylus neteisingas atsakymas, o tai yra blogiausias rezultatas, kurį gali sukurti skaičiuoklės variklis
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Model');
// Pakartotinai naudojama pavadinta funkcija, darbo knygos sritis
Book.DefinedNames.Add('NetOf', 'LAMBDA(amount, rate, amount*(1-rate))');
Sheet.Cells[2, 2].Formula := 'NetOf(1250, 0.19)';
// Uždarinys, susietas ir pritaikytas vienoje formulėje
Sheet.Cells[3, 2].Formula := 'LET(double, LAMBDA(x, x*2), double(21))';
// Įdėtas LET: kiekvienas susiejimas matomas tiems, kurie eina po jo
Sheet.Cells[4, 2].Formula :=
'LET(base, 100, bump, LAMBDA(v, v+base), LET(step, bump(5), step*2))';
Book.Recalculate;
Book.SaveAs('lambda-model.xlsx');
finally
Book.Free;
end;
end;
Kaip išsprendžiamas užstojimas, kai vardai sutampa?
Laimi parametrai. Kai HotXLS pritaiko uždarinį, jis pastumia pagautą leksinę aplinką pirmiausia, o argumentų susiejimus antra, todėl parametras, pavadintas rate, užstoja išorinį susiejimą, pavadintą rate, o taip pat užstoja tokio paties pavadinimo stulpelio nuorodą aplinkinėje formulėje. Ta tvarka ir daro pavadintą funkciją saugią pakartotiniam naudojimui: iškviečiantysis negali netyčia pakeisti to, ką reiškia kūnas, turėdamas panašiai pavadintą susiejimą srityje
Argumentų skaičius tikrinamas prieš bet ką įvertinant. Iškvietimas, kurio argumentų skaičius nesutampa su uždarinio parametrų skaičiumi, iškart grąžina reikšmės klaidą, o ne įvertina dalį argumentų ir tada suklysta, o tai palaiko šalutinio poveikio neturintį įvertinimą tikrai be dalinio darbo. Sričių dėklas sutrumpinamas atgal iki jo įėjimo žymos finally bloke, todėl klaida kūne negali palikti pasenusio susiejimo matomo kitai formulei
var
Book: TXLSXWorkbook;
Name: TXLSXDefinedName;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open('customer-model.xlsx') = 1 then
begin
// Patikrinkite, ką naudotojas parašė prieš pasitikint perskaičiavimu
Name := Book.DefinedNames.FindByName('NetOf');
if (Name <> nil) and
(UpperCase(Copy(Name.Formula, 1, 6)) = 'LAMBDA') then
Log('Named lambda found: ' + Name.Formula);
Book.Recalculate;
Log(VarToStr(Book.Sheets[1].Cells[2, 2].Value));
end;
finally
Book.Free;
end;
end;
LET nebe dalinė
Ankstesnės HotXLS versijos LET įgyvendino tik tiek, kad apdorotų įprastą vieno susiejimo atvejį. Dabartinė realizacija pilna: kiekvienas susiejimas matomas visiems vėlesniems susiejimams ir kūno išraiškai, o įdėtas LET dera normaliai, todėl LET(a, 1, b, a+1, LET(c, b*2, c)) įvertinamas taip, kaip jį įvertina Excel
Šis pilnumas svarbesnis, nei skamba. LET yra būdas, kuriuo naudotojai išvengia to paties poišraiškio perskaičiavimo penkis kartus vienoje formulėje, todėl realios darbo knygos jį naudoja būtent tokiose giliai įdėtose formose, kuriose dalinė realizacija klysta. Jei anksčiau apeidavote spragas išplėsdami LET susiejimus prieš įvertinimą, to darbo aplinkkelio nebereikia
Kablelis ar kabliataškis: dabar abu
Formulės tekstas HotXLS dabar priima kablelį kaip argumentų skirtuką šalia klasikinio kabliataškio. Tai ne lokalės nustatymas; tai priėmimo taisyklė analizatoriuje. Tai svarbu, nes formulės atkeliauja iš vietų, kurių nekontroliuojate: įklijuota iš pagalbos užklausos, nukopijuota iš dokumentacijos, sugeneruota scenarijaus, kuris išvedė Excel kanoninę sintaksę, importuota iš formulės eilučių CSV
Praktinė pasekmė ta, kad SUM(A1,A2) ir SUM(A1;A2) abi sukompiliuojamos. Atkūrimas išlaiko tai, ką naudojo šaltinis, todėl įkelta darbo knyga įrašoma atgal su savo originaliais skirtukais, o ne normalizuota už naudotojo nugaros
Kas atkuriama, ir ką tikrinti
Formulės tekstas saugomas tiksliai, todėl LAMBDA pavadintame varde išgyvena įkėlimo ir įrašymo ciklą nepakitusi ir atsidaro Excel kaip ta pati funkcija. Grynoji LAMBDA, saugoma kaip langelio rezultatas, tai yra formulė, kuri įvertinama kaip uždarinys, o ne kaip reikšmė, išlaiko esamą praleidimo-be-reikšmės elgseną: tekstas išsaugomas, joks kešuotas skaitinis rezultatas jam nesugalvojamas. Tai sąžiningas rezultatas, nes nėra ko kešuoti
Verta įprasti dviejų dalykų. Suteikite pavadintiems lambda darbo knygos sritį, jei nėra priežasties to nedaryti, nes lakšto apimties funkcija, kuri dingsta, kai lakštas nukopijuojamas, sukuria vardo klaidą toli nuo priežasties; srities taisyklės aprašytos straipsnyje apie apibrėžtus vardus ir tarplakštines formules. O kai darbo knyga, pilna pavadintų lambda, skirta ataskaitai, kuri turi būti stabili, apsvarstykite rezultatų užšaldymą su ConvertFormulasToValues, kad tolesni naudotojai matytų skaičius, o ne funkcijas, kurių jie gal nepalaiko
Sunkiam perskaičiavimui LAMBDA kūnai yra paprastos išraiškos priklausomybių grafe ir planuojamos kaip bet kuri kita formulė, o tai aprašyta straipsnyje apie prieauginį perskaičiavimą ir priklausomybių grafą. Jei jūsų modelis iškviečia vieną pavadintą funkciją per tūkstančius eilučių, kaina yra kūnas, ne iškvietimo mechanizmas, ir taikomas tas pats optimizavimo patarimas kaip bet kuriai pasikartojančiai formulei
HotXLS yra natyvus Delphi ir C++Builder skaičiuoklių komponentas, skaitantis ir rašantis XLS, XLSX ir ODS be Excel ar bet kokio Office automatizavimo. Formulių variklis, apibrėžti vardai ir perskaičiavimo API dokumentuoti HotXLS Delphi skaičiuoklių komponento puslapyje