Teknik Makale

HotXLS ile Excel Hücre Aralığını Tek Görüntüye Aktarmak

Bazen teslim edilecek şey bir belge değil, bir tablonun resmidir. Durum e-postasındaki bir özet bloğu, bir panoda çizilmiş bir KPI paneli, bir arama sonucunun yanındaki küçük resim: hepsi hücreleri ister ve hiçbiri kâğıt istemez. HotXLS'teki TXLSCellImageExporter, klasik ya da XLSX bir hücre dikdörtgenini alır ve sayfa boyutu olmadan, kenar boşlukları olmadan, üstbilgi ya da altbilgi olmadan, baskı başlıkları olmadan ve sayfa sonları olmadan tek bir kompakt PNG ya da JPEG üretir. Çözünürlük, ölçek, biçim ve JPEG kalitesi yapılandırılabilirdir; nesneler, kılavuz çizgileri ve hücre kenarlıklarının bağımsız anahtarları vardır; arka plan bir renk ya da saydam olabilir ve dosya yazımı, bir şey ters giderse mevcut hedefi dokunulmamış bırakan atomik aynı klasör değiştirmesinden geçer

Bunun, baskı yolundaki bir bayrak yerine kendi çıkarıcısını gerektirmesinin nedeni, sayfalamanın kapatabileceğiniz isteğe bağlı bir katman olmamasıdır. Sayfa hattı var olmak için yapılan şey odur

Aralık neden baskı hattı üzerinden çizilmez?

Çünkü baskı hattı, sizinle hücreler arasına bir sayfa koyar. Kâğıt boyutu neyin sığacağına karar verir, kenar boşlukları içeriği içeri iter, üstbilgi ve altbilgi istemediğiniz bantları işgal eder, baskı başlıkları zaten sahip olduğunuz satırları tekrarlar ve sayfa sonları aralığı böler. Tesadüfen bir son çizgisine denk gelen özet bloğu, ilgi çekici satırı ortadan bölünmüş iki görüntü olarak çıkar. Bütün bunları aralığı tam olarak eşleyen özel bir sayfa boyutu kurarak telafi edebilirsiniz ve insanlar eder, ama bu, aralık her değiştiğinde kâğıt geometrisini yeniden hesaplamak demektir ve üstbilgi bandı ile baskı başlığı mantığını da yolda bırakmaya devam eder

Hücre çıkarıcı dikdörtgeni ölçer, tam o boyutta bir bit eşlem ayırır, hücreleri içine çizer ve kodlar. Sayfa yoktur; dolayısıyla kapatılacak bir yapılandırma da yoktur. Gerçekten kâğıt istediğiniz durumlar için PDF dışa aktarma yolu doğru araçtır ve çalışma sayfası PDF dışa aktarma makalesinde kapsanır

TXLSCellImageExporter hücre aralığı başına bir görüntüyü ölçüp çizip kodlarken baskı hattı aralığı sayfa sonlarında böler
Sayfa hattı sizinle hücreler arasına kâğıt geometrisi koyar; hücre çıkarıcının yolda hiçbir yerde sayfası yoktur

Çizmeden önce ölçün

Measure, hiçbir şey kodlamadan geçerli ayarların üreteceği piksel boyutlarını döndürür. Bu iki nedenle önemlidir. Bir HTML ya da e-posta şablonu genellikle görüntü var olmadan önce boyutlarına ihtiyaç duyar; böylece kutuyu ayırabilir ve düzen kaymasını önler. Ve kullanıcı seçimli aralıkları çizen bir hizmet, ona ayırma yapmadan önce absürt bir isteği reddetmenin bir yoluna ihtiyaç duyar

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 ince vuruşları net tutar
      Exporter.DPI := 96;
      Exporter.Scale := 2.0;             // retina yoğunluklu çıktı
      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 ve H artık biliniyor; kodlamadan önce düzen kutusunu ayırın
      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;

Bütçeler, çünkü ölçek çarpar

MaxPixels ile MaxBytes savunmacı süs değildir. Piksel sayısı ölçek çarpanının karesiyle ve çözünürlük oranının karesiyle büyür; dolayısıyla 96 DPI'da makul bir 1200'e 800 olan aralık, 600 DPI'da kabaca 47 megapikselleşir ve bir özet bloğu yerine kullanılan tüm aralığı seçen kullanıcı bunun üstüne bir büyüklük mertebesi daha ekler. Sınır olmadan hata modu, işlemin karşılayamayacağı bir ayırmadır ve o işlemin yaptığı her başka şeyi de düşürür

Sınırla istek başarısız olur ve çağıran seçebilir: reddetmek, ölçeği azaltmak ya da aralığı daraltmak. Bir rapor sunucusu için çok daha iyi bir konumdur ve sınırlı EMF ve WMF kod çözücü makalesinde anlatılan metafile kod çözücünün açık bütçelerinin arkasındaki akıl da aynıdır

HotXLS'te TXLSCellImageExporter için bütçe akışı: Measure önce piksel boyutunu döndürür, sonra MaxPixels ile MaxBytes ayırmayı ve çıktı boyutunu sınırlar
Ret, ayırmadan önce gerçekleşir ve bir bayt bütçesi başarısızlığı önceki görüntüyü çağıran için dokunulmamış bırakır

Atomik değiştirme ve klasörün neden önemli olduğu

Bir dosya adına Save, hedefin içine yazmaz. Aynı klasörde geçici bir dosya yazar, onun içine kodlar ve ancak ondan sonra hedefin yerine koyar. Kodlama başarısız olursa, bütçe yolda aşılırsa ya da işlem öldürülürse önceki görüntü hâlâ oradadır ve hâlâ geçerlidir. Kutucuklarını bir zamanlamayla yeniden üreten bir pano bu nedenle asla kırpmış bir PNG göstermez; o, hedefi açıp akmaya başlayan naif bir yazımın alışılmış belirtisidir

Aynı klasör ayrıntısı tesadüfi değildir. Atomik bir değiştirme yalnızca tek bir birim içinde atomiktir; çünkü birimler arası işletim sisteminin önce kopyalayıp sonra silmesi gerekir ve bu, kapatmaya çalıştığınız pencereyi yeniden açar. Bu desenin geçici dosyasını sistem geçici dizinine koyan her uygulama, çıktının farklı bir sürücüde yaşadığı bir makinede atomik değildir

TXLSCellImageExporter Save, aynı klasörde geçici bir dosyaya kodlar, sonra hedefi atomik olarak değiştirir; başarısızlıklar önceki görüntüyü geçerli bırakır
Geçici dosya hedefin yanında yaşamalıdır; çünkü atomik değiştirme yalnızca tek bir birim içinde çalışır

Boyama olayları gerçek canvas üzerine çizer

Hem aralık çıkarıcı hem sayfa çıkarıcı ön ve arka boyama olayları açar ve bunlar yalnızca bir canvas tanıtıcısı değil eksiksiz salt okunur bir bağlam alır. TXLSPagePaintContext, canlı canvası, piksel sınırlarını, punto cinsinden sayfa boyutunu, gerçekte kullanımda olan çözünürlük ve ölçeği, belge sayfa numarasını, sayfa içi sayfa numarasını, toplam sayfa sayısını, sayfa adını ve hem klasik hem XLSX çeşidinde kaynak çalışma sayfasını taşır. Doğru ölçeklenen bir filigran ya da dizide nerede olduğunu bilen bir sayfa damgası çizmek için bu yeterlidir

procedure TReportJob.StampDraft(Sender: TObject;
  const AContext: TXLSPagePaintContext);
begin
  // Ölçek duyarlı, böylece damga 1x'te ve 3x'te aynı görünür
  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;

Üç davranış güvenilmeye değerdir. Olaylar, çok sayfalı bir TIFF'in her karesi dahil, çizilen kare başına tam olarak bir kez tetiklenir; dolayısıyla işleyicide artırılan bir sayaç güvenilirdir. Ölçüm sırasında sessiz kalırlar; dolayısıyla yan etkili bir işleyici bir çıktı için iki kez çalışmaz. Ve ön olay yükselirse arka olay tetiklenmez ve kısmi görüntü baytları yazılmaz; dolayısıyla kendi çizim kodunuzdaki bir istisna yarım damgalı bir dosya üretemez

Biçimi seçmek

Metin ağırlıklı her şey için PNG. JPEG, ince yüksek karşıtlıklı vuruşların çevresinde görünür çınlama üreten blok bir dönüşüm uygular; hücre kenarlıkları ve küçük metin tam olarak odur ve artefaktlar, bir fotoğrafın kusursuz göründüğü kalite ayarlarında hayatta kalır. JPEG, aralık gömülü fotoğraflarca domine edildiğinde ve dosya boyutu kenar sadakatinden önemli olduğunda yerini hak eder. Saydam arka planlar PNG gerektirir; JPEG'in alfa kanalı yoktur, dolayısıyla renkli bir yüzeyin üzerine oturması tasarlanan kutucuk seçimi sizin yerinize yapmıştır

Aralığınız birleştirilmiş hücreler içeriyorsa çıktıyı sayfayla karşılaştırın: birleştirilmiş bölgeler, insanları şaşırtan biçimlerde sütun genişlikleriyle etkileşir ve düzen kuralları birleştirilmiş hücreler ve rapor şablonları makalesinde kapsanır. HotXLS, XLS, XLSX, ODS ve CSV'yi Excel bağımlılığı olmadan Delphi ve C++Builder'dan okur ve yazar; çıkarıcı yüzeyinin tamamı HotXLS Delphi spreadsheet component ürün sayfasında belgelenir