مقاله فنی

wildcard های Excel در HotXLS: COUNTIF، MATCH، DSUM و Find

HotXLS Delphi Component یک رشته pattern را چهار جور متفاوت می‌خواند، چون Excel 16 همین کار را می‌کند. در COUNTIF و SUMIF متن a~b لفظی است مگر اینکه معیار هم * داشته باشد هم ?؛ در MATCH و حالت wildcard مربوط به XLOOKUP علامت مد همیشه یک escape است، پس a~b مقدار ab را پیدا می‌کند؛ در DSUM و بقیه توابع دیتابیس متن ساده یعنی «شروع می‌شود با»؛ و Find کل-سلولی باید به آخرین * برگردد و دوباره امتحان کند. HotXLS از v2.384.52 و v2.384.60 و v2.384.64 این قواعد اندازه‌گیری‌شده را دنبال می‌کند

باگ‌ریپورت‌های این حوزه هرگز اسمی از wildcard نمی‌برند. می‌گویند گزارشی که سرور تولید کرده چند سطر کمتر از همان فایلی می‌شمارد که در Excel دوباره محاسبه شده، یا شماره قطعه‌ای که داخلش علامت مد هست با یک فرمول پیدا می‌شود و با فرمول بعدی نه. علتش matcher ای است که فرض می‌کند یک pattern همه‌جا یک معنا دارد. Excel این‌طور کار نمی‌کند، پس موتوری که نتایج cache‌شده‌اش باید با Excel جور باشد هم نمی‌تواند. قبل از v2.384.52 HotXLS هر معیاری را از یک فایل‌ماسک سبک DOS می‌گذراند، که pattern های روزمره را درست درمی‌آورد و edge case ها را بی‌سروصدا غلط

چرا یک رشته pattern در Excel چهار معنای متفاوت دارد؟

یک رشته pattern چهار معنای متفاوت دارد چون Excel چهار قاعده مچ کردن را از چهار فیچر به ارث برده و هرگز یکدستشان نکرده. توابع معیار (‏COUNTIF و SUMIF و AVERAGEIF و خانواده *IFS) به‌ازای هر معیار تصمیم می‌گیرند که اصلاً wildcard اعمال شود یا نه. توابع lookup (‏MATCH با match type صفر، ‏XLOOKUP با match_mode برابر 2) همیشه اعمالشان می‌کنند. توابع دیتابیس (‏DSUM و DCOUNTA و رفقا) از Advanced Filter پیروی می‌کنند که در آن یک کلمه لخت یعنی پیشوند. دیالوگ Find هم حالت‌های کل-سلول و جزئی خودش را دارد. جدول پایین نشان می‌دهد کدام سلول‌ها هر pattern را مچ می‌کنند وقتی ستون مقادیر a~b و ab و AB و abc و abcb و a*b و axb را دارد و همه توابع در حالت پیش‌فرض بی‌حساسیت-به-حروف‌اند

PatternCOUNTIF / SUMIFMATCH(…,0) / حالت 2 مربوط به XLOOKUPمعیار DSUMFind، کل سلول، wildcard روشن
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 از همان قاعده پیشوند دنبال می‌شود، چون همان * اضافه‌شده معیار را به یک pattern wildcard می‌برد که در آن ~b یک b با escape است

COUNTIF کی وارد حالت wildcard می‌شود؟

COUNTIF فقط وقتی وارد حالت wildcard می‌شود که متن معیار * یا ? داشته باشد، با escape یا بدون آن. بدون هیچ‌کدام از این دو کاراکتر، Excel معیار را با هر سلول به‌عنوان یک رشته کامل مقایسه می‌کند، بی‌حساسیت به بزرگی حروف، و یک علامت مد فقط همان علامت مد است، پس COUNTIF(A1:A7,"a~b") سلولی را می‌شمارد که لفظی a~b دارد. یک ستاره اضافه کنید و معنا برمی‌گردد: در "a~b*" حالا علامت مد آن b را escape می‌کند، pattern خوانده می‌شود «ab و بعدش هر چیزی»، و سلول a~b دیگر شمرده نمی‌شود. HotXLS این قاعده را از v2.384.52 در هر دو موتور اعمال می‌کند، از طریق یک matcher معیار واحد در lxCalc که بین COUNTIF و SUMIF و AVERAGEIF و COUNTIFS و SUMIFS و AVERAGEIFS و توابع دیتابیس مشترک است

نمودار دروازه wildcard در HotXLS: COUNTIF و SUMIF فقط وقتی wildcard را اعمال می‌کنند که معیار ستاره یا علامت سؤال داشته باشد، پس a~b سلول لفظی را می‌شمارد و 1 برمی‌گرداند، درحالی‌که MATCH نوع 0 و حالت 2 مربوط به XLOOKUP همیشه در حالت wildcard هستند، پس a~b مقدار ab را در موقعیت 2 پیدا می‌کند
همین دروازه کل تفاوت است: COUNTIF قبل از اینکه علامت مد را escape حساب کند ستاره یا علامت سؤال می‌خواهد، MATCH هرگز نمی‌خواهد، پس یک رشته pattern یک سلول را می‌شمارد و سلول دیگر را پیدا می‌کند

داخل حالت wildcard قواعد escape همان بقیه جاهای Excel است: ~ کاراکتر بعدی را لفظی می‌کند هر چه باشد، پس ~b یعنی b و ~~ یعنی یک علامت مد، و علامت مد در انتهای pattern حذف می‌شود، پس "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 این شامل اعداد و boolean ها و مقادیر خطا و سلول‌های خالی هم می‌شود. یک "<>" لخت سؤال دیگری است کلاً: یعنی «سلول خالی نباشد»، پس سلول‌های خالی را رد می‌کند اما هر مقداری را می‌شمارد، از جمله متن خالی‌ای که فرمولی مثل ="" برمی‌گرداند. کد قدیمی HotXLS سلول‌های متنی را درست درمی‌آورد اما اعداد را نه: یک نابرابری Variant باعث می‌شد Delphi مقدار 'ab' را به عدد تبدیل کند، تبدیل exception می‌داد، یک handler آن را به‌عنوان «مچ نشد» قورت می‌داد، و سلول‌های عددی بی‌سروصدا از شمارش می‌افتادند. سمت سلول‌های خالی این ماجرا، از جمله اینکه یک عملوند خالی در مقایسه معمولی با چه چیزی برابر است، در نحوه مدیریت زنجیره‌های مقایسه، سلول‌های خالی و SUMIF در HotXLS پوشش داده شده

چرا وقتی دنبال a~b هستید MATCH مقدار ab را پیدا می‌کند؟

MATCH وقتی دنبال a~b هستید مقدار ab را پیدا می‌کند چون MATCH با match type صفر و XLOOKUP با match_mode برابر 2 همیشه در حالت wildcard هستند، پس علامت مد حتی وقتی pattern هیچ * یا ? ندارد یک escape است. Excel 16 روی بازه دو سلولی که a~b و ab دارد همین را تأیید می‌کند: MATCH("a~b",D1:D2,0) برمی‌گرداند 2، و روی بازه‌ای که فقط a~b دارد همان فراخوانی برمی‌گرداند #N/A. برای lookup کردن متن لفظی a~b باید بنویسید "a~~b". در همین حال COUNTIF(D1:D2,"a~b") روی همان دو سلول برمی‌گرداند 1 و سلول دیگر را می‌شمارد. همان رشته، همان بازه، سلول مخالف

برای همین HotXLS این دو تصمیم را جدا نگه می‌دارد نه پشت یک نقطه ورود واحد به نام «pattern را مچ کن». خود matcher مشترک است: از v2.384.52 به بعد MATCH و XLOOKUP و توابع معیار همان matcher بازگشتی را اجرا می‌کنند، با همان مدیریت escape و همان قاعده علامت-مد-انتهایی. چیزی که فرق دارد دروازه جلوی آن است. مسیر معیارها اول می‌پرسد «آیا این متن * یا ? دارد؟»؛ مسیر lookup هیچ‌وقت نمی‌پرسد. ادغام این دو یکی از دو خانواده را فیکس می‌کرد و دیگری را خراب می‌کرد، و هر دو جهت در هر دو موتور مقابل مقادیر Excel 16 چک می‌شوند. lookup های wildcard هم پیش‌شرط خودشان را دارند: XLOOKUP مچ کردن wildcard را با حالت جست‌وجوی دودویی نمی‌پذیرد، قاعده‌ای که در راهنمای HotXLS برای مدهای جست‌وجوی XLOOKUP و XMATCH توضیح داده شده

DSUM و توابع دیتابیس یک معیار متنی ساده را چطور می‌خوانند؟

DSUM و بقیه توابع دیتابیس معیار متنی را که با = یا < یا > شروع نمی‌شود به‌عنوان «شروع می‌شود با» می‌خوانند، با wildcard های همچنان فعال. همان قاعده 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? هم pattern های پیشوندی‌اند؛ ‏>ab یک مقایسه معمولی است. قبل از v2.384.64 HotXLS مقدار ab را دقیق مچ می‌کرد، پس یک DSUM روی همان داده تست برمی‌گرداند 10 در جایی که Excel برمی‌گرداند 11

فیکس باید دور parser شرط می‌خورد، که هم ab و هم =ab را در همان شرط تساوی می‌تالد. HotXLS پس قبل از اینکه به شرط parse‌شده اعتماد کند متن خام معیار را بازرسی می‌کند: معیار متنی که اولین کاراکترش = یا < یا > نباشد یک * بهش می‌خورد و از matcher wildcard می‌گذرد، و همه چیز دیگر مقایسه کل-درایه خودش را نگه می‌دارد. یک نکته عملی وقتی بازه معیارها را در کد می‌سازید: در موتور XLSX assign کردن رشته '=ab' به TXLSXCell.Value متن ذخیره می‌کند، در حالی که موتور کلاسیک یعنی TXLSWorkbook مقداری را که با = شروع شود به‌عنوان فرمول کامپایل می‌کند مگر اینکه جلوش آپاستروف بگذارید

نمودار HotXLS از قاعده معیار DSUM: معیار متنی لخت یک ستاره می‌گیرد و به‌عنوان پیشوند مچ می‌شود پس ab به مقدارهای ab و AB و abc و abcb می‌رسد، تساوی با ab کل درایه را مقایسه می‌کند، علامت بزرگتر و کوچکتر هر دو را بیرون می‌گذارد، و مد-ستاره به‌شکل a*b لفظی سالم می‌ماند، با جمع‌های اندازه‌گیری‌شده DSUM یعنی 30 و 6 و 121 و 32
Excel قاعده Advanced Filter را برای توابع دیتابیس به ارث برده: متن لخت یعنی شروع می‌شود با، در حالی که علامت مساوی یا نامساوی ابتدایی کل درایه را مقایسه می‌کند؛ HotXLS قبل از اعتماد به شرط parse‌شده متن خام معیار را بازرسی می‌کند
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;

یک تفاوت مرتبط از فیکس پیشوند عمر بیشتری داشت و روی buildهای قدیمی مهم می‌شود. مقایسه‌های متنی مثل >ab ترتیب کدپوینت را استفاده می‌کردند، در حالی که Excel علائم نگارشی را قبل از حروف می‌گذارد، پس "a~b">"ab" در Excel برابر FALSE است و در HotXLS برابر TRUE بود. از v2.384.67 معیارهای > و < همراه با مقایسه متنی معمولی و مرتب‌سازی از collation ای به سبک word sort خود Excel زیر locale فعلی کاربر استفاده می‌کنند، و دوباره با هم یکی‌اند

چرا Find کل-سلولی مقدار abcb را از دست می‌داد؟

Find کل-سلولی مقدار abcb را از دست می‌داد چون matcher در اولین نقطه‌ای که pattern تمام می‌شد می‌ایستاد به‌جای اینکه به آخرین * برگردد و دوباره امتحان کند. matcher مچ-جزئی پشت Replace هر وقت pattern تمام می‌شد برمی‌گشت؛ Find کل-سلولی همان را reuse می‌کرد و بعدش شرط می‌گذاشت که مچ کل سلول را بپوشاند: مقدار a*b مقابل abcb بعد از ab می‌ایستاد، 2 کاراکتر از 4 را مصرف کرده بود، و رد می‌شد. از v2.384.60 matcher کل-سلولی یک پیاده‌سازی جداگانه است که «pattern تمام شد، متن نه» را یک مچ-نشد دیگر حساب می‌کند و از آخرین ستاره دوباره تلاش می‌کند، پس a*b مقدار abcb را مچ می‌کند و a?b*b مقدار axbyb را، همان‌طور که Find در Excel 16 با تیک خوردن «Match entire cell contents» انجام می‌دهد

نمودار HotXLS از برگشت به عقب در Find کل-سلولی با wildcard: مقدار a*b حروف a و b را در سلول abcb مصرف می‌کند و matcher قدیمی با pattern تمام‌شده می‌ایستاد و سلول را رد می‌کرد، درحالی‌که matcher فعلی «pattern تمام شد با متن باقی‌مانده» را یک مچ-نشد دیگر حساب می‌کند و از آخرین ستاره دوباره تلاش می‌کند تا کل سلول مچ شود
یک مچ کل-سلولی وقتی pattern تمام می‌شود هنوز تمام نشده؛ گرفتن باقی‌مانده متن به‌عنوان یک مچ-نشد دیگر matcher را به آخرین ستاره برمی‌گرداند، و همین‌طور است که a*b مثل Find در Excel 16 به abcb می‌رسد

همان نسخه علامت مد را هم عوض کرد. Find در Excel 16، هم در حالت کل-سلول و هم جزئی، مقدار ~ را برای هر کاراکتر بعدی یک escape می‌گیرد: ‏a~b مقدار ab را پیدا می‌کند، ‏a~~b مقدار a~b را پیدا می‌کند، و علامت مد انتهایی نادیده گرفته می‌شود، پس q~ مثل q رفتار می‌کند. matcher قدیمی HotXLS فقط ~* و ~? و ~~ را escape می‌شناخت، پس a~b همان متن a~b را پیدا می‌کرد. یک pattern مربوط به Find که فقط ~ باشد خود در Excel ناپایدار است و هر سلولی را مثل pattern خالی مچ می‌کند، و HotXLS آن را تقلید نمی‌کند

در موتور XLSX جست‌وجو با TXLSXWorksheet.FindText و یک مجموعه TXLSXFindOptions انجام می‌شود: ‏lxfUseWildcards مقدارهای * و ? و ~ را روشن می‌کند، ‏lxfWholeCell شرط می‌گذارد کل سلول مچ شود، و lxfMatchCase مقایسه را حساس به بزرگی حروف می‌کند. بدون lxfUseWildcards هر کاراکتری، ستاره هم شامل، لفظی است. Find فقط مقادیر متنی را نگاه می‌کند؛ سلول‌های عددی رد می‌شوند و سلول‌های فرمول هم رد می‌شوند مگر اینکه lxfSearchFormulas ست شده باشد که در آن صورت متن فرمول جست‌وجو می‌شود. لنگری که StartRow و StartCol می‌دهند inclusive است، پس حلقه Find All باید بعد از هر hit یک ستون جلوتر قدم بگذارد

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 با escape است
    if Sheet.FindText('a~~b', Row, Col, Opts, 1, 1) then
      Writeln('a~~b whole cell -> row ', Row);   // 3: مقدار ~~ یک علامت ~ لفظی است

    // مچ جزئی و Find All: سلول لنگر هم داخل است، پس از هر hit رد شوید
    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 با سه boolean بیرون می‌دهد، یعنی TXLSWorksheet.FindText(SearchText, Row, Col, MatchCase, UseWildcards, WholeCell)، به‌علاوه یک overload متناظر برای ReplaceText، با نتایج سطر و ستون یک-مبنا:

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 اکسل. قبل از v2.384.52 توابع معیار و توابع دیتابیس هر pattern را به MatchesMask می‌دادند، یک matcher فایل‌ماسک در یونیت lxMasks. سینتکسش برای حالت‌های رایج با Excel هم‌پوشانی دارد، و برای همین مشکل پنهان می‌ماند، اما هر جا که داده واقعی جالب می‌شود واگرا می‌شود:

  • مقدار [x] به‌عنوان یک مجموعه کاراکتر خوانده می‌شد، پس COUNTIF(A1:A10,"[x]") سلول‌هایی را می‌شمارد که x دارند به‌جای متن براکت‌دار، و "[a-z]" هر سلول یک‌حرفی را مچ می‌کرد
  • هیچ escape ای برای علامت مد نبود، پس "a~*b" نمی‌توانست یک ستاره لفظی را مچ کند
  • یک ماسک بدفرم، مثل براکت بسته‌نشده، exception می‌داد که فراخواننده آن را به‌عنوان «مچ نشد» قورت می‌داد، و یک غلط تایپی در معیار به یک جمع غلط بی‌صدا تبدیل می‌شد
  • در سمت lookup، ‏MATCH و XLOOKUP فقط ~* و ~? و ~~ را escape می‌گرفتند، پس MATCH("a~b",…,0) همان a~b لفظی را پیدا می‌کرد به‌جای ab

اگر workbookهایتان همیشه فقط روی داده الفبایی ساده از * و ? استفاده می‌کردند، نتایج از قبل درست بود و عوض نمی‌شود. اگر براکت دارند، علامت مد دارند، ستون‌های نوع-مخلوط زیر "<>text" دارند، یا معیارهای DSUM به‌شکل کلمه لخت نوشته شده‌اند، دوباره محاسبه کردنشان با v2.384.64 یا بعدتر می‌تواند جمع‌ها را عوض کند، و جمع‌های جدید همان‌هایی است که Excel نشان می‌دهد. همان تمایز بین اینکه Excel معیار را چطور ذخیره می‌کند و چطور مقایسه‌اش می‌کند سراغ filterهای ذخیره‌شده هم می‌آید، که در مقاله HotXLS درباره معیارهای DOPER مربوط به AutoFilter در BIFF8 بحث شده

مرجع سریع: قواعد wildcard اکسل در HotXLS

  • COUNTIF و SUMIF و AVERAGEIF و خانواده *IFS فقط وقتی wildcard استفاده می‌کنند که معیار * یا ? داشته باشد؛ وگرنه رشته‌ها را کامل و بی‌حساسیت به بزرگی حروف مقایسه می‌کنند و ~ لفظی است (از v2.384.52)
  • MATCH با match type صفر و XLOOKUP با match_mode برابر 2 همیشه wildcard دارند، پس a~b مقدار ab را پیدا می‌کند و برای متن لفظی باید a~~b نوشت (از v2.384.52)
  • در حالت wildcard مقدار ~ هر کاراکتر بعدی را escape می‌کند و ~ انتهایی حذف می‌شود؛ ‏[ و ] کاراکترهای معمولی‌اند
  • ‏"<>text" اعداد و boolean ها و خطاها و سلول‌های خالی را می‌شمارد؛ یک "<>" لخت سلول‌های ناخالی را می‌شمارد، نتیجه‌های ="" هم شامل
  • 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 در یک موتور فرمول بیشتر همین edge case ها است، که مقابل خود Excel اندازه‌گیری می‌شوند نه از مستندات حدس زده می‌شوند. HotXLS مقدارهای COUNTIF و MATCH و XLOOKUP و DSUM و بقیه کتابخانه توابعش را به‌صورت بومی در Delphi و C++Builder ارزیابی می‌کند، در موتور کلاسیک و موتور XLSX، بدون نصب بودن Excel. جزئیات و نسخه‌ها و دانلود آزمایشی در صفحه کامپوننت صفحه‌گسترده HotXLS در Delphi است