Artikel Teknis

Notasi Rumus R1C1 di Delphi dengan HotXLS

HotXLS mengompilasi rumus yang ditulis dalam notasi referensi R1C1 melalui TXLSCalculator.GetCompiledFormulaR1C1, yang menerima bentuk seperti R2C3 (absolut), R[-1]C[2] (offset relatif), dan RC (sel saat ini), mengonversinya ke notasi A1 terhadap baris dan kolom sel tempat rumus tersebut berada, dan memasukkan hasilnya ke kompiler yang sama yang menangani rumus A1 biasa. Untuk kode Delphi dan C++Builder yang menghasilkan rumus yang sama di ratusan baris, metode tunggal tersebut menghilangkan seluruh kelas bug penggabungan string

Kelas bug ini akrab bagi siapa saja yang telah mengisi kolom secara terprogram. Anda melakukan loop di atas baris, dan untuk setiap baris Anda membangun string rumus A1 dengan Format('D%d*E%d', [Row, Row]). Setiap iterasi menyambungkan nomor baris ke dalam teks, dan nomor baris adalah satu-satunya bagian yang berubah. Salah menentukan offset sekali saja, mencampur penghitung loop berbasis 0 dengan nomor baris A1 berbasis 1, atau menggeser blok data oleh baris tajuk, dan setiap rumus dalam kolom akan menunjuk selisih satu baris. Tidak ada kesalahan yang muncul; angkanya salah begitu saja. Rumus yang sebenarnya Anda maksud, "kalikan dua sel di sebelah kiri saya," tidak pernah menyebutkan nomor baris sama sekali, dan notasi R1C1 memungkinkan Anda menulisnya seperti itu

Apa itu notasi R1C1 dan kapan Anda harus menggunakannya?

Notasi R1C1 mengalamatkan sel berdasarkan nomor baris dan kolom alih-alih huruf kolom ditambah nomor baris, dan notasi ini menandai referensi relatif sebagai offset eksplisit dari sel rumus. R2C3 adalah sel absolut pada baris 2, kolom 3, yang dieja A1 sebagai $C$2. R[-1]C[2] adalah satu baris di atas dan dua kolom di sebelah kanan dari mana pun rumus tersebut berada. RC adalah sel rumus itu sendiri. Offset dalam tanda kurung siku adalah intinya: referensi relatif dalam R1C1 dibaca sama tidak peduli sel mana yang menampungnya, sedangkan penggambaran A1 dari referensi yang sama berubah di setiap baris

Notasi ini sangat berharga dalam satu skenario yang sangat umum

Notasi ini sangat berharga dalam satu skenario yang sangat umum: pembuatan templat, di mana rumus relatif yang sama harus ditempatkan di setiap baris wilayah data. Di A1 Anda harus merender ulang teks rumus per baris. Di R1C1 teks tersebut adalah konstanta. Ini juga lebih dekat dengan cara format berkas spreadsheet berpikir secara internal: rekaman rumus bersama (shared-formula records) menyimpan referensi relatif sebagai offset baris dan kolom dari sel host, sehingga string A1 per baris adalah sesuatu yang disintesis kode Anda hanya untuk diuraikan kembali menjadi offset oleh parser. R1C1 melewatkan perjalanan pulang pergi (round trip). Untuk rumus interaktif buatan manusia, A1 tetap menjadi pilihan alami, itulah sebabnya notasi A1 tetap menjadi default di mana-mana di HotXLS

Bagaimana HotXLS mengompilasi rumus R1C1?

HotXLS mengekspos fitur ini pada dua tingkat, yang ditambahkan di versi 2.175.0. TXLSCalculator.GetCompiledFormulaR1C1(UncompiledFormula: String; SheetID, CurRow, CurCol: Integer): TXLSCompiledFormula adalah yang paling sering dipanggil: ia mengembalikan rumus terkompilasi yang siap untuk dievaluasi, persis seperti saudara A1-nya GetCompiledFormula, tetapi dengan dua parameter ekstra yang menyebutkan baris dan kolom berbasis 0 dari sel tempat rumus tersebut berada. Di bawahnya, TXLSFormula.GetCompiledR1C1 menghasilkan pohon sintaksis mentah, dan fungsi mandiri R1C1ToA1(const AFormula: String; CurRow, CurCol: Integer): String melakukan konversi notasi yang sebenarnya. Salurannya sengaja dibuat sederhana: menerjemahkan teks R1C1 ke teks A1 yang setara menggunakan koordinat sel host, lalu mengompilasi teks A1 melalui mesin yang ada — mesin yang sama yang menyelesaikan nama yang ditentukan dan referensi lintas lembar kerja serta mengirimkan fungsi lembar kerja kustom

Karena konversi terjadi sebelum kompilasi, segala sesuatu di hilir berperilaku seolah-olah Anda telah menulis sendiri rumus A1 tersebut. R1C1ToA1('R2C3', 4, 3) mengmengembalikan '$C$2' terlepas dari sel host, karena kedua koordinat bersifat absolut. R1C1ToA1('SUM(R[-3]C[0]:R[-1]C[0])', 4, 3) — rumus yang berada di D5, karena CurRow = 4 dan CurCol = 3 berbasis 0 — mengmengembalikan 'SUM(D2:D4)': offset diselesaikan terhadap baris 5, kolom D, dan dipancarkan sebagai referensi A1 relatif biasa. Rentang tidak memerlukan penanganan khusus; titik dua lewat dan setiap titik akhir dikonversi secara independen

// Rumus berada di D5: CurRow = 4, CurCol = 3 (keduanya berbasis 0)
S := R1C1ToA1('R2C3', 4, 3);
// S = '$C$2'  (baris dan kolom absolut)

S := R1C1ToA1('SUM(R[-3]C[0]:R[-1]C[0])', 4, 3);
// S = 'SUM(D2:D4)'  (offset diselesaikan terhadap D5)

S := R1C1ToA1('ROUND(R[-1]C[0], 2)', 4, 3);
// S = 'ROUND(D4, 2)'  (huruf R pada ROUND dibiarkan)

Mengisi kolom dengan satu rumus relatif

Hasilnya terlihat di dalam loop. Bandingkan versi A1, yang merender ulang teks rumus di setiap iterasi, dengan versi R1C1, di mana rumus tersebut adalah konstanta dan hanya koordinat host yang bergerak. Keduanya dikompilasi melalui TXLSCalculator dan dievaluasi dengan GetValue; kalkulator mengambil callback penyedia sel (cell-provider callback) pada saat konstruksi sehingga evaluator dapat menarik nilai sel dari sumber data Anda

// Gaya A1: string rumus berbeda untuk setiap baris
for Row := 1 to 500 do
begin
  FormulaText := Format('D%d*E%d', [Row + 1, Row + 1]);  // baris A1 berbasis 1
  Compiled := Calc.GetCompiledFormula(FormulaText, 0);
  // ... evaluasi, simpan, bebaskan ...
end;
const
  AmountFormula = 'RC[-2]*RC[-1]';  // dua sel di sebelah kiri, baris yang sama
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;

Loop R1C1 tidak memiliki aritmatika baris dalam teks rumus sama sekali. 'RC[-2]*RC[-1]' berarti "baris yang sama, dua kolom kiri, dikali baris yang sama, satu kolom kiri" di baris 2 and di baris 500 sama saja, dan jika blok data kemudian bergeser ke bawah oleh baris tajuk, konstanta rumus tidak berubah — hanya batas loop yang berubah. Versi A1 memiliki dua tempat yang berisiko salah dalam penyesuaian + 1; versi R1C1 memiliki nol

Bentuk R1C1 mana yang diterima konverter?

Konverter R1C1ToA1 mengenali bentuk yang didokumentasikan untuk versi 2.175.0: R[n]C[m] untuk offset relatif di kedua arah, RnCm untuk baris-dan-kolom absolut, R[-n]C[m] dengan offset negatif, RC kosong untuk sel rumus itu sendiri, dan rentang seperti R1C1:R3C3 atau R[-1]C:R[1]C. Bagian baris dan kolom diurai secara independen, sehingga bentuk campuran seperti R[1]C3 — baris relatif, kolom absolut — berfungsi juga, dan huruf-hurufnya tidak sensitif huruf (case-insensitive), sehingga r[-1]c[2] dikompilasi sama dengan kembaran huruf besarnya. Bagian dalam tanda kurung siku menjadi koordinat A1 tanpa jangkar (relatif); nomor kosong menjadi koordinat absolut yang dijangkar $

Pertanyaan menariknya adalah bagaimana konverter menghindari kerusakan elemen lain dalam rumus, karena R dan C adalah huruf yang umum. Aturan diskriminasinya berbasis token: huruf R hanya dianggap sebagai awal referensi ketika tidak didahului oleh huruf lain, dan kandidat harus dapat diurai sepenuhnya — bagian baris opsional, huruf C wajib, bagian kolom opsional — atau teks dikembalikan tanpa disentuh. Itulah sebabnya ROUND(R[-1]C[0], 2) hanya mengonversi referensi di dalamnya: R dalam ROUND diikuti oleh O alih-alih digit, tanda kurung, atau C, sehingga penguraian gagal dan nama fungsi dilewatkan kata demi kata. Logika yang sama melindungi fungsi ROW(), dan nama fungsi yang dimulai dengan C tidak pernah menjadi kandidat sama sekali, karena hanya R yang memulai referensi. Catatan rilis v2.175.0 menyatakan bahwa literal string dan pengidentifikasi (identifiers) juga dilewati; meskipun demikian, jika literal dalam tanda kutip dalam rumus Anda kebetulan berisi teks yang bentuknya persis seperti referensi R1C1, ada baiknya untuk memeriksa hasil kompilasi sekali sebelum memercayainya di produksi

Basis koordinat dan detail penjangkaran yang perlu diketahui

Dua konvensi bertemu di dalam API ini, dan memahaminya dengan benar menghindari satu-satunya perangkap nyata. Parameter CurRow dan CurCol dari GetCompiledFormulaR1C1 berbasis 0, mengikuti API kalkulator, sedangkan nomor di dalam notasi itu sendiri berbasis 1, cocok dengan apa yang ditampilkan Excel: R2C3 adalah baris 2, kolom 3, yang merupakan $C$2, tidak $D$3. Jika penghitung loop Anda sudah berbasis 0, Anda meneruskannya langsung sebagai CurRow; penyesuaian + 1 hidup di dalam konverter, bukan di kode Anda

Satu detail lagi penting jika rumus terkompilasi bertahan lebih lama daripada sel tempat ia dikompilasi. Ketika Anda menghilangkan bagian baris atau kolom — bentuk RC[-1] atau R[2]C — koordinat yang dihilangkan akan diselesaikan ke sel host dan dipancarkan sebagai koordinat absolut yang dijangkar $ dalam teks A1 yang dikonversi. Pada waktu evaluasi hal ini tidak terlihat, karena nilainya sama saja. Namun, penjangkaran relatif versus absolut menentukan bagaimana referensi bergeser ketika baris atau kolom disisipkan atau dihapus kemudian, seperti yang dibahas dalam artikel pendamping tentang penyesuaian referensi rumus. Jika Anda memerlukan koordinat untuk tetap relatif melalui pengeditan struktural, tulis offset secara eksplisit — R[0]C[-1] alih-alih RC[-1] — sehingga konverter memancarkan referensi A1 tanpa jangkar

Kompilasi R1C1 adalah bagian dari mesin rumus di HotXLS Delphi Excel Component, bersama dengan kompiler A1, grafik perhitungan ulang, dan API evaluasi yang ditunjukkan di atas. Jika kode Anda membangun lembar kerja dengan melakukan loop rumus ke bawah kolom, memindahkan loop tersebut dari A1 yang disambung string menjadi konstanta R1C1 tunggal adalah salah satu peningkatan keandalan termurah yang tersedia