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
Ç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
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
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