Kadang hasil kerjanya bukan dokumen, melainkan gambar dari sebuah tabel. Blok ringkasan di email status, panel KPI yang dirender di dashboard, thumbnail di samping hasil pencarian: semuanya menginginkan sel-selnya dan tidak ada yang menginginkan kertas. TXLSCellImageExporter di HotXLS menerima persegi sel klasik atau XLSX dan menghasilkan satu PNG atau JPEG kompak tanpa ukuran halaman, tanpa margin, tanpa header atau footer, tanpa judul cetak, dan tanpa pemisah halaman. Resolusi, skala, format, dan kualitas JPEG dapat dikonfigurasi, objek, gridline, dan border sel punya switch independen, latar bisa berupa warna atau transparan, dan penulisan berkas melewati penggantian atomik satu folder yang membiarkan target yang ada tak tersentuh jika ada yang gagal
Alasan ini membutuhkan exporter sendiri alih-alih flag pada jalur pencetakan adalah paginasi bukan lapisan opsional yang bisa Anda matikan. Ia adalah hal yang menjadi alasan keberadaan pipeline halaman
Mengapa tidak merender rentang melalui pipeline cetak?
Karena pipeline cetak menyisipkan halaman antara Anda dan sel-selnya. Ukuran kertas menentukan berapa yang muat, margin mendorong konten ke dalam, header dan footer menempati pita yang tidak Anda minta, judul cetak mengulang baris yang sudah Anda punya, dan pemisah halaman membelah rentangnya. Blok ringkasan yang kebetulan mengangkasa di atas pemisah keluar sebagai dua gambar dengan baris yang menarik terpotong di tengah. Anda bisa mengompensasi semua itu dengan menyiapkan ukuran halaman kustom yang persis cocok dengan rentangnya, dan orang-orang memang melakukannya, tetapi itu berarti menghitung ulang geometri kertas setiap kali rentang berubah dan tetap menyisakan logika pita header dan judul cetak di jalurnya
Exporter sel mengukur persegi itu, mengalokasikan bitmap berukuran persis itu, menggambar sel-sel ke dalamnya, dan mengodekan. Tidak ada halaman, sehingga tidak ada yang perlu dikonfigurasi agar pergi. Untuk kasus di mana Anda memang menginginkan kertas, jalur ekspor PDF adalah alat yang tepat dan dibahas dalam artikel ekspor PDF worksheet
Ukur sebelum Anda merender
Measure mengembalikan dimensi piksel yang akan dihasilkan pengaturan saat ini tanpa mengodekan apa pun. Itu penting karena dua alasan. Template HTML atau email biasanya membutuhkan dimensi gambar sebelum gambarnya ada, sehingga bisa mencadangkan kotaknya dan menghindari layout shift. Dan layanan yang merender rentang pilihan pengguna membutuhkan cara menolak permintaan yang absurd sebelum mengalokasikan untuknya
uses
lxHandleX, lxPagination;
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Exporter: TXLSCellImageExporter;
Summary: TXLSXRange;
W, H, Bytes: Integer;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('quarter.xlsx');
Sheet := Book.Sheets.ByPos[0];
Summary := Sheet.Range['A1:F20'];
Exporter := TXLSCellImageExporter.Create;
try
Exporter.ImageFormat := xpifPng; // PNG menjaga goresan tipis tetap tajam
Exporter.DPI := 96;
Exporter.Scale := 2.0; // output dengan kepadatan retina
Exporter.IncludeGridlines := False;
Exporter.IncludeCellBorders := True;
Exporter.TransparentBackground := True;
Exporter.MaxPixels := 40 * 1000 * 1000;
Exporter.MaxBytes := 8 * 1024 * 1024;
if not Exporter.Measure(Summary, W, H) then
raise Exception.Create('range exceeds the configured budget');
// W dan H kini diketahui; cadangkan kotak layout sebelum mengodekan
Bytes := Exporter.Save(Summary, 'summary.png');
if Bytes <= 0 then
raise Exception.Create('image export failed, previous file kept');
finally
Exporter.Free;
end;
finally
Book.Free;
end;
end;
Budget, karena skala berlipat
MaxPixels dan MaxBytes bukan hiasan defensif. Jumlah piksel tumbuh dengan kuadrat faktor skala dan dengan kuadrat rasio resolusi, sehingga rentang yang wajar berukuran 1200 kali 800 pada 96 DPI menjadi kira-kira 47 megapiksel pada 600 DPI, dan pengguna yang memilih seluruh rentang terpakai alih-alih blok ringkasan menambahkan satu orde magnitudo lagi di atasnya. Tanpa batas, mode kegagalannya adalah alokasi yang tidak bisa dipenuhi proses, yang merobohkan apa pun yang sedang dikerjakan proses itu
Dengan batas, permintaan gagal dan caller bisa memilih: menolak, mengurangi skala, atau menyempitkan rentang. Itu posisi yang jauh lebih baik untuk report server, dan itu penalaran yang sama di balik budget eksplisit di dekoder metafile yang dijelaskan dalam artikel dekoder EMF dan WMF berbatas
Penggantian atomik, dan mengapa folder itu penting
Save ke sebuah nama berkas tidak menulis ke dalam target. Ia menulis berkas sementara di folder yang sama, mengodekan ke dalamnya, dan baru kemudian mengganti target. Jika pengodean gagal, jika budget terlampaui di tengah jalan, atau jika proses dibunuh, gambar sebelumnya masih ada dan masih valid. Dashboard yang meregenerasi tile-nya terjadwal karenanya tidak pernah menampilkan PNG terpotong, yang merupakan gejala lazim dari penulisan naif yang membuka tujuan dan mulai mengalirkan
Detail satu folder itu bukan kebetulan. Replace atomik hanya atomik dalam satu volume, karena lintas volume sistem operasi harus menyalin lalu menghapus, yang mengembalikan jendela yang sedang Anda tutup. Implementasi apa pun dari pola ini yang menaruh berkas sementaranya di direktori temp sistem tidak atomik di mesin yang outputnya berada di drive berbeda
Event paint menggambar di canvas yang sesungguhnya
Baik exporter rentang maupun exporter halaman memaparkan event paint pembuka dan penutup, dan keduanya menerima konteks read-only yang lengkap alih-alih sekadar handle canvas. TXLSPagePaintContext membawa canvas yang hidup, batas piksel, ukuran halaman dalam poin, resolusi dan skala yang benar-benar dipakai, nomor halaman dokumen, nomor halaman dalam sheet, total jumlah halaman, nama sheet, dan worksheet asalnya dalam varian klasik maupun XLSX. Itu cukup untuk menggambar watermark yang terskala dengan benar, atau cap halaman yang tahu di mana ia berada dalam rangkaian
procedure TReportJob.StampDraft(Sender: TObject;
const AContext: TXLSPagePaintContext);
begin
// Sadar skala, sehingga cap tampak sama pada 1x dan 3x
AContext.Canvas.Font.Height := Round(-48 * AContext.Scale);
AContext.Canvas.Font.Color := clSilver;
AContext.Canvas.Brush.Style := bsClear;
AContext.Canvas.TextOut(AContext.Bounds.Left + Round(24 * AContext.Scale),
AContext.Bounds.Top + Round(24 * AContext.Scale), 'DRAFT');
end;
Exporter.AfterPaint := Job.StampDraft;
Tiga perilaku layak diandalkan. Event-event itu menembak tepat sekali per frame yang dirender, termasuk setiap frame TIFF multi halaman, sehingga penghitung yang dinaikkan di handler bisa dipercaya. Mereka tetap diam selama pengukuran, sehingga handler dengan efek samping tidak berjalan dua kali untuk satu output. Dan jika event pembuka melempar exception, event penutup tidak menembak dan tidak ada byte gambar parsial yang ditulis, sehingga exception di kode menggambar Anda sendiri tidak bisa menghasilkan berkas setengah bercap
Memilih format
PNG untuk apa pun yang padat teks. JPEG menerapkan transform blok yang menghasilkan ringing yang terlihat di sekitar goresan tipis kontras tinggi, yang persis adalah border sel dan teks kecil, dan artefaknya bertahan pada pengaturan kualitas di mana foto tampak sempurna. JPEG mengukir tempatnya ketika rentang didominasi foto tertanam dan ukuran berkas lebih penting daripada kesetiaan tepi. Latar transparan mensyaratkan PNG, karena JPEG tidak punya channel alpha, sehingga tile yang dimaksudkan duduk di atas permukaan berwarna telah membuat pilihan itu untuk Anda
Jika rentang Anda berisi sel gabungan, periksa outputnya terhadap sheet: region gabungan berinteraksi dengan lebar kolom dengan cara yang mengejutkan orang, dan aturan layoutnya dibahas dalam artikel sel gabungan dan template laporan. HotXLS membaca dan menulis XLS, XLSX, ODS, dan CSV dari Delphi dan C++Builder tanpa dependensi Excel, dan permukaan exporter lengkap didokumentasikan di halaman produk HotXLS Delphi spreadsheet component