HotXLS, XLS, XLSX, XLSM ve ODS çalışma kitaplarını bir Delphi veya C++Builder formu içinde etkileşimli bir elektronik tablo grid'i olarak render eden yerel bir VCL kontrolü olan TXLSWorkbookViewer'ı sunar; Excel yüklemeden veya onu OLE otomasyonu üzerinden yönlendirmeden. Bu tür bir kontrolü iyi kurmak, üç belirli sorunu çözmek anlamına gelir: birleştirilmiş bir hücrenin içine inen bir fare tıklamasını doğru mantıksal hücreye eşlemek, bir kullanıcı görünür pencereden çok daha büyük bir sayfada gezinirken kaydırma konumunu, başlık bantlarını ve hücre seçimini tutarlı tutmak ve bir yorum işaretçisine veya bir köprü hücresine tıklamanın gerçekte ne yapması gerektiğine karar vermek
Çoğu Delphi firması, düzenlemeyle hiçbir ilgisi olmayan nedenlerle bir elektronik tablo görüntüleyicisine başvurur: yüklenen çalışma kitaplarını bir hatta girmeden önce önizleyen bir denetim istasyonu, Microsoft Office'in dağıtım imajının parçası olmadığı bir kiosk veya rapor görüntüleyici, ya da gerçek bir Excel sürecini COM üzerinden otomatikleştirmenin öngörülemezliği olmadan bir çalışma kitabının içeriğini göstermesi gereken bir QA aracı. Düz bir string grid size hücrelerde metni hızlıca verir, ama bir elektronik tablo dosyası düz bir grid değildir: hücreler, altta yatan modelde yalnızca bir kez var olan bloklara birleşir, sayfalar sabit başlık bantları ve bağımsız yatay ve dikey kaydırma konumları taşır ve tek tek hücreler kendi etkileşim modellerine ihtiyaç duyan yorumlar ve köprüler taşır. TXLSWorkbookViewer, HotXLS'in bu boşluğa verdiği yanıttır ve dahili tasarımı, sıfırdan benzer bir kontrol kuran herkes için makul bir taslaktır
Bir çalışma kitabı görüntüleyicisi Excel'e bağımlı olmaktan nasıl kaçınır?
TXLSWorkbookViewer, bir belgeyi Excel üzerinden açıp onu kukla gibi yönetmek yerine HotXLS'in kendi ayrıştırılmış nesne modeli üzerinden okuyarak Excel'den tamamen kaçınır. Workbook özelliği klasik XLS dosyaları için mevcut bir TXLSWorkbook'a bağlanır ve XlsxWorkbook, XLSX, XLSM ve şablon varyantları için bir TXLSXWorkbook'a bağlanır; her ikisi de uygulamanın başka bir yerinde zaten açık olabilir ve görüntüleyici yalnızca ondan okur. Kontrolün dosyanın kendisine sahip olması gerektiğinde, LoadFromFile uzantıyı inceler, XLSX, XLSM, XLTX, XLTM ve ODS'yi modern motor üzerinden ve geri kalan her şeyi klasik motor üzerinden yönlendirir ve kontrol temizlendiğinde veya yok edildiğinde oluşturduğu çalışma kitabı her ne ise onu serbest bırakır
var
Viewer: TXLSWorkbookViewer;
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
if Book.Open('quarterly-report.xlsx') <> 1 then
raise Exception.Create('Could not open workbook');
Viewer := TXLSWorkbookViewer.Create(Self);
Viewer.Parent := Self;
Viewer.Align := alClient;
Viewer.XlsxWorkbook := Book; // the viewer does not take ownership
Viewer.GoToCell(1, 1);
Caption := Viewer.WorksheetName + ': ' + Viewer.SelectedCellText;
end;
Birleştirilmiş bir aralık içinde doğru hücreyi bulmak
TXLSWorkbookViewer'da bir tıklamayı doğru hücreye çözmek iki aşamalı bir aramadır ve bu ayrım önemlidir çünkü piksel geometrisi ve elektronik tablo semantiği gerçekten farklı sorunlardır. İlk aşama saf geometridir: özel bir CellAtPoint metodu, tıklanan X ve Y koordinatını içeren bandı bulana kadar mevcut kaydırma konumundan sütun genişliklerini ve satır yüksekliklerini dolaşır, birleştirilmiş hücrelerin hiç farkında olmadan. İkinci aşama semantiktir: seçimi değiştiren her yol -bir fare tıklaması, bir ok tuşu, Tab veya GoToCell'e doğrudan bir çağrı- tek bir dahili ChangeSelection rutininden geçer; bu, ham satır ve sütunu herhangi bir birleştirmeye karşı normalleştirir ve seçim gerçekte değişmeden önce onları birleştirmenin çapa hücresine yapıştırır
Çapa, birleştirilmiş aralığın sol üst hücresidir ve o blok içinde altta yatan çalışma kitabı modelinde gerçekten bir değer, bir format, bir yorum veya bir köprü tutan tek hücredir; birleştirmenin görsel olarak kapladığı diğer her hücre verinin kendisinde boştur. Klasik XLS çalışma kitapları için çapa, Row ve Column'u sahip hücreye işaret eden bir IXLSRange olan Cell.MergeArea'dan gelir; XLSX ve ODS çalışma kitapları için, MergedCells.FindAt, aynı çapayı Row1 ve Col1 olarak sunan bir TXLSXMergedRange döndürür. Boyama, eşdeğer bir sorunu bağımsız olarak çözer; birleştirilmiş bir hücrenin dikdörtgenini tam satır ve sütun kapsamına genişletir ve o kapsam içindeki hücreleri atlar; böylece seçim ana hattı yalnızca çapa köşesini değil tüm birleştirilmiş bloğu sarar ve birleştirilmiş düzenleri yalnızca geri okumak yerine yazmak, rapor şablonları için birleştirilmiş hücre düzeni üzerine tamamlayıcı makalede ele alınan ilgili ama ayrı bir sorundur
var
Sheet: TXLSXWorksheet;
begin
Sheet := Book.Sheets.Add('Summary');
Sheet.MergeCells(2, 2, 3, 4); // B2:D3
Sheet.Cells[2, 2].Value := 'Region totals';
Viewer.XlsxWorkbook := Book;
Viewer.GoToCell(3, 4); // targets the bottom-right corner of the merge
// SelectedRow is now 2 and SelectedCol is now 2: normalized to the anchor cell
end;
Kaydırmayı, başlıkları ve seçimi senkronize tutan nedir?
TXLSWorkbookViewer üç ayrı durum parçasını tutarlı tutar: TopRow ve LeftCol'da tutulan mantıksal kaydırma konumu, kontrolün CreateParams içinde WS_HSCROLL ve WS_VSCROLL üzerinden istediği yerel Windows kaydırma çubukları ve SelectedRow ve SelectedCol'daki mevcut seçim. Bir kaydırma çubuğunu sürüklemek veya fare tekerleğini döndürmek, TopRow veya LeftCol'u güncelleyen ve yeniden boyayan WM_HSCROLL, WM_VSCROLL veya WM_MOUSEWHEEL'i tetikler; seçim hareket etmez, bu da Excel'in kendisinin gezinmeyi seçmekten nasıl ayırdığıyla eşleşir. Bu güncellemelerden herhangi birinden sonra, UpdateScrollBars yeni konumu SetScrollInfo aracılığıyla yerel kaydırma çubuğuna geri iter; bu yüzden başparmak, grid'in gerçekte gösterdiğiyle asla uyuşmazlığa düşmez
Klavye gezinmesi aynı senkronizasyonu ters yönde çalıştırır: seçimi görünür grid'in kenarının ötesine taşımak EnsureSelectionVisible'ı çağırır; bu, satır ve sütunlar özel boyutlar taşıyabildiğinden basitçe bir artırmak yerine gerçek sütun genişliklerini ve satır yüksekliklerini biriktirerek TopRow veya LeftCol'u iter, ardından klavyenin görünümü az önce nereye taşıdığını başparmağın yansıtması için UpdateScrollBars'ı çağırır. RowHeaderWidth ve ColumnHeaderHeight üzerinden boyutlandırılan satır numarası ve sütun harfi başlık bantları, TopRow ve LeftCol altındaki veriyi kaydırırken ekranda sabit kalan bu kontrolün parçasıdır ve bu kontrolün kendi başına yaptığı dondurmanın kapsamı budur: bu, Excel'in Bölmeleri Dondur özelliği değildir ve sayfanın geri kalanı kayarken keyfi bir veri satırını veya sütununu sabitlemenin yerleşik bir yolu yoktur. Tam olarak kontrol etmediğiniz dosyalar üzerinden bir görüntüleyici göndermeden önce test edilmeye değer bir sınır, TopRow ve LeftCol'un çalışma sayfasının gerçek kullanılan aralığına karşı sıkıştırılmamış olmasıdır; bu yüzden yapısal sınırına sürüklenen bir başparmak, verinin gerçekte tuttuğu son satır veya sütun yerine 1.048.576 satırına veya 16.384 sütununa inebilir ve boş bir grid gösterebilir; bunu fark edilir kılacak kadar büyük çalışma kitapları genellikle büyük çalışma kitabı performansı makalesinde ele alınan yükleme tarafı dikkati gerektirecek kadar da büyüktür
Yorumları ve köprüleri fare ve seçim olaylarına bağlamak
TXLSWorkbookViewer, yorumları ve köprüleri bir üzerine gelme hedefi olarak değil, o anda seçili olan hücrenin öznitelikleri olarak ele alır; bu yüzden SelectedCellCommentText, SelectedCellCommentAuthor ve SelectedCellHyperlink, seçim fare tıklamasıyla, ok tuşuyla veya GoToCell'e bir çağrıyla hareket etsin, OnSelectionChange her tetiklendiğinde güncellenir. Yorumlu bir hücre, Excel'in kendi yorum bayrağına benzer görsel bir ipucu olarak sağ üst köşesine boyanmış küçük bir kırmızı üçgen alır, ama bu işaretçi salt görseldir; kontrole yerleşik üzerine gelmeyle tetiklenen bir araç ipucu yoktur; bu yüzden seçim üzerine değil fare üzerine gelme üzerine bir açılır pencere isteyen bir uygulama, o katmanı kendisi kurmak zorundadır. Köprü etkinleştirme aynı seçim-öncelikli şekilde çalışır: bir hücreye çift tıklamak ActivateSelectedCell'i çağırır; bu, SelectedCellHyperlink'i okur ve boş değilse, hedef adresle ve işleyicinin ayarlaması için bir var Handled: Boolean parametresiyle OnHyperlinkClick'i yükseltir
OnHyperlinkClick'in yapmadığı şey de en az yaptığı kadar önemlidir: TXLSWorkbookViewer, işleyici Handled'ı true olarak ayarlasın ya da false bıraksın, kendi başına asla ShellExecute'u çağırmaz veya bir tarayıcı açmaz. Gezinme ve neyin güvenli bir hedef sayıldığına dair herhangi bir karar, tamamen ana bilgisayar uygulamasının sorumluluğundadır ki bu, güvenilir bir dahili araç içine mi yoksa bir müşterinin az önce yüklediği dosyalar için bir görüntüleyici içine mi gömülü olduğu hakkında hiçbir fikri olmayan bir bileşen için doğru varsayılandır
procedure TMainForm.ViewerSelectionChange(Sender: TObject; Row, Col: Integer);
begin
if Viewer.SelectedCellCommentText <> '' then
StatusBar.SimpleText := Viewer.SelectedCellCommentAuthor + ': ' +
Viewer.SelectedCellCommentText
else
StatusBar.SimpleText := Viewer.SelectedCellHyperlink;
end;
procedure TMainForm.ViewerHyperlinkClick(Sender: TObject;
const Target: WideString; var Handled: Boolean);
begin
ShellExecute(0, 'open', PWideChar(Target), nil, nil, SW_SHOWNORMAL);
Handled := True;
end;
Seçim kapsamı ve klavye gezinme sınırları
TXLSWorkbookViewer'da seçim her zaman SelectedRow ve SelectedCol olarak izlenen tek bir mantıksal hücredir; temel kontrolde dikdörtgen çok hücreli aralık seçimi yoktur; bu yüzden bir hücre bloğu üzerinde işlem yapması gereken herhangi bir özellik, bir seçim nesnesinden okunmak yerine onun üzerine kurulmak zorundadır. Klavye kapsamı kasıtlı olarak temeldir: ok tuşları bir seferde bir hücre hareket eder, Home satırın başına veya Ctrl ile A1 hücresine döner, Page Up ve Page Down on satır atlar ve Tab ile Shift+Tab sütunlar arasında adımlar; bir veri bölgesinin kenarına Ctrl+Ok atlaması ve Shift ile genişletilmiş aralık seçimi yoktur; bu yüzden doğrudan Excel'den gelen kullanıcılar yoğun bir sayfada bu boşluğu fark edecektir
Sütun sınırları, birleştirme normalleştirmesini ele alan aynı ChangeSelection boğaz noktasında uygulanır ve kasıtlı olarak motora göre farklılık gösterir: klasik bir TXLSWorkbook'a bağlı bir görüntüleyici, BIFF8 formatının yapısal tavanı olan 256 sütununda sıkıştırırken, TXLSXWorkbook'a bağlı olan, XLSX'in Excel 2007'den itibaren miras aldığı modern 16.384 sütun sınırına saygı gösterir. Satırlar her iki durumda da 1.048.576'da sınırlanır; bu yüzden aynı görüntüleyicide eski bir XLS dosyası ile bir XLSX dosyası açmak arasındaki pratik fark, tamamen grid'in sağa ne kadar gitmenize izin vereceğiyle ilgilidir
Bunların hiçbiri piksel arama, çapa normalleştirme ve bir avuç mesaj işleyicisine bölündüğünde egzotik değildir, ama üçünü gerçek dosyalar, gerçek birleştirmeler, yorumlar ve köprüler altında anlaşmaya getirmek, bunun gibi bir bileşendeki işin büyük kısmıdır. TXLSWorkbookViewer, Delphi ve C++Builder için HotXLS Excel Bileşeni'nin standart bir parçası olarak, render ettiği klasik ve XLSX nesne modellerinin yanında gönderilir