HotXLS bisa menempatkan chart langsung di worksheet, ter-anchor ke sebuah rentang sel, alih-alih menaruhnya di chart sheet khusus. Dalam istilah BIFF8 itu berarti menulis drawing shape dengan record OBJ tipe 5 dan memarkir substream chart di ujung record stream sheet — persis tata letak yang dihasilkan Excel dan persis tempat reader mengharapkannya
Distingsinya berarti bagi siapa pun yang menghasilkan laporan operasional. Chart sheet adalah rumah yang pas untuk satu visual headline. Rincian bulanan per wilayah ingin chart-nya di samping angka yang dirangkumnya, di sheet yang sama, berukuran sesuai blok sel tempatnya — sehingga pembaca menggulir sekali alih-alih berpindah tab dan kehilangan konteks
Membaca sudah ada, menulis belum
Asimetrinya layak dinamai karena membentuk pekerjaannya. HotXLS sudah bisa membaca chart tersemat: ketika record stream worksheet memuat BOF yang ditandai sebagai substream chart, parser mengganti konteks, mengumpulkan record chart, dan pada EOF penutup menyerahkannya kembali ke drawing shape yang diperkenalkan record OBJ. Jalur itu sudah terlatih oleh setiap workbook buatan Excel yang pernah dibuka pustaka ini
Yang belum ada adalah sisi penulisannya, dan konsekuensi bermanfaatnya adalah writer baru itu punya spesifikasi tepat untuk dipenuhi: hasilkan tata byte yang sudah ditempelkan kembali oleh reader yang ada. Tidak ada kriteria penerimaan yang lebih baik untuk fitur format biner daripada reader yang ditulis independen yang tidak Anda minta untuk diubah
Dari apa chart tersemat itu tersusun
Tiga bagian harus sepakat. Lapisan drawing menyumbangkan host-control shape, lapisan objek menyumbangkan record OBJ yang common object data-nya mendeklarasikan tipe objek 5, dan record stream menyumbangkan substream chart itu sendiri. Flag opsi pada record OBJ adalah yang ditulis Excel untuk chart frame: positioned, locked, automatic line dan automatic fill — itulah yang membuat chart tersemat berperilaku seperti chart native saat pengguna mengekliknya
Anchor-nya layak dicatat karena sumber umum bug off-by-one. API HotXLS menerima nomor baris dan kolom basis satu, serasi dengan sisa pustaka, dan client anchor yang ditulis ke file berbasis nol. Konversinya terjadi di dalam AddChartObject, jadi pemanggil tetap berada di sistem koordinat yang dipakai di mana-mana, tapi siapa pun yang membandingkan hex dump dengan pemanggilannya sendiri perlu ingat berada di sisi mana dari batas itu
var
Book: TXLSWorkbook;
Sheet: TXLSWorksheet;
Series: array[0..1] of TXLSChartSeriesInfo;
begin
Book := TXLSWorkbook.Create(nil);
try
Book.LoadFromFile('regional-sales.xls');
Sheet := Book.Sheets[0];
FillChar(Series, SizeOf(Series), 0);
Series[0].Name := 'Actual';
Series[0].Categories := 'Data!$A$2:$A$13';
Series[0].Values := 'Data!$B$2:$B$13';
Series[0].DataLabels.ShowValue := True;
Series[0].HasDataLabels := True;
Series[1].Name := 'Target';
Series[1].Categories := 'Data!$A$2:$A$13';
Series[1].Values := 'Data!$C$2:$C$13';
Series[1].SecondaryAxis := True;
// Ter-anchor ke E2:M20 di sheet ini, basis satu
Sheet.AddChartObject(xlsChartTypeColumn, 'Regional sales',
'Month', 'Amount', Series, 2, 5, 20, 13);
Book.SaveToFile('regional-sales-charted.xls');
finally
Book.Free;
end;
end;
FillChar pada array series itu bukan hiasan. TXLSChartSeriesInfo membawa beberapa sub-record opsional — data label, style per series, trendline, dan error bar — masing-masing digerbangi boolean, dan record setengah terinisialisasi di stack akan menyerahkan flag kepada emitter yang tidak pernah disetel siapa pun. Nolkan arraynya, lalu set field yang Anda maksud
Referensi series mana yang diterima jalur tersemat?
Rentang gaya A1 polos di dalam workbook yang sama, dan pembatasan itu disengaja, bukan kelalaian. Setiap referensi di-resolve terhadap daftar sheet workbook dan diubah menjadi indeks external reference yang dibutuhkan record chart. Named range atau referensi workbook eksternal jatuh ke placeholder dengan parsed expression berpanjang nol, jadi chart-nya ditulis bersih tapi series khusus itu tak punya sumber data sampai Anda mengarahkannya ke sebuah rentang
Alasannya adalah pertukaran rekayasa yang lugas. Jalur kompilasi referensi penuh ada di rute chart sheet, dibungkus di dalam lapisan koleksi worksheet, dan mengangkatnya keluar dengan bersih berarti menduplikasi seratus baris logika resolusi untuk kasus yang tidak umum dalam praktik. Chart tersemat hampir selalu mem-plot sel di sheet-nya sendiri atau sheet data kandung. Named dan external reference dicakup di jalur chart sheet lewat AddChartSheet, jadi tak ada yang tidak tersedia — hanya dijangkau dari entry point berbeda
Sisanya dalam model series bekerja identik di kedua rute. Binding sumbu sekunder, style line, fill dan marker per series, trendline, error bar dan data label semuanya bagian dari TXLSChartSeriesInfo dan semuanya dipancarkan dengan cara sama, sehingga definisi chart bisa berpindah antara objek tersemat dan chart sheet dengan hanya pemanggilannya yang berubah. Mekanika axis-group di balik flag sumbu sekunder dibahas di grup sumbu sekunder pada penulisan BIFF
Mengapa judul chart terbaca dua karakter?
Karena jumlah karakter diberikan di tempat jumlah byte yang diharapkan, dan string Unicode BIFF membuat kesalahan itu gampang ditulis dan sulit dilihat. String Unicode BIFF pendek diawali jumlah karakter dan satu byte flag, dan byte flag itu membawa bit high-byte yang menyatakan apakah payload satu byte per karakter atau dua. Baca payload 16-bit dengan jumlah karakter seolah panjang byte dan Anda mendapat persis separuh string: series bernama Sales kembali sebagai Sa, dan judul chart terpotong dengan cara sama karena judul dan label series berbagi jalur dekode
Yang membuat cacat ini patut dicatat adalah kemunculannya tiga kali dalam keluarga record yang sama: sekali di nama trendline, sekali di nama pivot chart, dan sekali di judul chart. Tiap kemunculan tampak seperti bug segar di fitur baru. Ketiganya adalah perkalian yang hilang yang sama. Aturan yang akhirnya menutup kasus ini mekanis dan seharusnya diterapkan tanpa penilaian: kapan pun Anda membaca salah satu string ini, periksa flag high-byte dulu dan kalikan jumlah karakter dengan lebar payload sebelum menyentuh buffer. Detail level record dibahas di mendekode jumlah karakter XLUnicodeString dan flag high-byte
// Chart tersemat berbagi drawing layer dengan image dan shape,
// jadi drawing yang sudah ada di sheet dipertahankan. AddChartObject
// mengembalikan indeks objek yang dibuat
var
ObjIndex: Integer;
begin
ObjIndex := Sheet.AddChartObject(xlsChartTypeLine, 'Trend',
'Week', 'Units', Series, 2, 8, 18, 16);
if ObjIndex < 0 then
raise Exception.Create('chart object was not created');
end;
Di mana chart tersemat menempati posisi dibanding alternatifnya
Tiga rute ada dan ketiganya menjawab pertanyaan berbeda. Objek chart tersemat berhak berada di samping datanya di worksheet dan itulah yang diinginkan kebanyakan laporan. Chart sheet cocok untuk satu visual presentasi dan memberi Anda jalur kompilasi referensi penuh. Mempertahankan chart yang sudah ada dari file termuat, tanpa disentuh, adalah jawaban yang tepat ketika workbook datang dari Excel dengan format yang tak ingin pustaka reinterpretasikan; perilaku pass-through itu dideskripsikan di ChartML terpelihara dan combination chart
Karena chart tersemat menumpang lapisan drawing, ia hidup berdampingan dengan image dan shape di sheet yang sama alih-alih menggantikan mereka, dan model umum lapisan itu dibahas di chart, image dan drawing di HotXLS. Ketiga rute tersedia dalam komponen spreadsheet Delphi HotXLS, jadi pilihannya adalah soal seperti apa laporan itu seharusnya terlihat, bukan soal apa yang bisa diekspresikan pustaka
Poin metodologislah yang layak disimpan. Ketika fitur format biner punya reader yang sudah ada, bangun writernya terhadap reader itu, bukan terhadap pembacaan Anda atas spesifikasinya. Reader mengenkode bertahun-tahun kontak dengan file yang benar-benar dihasilkan aplikasi nyata, termasuk bagian yang dinyatakan spesifikasi secara longgar, dan writer yang memenuhinya jauh lebih mungkin memenuhi Excel juga