Büyük Excel elektronik tablo (spreadsheet) yığınlarını otomatik bir boru hattında (pipeline) işlerken, bir belgenin ne olduğunu anlamak için nadiren tüm belgeyi belleğe yüklemek istersiniz. Genellikle, dosyanın içine gömülü olan meta veriler (yazar, başlık, oluşturma tarihi ve özel özellikler) belgeyi yönlendirmek, indekslemek veya reddetmek için yeterlidir. Microsoft Office dünyasında bu meta veriler Belge Özet Bilgileri (Document Summary Information) olarak bilinir.
OLE otomasyonuna güvenmeden (ki bu, Excel'in ana makinede kurulu olmasını gerektirir) bu bilgileri Delphi'de yerel (natively) olarak çıkarmak, temeldeki dosya yapısını doğrudan ayrıştırmayı gerektirir. Bu makalede, belge özetlerinin Excel dosyalarında nasıl çalıştığına ve ham akış ayrıştırması (raw stream parsing) kullanarak bunları verimli bir şekilde nasıl çıkaracağımıza bakacağız.
Excel Meta Veri Akışlarını Anlamak
Tarihsel olarak, daha eski Excel dosyaları (.xls) OLE Bileşik Belge (OLE Compound Document) formatlarında depolanır ve etkili bir şekilde akışlar (streams) ile depolar (storages) içeren mini dosya sistemleri olarak hareket ederler. Meta veriler iki özel akışta barındırılır:
SummaryInformation: Başlık, Konu, Yazar, Anahtar Kelimeler ve Revizyon Numarası gibi standart özellikleri içerir.DocumentSummaryInformation: Şirket, Yönetici ve kullanıcının tanımladığı özel özellikler gibi genişletilmiş özellikleri içerir.
Modern Excel dosyaları (.xlsx), sıkıştırılmış (zipped) bir XML yapısı olan Office Açık XML (OOXML) formatını kullanır. Buradaki meta veriler docProps/core.xml, docProps/app.xml ve docProps/custom.xml dosyalarında bulunur. Sağlam bir Delphi ayrıştırma bileşeni, geliştiriciye birleşik bir API sunarken her iki iç yapıyı da sorunsuz bir şekilde ele almalıdır.
Delphi'de OLE Bileşik Belgeleri Ayrıştırma
Eski bir .xls dosyasından SummaryInformation'ı üçüncü taraf araçlar olmadan okumak için, OLE Yapılandırılmış Depolamayı (OLE Structured Storage) ayrıştırmanız gerekir. Microsoft bunu IPropertySetStorage COM arayüzü (interface) aracılığıyla sunar. İşte Excel'i çalıştırmaktan kaçınan ham bir Delphi uygulaması:
uses
System.SysUtils, System.Win.ComObj, Winapi.ActiveX, Winapi.Windows;
procedure ExtractXlsSummaryInfo(const FileName: string);
var
Stg: IStorage;
PropSetStg: IPropertySetStorage;
PropStg: IPropertyStorage;
PropSpec: TPropSpec;
PropVariant: TPropVariant;
Hr: HRESULT;
begin
// Open the OLE Compound Document
Hr := StgOpenStorage(PWideChar(WideString(FileName)), nil,
STGM_READ or STGM_SHARE_DENY_WRITE, nil, 0, Stg);
if Failed(Hr) then
raise Exception.Create('Failed to open OLE storage. File may not be a valid .xls document.');
// Query for the property set storage interface
if Stg.QueryInterface(IPropertySetStorage, PropSetStg) = S_OK then
begin
// Open the SummaryInformation stream (FMTID_SummaryInformation)
Hr := PropSetStg.Open(FMTID_SummaryInformation, STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg);
if Succeeded(Hr) then
begin
// Read the Author property (PIDSI_AUTHOR = 4)
PropSpec.ulKind := PRSPEC_PROPID;
PropSpec.propid := PIDSI_AUTHOR;
if PropStg.ReadMultiple(1, @PropSpec, @PropVariant) = S_OK then
begin
if PropVariant.vt = VT_LPSTR then
Writeln('Author: ', string(AnsiString(PropVariant.pszVal)));
PropVariantClear(PropVariant);
end;
end;
end;
end;
HotXLS ile Programatik Çıkarım
Windows COM API .xls dosyaları için çalışırken, modern .xlsx dosyaları (ki bunlar ZIP arşivleridir) için çalışmaz. Dahası, COM API'sini çapraz platformda (örneğin, FireMonkey aracılığıyla Linux veya macOS'ta) kullanmak imkansızdır. HotXLS bileşenine yapılan son güncellemeler, bu özet akışların her iki formatta da tamamen yerel olarak Delphi kodunda okunmasını yalıtmak ve optimize etmek için özel birimler (örneğin, lxXlsSummary) tanıttı.
Çapraz Platform Bir Örnek
XlsReadDocumentSummaryInformation ve XlsReadSummaryInformation arayüzlerini kullanarak, temeldeki dosya sistemi mimarisi hakkında endişelenmeden hem .xls hem de .xlsx dosyalarından meta veri dizelerini (strings) hızlı bir şekilde alabilirsiniz.
uses
lxXlsSummary;
var
Summary: TXlsSummaryInfo;
ExtendedInfo: TXlsDocumentSummaryInfo;
begin
// Extract standard summary from an OOXML format seamlessly
Summary := XlsReadSummaryInformation('C:\Data\FinancialReport.xlsx');
try
Writeln('Title: ', Summary.Title);
Writeln('Author: ', Summary.Author);
Writeln('Creation Date: ', DateTimeToStr(Summary.CreateTime));
finally
Summary.Free;
end;
// Extract extended document summary
ExtendedInfo := XlsReadDocumentSummaryInformation('C:\Data\FinancialReport.xlsx');
try
Writeln('Company: ', ExtendedInfo.Company);
Writeln('Manager: ', ExtendedInfo.Manager);
finally
ExtendedInfo.Free;
end;
end;
Özel Özet Çıkarımı Neden Önemlidir?
Bu yaklaşımın birincil faydası performans ve bellek güvenliğidir. Tam çalışma kitabı (workbook) DOM'unu (Belge Nesne Modeli) örneklendirmekten kaçınarak ve yalnızca docProps/core.xml veya OLE özellik akışlarını ayrıştırarak, uygulamanızın bellek ayak izi inanılmaz derecede küçük kalır. Bir ağ paylaşımında (network share) 10.000 Excel dosyasını indeksliyorsanız, her birini tam olarak ayrıştırmaya çalışmak belleğinizi yoracak ve saatler sürecektir. Özel özet çıkarımı ise aynı görevi saniyeler içinde tamamlar.
Dahası, akışları yerel olarak okumak, uygulamanızın bir arka plan hizmeti olarak veya gözetimsiz (headless) bir Linux sunucusunda Excel.exe'yi hiç çağırmadan çalışabilmesini sağlar; bu, modern ölçeklenebilir mimariler için kritik bir gereksinimdir.
Not: Kapsamlı Excel ayrıştırma ve meta veri çıkarma araçları HotXLS VCL Component bileşeninde mevcuttur.