מאמר טכני

Wildcards של Excel ב-HotXLS: COUNTIF, MATCH, DSUM ו-Find

HotXLS Delphi Component קורא את אותה מחרוזת תבנית בארבע דרכים שונות, כי Excel 16 עושה זאת. ב-COUNTIF וב-SUMIF הטקסט a~b הוא ליטרלי אלא אם הקריטריון מכיל גם * או ?; ב-MATCH וב-XLOOKUP במצב wildcard הטילדה היא תמיד escape, ולכן a~b מוצא את ab; ב-DSUM ובשאר פונקציות המסד טקסט רגיל פירושו "מתחיל ב"; ו-Find של תא שלם חייב לחזור אחורה אל ה-* האחרון. HotXLS הולך אחרי הכללים הנמדדים האלה מאז v2.384.52, v2.384.60 ו-v2.384.64

דיווחי הבאגים בתחום הזה לא מזכירים wildcards. הם אומרים שדוח שנוצר בשרת סופר כמה שורות פחות מאשר אותו קובץ שחושב מחדש ב-Excel, או שמספר חלק שמכיל טילדה נמצא על ידי נוסחה אחת ומתעלם ממנו הנוסחה הבאה. הסיבה היא matcher שמניח שתבנית פירושה דבר אחד בכל מקום. Excel לא עובד כך, ולכן גם מנוע שהתוצאות השמורות במטמון שלו חייבות להסכים עם Excel לא יכול לעבוד כך. לפני v2.384.52 HotXLS הזרים כל קריטריון דרך מסכת קבצים בסגנון DOS, שקיבלה תבניות יומיומיות נכון ואת מקרי הקצה שגויים בשקט

מדוע מחרוזת תבנית אחת פירושה ארבעה דברים שונים ב-Excel?

מחרוזת תבנית אחת פירושה ארבעה דברים שונים כי Excel ירש ארבעה כללי התאמה מארבע תכונות ומעולם לא איחד אותם. פונקציות הקריטריונים (COUNTIF, SUMIF, AVERAGEIF ומשפחת ה-*IFS) מחליטות לכל קריטריון אם wildcards חלים בכלל. פונקציות החיפוש (MATCH עם טיפוס התאמה 0, XLOOKUP עם match_mode 2) תמיד מיישמות אותם. פונקציות המסד (DSUM, DCOUNTA וחברותיהן) הולכות אחרי ה-Advanced Filter, שבו מילה רגילה היא קידומת. לתיבת הדו-שיח של Find יש מצבי תא-שלם וחלקי משלה. הטבלה להלן מפרטת אילו תאים תואמים כל תבנית מול עמודה אחת שמחזיקה a~b, ab, AB, abc, abcb, a*b ו-axb, כשכל פונקציה במצב ברירת המחדל שלה ללא רגישות לרישיות

תבניתCOUNTIF / SUMIFMATCH(…,0) / XLOOKUP מצב 2קריטריון DSUMFind, תא שלם, wildcards פעילים
abab, ABab, ABab, AB, abc, abcbab, AB
a*ba~b, ab, AB, abcb, a*b, axbכמו COUNTIFכל ערך, כולל abcכמו COUNTIF
a~bרק a~bab, ABab, AB, abc, abcbab, AB
a~*bרק a*bרק a*bרק a*bרק a*b
=abab, ABלא רלוונטיab, ABלא רלוונטי

השורה של a~b היא המקום שבו COUNTIF ו-MATCH חולקים, ומספרי חלקים וקודים שהוקלדו ידנית מכילים טילדות יותר מכפי שסביר לצפות. השורה של a*b מציגה את המוקש השני: abc תואם עבור DSUM ולא עבור COUNTIF, כי פונקציית המסד מוסיפה * בשקט. ערכי ה-DSUM עבור ab, a*b ו-=ab הגיעו ישירות מהרצות של Excel 16; הערך של DSUM עבור a~b נובע מאותו כלל קידומת, מכיוון שה-* המתווסף הופך את הקריטריון לתבנית wildcard שבה ~b הוא b מהונק

מתי COUNTIF עובר למצב wildcard?

COUNTIF עובר למצב wildcard רק כשטקסט הקריטריון מכיל * או ?, מהונקים או לא. בלי אף אחד מהתווים, Excel משווה את הקריטריון מול כל תא בתור מחרוזת שלמה, ללא רגישות לרישיות, וטילדה היא סתם טילדה, ולכן COUNTIF(A1:A7,"a~b") סופר את התא שמחזיק באמת את a~b. מוסיפים כוכבית אחת והמשמעות מתהפכת: ב-"a~b*" הטילדה עכשיו מהנקה את ה-b, התבנית נקראת "ab ואחריו כל דבר", והתא a~b כבר לא נספר. HotXLS מיישם את הכלל הזה בשני המנועים מאז v2.384.52, דרך matcher קריטריונים אחד ב-lxCalc המשותף ל-COUNTIF, SUMIF, AVERAGEIF, COUNTIFS, SUMIFS, AVERAGEIFS ולפונקציות המסד

דיאגרמת שער ה-wildcard של HotXLS: COUNTIF ו-SUMIF מיישמים wildcards רק כשהקריטריון מכיל כוכבית או סימן שאלה, ולכן a~b סופר את התא הליטרלי ומחזיר 1, בזמן ש-MATCH טיפוס 0 ו-XLOOKUP מצב 2 תמיד במצב wildcard, ולכן a~b מוצא את ab במיקום 2
השער הוא כל ההבדל: COUNTIF דורש כוכבית או סימן שאלה לפני שהוא מתייחס לטילדה בתור escape, MATCH לעולם לא דורש, ולכן מחרוזת תבנית אחת סופרת תא אחד ומוצאת את השני

בתוך מצב ה-wildcard כללי ההנקה זהים לכל מקום אחר ב-Excel: ~ הופך את התו הבא לליטרלי מה שלא יהיה, ולכן ~b פירושו b ו-~~ פירושו טילדה אחת, וטילדה בסוף התבנית מושמטת, ולכן "a*~" מתנהג כמו "a*". סוגריים מרובעים לעולם אינם מיוחדים. קריטריון של "[x]" סופר תאים שמחזיקים את שלושת התווים [x], ו-"[a-z]" לא סופר דבר על נתונים רגילים. TXLSXWorkbook.Calculate מחשב מחרוזת נוסחה מול הגיליון הפעיל ומחזיר Variant, הדרך המהירה ביותר לבדוק את הכללים האלה מול הנתונים שלכם

uses
  System.Variants, lxHandleX;

const
  Names: array [1..7] of string = ('a~b', 'ab', 'AB', 'abc', 'abcb', 'a*b', 'axb');
var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  i: Integer;

  procedure Show(const Formula: string);
  begin
    Writeln(Formula, ' = ', VarToStr(Book.Calculate(Formula)));
  end;

begin
  Book := TXLSXWorkbook.Create;
  try
    Sheet := Book.Sheets.Add('Data');
    for i := 1 to High(Names) do
    begin
      Sheet.Cells[i, 1].Value := Names[i];
      Sheet.Cells[i, 2].Value := 1 shl (i - 1);  // 1, 2, 4 ... כך סכום SUMIF מזהה את שורותיו
    end;
    Sheet.Cells[8, 1].Value := 5;                // מספר; A9 נשאר ריק

    Show('=COUNTIF(A1:A7,"a~b")');      // 1    בלי * או ?: טקסט רגיל, התא a~b
    Show('=COUNTIF(A1:A7,"a~b*")');     // 4    מצב wildcard: ab, AB, abc, abcb
    Show('=COUNTIF(A1:A7,"a*b")');      // 6    wildcard על המחרוזת כולה, abc נשלל
    Show('=SUMIF(A1:A7,"a*b",B1:B7)');  // 119  כל שורה חוץ מ-abc (8)
    Show('=COUNTIF(A1:A7,"a~*b")');     // 1    ה-a*b הליטרלי
    Show('=COUNTIF(A1:A9,"<>ab")');     // 7    המספר 5 וה-A9 הריק נספרים
    Show('=COUNTIF(A1:A9,"<>")');       // 8    תאים לא ריקים
  finally
    Book.Free;
  end;
end.

מה "<>text" סופר?

קריטריון "<>text" סופר כל תא שאינו הטקסט הזה, וב-Excel 16 זה כולל מספרים, booleans, ערכי שגיאה ותאים ריקים. "<>" ריק הוא שאלה אחרת לגמרי: הפירוש הוא "לא תא ריק", ולכן הוא מדלג על תאים ריקים אבל סופר כל ערך, כולל הטקסט הריק שנוסחה כמו ="" מחזירה. הקוד הישן של HotXLS קיבל נכון תאי טקסט אבל לא מספרים: אי-שוויון של Variant גרם ל-Delphi להמיר את 'ab' למספר, ההמרה העלתה חריגה, handler בלע אותה בתור "אין התאמה", ותאים מספריים נשרו מהספירה בשקט. הצד של התאים הריקים בסיפור הזה, כולל למה שווה אופרנד ריק בהשוואה רגילה, מכוסה ב-איך HotXLS מטפל בשרשראות השוואה, בתאים ריקים וב-SUMIF

מדוע MATCH מוצא את ab כשמחפשים a~b?

MATCH מוצא את ab כשמחפשים a~b כי MATCH עם טיפוס התאמה 0 ו-XLOOKUP עם match_mode 2 תמיד במצב wildcard, ולכן הטילדה היא escape גם כשהתבנית לא מכילה * או ?. Excel 16 מאשר זאת על טווח של שני תאים שמחזיק a~b ו-ab: MATCH("a~b",D1:D2,0) מחזיר 2, ועל טווח שמחזיק רק a~b אותה קריאה מחזירה #N/A. כדי לחפש את הטקסט הליטרלי a~b כותבים "a~~b". במקביל, COUNTIF(D1:D2,"a~b") על אותם שני תאים מחזיר 1, וסופר את התא השני. אותה מחרוזת, אותו טווח, תא הפוך

זו הסיבה ש-HotXLS שומר על שתי ההחלטות בנפרד במקום מאחורי נקודת כניסה אחת של "התאם תבנית". ה-matcher עצמו משותף: מאז v2.384.52, MATCH, XLOOKUP ופונקציות הקריטריונים מריצות את אותו matcher עם backtracking, עם אותו טיפול בהנקות ועם אותו כלל טילדה סופית. מה ששונה הוא השער שלפניו. נתיב הקריטריונים שואל קודם "האם הטקסט הזה מכיל * או ??"; נתיב ה-lookup לעולם לא שואל. איחוד השניים היה מתקן משפחה אחת ושובר את השנייה, ושני הכיוונים נבדקים מול ערכי Excel 16 בשני המנועים. ל-lookups עם wildcard יש גם תנאי מוקדם משלהם: XLOOKUP דוחה התאמת wildcard משולבת עם מצב חיפוש בינארי, כלל שמתואר ב-המדריך של HotXLS למצבי החיפוש של XLOOKUP ו-XMATCH

איך DSUM ופונקציות המסד קוראות קריטריון טקסט רגיל?

DSUM ושאר פונקציות המסד קוראות קריטריון טקסט בלי =, < או > פותחים בתור "מתחיל ב", כשה-wildcards עדיין פעילים. זהו כלל ה-Advanced Filter, והוא שונה מ-COUNTIF בכוונה. Excel 16 נמדד על עמודת Name שמחזיקה abc, ab, xab, AB, a~b ו-a*b: הקריטריון ab תואם את abc, ab ו-AB; =ab תואם רק את ab ו-AB; <>ab הוא אי-שוויון של ערך שלם; a*b ו-a? הן תבניות קידומת גם כן; >ab הוא השוואה רגילה. לפני v2.384.64 HotXLS התאים את ab במדויק, ולכן DSUM על נתוני הבדיקה האלה החזיר 10 במקום 11 ש-Excel מחזיר

התיקון היה צריך לעקוף את מפרסר התנאים, שמקפל גם את ab וגם את =ab לאותו תנאי שוויון. HotXLS לכן בוחן את טקסט הקריטריון הגולמי לפני שהוא סומך על התנאי המפורסר: קריטריון טקסט שהתו הראשון שלו אינו =, < או > מקבל * מוסף ועובר דרך matcher ה-wildcards, וכל השאר שומר על השוואת הערך השלם שלו. הערה מעשית אחת כשבונים טווחי קריטריונים בקוד: במנוע ה-XLSX, שיוך המחרוזת '=ab' אל TXLSXCell.Value שומר טקסט, בזמן שהמנוע הקלאסי TXLSWorkbook מקמפל ערך שמתחיל ב-= בתור נוסחה אלא אם מקדימים אותו בגרש

דיאגרמת HotXLS של כלל הקריטריון של DSUM: קריטריון טקסט רגיל מקבל כוכבית מוספת ומתאים בתור קידומת, ולכן ab מגיע אל ab, AB, abc ו-abcb, equals ab משווה את הערך השלם, angle bracket ab שולל את שניהם, וטילדה-כוכבית שורדת בתור ה-a*b הליטרלי, עם סכומי ה-DSUM הנמדדים 30, 6, 121 ו-32
Excel ירש את כלל ה-Advanced Filter עבור פונקציות המסד: טקסט רגיל פירושו מתחיל ב, בזמן ש-equals או not-equals פותחים משווים את הערך השלם; HotXLS בוחן את טקסט הקריטריון הגולמי לפני שהוא סומך על התנאי המפורסר
const
  Names: array [1..7] of string = ('a~b', 'ab', 'AB', 'abc', 'abcb', 'a*b', 'axb');
  Criteria: array [0..4] of string = ('ab', '=ab', '<>ab', 'a*b', 'a~*');
var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  i: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    Sheet := Book.Sheets.Add('Db');
    Sheet.Cells[1, 1].Value := 'Name';
    Sheet.Cells[1, 2].Value := 'Val';
    for i := 1 to High(Names) do
    begin
      Sheet.Cells[i + 1, 1].Value := Names[i];
      Sheet.Cells[i + 1, 2].Value := 1 shl (i - 1);
    end;
    Sheet.Cells[1, 4].Value := 'Name';            // כותרת הקריטריון ב-D1
    for i := 0 to High(Criteria) do
    begin
      Sheet.Cells[2, 4].Value := Criteria[i];     // נשאר טקסט במנוע ה-XLSX
      Writeln(Criteria[i], ' -> ',
        VarToStr(Book.Calculate('=DSUM(A1:B8,"Val",D1:D2)')));
    end;
    // ab   -> 30   ab, AB, abc, abcb (מתחיל ב)
    // =ab  -> 6    ab, AB (הערך השלם)
    // <>ab -> 121  הכול חוץ מ-ab ו-AB
    // a*b  -> 127  a*b* תואם את כל השבעה, abc נכלל
    // a~*  -> 32   רק ה-a*b הליטרלי
  finally
    Book.Free;
  end;
end;

הבדל אחד קשור שרד את תיקון הקידומת וחשוב ב-builds ישנים. השוואות טקסט כמו >ab השתמשו בסדר code point, בזמן ש-Excel שם פיסוק לפני אותיות, ולכן "a~b">"ab" הוא FALSE ב-Excel והיה TRUE ב-HotXLS. מאז v2.384.67 הקריטריונים > ו-<, יחד עם השוואת טקסט רגילה ומיון, משתמשים ב-collation ה-word sort של Excel תחת ה-locale של המשתמש הנוכחי, והשניים מסכימים שוב

מדוע Find של תא שלם פספס את abcb?

Find של תא שלם פספס את abcb כי ה-matcher עצר בנקודה הראשונה שבה התבנית אזלה במקום לחזור אחורה אל ה-* האחרון. ה-matcher של ההתאמה החלקית שמאחורי Replace מחזיר ברגע שהתבנית מתרוקנת; Find של תא שלם השתמש בו ואז דרש שההתאמה תכסה את כל התא: a*b מול abcb עצר אחרי ab, צרך 2 תווים מתוך 4, ונדחה. מאז v2.384.60 ה-matcher של תא שלם הוא מימוש נפרד שמתייחס ל-"התבנית נגמרה, הטקסט לא" בתור אי-התאמה נוספת ומנסה שוב מהכוכבית האחרונה, ולכן a*b תואם את abcb ו-a?b*b תואם את axbyb, כפי ש-Find של Excel 16 עושה עם "Match entire cell contents" מסומן

דיאגרמת HotXLS של backtracking של Find עם wildcard בתא שלם: התבנית a*b צורכת את a ו-b בתא abcb וה-matcher הישן עצר עם התבנית אזלה ודחה את התא, בזמן שה-matcher הנוכחי מתייחס לתבנית שנגמרה כשהטקסט נותר בתור אי-התאמה נוספת ומנסה שוב מהכוכבית האחרונה עד שהתא כולו תואם
התאמת תא שלם אינה הושלמה כשהתבנית אזלה; התייחסות לטקסט שנותר בתור אי-התאמה נוספת שולחת את ה-matcher בחזרה אל הכוכבית האחרונה, וכך a*b מגיע אל abcb כמו Find של Excel 16

אותה מהדורה שינתה גם את הטילדה. Find של Excel 16, גם במצב תא-שלם וגם בחלקי, מתייחס ל-~ בתור escape לכל תו שאחריו: a~b מוצא את ab, a~~b מוצא את a~b, וטילדה סופית מתעלמת, ולכן q~ מתנהג כמו q. ה-matcher הישן של HotXLS זיהה רק את ~*, ~? ו-~~ כהנקות, ולכן a~b מצא את הטקסט a~b. תבנית Find של ~ בודדת אינה יציבה ב-Excel עצמו, מתאימה כל תא כמו תבנית ריקה, ו-HotXLS לא מחקה זאת

במנוע ה-XLSX החיפוש הוא TXLSXWorksheet.FindText עם סט TXLSXFindOptions: lxfUseWildcards מדליק את *, ? ו-~, lxfWholeCell דורש שהתא כולו יתאים, ו-lxfMatchCase הופך את ההשוואה לרגישה לרישיות. בלי lxfUseWildcards כל תו, כוכבית כוללת, הוא ליטרלי. Find מביט בערכי טקסט בלבד; תאים מספריים מדולגים, ותאי נוסחה מדולגים אלא אם מוגדר lxfSearchFormulas, ואז טקסט הנוסחה נחפש. העוגן שנקבע על ידי StartRow ו-StartCol הוא כולל, ולכן לולאת Find All צועדת עמודה אחת אחרי כל פגיעה

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Row, Col, NextRow, NextCol, Changed: Integer;
  Opts: TXLSXFindOptions;
begin
  Book := TXLSXWorkbook.Create;
  try
    Sheet := Book.Sheets.Add('Parts');
    Sheet.Cells[1, 1].Value := WideString('abc');
    Sheet.Cells[2, 1].Value := WideString('abcb');
    Sheet.Cells[3, 1].Value := WideString('a~b');
    Sheet.Cells[4, 1].Value := WideString('ab');

    Opts := [lxfUseWildcards, lxfWholeCell];
    if Sheet.FindText('a*b', Row, Col, Opts, 1, 1) then
      Writeln('a*b  whole cell -> row ', Row);   // 2: abc נדחה, abcb חוזר אחורה
    if Sheet.FindText('a~b', Row, Col, Opts, 1, 1) then
      Writeln('a~b  whole cell -> row ', Row);   // 4: ~b הוא b מהונק
    if Sheet.FindText('a~~b', Row, Col, Opts, 1, 1) then
      Writeln('a~~b whole cell -> row ', Row);   // 3: ~~ הוא טילדה ליטרלית אחת

    // התאמה חלקית, Find All: תא העוגן נכלל, ולכן מדלגים אחרי כל פגיעה
    NextRow := 1;
    NextCol := 1;
    while Sheet.FindText('a*b', Row, Col, [lxfUseWildcards], NextRow, NextCol) do
    begin
      Writeln('a*b  contained in row ', Row);     // שורות 1, 2, 3 ו-4
      NextRow := Row;
      NextCol := Col + 1;
    end;

    // החלפה עם wildcard של תא שלם משכתבת רק את ה-a~b הליטרלי
    Changed := Sheet.ReplaceText('a~~b', 'a-b', Opts);
    Writeln(Changed, ' cell(s) replaced');         // 1
  finally
    Book.Free;
  end;
end;

הלולאה החלקית מוצאת את כל ארבע השורות, כולל abc, כי במצב חלקי ל-a*b מספיק להופיע איפשהו בתוך התא. FindTextIn ו-ReplaceTextIn מקבלים את אותן אפשרויות בתוספת חלון FirstRow, FirstCol, LastRow, LastCol, המקבילה התוכנתית של חיפוש בתוך בחירה. המנוע הקלאסי חושף את אותם כללים דרך overload עם שלושה booleans, TXLSWorksheet.FindText(SearchText, Row, Col, MatchCase, UseWildcards, WholeCell), בתוספת overload מתאים של ReplaceText, עם תוצאות שורה ועמודה שמתחילות מ-1:

var
  Classic: IXLSWorkbook;
  Sheet: TXLSWorksheet;
  Row, Col: Integer;
begin
  Classic := TXLSWorkbook.Create;
  Sheet := Classic.Sheets.Add;
  Sheet.Range['A1', 'A1'].Value := 'abcb';
  // MatchCase = False, UseWildcards = True, WholeCell = True
  if Sheet.FindText('a*b', Row, Col, False, True, True) then
    Writeln('found at ', Row, ',', Col);           // 1,1
  if not Sheet.FindText('a*c', Row, Col, False, True, True) then
    Writeln('a*c does not cover abcb');
end;

מה matcher מסכת ה-DOS הישן קיבל שגוי?

ה-matcher הישן קיבל שגוי את התווים המיוחדים, כי מסכת קבצים של DOS היא שפה אחרת מ-wildcard של Excel. לפני v2.384.52 פונקציות הקריטריונים ופונקציות המסד העבירו כל תבנית אל MatchesMask, matcher של מסכות קבצים ביחידת lxMasks. התחביר שלו חופף את זה של Excel במקרים נפוצים, מה שהסתיר את הבעיה, אבל הוא סוטה בדיוק במקומות שבהם נתונים אמיתיים מתעניינים:

  • [x] נקרא בתור קבוצת תווים, ולכן COUNTIF(A1:A10,"[x]") ספר תאים שמחזיקים x במקום את הטקסט המסוגר, ו-"[a-z]" התאים כל תא בן אות אחת
  • לא הייתה הנקת טילדה, ולכן "a~*b" לא יכל להתאים כוכבית ליטרלית
  • מסכה משובשת, כמו סוגריים שלא נסגרו, העלתה חריגה שהקורא בלע בתור "אין התאמה", והפכה טעות הקלדה בקריטריון לסכום שגוי בשקט
  • בצד החיפוש, MATCH ו-XLOOKUP התייחסו רק ל-~*, ~? ו-~~ בתור הנקות, ולכן MATCH("a~b",…,0) מצא את ה-a~b הליטרלי במקום את ab

אם חוברות העבודה שלכם השתמשו רק ב-* וב-? על נתונים אלפאנומריים רגילים, התוצאות כבר היו נכונות ולא ישתנו. אם הן מכילות סוגריים, טילדות, עמודות מטיפוסים מעורבים תחת "<>text", או קריטריוני DSUM שנכתבו כמילים רגילות, חישוב מחדש עם v2.384.64 ומעלה עשוי לשנות סכומים, והסכומים החדשים הם אלה ש-Excel מציג. אותה הבחנה בין איך Excel שומר קריטריון ואיך הוא משווה אותו צצה גם עבור מסננים שמורים, שנדונו ב-המאמר של HotXLS על קריטריוני DOPER של AutoFilter ב-BIFF8

עזר זריז: כללי ה-wildcard של Excel ב-HotXLS

  • COUNTIF, SUMIF, AVERAGEIF ומשפחת ה-*IFS משתמשים ב-wildcards רק כשהקריטריון מכיל * או ?; אחרת הם משווים מחרוזות שלמות ללא רגישות לרישיות וה-~ הוא ליטרלי (מאז v2.384.52)
  • MATCH עם טיפוס התאמה 0 ו-XLOOKUP עם match_mode 2 תמיד משתמשים ב-wildcards, ולכן a~b מוצא את ab והליטרלי דורש a~~b (מאז v2.384.52)
  • במצב wildcard ה-~ מהנק כל תו בא וה-~ הסופית מושמטת; [ ו-] הם תווים רגילים
  • "<>text" סופר מספרים, booleans, שגיאות ותאים ריקים; "<>" ריק סופר תאים לא ריקים, כולל תוצאות =""
  • DSUM ושאר פונקציות המסד מתייחסות לטקסט רגיל בתור "מתחיל ב"; =text ו-<>text משווים את הערך השלם (מאז v2.384.64)
  • Find של תא שלם עם lxfUseWildcards ו-lxfWholeCell חוזר אחורה, ולכן a*b תואם את abcb; Find ו-Replace מתייחסים ל-~ בתור escape לכל תו (מאז v2.384.60)
  • סדר הטקסט בקריטריונים > ו-< הולך אחרי ה-collation של word sort של Excel, פיסוק לפני אותיות (מאז v2.384.67)

תאימות ל-Excel במנוע נוסחאות היא ברובה מקרי קצה כאלה, נמדדים מול Excel ולא ננחשים מהתיעוד. HotXLS מחשב את COUNTIF, MATCH, XLOOKUP, DSUM ושאר ספריית הפונקציות שלו באופן טבעי ב-Delphi וב-C++Builder, גם במנוע הקלאסי וגם במנוע ה-XLSX, בלי Excel מותקן. פרטים, מהדורות והורדת ניסיון נמצאים ב-דף רכיב הגיליונות HotXLS ל-Delphi