Redenumește o foaie din „Summary” în „Overview” într-un registru de lucru generat și fiecare hyperlink intern care trimitea către Summary!A1 nu mai duce nicăieri. Nicio excepție la salvare, niciuna la deschidere. Legătura se afișează în continuare, arată în continuare ca și cum s-ar putea da clic pe ea și se rezolvă discret către nimic. Același fel de stricăciune apare după o conversie de tip save-as sau după un dus-întors .xls/.xlsx, când un comentariu aterizează cu o coloană mai încolo sau o legătură relativă își pierde ținta. Ambele funcționalități poartă stare de recenzie pe baza căreia acționează oameni reali, așa că, atunci când se strică, eșecul rămâne invizibil până când un recenzent dă clic și nu se întâmplă nimic
Acesta este motivul practic pentru care comentariile și hyperlinkurile merită mai multă grijă decât sugerează înfățișarea lor cosmetică. HotXLS oferă codului Delphi și C++Builder acces direct de scriere la amândouă, în XLS și în XLSX, fără nicio automatizare Excel în buclă. Reversul acestui control este responsabilitatea: biblioteca scrie exact țintele pe care i le dai și nu validează niciuna, așa că păstrarea intactă a unui flux de recenzie este treaba codului tău, nu a Excel
Comentariile din celule ca înregistrări de recenzie scrise de mașină
În modelul de clase XLSX, un comentariu este un obiect la nivel de foaie de calcul: își cunoaște rândul, coloana, un autor și un corp de text. Câmpul de autor își merită locul. Când un registru de lucru generat de codul tău trece printr-un lanț de recenzie, prima întrebare pe care o pune un auditor este cine a scris o anumită notă, iar o notă lăsată fără autor răspunde la întrebarea aceea cu un gol. Marchează comentariile generate cu o identitate de serviciu, ca proveniența să nu fie niciodată ambiguă
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Note: TXLSXComment;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('reconciliation.xlsx');
Sheet := Book.Sheets[0];
// Notă cu autor pe cifra ajustată
Sheet.AddComment(14, 4, 'Manual adjustment: late FX rate, see ticket FIN-2214',
'recon-service');
// Actualizează o notă existentă în loc să stivuiești o a doua
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;
Sondarea cu FindAt cântărește mai mult decât pare. Un job în lot care reia execuția după o defecțiune trecătoare va apela voios AddComment a doua oară pe o celulă pe care a adnotat-o deja, iar celula ajunge cu două note stivuite pe care nu le-a cerut nimeni. Sondează întâi cu FindAt și actualizează obiectul pe care ți-l întoarce. Colecția Comments expune și DeleteAt, și DeleteInRange. Varianta pe interval este cea la care apelezi când igienizezi un registru de lucru înainte să iasă din firmă: ștergerea adnotărilor interne de QA dintr-o regiune întreagă este un singur apel, nu o buclă scrisă de mână peste celule
URL-urile externe și salturile din interiorul registrului sunt API-uri diferite
OOXML ține cele două feluri de legături în locuri diferite. Un URL extern devine o intrare de relație în partea .rels a foii, iar celula trimite către relație printr-un id. Un salt intern nu atinge deloc stratul de relații; este un simplu șir de locație, precum Summary!A1, stocat direct pe legătură. HotXLS păstrează distincția vizibilă în API în loc să încarce o singură metodă cu ambele roluri, ceea ce înseamnă că alegi apelul potrivit știind unde stă ținta:
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');
Pe obiectul TXLSXHyperlink rezultat, Url și Location se exclud reciproc, iar IsInternal îți spune care dintre cele două este populat. Indicatorul acela este ce verifici când inventariezi legăturile dintr-un registru de lucru deschis și trebuie să tratezi „iese din fișier” și „rămâne în fișier” după reguli diferite: o gazdă externă s-ar putea izbi de o listă de adrese permise, în timp ce o țintă internă trebuie doar să numească o foaie care există. Legăturile interne nu au în spate părți de relație, ceea ce le face și mai ieftin de rescris în masă
Stricăciunea din deschidere trăiește în întregime pe partea internă și decurge dintr-un singur fapt: un șir de locație nu este o referință analizată. HotXLS scrie exact textul pe care i-l dai, iar nimic nu reorientează textul acela când o foaie este redenumită mai târziu. Două apărări rezistă în practică. Prima este disciplina ordinii: redenumește fiecare foaie înainte să generezi vreo legătură, apoi tratează numele foilor ca pe niște identificatori înghețați. A doua este mai trainică și supraviețuiește redenumirilor făcute după aceea. Îndreaptă legătura către un nume definit la nivel de registru de lucru, nu către o adresă brută Sheet!Cell, pentru că Excel rescrie definiția unui nume când foaia de dedesubt se schimbă, așa că legătura merge automat odată cu ea. A doua abordare se împerechează firesc cu tehnicile din numele definite și formulele între foi în HotXLS
Partea XLS: aceleași concepte, instalație mai veche
Fațada BIFF8 atârnă comentariile de intervale, nu de o colecție la nivel de foaie de calcul. Apelezi AddComment pe un IXLSRange și primești înapoi un TXLSComment; proprietatea Comment a intervalului citește o notă existentă, iar ClearComments le șterge. Muchia tăioasă de aici ține de poziție. Un TXLSComment nu își expune public propriul rând și propria coloană, așa că bucla firească, „parcurge fiecare comentariu și raportează unde se află”, merge în răspăr cu API-ul. Trebuie să pornești de la celule. Fie conduci auditul pornind de la lista de adrese pe care le-ai adnotat, fie îți ții propriul jurnal de poziții pe măsură ce scrii, pentru că obiectul comentariu nu îți va spune după aceea unde stă
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; // deschide nota chiar de la prima vizualizare
Sheet.AddHyperlink(7, 2, 'https://intranet.example.com/signoff/4821',
'Sign-off form', 'Opens the controller queue');
Book.SaveAs('review.xls');
end;
Setarea lui Visible pe True este modul vechi de a face o notă imposibil de trecut cu vederea: cutia galbenă rămâne deschisă pe foaie în loc să aștepte trecerea cursorului. TXLSComment merge cu un pas mai departe decât omologul său XLSX expunând TextRuns, așa că o singură notă poate purta un avertisment îngroșat lângă o explicație simplă, o formatare pe care API-ul de comentarii XLSX nu o expune în același fel. Hyperlinkurile de pe partea aceasta sosesc prin trei supraîncărcări progresive (doar adresa, apoi cu text afișat, apoi cu un sfat de ecran) și se citesc înapoi prin colecția HyperLinks a foii de calcul, unde fiecare legătură scoate la suprafață Address, SubAddress, DisplayText și ScreenTip
O foaie-index de recenzie bate notele împrăștiate
Dincolo de vreo duzină de adnotări, cititul prin trecerea cursorului încetează discret să mai scaleze. Notele se adună pe foi pe care recenzentul nu le deschide niciodată, iar cele care contează cel mai mult sunt exact cele mai ușor de ratat. Structura care a rezistat cel mai bine este o foaie-index generată: câte un rând pentru fiecare locație adnotată, cu numele foii, adresa celulei, autorul și un scurt extras din notă. Ultima coloană poartă un hyperlink intern construit cu AddHyperlinkToCell, care sare direct la celula adnotată. Acum recenzentul citește o listă pe verticală în loc să vâneze prin toată grila, iar numărul de rânduri al acelui index ține loc și de inventar de comentarii pentru trecerea de audit de mai jos
Indexul este ieftin de construit pentru că generatorul tău cunoaște deja fiecare poziție pe care a atins-o. Adaugă la o listă câte un tuplu (foaie, rând, coloană, autor, rezumat) pe măsură ce scrii fiecare comentariu, apoi emite foaia-index la final, ca numărul ei de rânduri să fie definitiv înainte de salvare. Două rafinamente se răsplătesc: ordonează indexul după gravitate sau după foaie, nu după ordinea inserării, și pune o legătură de întoarcere în antetul indexului, ca recenzentul să poată sări înapoi sus după fiecare element. Fiindcă legăturile interne sunt simple șiruri de locație, fără nimic în stratul de relații în spatele lor, nici măcar un index de o mie de rânduri nu adaugă aproape nimic la dimensiunea fișierului sau la timpul de salvare
Aceeași foaie se răsplătește din nou la drumul de întoarcere. Când registrul de lucru recenzat vine înapoi, codul tău citește valorile de stare tastate în celulele de lângă rândurile indexului, în loc să rescaneze fiecare foaie după comentarii care s-ar putea să se fi schimbat. O coloană de celule de stare structurate se analizează curat; o împrăștiere de note în text liber, nu
O trecere de audit înainte de livrare care chiar prinde stricăciunea
Niciunul dintre aceste API-uri nu validează o țintă. O legătură către o foaie pe care ai șters-o, o gazdă de intranet scrisă greșit, o partajare de fișiere scoasă din uz trimestrul trecut: toate se salvează fără să crâcnească. ECMA-376 specifică felul în care este stocată o legătură, nu faptul că ea se rezolvă către ceva. Un registru de lucru care poartă metadate de recenzie își merită de aceea o scurtă etapă de audit proprie, rulată chiar înainte de SaveAs:
- Adună fiecare locație internă scrisă în timpul generării și confirmă faptul că numele de foaie dinaintea semnului de exclamare încă există în colecția de foi a registrului de lucru
- Verifică URL-urile externe față de o listă de scheme și gazde permise. Căile
file://goale și cele UNC scurg detalii de mediu și se strică în clipa în care fișierul iese din rețeaua ta - Numără comentariile de pe fiecare foaie și compară cu ce a intenționat generatorul tău să scrie. O reluare care a dublat notele iese la suprafață aici, nu în inboxul recenzentului
- Elimină adnotările strict interne cu
DeleteInRangeori de câte ori destinatarul se află în afara organizației
Echipele care își construiesc registrele de lucru pornind de la un strat de date pot plia etapa aceasta în același pas de pipeline care validează deja datele, așa că verificarea metadatelor merge la pachet, pe gratis. Mecanica este cea descrisă în exportul rezultatelor unei interogări de bază de date în rapoarte Excel, întoarsă către legături și comentarii în loc de rânduri
Un detaliu de ghilimele îi încurcă pe oameni când construiesc de mână șiruri de locație. O foaie al cărei nume conține un spațiu trebuie pusă între ghilimele în interiorul locației, exact așa cum o face bara de formule: 'Quarterly Totals'!A1, nu Quarterly Totals!A1. HotXLS aplică aceleași reguli pe care motorul de formule le folosește pentru referințele între foi, așa că, dacă o legătură funcționează într-o formulă de foaie de calcul, ghilimelele ei vor funcționa și aici. Dă-i un nume cu spațiu și fără ghilimele și obții exact legătura moartă și tăcută despre care avertiza deschiderea
Comentariile și hyperlinkurile sunt părțile dintr-un registru de lucru generat pe baza cărora recenzenții acționează fără să stea pe gânduri, exact de aceea o țintă care nu duce nicăieri face pagube reale înainte să observe cineva. Construiește o dată trecerea de validare, rulează-o pe fiecare registru de lucru înainte să plece și fluxul de recenzie rămâne intact peste redenumiri și conversii. Întreaga suprafață de API pentru fațadele XLS și XLSX este documentată pe pagina de produs HotXLS Delphi Component