Artikel Teknis

Ekspor Rentang Sel Excel sebagai Satu Gambar dengan HotXLS

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

TXLSCellImageExporter mengukur, menggambar, dan mengodekan satu gambar per rentang sel sementara pipeline cetak membelah rentang di pemisah halaman
Pipeline halaman menyisipkan geometri kertas antara Anda dan sel-selnya; exporter sel tidak punya halaman di mana pun di jalurnya

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

Alur budget untuk TXLSCellImageExporter di HotXLS: Measure mengembalikan ukuran piksel lebih dulu, lalu MaxPixels dan MaxBytes membatasi alokasi dan ukuran output
Penolakan terjadi sebelum alokasi, dan kegagalan budget byte membiarkan gambar sebelumnya tak tersentuh untuk caller

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

Save TXLSCellImageExporter mengodekan ke berkas temp di folder yang sama, lalu mengganti target secara atomik; kegagalan membiarkan gambar sebelumnya valid
Berkas sementara harus berdiam di sebelah target karena replace atomik hanya bekerja dalam satu volume

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