Kod içinde bir fatura çalışma kitabı oluşturan ve bunu aşağı akıştaki bir sistemin içe aktarması için CSV olarak yazan bir gece işi hayal edin. Sayılar Excel'de doğru görünüyor. CSV bir metin düzenleyicide temiz bir şekilde açılıyor. Ardından içe aktarıcı toplamlar sütununda tıkanıyor, çünkü satır 42 için miktar alanı hesaplaması gereken rakam değil, kelimenin tam anlamıyla =SUM(D2:D41) formül metni olarak okunuyor. Hiçbir şey bozuk değil. Bu belgelenmiş bir davranıştır ve HotXLS'ten dışa aktarma hakkında anlaşılması gereken ilk şeydir: Yazıcı, hücre modelini tam olarak durduğu gibi serileştirir ve değeri hiçbir zaman hesaplanmamış bir formül hücresinin teslim edecek yalnızca formül metni vardır
CSV dosyanız neden sayılar yerine formüller içeriyor?
HotXLS, formül metnini ve hesaplanan değeri iki ayrı şey olarak saklar. SaveAsCSV tasarım gereği çıkış yolunda hesaplama motorunu çalıştırmaz: Bir dışa aktarım çalışma kitabını değiştirmemeli (mutate) ve patolojik bir formül zincirinde takılma riski taşımamalıdır. Excel'in kendisinin kaydettiği dosyalar, formüllerin yanında önbelleğe alınmış sonuçlar taşır, bu nedenle bunları yeniden dışa aktarmak beklediğiniz gibi davranır. Tuzak, formüllerin yazıldığı ancak hiçbir zaman değerlendirilmediği, kendi kodunuzun oluşturduğu çalışma kitaplarına özgüdür. Düzeltme, sayfalar arası başvuruları ve özel işlevleri çözen aynı Calculate motorunu kullanarak, dışa aktarmadan önce değerlerin var olmasını sağlamaktır:
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
R: Integer;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('invoice-run.xlsx');
Sheet := Book.Sheets[0];
// CSV'nin '=...' metni yerine sayıları taşıması için formül sonuçlarını somutlaştırın
for R := 2 to 41 do
if Sheet.Cells[R, 4].Formula <> '' then
Sheet.Cells[R, 4].Value := Book.Calculate(Sheet.Cells[R, 4].Formula);
Book.SaveAsCSV('feed.csv', 0, ','); // sayfa 0, virgül
Book.SaveAsCSV('feed.tsv', 0, #9); // aynı sayfa TSV olarak
finally
Book.Free;
end;
end;
Döngünün aslında ne yaptığına dikkat edin: Formül hücrelerinin üzerine hesaplanan değerlerini yazar. Bu, tek kullanımlık bir dışa aktarma geçişi için kesinlikle doğrudur ve sonrasında çalışma kitabını tekrar .xlsx olarak kaydetmek istiyorsanız yanlıştır, çünkü canlı formülleri donmuş sayılarla değiştirmiş olursunuz. Bir kopyadan dışa aktarın veya geri yazmayı yalnızca dışa aktarma çalışmasına dokunacak şekilde sınırlayın. Calculate arkasındaki motor, kendi işlevlerinizi kaydetmek de dahil olmak üzere bundan daha ileri gider; bu konu HotXLS formül motoru ve özel işlevlerde ele alınmıştır
Sınırlı (delimited) yazıcının neleri garanti ettiği
CSV yolu; byte order mark (BOM) içeren UTF-8, CRLF satır sonları ve RFC 4180 alıntılama kuralları üretir. Sınırlayıcıyı, tırnak işaretini veya satır sonunu içeren herhangi bir alan sarılır ve gömülü tırnak işaretleri çiftlenir. Tarihler, hücrenin görüntüleme biçimine bakılmaksızın yyyy-mm-dd hh:nn:ss olarak işlenir. Ekrandaki biçimlendirmenin aktarılmasını bekleyen herkesi şaşırtsa da bu, makine tüketicisi için doğru çağrıdır. Zengin metin hücreleri, çalıştırmaları birleştirilerek düzleştirilir
Bu varsayılanlar, bir ithalatçıyla olan çoğu tartışmayı başlamadan önce çözer, ancak yine de bunlardan ikisi arayüz sözleşmenize aittir. Birincisi BOM'dur. Excel'in dosyayı aksanlı karakterler bozulmadan açmasını sağlayan şey budur, ancak birkaç katı ayrıştırıcı bu üç baytı veri olarak ele alır; sizinki de bunlardan biriyse, bunları aktarımda kaldırın. İkinci ise TSV'dir. Bu ayrı bir özellik değildir, sadece sınırlayıcı olarak #9 ile çağrılan aynı yazıcıdır, bu nedenle yukarıdaki her şey onun için de değişmeden geçerlidir. Dışa aktarılacak sayfa, çok bağımsız değişkenli aşırı yüklemede 0 tabanlı dizine göre seçilirken, tek bağımsız değişkenli SaveAsCSV(FileName) kısayolu aktif sayfayı alır
HTML dışa aktarımı bir anlık görüntüdür (snapshot), bir veri değişim biçimi değil
CSV'nin değerler dışındaki her şeyi çöpe attığı yerde, SaveAsHTML görünümü korumaya çalışır: Sayfa başına bir <table>, colspan ve rowspan olarak ifade edilen birleştirilmiş bölgeler, CSS olarak satır içine yerleştirilmiş temel hücre stilleri. Temaya bağlı renkler çözümlenmek yerine atlanır, bu nedenle tema yuvalarına dayanan bir şablon Excel'de göründüğünden daha düz çıkar. Yolculuktan sağ çıkması gereken her şeye açık RGB renkleri ayarlayın. Seçenekler nesnesi zarfı kontrol eder:
var
Opts: TXLSXHtmlExportOptions;
begin
Opts := TXLSXHtmlExportOptions.Create;
try
Opts.Title := 'Weekly settlement';
Opts.TableClass := 'report-grid'; // ana sayfa stil şablonu için kanca (hook)
Opts.WriteDocument := True; // parça değil, tam sayfa
if Book.SaveAsHTML('settlement.html', 0, Opts) <> 0 then
raise Exception.Create('Sheet index out of range');
finally
Opts.Free;
end;
end;
Bu kod parçacığındaki iki ayrıntı dikkat çekicidir. WriteDocument değerini False konumuna getirdiğinizde, çıktı tam bir sayfa yerine çıplak bir tablo parçası haline gelir; bu, mevcut bir düzene bir önizleme enjekte ederken istediğiniz şeydir: TableClass'ı ayarlayın ve tema oluşturmayı ana bilgisayar stil sayfasının yapmasına izin verin. Geri dönüş kuralı da çoğu HotXLS çağrısının tersidir. SaveAsHTML başarı durumunda 0 ve hatalı sayfa dizini için -1 döndürür, bu nedenle alışkanlıktan gelen = 1 kontrolü her başarılı dışa aktarmayı bir hata olarak bildirecektir. Bir sayfanın tamamı yerine bir bölgeye ihtiyacınız olduğunda (belki de tek bir bloğu e-postayla göndermek veya gömmek için), TXLSXRange.SaveAsHTML herhangi bir dikdörtgen aralığı aynı işleme kuralları altında dışa aktarır
RTF çıktısı ve hala değerini koruduğu yerler
Dördüncü hedef, SaveAsRTF aracılığıyla çağrı başına bir sayfa olmak üzere RTF 1.6 tabloları yazar. Sütun genişlikleri, sütun genişliğinin karakteri başına kabaca 96 twip olarak tahmin edilir. Bilinmesi gereken yapısal sınırlama, birleştirilmiş hücrelerin çıktıda yayılmamasıdır: Yalnızca çıpa hücresi içeriğini taşır ve kapsanan hücreler boşluk olarak yayınlanır. Bu, RTF'yi düzen ağırlıklı şablonlar için devre dışı bırakır. Tablo sonuçlarını bir kelime işlemciye veya HTML alımından önceye dayanan eski bir belge yönetim sistemine bırakmak için en az dirençli yol olarak yine de değerini korumaktadır
Gidiş-dönüş: CSV içe aktarımı tasarım gereği yıkıcıdır
CSV'yi geri okumanın kendi sözleşmesi vardır. OpenCSV tüm çalışma kitabını temizler ve Sheet1 adında tek bir sayfa olarak yeniden oluşturur. Bu özünde bir yapıcıdır (constructor), bir birleştirme değil; bu nedenle kaydedilmemiş içerik barındıran bir çalışma kitabında asla çağırmayınız. Ayrıcı olarak #0 geçirilmesi otomatik sınırlayıcı tespitini tetikler. ADetectTypes bayrağı tür yükseltmesini (type promotion) kontrol eder: Bu açıkken sayısal dizgeler sayıya, ISO-8601 dizgeleri tarihe ve true/false boolean'a dönüşür. Akışta başında sıfır olan tanımlayıcılar, posta kodları veya ürün kodları yer alıyorsa bunu kapatın, çünkü tür yükseltmesi bunları sessizce sayılara dönüştürerek bozar (başındaki sıfır, 00123'ün 123 olmasıyla doğrudan yok olur). Her iki arayüz de aynı içe aktarımı sunar. Bunu yukarıdaki dışa aktarma çağrılarıyla eşleştirin ve süreç hattının (pipeline) hiçbir yerinde Excel yüklü olmasına ihtiyaç duymayan bir biçim köprünüz olsun; bu senaryo HotXLS ile veri tabanından Excel'e rapor oluşturmada ele alınmıştır
Doğrudan bir akışa (stream) aktarma
Buradaki her yazıcının dosya adı sürümünün yanında bir akış (stream) aşırı yüklemesi bulunur: CSV, HTML, RTF ve çalışma kitabının kendi biçimleri. Sunucu kodunda yönelinecek olanlar bu aşırı yüklemelerdir. Bir CSV indirmesine hizmet eden bir web uç noktası, geçici bir dosya, temizleme işi olmadan ve aynı oluşturulan adı seçen iki istek arasında çakışma yaşanmadan doğrudan bir TMemoryStream içine yazabilir ve bunu doğrudan yanıt nesnesine verebilir. Aynı durum, dışa aktarımları bulut depolama alanına göndermek veya giden postalara eklemek için de geçerlidir. Dosya sistemi tamamen resimden çıkar
Bu kalıp, kütüphanenin dağıtım şekliyle birleşir. Her iki arayüz de yerel Object Pascal okuyucu ve yazıcılarıdır, bu nedenle Excel kurulumu, COM otomasyonu ve sunucuda istekleri serileştiren süreç başına bir darboğaz yoktur. Her istek kendi çalışma kitabı nesnesine sahip olabilir, ilk bölümdeki hesaplama geri yazmasını çalıştırabilir ve dışa aktarımını komşularıyla paralel olarak akıtabilir. Bellek göz kulak olunması gereken tek kaynaktır. Çalışma kitabı modeli dışa aktarma süresince RAM'de yaşar, bu nedenle çok büyük dosyaları yalnızca CSV olarak yeniden yayınlamak için açan bir servis, bir trafik artışının çalışma kümesine karar vermesine izin vermek yerine eşzamanlı işleri sınırlamalı veya aşırı büyük olanları sıraya almalıdır
Daha küçük bir düğme: Parça, aşağı akıştaki bir aracın kodlama için kokladığı (sniff) bağımsız bir dosya olarak kaydedildiğinde HTML seçeneklerinde IncludeBOM ayarını yapın. HTML'i doğrudan HTTP üzerinden sunduğunuzda, karakter kümesi (charset) bildirimini yanıt başlıklarına bırakın
Baytlar hala yanlış çıktığında
CSV dışa aktarımıyla ilgili en yaygın destek sorusu, başlangıçtaki sorunun farklı bir kostüm giymiş halidir: Excel, aksanlı karakterler yerine anlaşılmaz karakterler (mojibake) gösteriyor. İçgüdüsel olarak yazıcı suçlanır ancak yazıcı tam olarak bu nedenle bir UTF-8 BOM yayınlar ve dosya kodunuzdan ayrıldığında neredeyse her zaman doğrudur. Orası ile Excel arasındaki bir şey BOM'u yemiştir. Metin modunda bir FTP aktarımı, ilk üç baytı atlayan bir akış kopyası, geçerken yeniden kodlayan bir ara sunucu: Bunlardan herhangi biri işareti kaldıracak ve Excel'i kodlamayı tahmin etmeye bırakacaktır ki bunu kötü yapar. Bunu dışa aktarma çağrısında değil, sınırda teşhis edin. Teslim edilen dosyayı bir onaltılık (hex) görüntüleyicide açın ve EF BB BF değerinin hala içindeki ilk şey olduğunu onaylayın
Dört biçimin de ortak noktası budur. Dışa aktarma çağrısı kolay kısımdır ve HotXLS, yazıcının karşılaştığı her kararda savunulabilir bir seçim yapar. Başarısızlıklar; formül metninin sayı isteyen bir ayrıştırıcıyla karşılaştığı, bir BOM'un bunu korumayan bir taşıma protokolüyle karşılaştığı, birleştirilmiş bir hücrenin RTF'nin düz tablo modeliyle karşılaştığı dikiş yerlerinde yaşanır. Bunların her biri, dışa aktarıcınız ile onu tüketen her neyse arasındaki sözleşmeye yazılması gereken bir gerçektir, çünkü tüketici niyetlerinizi baytlardan okuyamaz. Her iki çalışma kitabı arayüzündeki eksiksiz yöntem listesi için HotXLS Bileşeni ürün sayfası tam referansı taşımaktadır