Műszaki cikk

HotXLS: Excel megjegyzések és hiperhivatkozások Delphiben

Nevezzen át egy lapot „Summary” névről „Overview” névre egy generált munkafüzetben, és minden belső hiperhivatkozás, amely a Summary!A1 címre mutatott, megszűnik bárhová is vinni. Mentéskor nincs kivétel, megnyitáskor sincs. A hivatkozás továbbra is megjelenik, továbbra is kattinthatónak látszik, és csendben a semmire oldódik fel. Ugyanez a törés jelentkezik egy mentés másként átalakítás vagy egy .xls/.xlsx körút után is, amikor egy megjegyzés egy oszloppal odébb landol, vagy egy relatív hivatkozás elveszíti a célját. Mindkét képesség olyan ellenőrzési állapotot hordoz, amelyre valódi emberek reagálnak, így amikor eltörnek, a hiba láthatatlan marad addig, amíg egy lektor rá nem kattint, és nem történik semmi

Ez a gyakorlati oka annak, hogy a megjegyzések és a hiperhivatkozások több figyelmet érdemelnek, mint amennyit kozmetikai megjelenésük sugall. A HotXLS közvetlen írási hozzáférést ad a Delphi és C++Builder kódnak mindkettőhöz, XLS és XLSX formátumban, Excel-automatizálás nélkül. Ennek az irányításnak a másik oldala a felelősség: a könyvtár pontosan azokat a célokat írja ki, amelyeket átad neki, és egyiket sem ellenőrzi, tehát egy ellenőrzési folyamat épségben tartása az Ön kódjának a dolga, nem az Excelé

A cellamegjegyzések mint géppel írt ellenőrzési feljegyzések

Az XLSX osztálymodellben a megjegyzés munkalapszintű objektum: ismeri a sorát, az oszlopát, egy szerzőt és egy szövegtörzset. A szerzőmező megszolgálja a helyét. Amikor egy kódja által generált munkafüzet végigmegy egy ellenőrzési láncon, egy auditor első kérdése az, hogy ki írt egy adott feljegyzést, és a szerző nélkül hagyott feljegyzés üresen válaszol erre a kérdésre. Bélyegezze meg a generált megjegyzéseket egy szolgáltatásidentitással, hogy az eredet soha ne legyen kétértelmű

Delphi HotXLS megjegyzés-újrapróbálkozást bemutató ábra, ahol egy FindAt szonda frissíti a meglévő cellafeljegyzést, míg a vakon ismételt AddComment hívás egy duplikátumot rak rá
Az az újrapróbálkozás, amely vakon hívja az AddComment metódust, második feljegyzést rak ugyanarra a cellára, míg a FindAt szonda a már ott lévő feljegyzést szerkeszti
var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Note: TXLSXComment;
begin
  Book := TXLSXWorkbook.Create;
  try
    Book.Open('reconciliation.xlsx');
    Sheet := Book.Sheets[0];

    // Szerzővel ellátott feljegyzés a korrigált értéken
    Sheet.AddComment(14, 4, 'Manual adjustment: late FX rate, see ticket FIN-2214',
      'recon-service');

    // Meglévő feljegyzés frissítése egy második ráhalmozása helyett
    Note := Sheet.Comments.FindAt(14, 4);
    if Note <> nil then
      Note.Text := Note.Text + ' [verified 2026-06-11]';

    Book.SaveAs('reconciliation-reviewed.xlsx');
  finally
    Book.Free;
  end;
end;

A FindAt szonda többet nyom a latban, mint amennyinek látszik. Az a kötegelt feladat, amely egy átmeneti hiba után újrapróbálkozik, boldogan hívja meg másodszor is az AddComment metódust egy olyan cellán, amelyet már megjegyzetelt, és a cellára két egymásra rakott feljegyzés kerül, amelyet senki nem kért. Előbb szondázzon a FindAt hívással, és frissítse az általa visszaadott objektumot. A Comments gyűjtemény a DeleteAt és a DeleteInRange metódust is elérhetővé teszi. A tartományos változatért akkor érdemes nyúlni, amikor egy munkafüzetet fertőtlenít, mielőtt elhagyná a házat: egy egész régió belső minőségbiztosítási jegyzeteinek törlése egyetlen hívás, nem pedig kézzel írt ciklus a cellákon

A külső URL-ek és a munkafüzeten belüli ugrások külön API-k

Az OOXML a kétféle hivatkozást különböző helyen tartja. A külső URL a lap .rels részében kapcsolatbejegyzéssé válik, és a cella azonosító alapján mutat a kapcsolatra. A belső ugrás egyáltalán nem érinti a kapcsolatréteget; egyszerű helymegjelölő karakterlánc, például Summary!A1, amely közvetlenül a hivatkozáson tárolódik. A HotXLS ezt a különbséget láthatóan tartja az API-ban ahelyett, hogy egyetlen metódust terhelne túl, ami azt jelenti, hogy a helyes hívást annak ismeretében választja ki, hol lakik a cél:

Ábra, amely szembeállítja, hogyan tárolja a HotXLS a külső URL-t kapcsolatként a rels részben, a belső ugrást pedig egyszerű helymegjelölő karakterláncként a Delphivel generált munkafüzetekben
A külső URL a kapcsolatrétegen át utazik, míg a belső ugrás egyszerű szöveg, így mindkét fajta a maga módján törik el, és saját auditszabályt igényel
Sheet.Cells[2, 1].Value := 'Source record';
Sheet.AddHyperlink(2, 1, 'https://intranet.example.com/records/2214',
  'Open record 2214', 'ERP source entry');

Sheet.Cells[3, 1].Value := 'Totals';
Sheet.AddHyperlinkToCell(3, 1, 'Overview!B12', 'Jump to totals');

Az így kapott TXLSXHyperlink objektumon az Url és a Location kölcsönösen kizárja egymást, és az IsInternal mondja meg, melyik a kettő közül a kitöltött. Ezt a jelzőt ellenőrzi akkor, amikor leltárba veszi egy megnyitott munkafüzet hivatkozásait, és a „kilép a fájlból” és a „bent marad a fájlban” esetet más szabályok szerint kell kezelnie: egy külső kiszolgálónak engedélyezőlistával kell szembenéznie, míg egy belső célnak csak egy létező lapot kell megneveznie. A belső hivatkozások mögött nincsenek kapcsolatrészek, ami olcsóbbá is teszi a tömeges átírásukat

A bevezetőben említett törés teljes egészében a belső oldalon él, és egyetlen tényből következik: a helymegjelölő karakterlánc nem elemzett hivatkozás. A HotXLS pontosan azt a szöveget írja ki, amelyet átad neki, és semmi nem irányítja át ezt a szöveget, amikor egy lapot később átneveznek. A gyakorlatban két védekezés állja meg a helyét. Az első a sorrendi fegyelem: nevezzen át minden lapot, mielőtt egyetlen hivatkozást is generálna, és onnantól kezelje a lapneveket befagyasztott azonosítóként. A második erősebb, és túléli az utólag elvégzett átnevezéseket is. Irányítsa a hivatkozást munkafüzetszintű definiált névre nyers Lap!Cella cím helyett, mert az Excel átírja a név definícióját, amikor a mögöttes lap megváltozik, így a hivatkozás automatikusan vele utazik. Ez a második megközelítés természetesen párosul a definiált nevek és lapok közötti képletek a HotXLS-ben cikkben leírt technikákkal

Az XLS oldal: ugyanazok a fogalmak, régebbi vezetékek

A BIFF8 homlokzat a megjegyzéseket tartományokra akasztja munkalapszintű gyűjtemény helyett. Meghívja az AddComment metódust egy IXLSRange objektumon, és egy TXLSComment objektumot kap vissza; a tartomány Comment tulajdonsága egy meglévő feljegyzést olvas, a ClearComments pedig törli őket. Az éles perem itt a pozíciónál van. A TXLSComment nem teszi nyilvánosan elérhetővé a saját sorát és oszlopát, így a természetes ciklus — „járd be az összes megjegyzést, és jelentsd, hol ülnek” — visszafelé fut az API-val szemben. A cellákból kell kiindulnia. Vagy azoknak a címeknek a listájából vezérelje az auditot, amelyeket megjegyzetelt, vagy írás közben vezessen saját pozíciónaplót, mert a megjegyzésobjektum utólag nem fogja megmondani, hol lakik

var
  Book: IXLSWorkbook;
  Sheet: IXLSWorksheet;
  Remark: TXLSComment;
begin
  Book := TXLSWorkbook.Create;
  Sheet := Book.Sheets.Add;
  Sheet.Name := 'Review';
  Sheet.Cells.Item[5, 2].Value := 4821.50;

  Remark := Sheet.Cells.Item[5, 2].AddComment('Awaiting sign-off from controller');
  Remark.Visible := True;   // a feljegyzés első megtekintéskor nyitva álljon

  Sheet.AddHyperlink(7, 2, 'https://intranet.example.com/signoff/4821',
    'Sign-off form', 'Opens the controller queue');
  Book.SaveAs('review.xls');
end;

A Visible igazra állítása a régi módja annak, hogy egy feljegyzést lehetetlen legyen figyelmen kívül hagyni: a sárga doboz nyitva marad a lapon ahelyett, hogy az egérmutatóra várna. A TXLSComment egy lépéssel tovább megy XLSX megfelelőjénél azzal, hogy elérhetővé teszi a TextRuns gyűjteményt, így egyetlen feljegyzés félkövér figyelmeztetést hordozhat egy sima magyarázat mellett — olyan formázást, amelyet az XLSX megjegyzés-API nem tesz ugyanígy elérhetővé. A hiperhivatkozások ezen az oldalon három, egymásra épülő túlterhelt változaton érkeznek (csak cím, majd megjelenített szöveggel, majd buboréksúgóval), és a munkalap HyperLinks gyűjteményén keresztül olvashatók vissza, ahol minden hivatkozás felszínre hozza az Address, SubAddress, DisplayText és ScreenTip értéket

Egy ellenőrzési indexlap többet ér a szétszórt feljegyzéseknél

Nagyjából egy tucat megjegyzés fölött az egérrel rámutatva olvasás csendben megszűnik skálázódni. A feljegyzések olyan lapokon halmozódnak, amelyeket a lektor soha nem nyit meg, és éppen a legfontosabbakat a legkönnyebb elnézni. Az a szerkezet vált be a legjobban, amely egy generált indexlapot használ: soronként egy megjegyzetelt hely, felsorolva a lap nevét, a cella címét, a szerzőt és a feljegyzés rövid kivonatát. Az utolsó oszlop olyan belső hiperhivatkozást hordoz, amelyet az AddHyperlinkToCell hívással épített, és amely egyenesen a megjegyzetelt cellára ugrik. Így a lektor egy listát olvas végig ahelyett, hogy egy rácsban vadászna, és az index sorainak száma egyben az alábbi auditmenethez tartozó megjegyzésleltár is

Az index olcsón felépíthető, mert a generátora már ismer minden pozíciót, amelyet megérintett. Fűzzön egy (lap, sor, oszlop, szerző, összefoglaló) ötöst egy listához minden megjegyzés írásakor, majd legutoljára bocsássa ki az indexlapot, hogy a sorainak száma véglegesnek számítson a mentés előtt. Két finomítás térül meg: rendezze az indexet súlyosság vagy lap szerint a beszúrási sorrend helyett, és tegyen visszatérő hivatkozást az index fejlécébe, hogy a lektor minden tétel után visszaugorhasson a tetejére. Mivel a belső hivatkozások egyszerű helymegjelölő karakterláncok, amelyek mögött semmi nincs a kapcsolatrétegben, még egy ezersoros index is szinte semmit nem ad a fájlmérethez vagy a mentési időhöz

Ugyanez a lap a visszaúton is megtérül. Amikor a lektorált munkafüzet visszaérkezik, a kódja az indexsorok mellé beírt állapotértékeket olvassa ahelyett, hogy minden lapot újra átvizsgálna esetleg megváltozott megjegyzésekért. A strukturált állapotcellák oszlopa tisztán elemezhető; a szabad szöveges feljegyzések szórása nem

Egy kiszállítás előtti auditmenet, amely tényleg elkapja a törést

Ezek közül az API-k közül egyik sem ellenőrzi a célt. Egy törölt lapra mutató hivatkozás, egy elgépelt intranetes kiszolgálónév, egy tavaly kivont fájlmegosztás: mindegyik mukkanás nélkül mentődik. Az ECMA-376 azt írja elő, hogyan tárolódik egy hivatkozás, nem azt, hogy fel is oldódjon valamire. Az a munkafüzet tehát, amely ellenőrzési metaadatokat hordoz, kiérdemel egy rövid, saját auditszakaszt, amely közvetlenül a SaveAs hívás előtt fut:

A HotXLS kiszállítás előtti auditmenetét bemutató ábra, amely a SaveAs hívás előtt ellenőrzi a belső célokat, az URL-engedélyezőlistát, a megjegyzésszámokat és a címzett szerinti tisztítást Delphiben
Négy ellenőrzés fut közvetlenül a SaveAs hívás előtt, és mindegyik olyan hibát kap el, amelyet maga a könyvtár soha nem fog jelezni
  • Gyűjtse össze a generálás során kiírt összes belső helymegjelölést, és erősítse meg, hogy a felkiáltójel előtti lapnév még mindig szerepel a munkafüzet lapgyűjteményében
  • Vesse össze a külső URL-eket a sémák és kiszolgálók engedélyezőlistájával. A csupasz file:// és UNC útvonalak környezeti részleteket szivárogtatnak, és abban a pillanatban eltörnek, amikor a fájl elhagyja a hálózatát
  • Számolja meg a megjegyzéseket laponként, és vesse össze azzal, amennyit a generátora írni szándékozott. Az az újrapróbálkozás, amely megduplázta a feljegyzéseket, itt bukkan felszínre, nem a lektor postafiókjában
  • A DeleteInRange hívással távolítsa el a kizárólag belső használatú jegyzeteket, valahányszor a címzett a szervezeten kívül ül

Azok a csapatok, amelyek adatrétegből építik a munkafüzeteiket, ezt a szakaszt beolvaszthatják ugyanabba a folyamatlépésbe, amely már az adatot is ellenőrzi, így a metaadat-ellenőrzés ingyen utazik vele. A mechanika ugyanaz, amelyet az adatbázis-lekérdezések eredményének Excel-jelentésekbe exportálása ír le, csak sorok helyett hivatkozásokra és megjegyzésekre fordítva

Egy idézőjelezési részlet buktatja el a fejlesztőket, amikor kézzel építenek helymegjelölő karakterláncokat. Azt a lapot, amelynek nevében szóköz van, idézőjelek közé kell tenni a helymegjelölésen belül, pontosan úgy, ahogy a szerkesztőléc teszi: 'Quarterly Totals'!A1, nem Quarterly Totals!A1. A HotXLS ugyanazokat a szabályokat alkalmazza, amelyeket a képletmotor használ a lapok közötti hivatkozásoknál, tehát ha egy hivatkozás működik egy munkalapképletben, akkor az idézőjelezése itt is működni fog. Adjon át idézőjel nélküli, szóközt tartalmazó nevet, és ugyanazt a csendes döglött hivatkozást kapja, amelyre a bevezető figyelmeztetett

A megjegyzések és a hiperhivatkozások a generált munkafüzet azon részei, amelyekre a lektorok további gondolkodás nélkül reagálnak, és éppen ezért okoz valódi kárt a semmire mutató cél, még mielőtt bárki észrevenné. Építse meg egyszer az ellenőrzési menetet, futtassa minden munkafüzeten a kiszállítás előtt, és az ellenőrzési folyamat átnevezéseken és átalakításokon át is épségben marad. Mind az XLS, mind az XLSX homlokzat teljes API-felülete a HotXLS Delphi Component termékoldalán van dokumentálva