Teknik Makale

HotXLS ile Satır Eklerken Formül Başvuruları

Bir XLSX çalışma sayfasında satır ya da sütun eklediğinizde veya sildiğinizde HotXLS formül başvurularını kendiliğinden ayarlar. Motorun InsertRows, DeleteRows, InsertCols ve DeleteCols yöntemleri, ayakta kalan her formülü, A1 başvuruları — göreli, mutlak ve aralık — yapısal düzenlemeden sonra da aynı veriyi göstermeye devam edecek biçimde yeniden yazar; silinen bir bloğun içine giden başvurular ise Excel davranışına uyarak #REF! olur

Bunun önlediği hata, rapor üretimindeki en sessiz hatalardan biridir. Bir üretici günlük rakamları C2:C9 aralığına, altına da =SUM(C2:C9) yazar, sonra bir adım en üste bir başlık satırı ekler. Motor yalnızca hücre değerlerini taşıyıp formül metnine dokunmazsa, o SUM hâlâ C2:C9 okur ama veri artık C3:C10 içindedir — yani toplam sessizce son günü düşürür ve bir başlığı iki kez sayar. Hiçbir şey istisna yükseltmez, dosya sorunsuz açılır ve sayı düpedüz yanlıştır. 2.160 sürümünden önce HotXLS XLSX motoru yapısal düzenlemeler sırasında formüllere dokunmuyordu; 2.160 sürümünden bu yana yeniden yazma kendiliğinden olur ve ayarlanacak bir bayrak yoktur

Excel içinde bir satır eklediğinizde formüllere ne olur?

Excel kuralı şudur: başvurular adresleri değil veriyi izler. Bir satır eklendiğinde, satır dizini ekleme noktasında ya da altında olan her başvuru, eklenen satır sayısı kadar aşağı kayar; tümüyle ekleme noktasının üstünde kalan başvurulara dokunulmaz. Satır silmek aynı kuralı tersten işletir: silinen bloğun altındaki başvurular yukarı kayar ve silinen bloğun içine giden başvurular, adlandırdıkları hücreler artık var olmadığı için #REF! olur. Sütunlar öbür eksende aynı biçimde davranır. Çıktısının Excel kullanıcılarıyla temasa dayanmasını isteyen bir elektronik tablo kütüphanesi bu mekaniği birebir yeniden üretmek zorundadır, çünkü kullanıcılar formüllerini hiç düşünmeden bu terimlerle akıl eder

Geliştiricileri şaşırtan kısım, mutlak başvuruların da taşınmasıdır. $B$2 içindeki $ sabitleyicileri, bir formül başka bir hücreye kopyalandığında ya da doldurulduğunda ne olacağını denetler — yapısal düzenlemeler sırasında hiçbir şey yapmazlar. 2. satırın üstüne bir satır ekleyin; Excel $B$2 ifadesini dolar işaretleri yerinde kalacak biçimde $B$3 olarak yeniden yazar, çünkü formülün bağlı olduğu değer fiziksel olarak 3. satıra taşınmıştır. Yalnızca göreli başvuruları kaydıran bir motor, tam da insanların en bilinçli biçimde sabitlediği formülleri bozardı. HotXLS her iki biçimi de kaydırır ve yeniden yazdığı metinde $ işaretlerini korur

HotXLS formül başvurularını kendiliğinden nasıl kaydırır?

TXLSXWorksheet üzerindeki dört yapısal düzenleme yönteminin dördü de tek bir geometri motoruna devreder: ShiftSheetGeometry(RowFrom, RowDelta, ColFrom, ColDelta). InsertRows(BeforeRow, Count) onu artı bir satır farkıyla, DeleteRows(StartRow, Count) eksi bir farkla çağırır; sütun yöntemleri de aynısını sütun ekseninde yapar. Yordam önce hücrelerin kendilerini yeniden konumlandırır — silinen bir bloğun içine düşen her hücreyi atarak — sonra ayakta kalan her formül hücresini dolaşır ve metnini, A1 biçimli başvuruları bulup satır ile sütun bileşenlerini kaymaya göre yeniden yazan bir tarayıcı olan XlsxAdjustFormulaRowColRefs içinden geçirir. Aynı geçiş birleştirilmiş aralıkları, köprüleri, açıklamaları, görüntüleri, grafikleri, koşullu biçimleri, veri doğrulamalarını ve tablo aralıklarını da yeniden konumlandırır, böylece sayfanın tamamı tek bir birim gibi taşınır

Delphi içinde HotXLS kütüphanesinin eklenen bir satırdan sonra elektronik tablo başvurularını kaydırmasını gösteren kılavuz karşılaştırması: C2:C9 günlük rakamları C3:C10 aralığına kayar, SUM formül metni buna uyacak biçimde yeniden yazılır ve $B$2 mutlak sabitlemesi de verisiyle birlikte taşınır
Tek bir InsertRows çağrısı bloğun üstüne boş bir satır bırakır ve motor =SUM(C2:C9) ifadesini =SUM(C3:C10) olarak yeniden yazar; böylece toplam veriyi izler, $B$2 gibi mutlak sabitlemeler de $B$3 konumuna iner
// Düzenlemeden önceki yerleşim:
//   C2..C9  günlük rakamlar
//   C10     =SUM(C2:C9)
Sheet.InsertRows(2, 1);      // 2. satırdan önce bir boş satır
// Çağrıdan sonraki yerleşim:
//   C3..C10 günlük rakamlar
//   C11     =SUM(C3:C10)    -- aralık veriyle birlikte taşındı

Tarayıcının birkaç ayrıntısını bilmeye değer. XlsxAdjustFormulaRowColRefs, tek hücre başvurularını dört sabitleme biçiminin hepsinde (A1, $A1, A$1, $A$1) ve A1:B3 gibi iki köşeli aralıkları tanır ve her ucu birbirinden bağımsız ayarlar. Metni zaten # ile başlayan formüller — daha önceki bir düzenlemeden kalan hata işaretleri — yeniden taranmak yerine atlanır. InsertCols ise kendine özgü bir Excel eşdeğerliği inceliği ekler: yeni eklenen sütunlar sol komşularının genişliğini devralır ki Excel içindeki Sayfa Sütunu Ekle komutu da tam olarak bunu yapar

Silinen bir başvuru ne zaman #REF! olur?

Tek bir satır ya da sütun dizini için kaydırma kuralının üç sonucu vardır. Düzenleme noktasından önceki bir dizin değişmez. Düzenleme noktasında ya da ötesindeki bir dizin fark kadar taşınır. Silme durumunda ise silinen bloğun içine düşen bir dizinin anlamlı bir yeni değeri yoktur — hücre gitmiştir — dolayısıyla tarayıcı başvurunun tamamını #REF! olarak yeniden yazar. Bir aralık başvurusunda her iki uç da aynı kuraldan geçirilir ve uçlardan biri silinen bloğun içine düşerse başvuru, yarı geçerli bırakılmak yerine #REF! olarak yeniden yazılır

Delphi kodu çalışma sayfasının 5 ile 7 arasındaki satırlarını sildiğinde HotXLS yeniden yazma kuralının karar biçimli görünümü: A4 terimi bloğun üstünde kalır, A6 içeriye düşer ve #REF! olur, A10 üç satır yukarı kayarak A7 olur, böylece A9 içindeki yeni konumlanmış formül =A4+#REF!+A7 diye okunur
DeleteRows ayakta kalan her başvuruyu üç kadere ayırır: bloğun üstünde değişmeden kalanlar, bloğun içinde yüksek sesle #REF! olarak yeniden yazılanlar ve bloğun altında silinen sayı kadar yukarı kayanlar
// A12 şunu tutar  =A4+A6+A10
Sheet.DeleteRows(5, 3);      // 5..7 satırlarını sil
// Formül, artık A9 içinde, şöyle okunur  =A4+#REF!+A7
//   A4  : silinen bloğun üstünde, değişmez
//   A6  : 5..7 satırlarının içinde, yok  -> #REF!
//   A10 : bloğun altında, yukarı kayar   -> A7

Sessizce yeni bir hedef vermek yerine yüksek sesle #REF! üretmek doğru takastır ve Excel de bu takası yapar. Gerçek girdisi silindikten sonra komşu bir hücreyi gösteren bir formül, akla yatkın görünen bir sayı döndürürdü; #REF! ise bağımlı formüller boyunca yayılır ve ilk duman testinde yüzeye çıkar. Aynı dönüşüm sütun ekseninde de geçerlidir

// E1 şunu tutar  =B1*$C$1
Sheet.DeleteCols(3, 1);      // C sütununu kaldır
// Formül, artık D1 içinde, şöyle okunur  =B1*#REF!
// Mutlak sabitleme $C$1 değerini korumadı -- hücrenin kendisi yok

Hangi başvuru biçimleri yeniden yazılmaz?

Tarayıcı, açık sütun harfi artı satır numarası biçimindeki aynı sayfa A1 başvurularını hedefler ve bunun dışında ne kaldığı konusunda kesin olmakta yarar var. A:A gibi tam sütun başvuruları ve 1:1 gibi tam satır başvuruları iki bileşenden birinden yoksundur, dolayısıyla tarayıcı onları yazıldığı gibi bırakır. Yapılandırılmış tablo başvuruları (Table1[Amount]) da aynı şekilde dokunulmadan geçirilir. Yeniden yazma yalnızca A1 gösterimi üzerinde çalışır — kodunuz formülleri R1C1 biçeminde kuruyorsa, Delphi içinde R1C1 formül gösterimi üzerine kardeş yazıda anlatıldığı gibi yapısal düzenlemeden önce onları A1 biçimine çevirin

Sayfalar arası ve çalışma kitabı düzeyindeki yapılar, hücre metni tarayıcısıyla değil ayrı geçişlerle ele alınır. Düzenlenen sayfayı ayarladıktan sonra ShiftSheetGeometry, aynı geometri değişikliğini düzenlenen sayfaya başvuran diğer sayfalardaki formüllere, grafik seri aralıklarına, belge içi köprü hedeflerine ve tanımlanmış adlara yayar. Tanımlanmış adlar sayfa yaşam döngüsü düzeyinde ek koruma alır: 2.150 sürümünden bu yana, bir çalışma sayfasını silmek tanımlanmış bir adın formülündeki her SheetN! niteleyicisini #REF! olarak yeniden yazar, bir sayfayı yeniden adlandırmak ise niteleyiciyi yeni adla değiştirir; böylece adlar artık var olmayan bir sayfayı hiçbir zaman göstermez. Adların ve sayfalar arası formüllerin nasıl bir araya geldiği tanımlanmış adlar ve sayfalar arası formüller yazısında ele alınmaktadır

Kaydırmadan sonra yeniden hesaplayın

Başvuru ayarlaması formül metnini yeniden yazar; sonuçları yeniden hesaplamaz. Yapısal bir düzenlemeden sonra formüllerin yanında saklanan önbellek değerleri eski geometriyi anlatır, dolayısıyla güvenilir sıra şudur: önce bütün ekleme ve silmeleri yapın, sonra yeniden hesaplamayı bir kez tetikleyin, sonra kaydedin. Kaydırmayı yeniden hesaplamadan önce çalıştırmak bağımlılık bilgisini de dürüst tutar — yeniden yazılan her başvuru gerçek öncülünü adlandırır ki artımlı yeniden hesaplama motorunun ve bağımlılık çizgesinin etkilenen en küçük hücre kümesini yeniden hesaplamak için ihtiyaç duyduğu tam olarak budur. Yeniden yazılmış bir formül artık #REF! içeriyorsa, yeniden hesaplama dosyada bayat bir sayı bırakmak yerine hata değerini hemen yüzeye çıkarır

Formül başvuru ayarlaması, Delphi ve C++Builder için HotXLS Delphi Excel Bileşeni içindeki XLSX motorunun standart davranışı olarak gelir; ürün sayfası, burada gösterilen ekleme ve silme yöntemleri dahil eksiksiz çalışma sayfası düzenleme API başvurusunu taşır