Yıllardır .xlsx üreten bir Delphi raporlama arka ucu yeni bir gereksinim alır: kamu sektöründen bir müşterinin satın alma kuralları OpenDocument Spreadsheet çıktısını zorunlu kılar ve o hesaptaki analistler düzenlemelerini LibreOffice'ten kaydedilmiş .ods dosyaları olarak geri gönderir. Şimdi aynı kodun ODS'yi hem yazması hem okuması gerekiyor. losLab'ın Delphi ve C++Builder için yerel Object Pascal elektronik tablo kütüphanesi olan HotXLS, hiçbir yerde Excel ya da LibreOffice kurulu olmadan her iki yönü de ele alır. Yapmadığı şey ise iki yönü simetrik yapmaktır. Dışa aktarma, içe aktarmanın geri kazandığından çok daha fazlasını taşır ve aksini varsayan bir ekip, formüllerin ve biçimlendirmenin müşterinin revizyonu ile bir sonraki rapor arasında bir yerde, işaret edecek hiçbir hata olmadan buharlaştığını izler
ODS desteği XLS cephesinde değil, XLSX cephesinde yaşar
HotXLS tek bir paket içinde iki bağımsız sınıf hiyerarşisi gönderir: ikili BIFF8 .xls dosyaları için lxHandle biriminde TXLSWorkbook ve OOXML .xlsx paketleri için lxHandleX biriminde TXLSXWorkbook. Her OpenDocument giriş noktası - OpenODS, SaveAsODS, GetODSSheetNames - TXLSXWorkbook'a asılıdır. Bu yerleşim keyfi değildir. OASIS ODF 1.3'te belirtildiği gibi bir ODS paketi, bir mimetype üyesi, bir manifest ve bir content.xml gövdesi taşıyan bir zip arşividir, ki bu onu OOXML zip'inin yapısal bir kuzeni yapar; BIFF8 ise ortak hiçbir yanı olmayan 1990'lardan kalma ikili bir kayıt akışıdır
Bu yerleşimin pratik bir keskin kenarı var: eski bir .xls çalışma kitabı tek bir çağrıda .ods olamaz. BIFF içeriğini önce lxXlsxExport biriminden SaveXLSWorkbookAsXLSX ile XLSX modeline köprülersiniz, sonucu TXLSXWorkbook aracılığıyla yeniden açarsınız, ardından oradan dışa aktarırsınız. Köprü kayıpsız değildir ve üzerine inşa etmeden önce boşlukları bilmeye değer. Değerleri, formülleri, sayı biçimlerini, fontları, dolguları ve sütun genişliklerini kopyalar. Kenarlıkları, birleştirilmiş aralıkları, yorumları, grafikleri ve koşullu biçimlendirmeyi düşürür. Ağır biçimlendirmeli bir .xls kaynağı, ODS'ye ayrıldığından daha sade görünerek ulaşır ve bu, ODS yazıcısının değil, köprünün bir özelliğidir
İçe aktarma tarafında tespit otomatiktir. Düz Open metodu bir ODS paketini mimetype üyesinden tanır, bu üye yoksa üst düzey bir content.xml kontrolüne geri döner, bu yüzden genel bir "kullanıcının ne yüklediğini aç" kod yolunun kendi uzantı koklamasına ihtiyacı yoktur. Açıldıktan sonra, SourceFormat özelliği hangi dalın tetiklendiğini bildirir
TODSExportOptions ile ODS'ye dışa aktarma
Dışa aktarma çağrısının kendisi tek bir satırdır; onun etrafındaki seçenekler nesnesi, bir incelemecinin daha sonra soracağı kararları taşır:
var
Book: TXLSXWorkbook;
Opts: TODSExportOptions;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('quarterly-report.xlsx');
Opts := TODSExportOptions.Create; // çağıran buna sahiptir ve serbest bırakır
try
Opts.Generator := 'ReportService 4.2'; // meta:generator geçersiz kılma
Opts.IncludeCharts := True;
Opts.IncludeImages := True;
Book.SaveAsODS('quarterly-report.ods', Opts);
finally
Opts.Free;
end;
finally
Book.Free;
end;
end;
Seçenekler nesnesine çağıran sahiptir. HotXLS onu serbest bırakmaz, bu yüzden içteki try..finally oradadır ve isteğe bağlı değildir. Çıktıyı yalnızca etiketlemek yerine değiştiren iki özelliğe daha yakından bakmaya değer. IncludeCharts := False ayarlamak grafikleri gizlemekten fazlasını yapar: grafik alt belgelerini ve manifest girdilerini paketten çıkarır, ki bu tam olarak tüketicinin onlara takılacak bir veri hattı olduğu durumda istediğiniz şeydir. Generator, aksi halde HotXLS/<version> okuyan ODF meta:generator dizesini geçersiz kılar; aşağı akış araçları desteği yönlendirmek için dosya üreticilerini parmak izi olarak tanıdığında bunu geçersiz kılın. Bunların hiçbiri geçerli değilse, seçenekler nesnesini tamamen atlayın. SaveAs(FileName, xlsxOpenDocumentSpreadsheet)'i çağırmak, varsayılanlarla SaveAsODS ile aynıdır ve ikisindeki akış aşırı yüklemeleri, paketi hiçbir geçici dosya olmadan doğrudan bir HTTP yanıtına yazmanıza izin verir
İçe aktarma yolunun okuduğu - ve kasıtlı olarak atladığı
Herhangi birine gidiş-dönüş sadakati vaat etmeden önce bu kısmı dikkatle okuyun. HotXLS'te ODS içe aktarma kasıtlı olarak hafif bir yoldur. Skaler hücre değerlerini ve her formülün kayıt zamanında taşıdığı önbelleğe alınmış sonucu korur ve tekrarlanan satırları ve sütunları ızgaraya genişletir. Stilleri, ODS formül ifadelerini ya da çizimleri taşımaz
Formül seçimi en çok ısırma olasılığı olandır ve kasıtlı olarak yapılmıştır. Bir ODF hücresi yan yana iki şey saklar: ODF 1.3 Bölüm 4'te tanımlanan OpenFormula lehçesinde yazılmış formül ifadesi ve üreten uygulamanın onun için hesapladığı son değer. OpenFormula'yı Excel formül sözdizimine çevirmek, fonksiyon kelime dağarcıkları, referans sözdizimi ve hata modelleri etrafında gerçek uç durumlara sahip kendi lehçe dönüştürme problemidir. Bunun yerine önbelleğe alınmış değeri okumak, o sessiz yanlış çeviri sınıfının tamamını atlar, bu yüzden içe aktardığınız sayılar tam olarak göndericinin son gördüğü sayılardır. Maliyeti, onların canlı, kendilerini üreten formüller olarak değil sayılar olarak gelmesidir
Etrafında tasarım yapılması gereken hata modu doğrudan buradan çıkar: LibreOffice onu son kaydettiğinde toplamları doğru olan bir elektronik tablo, doğru sayılarla içe aktarılır, ama bu sayılar artık sabittir. Bir girdi hücresini düzenleyin, yeniden hesaplayın, hiçbir şey değişmez - formül gitmiştir, yalnızca son sonucu kalır. İş akışının içe aktarmadan sonra canlı formüllere ihtiyacı varsa, bunları kendi iş kurallarınızdan, XLSX cephesinde başında eşittir işareti olmadan ifadeyi alan Cell.Formula aracılığıyla programatik olarak yeniden kurun
Asimetrik gidiş-dönüş etrafında tasarım yapmak
Dışa aktarma, tam bellek içi çalışma kitabı modelinden render eder: değerler, stiller ve isterseniz grafikler ve görüntüler. İçe aktarma yalnızca değerleri döndürür. Bu yüzden .xlsx'ten .ods'ye ayak yüksek sadakatlidir ve .ods'ten .xlsx'e ayak değerleri ve önbelleğe alınmış sonuçları geri getirir ama biçimlendirme ya da canlı formül getirmez. İkisini zincirleyin, asimetri katlanır. Tam bir .xlsx'ten .ods'ye .xlsx döngüsü, giderken her şeyi sadakatle yazar ve geri dönerken, her iki adımda da hiçbir şey yanlış gitmemiş olsa bile, stilleri ve formülleri kaybeder
Book := TXLSXWorkbook.Create;
try
Book.Open('vendor-revision.ods'); // biçim otomatik tespit edilir
if Book.SourceFormat = xlsxOpenDocumentSpreadsheet then
begin
// Bir ODS içe aktarmadan sonra değerler ve önbelleğe alınmış formül
// sonuçları mevcuttur; stiller ve canlı formüller değil. Kaydetmeden
// önce aşağı akış hattının neye bağlı olduğunu yeniden kurun.
Book.Sheets[0].Cells[2, 5].Formula := 'SUM(B2:D2)';
Book.SaveAs('vendor-revision.xlsx');
end;
finally
Book.Free;
end;
Bundan çıkan mimari kalıp: gelen .ods dosyalarını, yerinde düzenlenecek belgeler olarak değil, veri beslemeleri olarak ele alın. Kanonik çalışma kitabını .xlsx'te tutun, müşteri revizyonlarından değerleri okuyun ve kanonik kopyadan talep üzerine taze ODS üretin. Doğrulama her iki kampa da aittir - dışa aktarılan dosyaları, referans ODF tüketicisi olan LibreOffice Calc'ta ve yıllardır ODS okuyan ama grafik ve stil desteğinin kenarlarında LibreOffice ile anlaşmayan Excel'de açın. Sayfa sayısı, bir avuç anahtar hücre ve grafik varlığı, dışa aktarma profili başına yeterli bir duman kontrolü oluşturur
Bir içe aktarmaya bağlanmadan önce bir ODS dosyasını triyaj etmek
Bir uç nokta yüklemeleri kabul ettiğinde, sayfa adlarını listelemek tam bir ayrıştırmadan çok daha ucuzdur ve yapısal sürprizleri erkenden yakalar:
Names := TStringList.Create;
Book := TXLSXWorkbook.Create;
try
if Book.GetODSSheetNames('incoming.ods', Names) <= 0 then
raise Exception.Create('not a readable ODS package');
if Names.IndexOf('Data') < 0 then
raise Exception.Create('revision is missing the Data sheet');
finally
Book.Free;
Names.Free;
end;
Dönüş kuralı insanları takılmasına neden olur: HotXLS çağrıları genellikle başarıda pozitif bir sayı veya 1 ve başarısızlıkta -1 döndürür, başarısız olduklarında listeyi temizler, bu yüzden belirli bir pozitif değerle karşılaştırmak yerine <= 0 test edin. GetODSSheetNames, çalışma kitabı örneğini ne sıfırlar ne de doldurur, bu yüzden tek bir yoklama nesnesi, gelen dosyaların tüm bir dizinini denetleyebilir. Bunun gibi yapısal kontroller, en yaygın gerçek dünya hatasını - bir analistin revizyonu geri göndermeden önce bir sayfayı yeniden adlandırması ya da silmesi - hata mesajının hâlâ dosyayı ve eksik sayfayı adlandırabildiği kapıda yakalar, üç katman derinde nil bir referans olarak yüzeye çıkmak yerine
Bunun etrafında daha geniş bir dönüştürme hattı inşa ediyorsanız, çalışma kitabı denetimi ve dönüştürme çalışma tezgahı kalıbı, bir hedef biçim seçmeden önce bir dosyanın özelliklerini nasıl envanterleyeceğinizi gösterir ve büyük çalışma kitabı performansı rehberi, toplu dışa aktarmaları makul bellek sınırları içinde tutar
HotXLS, tam kaynak koduna sahip yerel bir Delphi ve C++Builder elektronik tablo kütüphanesidir; tam özellik listesi ve lisanslama ayrıntıları HotXLS Delphi Component ürün sayfasındadır