מאמר טכני

שמות מוגדרים ונוסחאות בין-גיליונות ב-HotXLS עבור Delphi

שמות מוגדרים ב-Excel הם כינויים לטווחי תאים, קבועים או נוסחאות שאפשר להפנות אליהם מכל מקום בחוברת. HotXLS, ספריית גיליונות אלקטרוניים נייטיבית עבור Delphi ו-C++Builder, חושפת שמות מוגדרים דרך שני מאגרים שונים, אחד לחזית XLS ואחד לחזית XLSX

שני מאגרי שמות

ב-XLS, שמות מוגדרים נגישים ע"י IXLSWorkbook.Names שמחזיר אוסף IXLSNames. ב-XLSX, הם נמצאים ב-TXLSXWorkbook.DefinedNames שמחזיר TXLSXDefinedNames. שני המאגרים מאפשרים קריאה וכתיבה של שמות, אך ה-API שונה — לא ניתן לטעות בפשטות בין השניים

תחום: כלל-חוברת לעומת תחום גיליון

שם מוגדר ב-XLSX יכול להיות ברמת החוברת כולה, או מוגבל לגיליון ספציפי (sheet-scoped). ב-TXLSXDefinedName, הנכס LocalSheetId קובע: ערך -1 (ברירת מחדל) הוא ברמת החוברת, וערך אחר הוא index הגיליון הספציפי. שני גיליונות יכולים לשתף שם מוגדר עם אותו שם כשהם ב-scope שונה — Excel מבחין ביניהם לפי הקשר

הבדל קידומת נוסחה: XLS לעומת XLSX

מלכודת נפוצה בעת מעבר בין פורמטים: ב-XLSX, Cell.Formula מקבל ביטוי ללא קידומת = (למשל 'SUM(A1:A10)'). ב-XLS, Cell.Value מקבל את הנוסחה עם קידומת = (למשל '=SUM(A1:A10)'). ערבוב המוסכמות גורם לתא להציג טקסט מילולי במקום לחשב ערך — ללא הודעת שגיאה

שמות שמורים _xlnm.*

Excel שומר קבוצת שמות מיוחדים עם קידומת _xlnm. לצרכי מערכת: _xlnm.Print_Area, _xlnm.Print_Titles, _xlnm.Database ועוד. HotXLS חושף אותם דרך אותם אוספי שמות. אל תמחק או תשנה שמות אלה ישירות — הם קשורים להגדרות הדפסה ולפעולות Excel מובנות

InsertRows מזיז שמות מוגדרים

InsertRows ב-XLSX מעדכן הפניות בתוך אותו הגיליון, כולל הפניות בשמות מוגדרים ברמת הגיליון. אך הפניות בין-גיליונות בשמות ברמת החוברת אינן מתעדכנות — נוסחה שמפנה לאזור שעבר הזזה בגיליון אחר תמשיך לקרוא את הקואורדינטות הישנות. שמות ברמת החוברת הם הבחירה הבטוחה יותר כשתצורות הגיליון משתנות

HotXLS קומפל לתוך אפליקציית Delphi או C++Builder ללא תלויות חיצוניות; מהדורות ורישוי זמינים בדף HotXLS Component

דוגמאות קוד נוספות

var
  Book: TXLSXWorkbook;
  Data, Summary: TXLSXWorksheet;
begin
  Book := TXLSXWorkbook.Create;
  try
    Data := Book.Sheets.Add('Data');
    Summary := Book.Sheets.Add('Summary');
    // ... fill Data!A2:D100 with detail rows ...

    Book.DefinedNames.Add('TaxRate', '0.08');                // workbook scope, a constant
    Book.DefinedNames.Add('DataBlock', 'Data!$A$2:$D$100');  // workbook scope, a range
    Book.DefinedNames.Add('LocalNote', 'Summary!$B$1', 1);   // scoped to sheet index 1 only

    // XLSX formulas take no leading '='
    Summary.Cells[2, 2].Formula := 'SUM(Data!D2:D100)*TaxRate';
    Book.SaveAs('model.xlsx');
  finally
    Book.Free;
  end;
end;
var
  Book: IXLSWorkbook;   // interface-counted: do not Free
  Names: IXLSNames;
begin
  Book := TXLSWorkbook.Create;
  // assume a sheet named 'Data' already holds the detail rows
  Names := Book.GetNames;
  Names.Add('TaxRate', '0.08');
  Names.Add('Helper', 'Data!$A$2:$A$100', False);  // False = hidden from the Name Manager

  // XLS formulas go through Value, with the '=' prefix
  Book.Sheets[1].Cells.Item[2, 2].Value := '=SUM(Data!A2:A100)*TaxRate';
  Book.SaveAs('model.xls');
end;
// the calculation engine resolves names and cross-sheet references in-process
V := Book.Calculate('SUM(Data!D2:D100)*TaxRate');
if VarIsNumeric(V) then
  Log('net total checks out: ' + FloatToStr(V));