HotXLS kompilerer formler skrevet i R1C1-referansenotasjon via TXLSCalculator.GetCompiledFormulaR1C1, som godtar former som R2C3 (absolutt), R[-1]C[2] (relativt avvik) og RC (den gjeldende cellen), konverterer dem til A1-notasjon basert på raden og kolonnen til cellen formelen lever i, og sender resultatet til den samme kompilatoren som håndterer vanlige A1-formler. For Delphi- og C++Builder-kode som genererer den samme formelen over hundrevis av rader, fjerner denne ene metoden en hel klasse med streng-sammenslåingsfeil
Denne feilklassen er velkjent for alle som har fylt en kolonne programmatisk. Du går i løkke over rader, og for hver rad bygger du en A1-formelstreng med Format('D%d*E%d', [Row, Row]). Hver iterasjon spleiser radnumre inn i teksten, og radnumrene er den eneste delen som endres. Gjør du feil med avviket én gang, blander en 0-basert løkketeller med 1-baserte A1-radnumre, eller forskyver datablokken med en overskriftsrad, vil hver formel i kolonnen peke én rad feil. Ingenting utløser unntak; tallene blir rett og slett feil. Formelen du faktisk mente, "multipliser de to cellene til venstre for meg," nevner aldri et radnummer i det hele tatt, og R1C1-notasjon lar deg skrive den slik
Hva er R1C1-notasjon og når bør du bruke den?
R1C1-notasjon adresserer celler etter rad- og kolonnenummer i stedet for kolonnebokstav pluss radnummer, og den markerer relative referanser som eksplisitte avvik fra formelcellen. R2C3 is den absolutte cellen på rad 2, kolonne 3, som A1 skriver som $C$2. R[-1]C[2] er én rad opp og to kolonner til høyre for der formelen befinner seg. RC er selve formelcellen. Avvikene i klammeparenteser er poenget: en relativ referanse i R1C1 leses likt uansett hvilken celle som er vert for den, mens A1-gjengivelsen av den samme referansen endres for hver rad
Notasjonen forsvarer plassen sin i akkurat ett scenario, og det er et vanlig et: malgenerering, der den samme relative formelen må plasseres i hver rad i et dataområde. I A1 må du generere formelteksten på nytt per rad. I R1C1 er teksten en konstant. Dette er også nærmere hvordan filformater for regneark tenker internt: poster for delte formler lagrer relative referanser som rad- og kolonneavvik fra vertscellen, så en A1-streng per rad er noe koden din bare syntetiserer for at tolkeren skal dekomponere den rett tilbake til avvik. R1C1 hopper over denne omveien. For interaktive, menneskeskrevne formler forblir A1 det naturlige valget, noe som er grunnen til at det forblir standarden overalt i HotXLS
Hvordan kompilerer HotXLS en R1C1-formel?
HotXLS eksponerer funksjonen på to nivåer, lagt til i v2.175.0. TXLSCalculator.GetCompiledFormulaR1C1(UncompiledFormula: String; SheetID, CurRow, CurCol: Integer): TXLSCompiledFormula er den de fleste kaller: den returnerer en kompilert formel klar for evaluering, akkurat som sitt A1-søsken GetCompiledFormula, men med to ekstra parametere som angir den 0-baserte raden og kolonnen for cellen formelen tilhører. Under den produserer TXLSFormula.GetCompiledR1C1 det rå syntakstreet, og en frittstående funksjon R1C1ToA1(const AFormula: String; CurRow, CurCol: Integer): String utfører selve notasjonskonverteringen. Rørledningen er bevisst enkel: oversett R1C1-tekst to tilsvarende A1-tekst ved hjelp av koordinatene til vertscellen, og kompiler deretter A1-teksten gjennom den eksisterende motoren — den samme motoren som løser opp definerte navn og referanser på tvers av ark og utfører egendefinerte regnearkfunksjoner
Fordi konverteringen skjer før kompilering, oppfører alt nedstrøms seg som om du hadde skrevet A1-formelen selv. R1C1ToA1('R2C3', 4, 3) returnerer '$C$2' uavhengig av vertscellen, fordi begge koordinater er absolutte. R1C1ToA1('SUM(R[-3]C[0]:R[-1]C[0])', 4, 3) — en formel som lever i D5, ettersom CurRow = 4 og CurCol = 3 er 0-baserte — returnerer 'SUM(D2:D4)': avvikene ble løst opp mot rad 5, kolonne D, og sendt ut som vanlige relative A1-referanser. Områder trenger ingen spesiell behandling; kolonet passerer gjennom, og hvert endepunkt konverteres uavhengig
// The formula lives in D5: CurRow = 4, CurCol = 3 (both 0-based)
S := R1C1ToA1('R2C3', 4, 3);
// S = '$C$2' (absolute row and column)
S := R1C1ToA1('SUM(R[-3]C[0]:R[-1]C[0])', 4, 3);
// S = 'SUM(D2:D4)' (offsets resolved against D5)
S := R1C1ToA1('ROUND(R[-1]C[0], 2)', 4, 3);
// S = 'ROUND(D4, 2)' (the R in ROUND is left alone)
Fylle en kolonne med én relativ formel
Gevinsten viser seg i løkken. Sammenlign A1-versjonen, som genererer formelteksten på nytt ved hver iterasjon, med R1C1-versjonen, der formelen er en konstant og bare vertskoordinatene beveger seg. Begge kompilerer via TXLSCalculator og evaluerer med GetValue; kalkulatoren tar en celle-leverandør-tilbakekall ved opprettelse, slik at evaluatoren kan hente celleverdier fra datakilden din
// A1 style: a different formula string for every row
for Row := 1 to 500 do
begin
FormulaText := Format('D%d*E%d', [Row + 1, Row + 1]); // 1-based A1 rows
Compiled := Calc.GetCompiledFormula(FormulaText, 0);
// ... evaluate, store, free ...
end;
const
AmountFormula = 'RC[-2]*RC[-1]'; // two cells to the left, same row
var
Calc: TXLSCalculator;
Compiled: TXLSCompiledFormula;
Value: Variant;
Row: Integer;
begin
Calc := TXLSCalculator.Create(nil, Provider.GetValue);
try
for Row := 1 to 500 do
begin
Compiled := Calc.GetCompiledFormulaR1C1(AmountFormula, 0, Row, 5);
try
if Calc.GetValue(0, Compiled, Row, 5, Value, 1) = lxOk then
StoreResult(Row, 5, Value);
finally
Compiled.Free;
end;
end;
finally
Calc.Free;
end;
end;
R1C1-løkken har ingen rad-aritmetikk i selve formelteksten i det hele tatt. 'RC[-2]*RC[-1]' betyr "samme rad, to kolonner til venstre, ganget med samme rad, én kolonne til venstre" på rad 2 så vel som på rad 500, og hvis datablokken senere flyttes ned med en overskriftsrad, endres ikke formelkonstanten — bare løkkegrensene gjør det. A1-versjonen har tre steder hvor + 1-justeringen kan bli feil; R1C1-versjonen har null
Hvilke R1C1-former godtar konvertereren?
Konvertereren R1C1ToA1 gjenkjenner formene dokumentert for v2.175.0: R[n]C[m] for relative avvik i begge retninger, RnCm for absolutt rad og kolonne, R[-n]C[m] med negative avvik, bare RC for selve formelcellen, og områder som R1C1:R3C3 eller R[-1]C:R[1]C. Rad- og kolonnedelene tolkes uavhengig, så blandede former som R[1]C3 — relativ rad, absolutt kolonne — fungerer også, og bokstavene er ufølsomme for store/små bokstaver, slik at r[-1]c[2] kompilerer likt som sin storebror. Deler i klammeparentes blir til uforankrede (relative) A1-koordinater; rene tall blir til $-forankrede absolutte koordinater
Det interessante spørsmålet er hvordan konvertereren unngår å ødelegge alt annet i formelen, ettersom R og C er vanlige bokstaver. Diskrimineringsregelen er token-basert: en R regnes bare som starten på en referanse når den ikke har en annen bokstav foran seg, og kandidaten må deretter tolkes fullstendig — valgfri raddel, obligatorisk C, valgfri kolonnedel — ellers gjenopprettes teksten urørt. Det er derfor ROUND(R[-1]C[0], 2) konverterer den indre referansen: R-en i ROUND blir etterfulgt av O i stedet for et siffer, en klamme eller C, så tolkningen feiler og funksjonsnavnet passerer uendret gjennom. Den samme logikken beskytter ROW(), og funksjonsnavn som begynner med C er aldri kandidater i det hele tatt, ettersom bare R starter en referanse. Utgivelsesnotatene for v2.175.0 slår fast at strengliteraler og identifikatorer også hoppes over; likevel, hvis en sitert literal i formelen din skulle inneholde tekst som er utformet nøyaktig som en R1C1-referanse, er det verdt å sjekke de kompilerte utdataene én gang før du stoler på dem i produksjon
Koordinatbaser og forankringsdetaljer verdt å vite
To konvensjoner møtes i dette API-et, og å holde dem adskilt unngår den eneste virkelige fellen. Parameterne CurRow og CurCol i GetCompiledFormulaR1C1 er 0-baserte, i tråd med kalkulator-API-et, mens tallene inne i selve notasjonen er 1-baserte, noe som matcher det Excel viser: R2C3 er rad 2, kolonne 3, som er $C$2, ikke $D$3. Hvis løkketelleren din allerede er 0-basert, sender du den rett gjennom som CurRow; + 1-justeringen lever inne i konvertereren, ikke i din kode
En detalj til betyr noe hvis den kompilerte formelen vil overleve cellen den ble kompilert for. Når du utelater en rad- eller kolonnedel — formene RC[-1] eller R[2]C — løses den utelatte koordinaten opp til vertscellen og sendes ut som en absolutt, $-forankret koordinat i den konverterte A1-teksten. Ved evalueringstidspunktet er dette usynlig, ettersom verdien er den samme uansett. Men relativ-mot-absolutt forankring bestemmer hvordan referanser forskyves når rader eller kolonner settes inn eller slettes senere, som dekket i den tilhørende artikkelen om justering av formelreferanser. Hvis du trenger at en koordinat skal forbli relativ gjennom strukturelle endringer, skriver du avviket eksplisitt — R[0]C[-1] i stedet for RC[-1] — slik at konvertereren sender ut en uforankret A1-referanse
R1C1-kompilering er en del av formelmotoren i HotXLS Delphi Excel Component, ved siden av A1-kompilatoren, rekalkuleringsgrafen og evaluerings-API-et vist over. Hvis koden din bygger regneark by looping formulas down columns, moving those loops from string-spliced A1 to a single R1C1 constant is one of the cheapest reliability upgrades available