Excel menyembunyikan sebuah alat pengawakutu (debugger) kecil yang terpampang jelas. Pilih sebuah sel, buka Formulas lalu klik Evaluate Formula, dan sebuah dialog akan menampilkan rumus tersebut beserta satu sub-ekspresi yang bergaris bawah. Tekan Evaluate dan sub-ekspresi tersebut akan mengempis menjadi bentuk nilainya, lantas bagian berikutnya akan ganti digarisbawahi, dan Anda dapat menyaksikan sebuah ekspresi panjang menyusut menjadi sebuah angka tunggal dari satu reduksi ke reduksi lainnya. Ini adalah cara tercepat untuk menemukan cabang mana dari fungsi IF bersarang yang sebenarnya sedang terpicu, atau referensi mana yang telah memasok nilai total yang salah. HotXLS memproduksi ulang perilaku yang persis sama tersebut melalui TXLSFormulaTracer, sehingga program Delphi atau C++Builder dapat merender daftar tahapan yang sama untuk melakukan audit pada buku kerja (workbook), mengawakutu sebuah rumus yang dihasilkan, atau mengajari seseorang tentang mengapa sebuah hasil hitung bisa muncul seperti itu. Masing-masing langkah yang terekam akan turut membawa teks sub-ekspresi serta bentuk nilai yang dihasilkan dari reduksinya
Bagaimana mesin reduksi menelusuri ekspresinya
Alat pelacak ini tidak menjangkau masuk ke dalam mesin kalkulasinya. Ia menokenisasi rumus dan mengurainya dengan pengurai turun-rekursif (recursive-descent parser), kemudian mereduksi pohon tersebut secara pencarian mendalam-dahulu (depth-first), mendahulukan sub-ekspresi terdalam yang dapat dievaluasi pertama kali. Sewaktu suatu simpul berhasil direduksi ke sebuah nilai, nilai tersebut akan disubstitusi kembali ke dalam ekspresi di sekelilingnya sebagai sebuah literal, lantas mesin tersebut bakal menanyakan kepada kalkulator aslinya untuk menghitung ulang ekspresi yang kini telah menjadi lebih sederhana itu. Karena setiap langkah dievaluasi melalui metode Calculate publik milik lembar kerjanya, alih-alih mengambil jalan pintas privat, setiap langkah akan sejalan secara presisi selaras dengan wujud apa yang niscaya bakal diproduksi oleh kalkulasi ulang secara penuh terhadap sel yang dimaksud. Pengurainya dirancang secara non-invasif dari sananya, yang mana pendekatan inilah yang memungkinkannya dapat berjalan pada lembar kerja mana pun tanpa perlu mengganggu status miliknya
Pengurai mengikuti hierarki tingkatan preseden operator, dengan satu tingkat level rekursif per pita hierarki. Berturut-turut dari ikatan hierarki terendah hingga puncaknya, tingkatan pitanya adalah: level 0 untuk pembandingan (=, <>, <, >, <=, >=), level 1 penggabungan (concatenation) string (&), level 2 pertambahan dan pengurangan, level 3 perkalian dan pembagian, level 4 eksponensiasi, serta yang terakhir adalah operator unary plus dan minus yang berada di tingkatan paling bawah. Setiap level akan mengurai level di atasnya untuk mencari operand-nya, sehingga pita hierarki yang posisinya lebih tinggi akan memiliki ikatan yang lebih kuat. Preseden yang sama inilah yang juga senantiasa diaplikasikan Excel, yang mana ia juga yang menaungi jawaban atas mengapa operasi A1*B1+A2*B1 terlebih dahulu mereduksi dua buah perkalian tersebut sebelum melakukan aksi penjumlahannya: status perkalian duduk manis di level 3, penambahan di posisi level 2, dengan kata lain posisi perkalian berada jauh lebih dalam menjorok di pepohonannya makanya ia direduksi terlebih dahulu
Melacak rumus dan menelusuri langkah-langkahnya
Skema pemakaiannya mencerminkan proyek demo yang disertakan pada direktori Demo/Delphi/FormulaTrace/FormulaTrace.dpr. Buat sebuah lembar kerja (atau buka buku kerja yang sudah ada), konstruksikan sebuah pelacak pada lembar tersebut, panggil metode Trace, dan lakukan iterasi pada larik kembaliannya. Setiap obyek TXLSFormulaStep mengekspos Depth untuk kebutuhan indentasi, Source untuk menampung sub-ekspresi aslinya, Expression untuk mewakili sub-ekspresi tersebut di mana nilai operand-nya sudah disubstitusikan, serta properti Value untuk mewadahi hasil dari langkah itu sendiri
uses
SysUtils, Variants, lxHandle, lxHandleX, lxFormulaTrace;
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Tracer: TXLSFormulaTracer;
Steps: TXLSFormulaStepArray;
Final: Variant;
I: Integer;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Order');
Sheet.Cells[1, 1].Value := 10; // A1 units
Sheet.Cells[1, 2].Value := 25; // B1 unit price
Sheet.Cells[1, 3].Value := 0.08; // C1 tax rate
Tracer := TXLSFormulaTracer.Create(Sheet);
try
Final := Tracer.Trace('A1*B1*(1+C1)', Steps);
for I := 0 to High(Steps) do
Writeln(StringOfChar(' ', Steps[I].Depth * 2),
Steps[I].Source, ' -> ', Steps[I].Expression,
' = ', VarToStr(Steps[I].Value));
Writeln('result = ', VarToStr(Final));
finally
Tracer.Free;
end;
finally
Book.Free;
end;
end;
Referensi sel akan dipecahkan pertama kali dan tampil sebagai langkah-langkah tersendiri, kemudian operasi perkalian pun direduksi, lantas disusul perhitungan faktor pajak di dalam kurung, dan akhirnya operasi perkalian terakhir akan menutupnya. Ruas Depth memudahkan Anda memberikan indentasi sehingga tingkat reduksi paling dalam nampak terlihat berada paling dalam, secara nyata persis selayaknya Excel memberikan garis bawah pada istilah bagian terdalamnya sebelum merambah menjangkau ke kawasan posisi letak porsi luar mana pun
Jebakan literal bebas-locale
Rincian paling berbahaya pada skema ini sama sekali tidak tampak pada mesin bersistem operasi Inggris, namun akan langsung memicu masalah serius pada perangkat berbahasa Jerman. Tatkala sebuah nilai hasil hitungan disubstitusi kembali ke dalam teks rumusnya, nilai tersebut wajib ditulis sebagai sebuah untaian string untuk kemudian diurai kembali oleh mesin kalkulasi yang menganggap tanda . (titik) sebagai titik desimal. Jikalau proses substitusi memanfaatkan setelan locale sistem, konfigurasi TFormatSettings milik Jerman akan menulis 1,08 untuk faktor pajaknya, dan tanda komanya akan seketika dibaca sebagai separator argumen, lantas proses perhitungan ulang atas A1*B1*1,08 akan berujung terurai ke dalam bentuk struktur yang salah atau malah gagal total sama sekali
Alat pelacak menghindari hal ini dengan jalan memformat setiap literal numerik melalui aturan TFormatSettings privat yang lantas disematkan di saat konstruksi awal, di mana parameter DecimalSeparator dipaksa menjadi . dan pengaturan ThousandSeparator disetel sebagai #0 sehingga takkan pernah ada karakter pemisah ribuan yang diterbitkan. Setelahnya FloatToStr pun akan memproduksi sebuah literal yang bakal dapat selalu dibaca kembali oleh mesin kalkulasi, tanpa perlu memusingkan seperti apa pengaturan region dari operator komputernya
// Konsep dari porsi setelan pelacak ini disematkan permanen di saat pembuatannya
FFloatFmt := FormatSettings;
FFloatFmt.DecimalSeparator := '.';
FFloatFmt.ThousandSeparator := #0;
// Tiap angka yang disusutkan kelak dicetak merujuk: FloatToStr(Double(V), FFloatFmt)
Ini adalah sebentuk jenis kutu yang tidak pernah muncul di atas pengujian pribadi si penulis program namun hanya akan mendadak mengemuka di saat ada konsumen dengan locale lain mencoba menjalankan kode yang sama, sehingga hal ini amat layak untuk dinyatakan secara nyata: proses bolak-balik pengiriman angka melewati teks rumus merupakan persoalan serialisasi, dan setiap serialisasi harus terbebas murni tanpa terikat batasan locale sedikit pun
Logika boolean direduksi ke nilai 1 dan 0
Keputusan substitusi yang berkaitan erat memusatkan fokusnya pada perlakuan atas nilai logika. Saat sebuah sub-ekspresi dievaluasi ke dalam wujud boolean, pelacak akan menuliskannya kembali sebagai 1 atau 0, bukannya sebagai TRUE atau FALSE. Alasannya adalah literal hasil reduksi tersebut diwajibkan harus mampu diuraikan ulang secara rapi di dalam konteks apa pun yang tengah menyelimutinya, dan pada wilayah operasi aritmatika hal ini menjadi persoalan yang amat krusial. Jikalau sebuah komparasi seperti A1>A2 direduksi menjadi teks TRUE lantas teks tersebut mendarat jatuh di dalam operasi TRUE*B1, kalkulasi ulang tersebut amat bergantung pada kemampuan mesin dalam menerima hadirnya kata kunci boolean begitu saja ke dalam operasi perkaliannya. Mensubstitusikan nilai 1 dapat menyingkirkan permasalahan ini secara murni, dikarenakan bilangan 1*B1 terbukti takkan punya tafsiran bias ganda dalam porsi operasi aritmatika mana pun. Hal ini juga sepenuhnya selaras dengan paksaan nilai tipe pada Excel sendiri, di mana teks TRUE berperilaku sebagai angka 1 dan susunan nilai FALSE tampil selayaknya angka 0 bilamana di mana sebuah nilai angka sangat diharapkan kemunculannya
Pemanggilan fungsi akan direduksi secara atomik
Sebuah mesin pelangkah yang naif barangkali akan lebih dulu mereduksi argumen dari fungsinya sebelum mengeksekusi pemanggilannya. Hal tersebut adalah kesalahan bagi sistem perhitungan Excel, dan alat pelacak kami menolak bertindak demikian. Sebuah pemanggilan fungsi dievaluasi secara utuh satu kesatuan, berdasarkan teks aslinya, di dalam satu langkah tunggal. Alasannya adalah semantik sirkuit-pendek (short-circuit). Fungsi IF, CHOOSE dan IFERROR mengevaluasi hanya pada cabang yang dipilihnya, dan mereduksi argumen di tahap awal akan memaksa mesin menghitung cabang yang takkan pernah disentuh oleh Excel. Korban klasik dari kejadian ini adalah pelindung pembagian-oleh-nol seperti IF(B1=0,0,A1/B1): apabila pelacak mereduksi perhitungan A1/B1 sebelum menelaah kondisi fungsi IF, porsi pelindung tersebut akan seketika meleset dan malahan menerbitkan galat yang sejatinya coba dicegahnya. Dengan mengevaluasi pemanggilan secara utuh dalam metode atomik, alat pelacak berhasil mengawetkan konsep evaluasi komputasi malas (lazy evaluation) yang membantu fitur pelindung tadi tetap bekerja sebagaimana mestinya
// IF adalah satu tahapan atomik; hanya cabang terpilih saja yang dievaluasi
Final := Tracer.Trace('IF(A1>A2,A1*B1,A2*B1)', Steps);
// A1>A2 bernilai true, karenanya rekaman jejak bakal membukukan A1*B1 sebagai hasil yang terpilih;
// Perhitungan A2*B1 tidak akan pernah diproses, langkah persis yang juga dieksekusi di dalam Excel.
Kompensasi dari hal ini adalah Anda takkan bisa meninjau bagian internal dari area pemanggilan fungsi-fungsi tersebut sebagai deretan ragam tahapan yang berdiri secara terpisah, akan tetapi itulah ragam perilaku eksekusi yang tepat. Memaksa memperlihatkan deretan langkah reduksi pemangkasan rumusan operand komponen argumen yang memang tak pernah diproses oleh Excel, hanya akan membuahkan sebuah daftar rekaman jejak yang jauh lebih menyesatkan ketimbang sebatas memosisikannya layaknya satu unit evaluasi operasi tunggal apa adanya
Separator argumen dan kelestarian rentang (range)
Dua hal seputar bentuk normalisasi lainnya turut membantu agar re-komputasi dapat beroperasi dengan jujur. Kompilator mesin penghitung sangat mengharapkan tanda ; sebagai penyekat argumen fungsi, sehingga sewaktu pelacak merekonstruksi ulang sebuah pemanggilan fungsi dari struktur pohon hasil uraiannya, ia akan senantiasa menyatukan semua argumen menggunakan ;, meskipun sang pengguna pada awalnya mengetikkan ,. Sebuah rumus yang ditulis dalam format SUM(A1,A2,A3) akan lekas direkomputasikan ulang bentuknya ke dalam SUM(A1;A2;A3), sehingga barulah pihak mesin kalkulasinya dapat berkenan membacanya. Penggantian nilai rupa nilai dari angka aslinya hal ini merupakan pemicu dibangunnya format rekonstruksi ini amatlah krusial diwujudkan, di samping mendapatkan karakter pemisah argumen secara benar hal mana pula ia yang memuluskan jalannya proses urai rekonstruksi itu
Referensi rentang (range) adalah kasus kedua. Sebuah rentang seperti A1:A3 bukanlah bilangan skalar tunggal dan dilarang keras untuk dipecah ke dalam wujud tiga besaran yang saling terpisah, mengingat fungsi pengonsumsi yang dituju memang mengharuskan asupan dari argumentasi berwujud rentang. Peranti pelacak sanggup senantiasa memelihara kelestarian wujud teks murni milik rentang tersebut untuk kemudian dievaluasi langsung oleh penampung fungsi keseluruhannya secara utuh merangkul. Pada perintah semacam SUM(A1:A3)*B1 rentangan operasinya tersebut akan selalu terjaga utuh murni, blok komponen instruksi SUM(A1:A3) pun bakal segera direduksi ke dalam bentuk sebuah wujud nilai besaran tunggal secara satu tahap komputasi penguraian reduksi atomik, barulah operasi perkalian sisi terluarnya akan turut memproses fungsinya. Hal ini sejalan lurus persis wujud pembatas ranah yang turut ditarik diimplementasikan oleh pihak Excel yang menempatkan pemisahan tegas antara bagian parameter rupa rentang dengan elemen komponen format skalar mutlak yang pada ahirnya nanti akan dipersembahkannya pada pihak fungsi pemanggil tersebut
// Area rentang wujud A1:A3 tak bakal dibongkar pisah; SUM tampil murni satu tahapan pengerjaan reduksi satuan,
// kelak selanjutnya operasi urusan di lini kalinya rupa bersanding B1 akan disorongkan masuk tahap jalannya.
Final := Tracer.Trace('SUM(A1:A3)*B1', Steps);
for I := 0 to High(Steps) do
Writeln(Steps[I].Source, ' = ', VarToStr(Steps[I].Value));
Bila dipadukan bersama, deretan semua rumusan pedoman ini akan sukses membantu wujud dari daftar barisan susunan langkah tersebut menjadi tak ubahnya sebatas kembaran bayangan wujud perlakuan tulus cerminan presisi seputar bagaimana proses sesungguhnya tata aksi perintah Evaluate Formula punya Excel itu, alih-alih menjadi format rekaan komputasi semu sebatas pengaproksimasian bayangannya belaka. Runtutan segala tahapan di proses pemangkasan itu benar-benar murni diaplikasikan secara sinkron di segenap alur urutan tahapan kerjanya di sisi pihak Excel jalankan, elemen kembalian hasil angkanya bakal tangguh beroperasi pada semua rentangan locale, unsur jenis data boolean diyakini turut bertindak sesuai hukum Excel memaksa wujud rupa hal tersebut, lantas fungsional gaya santai pada pemrosesan fungsional bermalasnya akan selalu menjaga ketetapannya. Andaikata porsi rupa perihal hasrat dan antusias Anda sekiranya kian kencang memacu agar daya komponen dapur pacu mesin penelusur ini melesat kian mendalam dalam rupa dukungan fungsi penunjang buatan spesifik milik Anda, artikel mengenai mesin fungsional komputasi rumus dan fasilitas komputasi racikan kustom (custom functions) khusus memperlihatkan bagaimanakah rutinitas pencatatannya, sementara terkhusus pekerjaan porsi numerik yang lebih berat lagi artikel panduan seputar komponen sarana operasional distribusi perhitungan statistik edisi Delphi menaungi sepenuhnya rupa jajaran himpunan fungsi pustaka standar peruntukan fungsionalnya yang menjadi penopang operasional pengerjaan sang peranti komponen alat pelacak ini mengevaluasi muatan nilai di dalamnya. Segenap muatan tersebut semuanya sudah dipaket merata menjadi wujud sebentuk satuan edisi komponen rupa wujud format sebentuk sepotong ranah perangkat sarana fungsional fitur rupa wujud sarana wujud fitur wujud bentuk fungsional format komponen wujud komponen HotXLS spreadsheet (lembar kerja komputasi hamparan) untuk Delphi dan C++Builder, berdampingan menyertai porsi barisan jangkauan koleksi operasional proses deretan baca, tulis, format, dan kumpulan komponen penyusunan proses komputasi yang pernah diliput ranah peninjauannya di dalam kumpulan tulisan di segenap ranah laman ranah rute lingkungan rute blog blog lingkungan blog ini