Artikel Teknis

Menyematkan Objek Chart di Worksheet dengan HotXLS

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

HotXLS meng-anchor substream chart BIFF8 ke worksheet Delphi melalui tiga bagian yang sepakat: host-control shape lapisan drawing, record OBJ yang common object data-nya mendeklarasikan tipe objek 5, dan rantai record chart yang diparkir di ujung record stream sheet, tempat BOF chart mengganti konteks parser dan EOF penutup menempelkan kembali record-recordnya
Tiga lapisan mengangkut satu chart tersemat: drawing shape meng-anchor-nya, record OBJ mengetiknya sebagai host chart, dan substream chart di ujung sheet stream menyuplai record yang ditempelkan kembali oleh reader

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

Penerimaan referensi series HotXLS pada jalur chart BIFF8 tersemat: rentang gaya A1 seperti Data!$B$2:$B$13 di dalam workbook yang sama di-resolve terhadap daftar sheet menjadi indeks external reference yang dibutuhkan record chart, sementara named range dan referensi workbook eksternal jatuh ke placeholder dengan parsed expression berpanjang nol, keduanya dicakup AddChartSheet
Hanya rentang gaya A1 polos di dalam workbook yang sama yang dikompilasi menjadi referensi series chart; sisanya ditulis bersih sebagai placeholder sampai diarahkan ulang, dan jalur penuhnya tinggal di AddChartSheet

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