HotXLS Delphi Component เทียบค่าข้อความสองค่าแบบเดียวกับ Excel 16 ตั้งแต่ v2.384.67: ไม่สนตัวพิมพ์ ด้วยลำดับ “word sort” ของ Windows user locale ซึ่งก็คือผลที่ CompareStringW คืนเมื่อใส่ flag NORM_IGNORECASE ขีดกับ apostrophe ถูกข้ามในรอบแรกและแค่ตัดสินแพ้ชนะตอนเสมอ ="a-b">"ab" จึงเป็น TRUE ขณะที่เครื่องหมายวรรคตอนอื่นเรียงอยู่หน้าตัวเลขกับตัวอักษร ="a~b"<"ab" จึงเป็น TRUE เช่นกัน ลำดับเดียวกันนี้ตอนนี้ขับเคลื่อน operator เปรียบเทียบ เกณฑ์ > / < การเรียงช่วง และ VLOOKUP
ไม่มีใครเปิดบั๊กชื่อว่า “collation ไม่ตรงกัน” รายงานจริงพูดว่า COUNTIF(A:A,">M") นับได้มากกว่าบนเซิร์ฟเวอร์สองแถว, ราคาสินค้าที่เรียงโดย reporting service วาง X-100 ไว้ตรงที่ Excel ไม่วาง หรือ VLOOKUP("ABC",...) คืน #N/A ทั้งที่คอลัมน์มี abc ตรง ๆ ทั้งสามเรื่องมาจากคำถามเดียวกัน: เมื่อ operand ทั้งสองเป็นข้อความ ตัวไหนเล็กกว่า Excel มีคำตอบที่เป๊ะ ซึ่งไม่ใช่คำตอบที่โค้ด Delphi ส่วนใหญ่ให้ และก่อน v2.384.67 HotXLS เองก็ให้สามคำตอบต่างกันตามเส้นทางโค้ดที่ถูกถาม
Excel ใช้กฎอะไรเทียบข้อความสองสาย
Excel เทียบข้อความด้วย word sort ของ locale ผู้ใช้ โดยไม่สนตัวพิมพ์ word sort คือ collation เริ่มต้นของฟังก์ชันเปรียบเทียบ Windows NLS: ตัวอักษรเทียบกันตามลำดับทางภาษาศาสตร์ ไม่ใช่ตาม code point ตัวอักษรมีวรรณยุกต์นั่งติดกับตัวฐานของมัน และมีสองอักขระที่ได้รับการปฏิบัติพิเศษ ขีด - กับ apostrophe ' ถูกเมินในรอบแรก co-op กับ coop จึงตกลงข้าง ๆ กัน และเมื่อส่วนที่เหลือของสองสายเสมอกันเท่านั้นที่การมีอยู่ของมันตัดสินลำดับ เครื่องหมายวรรคตอนอื่นทุกตัวมีน้ำหนักและเรียงอยู่หน้าตัวเลข ส่วนตัวเลขเรียงอยู่หน้าตัวอักษร
ตารางแสดงว่ามันแปลว่าอะไรในทางปฏิบัติ คู่กับการเปรียบเทียบสองแบบที่นักพัฒนา Delphi มักหยิบมาใช้ คอลัมน์ Excel เก็บคำตัดสินที่ Excel 16 คืนให้กับ IF(A<B,...) ซึ่ง HotXLS ทำให้ตรงกันตั้งแต่ v2.384.67
| A vs B | Excel 16 / HotXLS | CompareStr (ordinal) | CompareText |
|---|---|---|---|
"a-b" vs "ab" | มากกว่า | น้อยกว่า | น้อยกว่า |
"a'b" vs "ab" | มากกว่า | น้อยกว่า | น้อยกว่า |
"a~b" vs "ab" | น้อยกว่า | มากกว่า | มากกว่า |
"a_b" vs "ab" | น้อยกว่า | น้อยกว่า | มากกว่า |
"ab" vs "AB" | เท่ากัน | มากกว่า | เท่ากัน |
"é" vs "f" | น้อยกว่า | มากกว่า | มากกว่า |
"Z" vs "f" | มากกว่า | น้อยกว่า | มากกว่า |
สองผลลัพธ์ที่พลาดง่าย หนึ่ง บทบาทตัดสินแพ้ชนะของขีดแปลว่า ="a-b"="ab" เป็น FALSE: สองสายเป็นเพื่อนบ้านสนิทในการเรียง แต่ไม่เท่ากัน สอง ความเท่ากันเมินตัวพิมพ์สนิท ab, AB กับ Ab เป็น key เดียวกันในสายตาการเปรียบเทียบทุกรูปแบบ เรียงคำทดสอบ 20 คำด้วย Range.Sort ของ Excel จะได้ a b, a.b, a_b, a~b, a0, a1b, ab / AB / Ab, ab-, a'b, a-b, -ab, ab1, abc, b, e, é, f, Z ภายในกลุ่ม ab ตำแหน่งของอักขระที่ถูกเมินตัดสินลำดับ
ลำดับข้อความของ Excel ถูกค้นพบอย่างไร
ลำดับข้อความของ Excel ถูกค้นด้วยการวัด ไม่ใช่ด้วยเอกสาร เพราะเอกสารของ Excel ไม่เคยเอ่ยชื่อ collation การทดสอบสุ่มคู่สตริงมา 4,000 คู่จากเครื่องหมายวรรคตอน ASCII ตัวเลข ทั้งตัวพิมพ์ใหญ่เล็ก ช่องว่าง é, ß, ä อักษรจีน full-width form และ non-breaking space ความยาว 0 ถึง 4 โดยครึ่งหนึ่งของคู่ถูกประกอบให้ต่างกันนิดเดียว Excel 16 ประเมิน IF(A<B,-1,IF(A=B,0,1)) ให้ทุกคู่ แล้วเอาคำตัดสินไปเทียบกับ Windows comparison API ด้วยชุด flag ต่าง ๆ
NORM_IGNORECASEเดี่ยว ๆ (word sort เริ่มต้น locale ผู้ใช้): ไม่มี mismatch แท้เลย 7 ต่างที่เจอคือเซลล์ที่เนื้อหาทั้งเซลล์เป็น'ซึ่ง Excel กลืนไปเป็น text prefix character เป็นของเสียจากการสุ่ม ไม่ใช่ความต่างของ collationNORM_IGNORECASEคู่กับSORT_STRINGSORT: mismatch 41 จุด string sort ถือขีดกับ apostrophe เป็นสัญลักษณ์ธรรมดา ซึ่งเป็นพฤติกรรมที่ Excel ไม่มีเป๊ะ ๆ- เพิ่ม
NORM_IGNOREWIDTH: ผิดอีกแบบ เพราะมันทำให้รูป full-width กับ half-width ของตัวอักษรเดียวกันเทียบเท่ากัน ขณะที่ Excel แยกพวกมันออกจากกัน
การเช็กชุดที่สองคัดมือ เทียบคู่ทั้ง 190 คู่ที่หยิบจากคำเข้ายาก 20 คำกับผล Range.Sort ของ Excel บนคอลัมน์เดียวกัน สองอย่างลงรอยกับ word sort แบบ NORM_IGNORECASE ธรรมดา และคำตัดสิน 190 คำพวกนี้บวกลำดับที่เรียงแล้วตอนนี้อยู่ในชุด regression ของ HotXLS รันผ่านทั้งเอนจินคลาสสิก TXLSWorkbook และเอนจินแท้ XLSX อย่าง TXLSXWorkbook
ทำไม CompareText กับการเทียบแบบ ordinal ถึงตอบผิด
CompareText กับการเทียบแบบ ordinal ตอบลำดับของ Excel ผิดเพราะพวกมันเทียบ UTF-16 code unit และลำดับ code point โยนเครื่องหมายวรรคตอนไปวางที่อับ ๆ ตามดวงเมื่อเทียบกับตัวอักษร ขีดคือ U+002D apostrophe คือ U+0027 ทั้งคู่ต่ำกว่าตัวอักษรทุกตัว การเทียบแบบ ordinal จึงบอกว่า "a-b" เล็กกว่า "ab" แทนที่จะถือขีดเป็นตัวตัดสินแพ้ชนะ ส่วน tilde U+007E สูงกว่าตัวอักษรทุกตัว "a~b" จึงออกมาใหญ่กว่า ตรงข้ามกับ Excel ทั้งหมด CompareText ใน Delphi RTL พับแค่ a..z ขึ้นเป็นตัวพิมพ์ใหญ่แล้วเทียบ code unit ซึ่งเติมความบิดเบี้ยวรอบที่สอง: ขีดล่าง U+005F นั่งอยู่ระหว่างตัวพิมพ์ใหญ่กับตัวพิมพ์เล็ก การพับเป็นตัวพิมพ์ใหญ่จึงเลื่อน "a_b" จากใต้ "ab" ขึ้นไปอยู่เหนือมัน และไม่มีฟังก์ชันไหนรู้ว่า é ควรอยู่ระหว่าง e กับ f
เครื่องมือ Delphi ทั่วไปตกอยู่สองฟากฝั่ง:
CompareStr, operator<ของ string กับTComparer<string>.Default(ที่เรียกCompareStr) เป็นแบบ ordinal สนตัวพิมพ์TArray.Sort<string>ที่ไม่ส่ง comparer จึงวางZไว้หน้าfCompareTextกับSameTextเป็น ordinal หลังพับตัวพิมพ์แค่ช่วง ASCIIAnsiCompareTextกับWideCompareTextใน Delphi RTL บน Windows เรียกCompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, ...)ซึ่งเป็น call เดียวกับที่ตรงกับ ExcelTStringListที่เรียงด้วยค่าเริ่มต้น (UseLocaleTrue,CaseSensitiveFalse) วิ่งผ่านAnsiCompareTextจึงลงรอยกับ Excel ด้วย- บนเป้าหมาย POSIX Delphi RTL ส่ง
AnsiCompareTextไปผ่าน ICU collator ซึ่งเป็นอัลกอริทึมคนละแบบที่กฎเครื่องหมายวรรคตอนต่างกัน และAnsiCompareTextของ Free Pascal บน Windows เรียกCompareStringAหลังแปลงเป็น ANSI code page ซึ่งทำอักขระที่ code page นั้นแทนไม่ได้หายไปทั้งตัว
ฟังก์ชัน RTL ที่รู้เรื่อง locale จึงถูกบน Windows ด้วย implementation ไม่ใช่ด้วยสัญญา และโค้ดที่ต้องการลำดับของ Excel ควรเรียก API นั้นเองชัด ๆ HotXLS เองก็เคยมีส่วนผสมแบบเดียวกันภายใน operator เปรียบเทียบยกตัวพิมพ์ใหญ่ทั้งคู่แล้วเทียบ code point กิ่ง > / < ของฟังก์ชันเกณฑ์ใช้การเทียบ Variant แบบสนตัวพิมพ์ของ Delphi และ VLOOKUP / HLOOKUP จับคู่ข้อความด้วยการเทียบ Variant สนตัวพิมพ์แบบเดียวกัน VLOOKUP("ABC",A1:A20,1,FALSE) จึงหา abc ไม่เจอ ส่วนการเรียงช่วงใช้ WideCompareText อยู่แล้ว สามเส้นทาง สามลำดับ
HotXLS v2.384.67 เปลี่ยนอะไรไป
ตั้งแต่ v2.384.67 การเทียบข้อความกับข้อความในเส้นทางคำนวณและเรียงลำดับของ HotXLS วิ่งผ่านฟังก์ชันเดียว คือ XlsCompareText ใน lxStandard.pas ซึ่งเรียก CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, ...) แล้วลบ CSTR_EQUAL ออก ผู้เรียกได้แก่ operator เปรียบเทียบทั้งหก การเทียบทีละ element ใน array formula กิ่ง >, <, >= กับ <= ของเกณฑ์สไตล์ COUNTIF และฟังก์ชันฐานข้อมูล, VLOOKUP กับ HLOOKUP (ทั้งตรงเป๊ะและประมาณ), ตัวช่วยจัดลำดับหลังฟังก์ชัน dynamic-array กับ XLOOKUP / XMATCH และการเรียงช่วงของทั้งสองเอนจิน การผลักการเรียงช่วงผ่านฟังก์ชันเดียวกันรับประกันว่าลำดับการเรียงกับลำดับการเปรียบเทียบจะไม่แยกทางกันอีก ซึ่งสำคัญเพราะ VLOOKUP แบบประมาณบนข้อความมีความหมายก็ต่อเมื่อคอลัมน์ถูกเรียงไว้ในลำดับเดียวกับที่ lookup เทียบ
uses
System.Variants, lxHandleX;
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
Book.Sheets.Add('Data'); // Calculate ประเมินบน active sheet
Writeln(VarToStr(Book.Calculate('="a-b">"ab"'))); // True: ขีดแค่ตัดสินแพ้ชนะ
Writeln(VarToStr(Book.Calculate('="a-b"="ab"'))); // False: เสมอกันแต่ไม่เท่ากัน
Writeln(VarToStr(Book.Calculate('="a~b"<"ab"'))); // True: เครื่องหมายวรรคตอนมาก่อน
Writeln(VarToStr(Book.Calculate('="ABC"="abc"'))); // True: ไม่สนตัวพิมพ์
finally
Book.Free;
end;
end;
การเทียบคนละชนิดเป็นกฎแยกและไม่เปลี่ยน: ตัวเลขทุกตัวต่ำกว่าข้อความทุกค่า และข้อความทุกค่าต่ำกว่าค่า boolean ทุกค่า ตามที่เล่าไว้ในบทความเรื่องลูกโซ่การเปรียบเทียบ operand ว่าง และ SUMIF word sort ทำงานก็ต่อเมื่อ operand ทั้งสองเป็นข้อความเท่านั้น การจับคู่ wildcard ก็แยกต่างหาก เกณฑ์อย่าง "a*" หรือ "=ab" เป็นการทดสอบรูปแบบหรือความเท่ากัน เล่าไว้ในคู่มือ wildcard ของ Excel ใน COUNTIF, MATCH และ DSUM ส่วน collation ที่พูดถึงในนี้ตัดสินแค่ operator เรียงลำดับเท่านั้น
ตัวอย่างถัดไปโหลดคำทดสอบ 20 คำลงคอลัมน์ เรียงด้วย TXLSXWorksheet.SortRange แล้วเช็กจำนวนจากเกณฑ์กับ lookup หนึ่งครั้ง จำนวนที่ได้คือค่าที่ Excel 16 คืนสำหรับคอลัมน์เดียวกัน
const
Words: array [0..19] of string = ('ab', 'a-b', 'a~b', 'a_b', 'AB', 'a b',
'ab1', 'ab-', '-ab', 'abc', 'a''b', 'Ab', 'b', 'a.b', 'a1b', 'a0',
#$00E9, 'e', 'f', 'Z');
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
i: Integer;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Words');
for i := 0 to High(Words) do
Sheet.Cells[i + 1, 1].Value := WideString(Words[i]);
// Excel 16 บนคอลัมน์เดียวกัน: 11, 11, 14
Writeln(VarToStr(Book.Calculate('=COUNTIF(A1:A20,">ab")')));
Writeln(VarToStr(Book.Calculate('=COUNTIF(A1:A20,"<a-b")')));
Writeln(VarToStr(Book.Calculate('=COUNTIF(A1:A20,">=AB")')));
// เดิมเป็น #N/A ก่อน v2.384.67: lookup เทียบแบบสนตัวพิมพ์
Sheet.Cells[1, 3].Formula := '=VLOOKUP("ABC",A1:A20,1,FALSE)';
Book.Recalculate;
Writeln(VarToStr(Sheet.Cells[1, 3].Value)); // abc
// คอลัมน์ key เดียว เรียงขึ้น: a b, a.b, a_b, a~b, a0, a1b, ab, AB, Ab, ...
Sheet.SortRange(1, 1, 20, 1, [1], [False]);
for i := 1 to 20 do
Writeln(VarToStr(Sheet.Cells[i, 1].Value));
finally
Book.Free;
end;
end;
TXLSXWorksheet.SortRange ใช้ merge sort แบบเสถียร ab, AB กับ Ab ที่เทียบเท่ากันจึงคงลำดับสัมพัทธ์เดิมก่อนเรียง เซลล์ว่างไปท้ายทั้งสองทิศทาง เหมือนใน Excel
จะให้โค้ด Delphi ของตัวเองเรียงตาม Excel ทำอย่างไร
ให้โค้ด Delphi ของคุณได้ลำดับข้อความแบบ Excel เรียก CompareStringW ด้วย LOCALE_USER_DEFAULT กับ NORM_IGNORECASE และอย่าเติม SORT_STRINGSORT หรือ NORM_IGNOREWIDTH ค่าที่คืนไม่ใช่ผลเปรียบเทียบแบบมีเครื่องหมาย: API คืน CSTR_LESS_THAN (1), CSTR_EQUAL (2) หรือ CSTR_GREATER_THAN (3) และคืน 0 เมื่อ call ล้ม ลบ 2 เพื่อได้ธรรมเนียมติดลบ / ศูนย์ / บวกตามปกติ และเช็ก 0 ก่อน เพราะความล้มเหลวที่ถูกเข้าใจผิดเป็นผลลัพธ์จะกลายเป็น -2 ซึ่งคือ “น้อยกว่า” อย่างเงียบ ๆ
uses
Winapi.Windows, System.SysUtils, System.Generics.Defaults,
System.Generics.Collections;
// ลำดับข้อความแบบ Excel: word sort ตาม locale ผู้ใช้ ไม่สนตัวพิมพ์
function ExcelCompareText(const A, B: string): Integer;
var
R: Integer;
begin
R := CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
PWideChar(A), Length(A), PWideChar(B), Length(B));
if R = 0 then
RaiseLastOSError; // 0 คือความล้มเหลว ไม่ใช่ผลการเปรียบเทียบ
Result := R - CSTR_EQUAL; // 1/2/3 กลายเป็น -1/0/1
end;
var
Keys: TArray<string>;
begin
Keys := ['abc', 'a-b', 'AB', 'a~b', '-ab', 'ab'];
TArray.Sort<string>(Keys, TComparer<string>.Construct(
function(const L, R: string): Integer
begin
Result := ExcelCompareText(L, R);
end));
// a~b, ab / AB (เท่ากัน เรียงแบบไหนก็ได้), a-b, -ab, abc
end;
TArray.Sort ไม่เสถียร key ที่เทียบเท่ากันอย่าง ab กับ AB อาจออกมาสลับกันก็ได้ ถ้าลำดับเดิมของ key ที่เท่ากันสำคัญ เรียงผ่าน array ของ index โดยใช้ตำแหน่งเดิมเป็น key รอง กรณีตรงข้ามก็มีขึ้นเหมือนกัน บางทีคอลัมน์ต้องไม่เดินตามลำดับของ Excel เช่น part number ที่ X-100 กับ X100 เป็นรหัสต่างกันและควรเรียงตาม code point TXLSXWorksheet.SortRange มี overload ที่รับ TXLSSortCompareEvent เมธอดที่ลายเซ็นเป็น function(const Left, Right: Variant): Integer of object แล้วใช้มันแทนการเปรียบเทียบในตัว
uses
System.SysUtils, System.Variants, lxStandard, lxHandleX;
type
TPartNumberOrder = class
function Compare(const Left, Right: Variant): Integer;
end;
function TPartNumberOrder.Compare(const Left, Right: Variant): Integer;
begin
// comparer แบบกำหนดเองก็ได้รับเซลล์ว่าง (เป็น Null) ด้วย: จัดที่เอง
if VarIsNull(Left) or VarIsNull(Right) then
Exit(Ord(VarIsNull(Left)) - Ord(VarIsNull(Right)));
Result := CompareStr(VarToStr(Left), VarToStr(Right)); // ตาม code point สนตัวพิมพ์
end;
var
Sheet: TXLSXWorksheet; // sheet ที่มีข้อมูลแล้ว แถว 2..501 คอลัมน์ A..D
Order: TPartNumberOrder;
begin
// ...
Order := TPartNumberOrder.Create;
try
// ใช้คอลัมน์ A เป็น key เรียงขึ้น
Sheet.SortRange(2, 1, 501, 4, [1], [False], xlsSortByRows,
xlsSortExcelLike, Order.Compare);
finally
Order.Free;
end;
end;
เมื่อส่ง comparer แบบกำหนดเองเข้าไป HotXLS จะข้ามการจัดการเซลล์ว่างของตัวเองแล้วส่งค่า key ดิบให้ comparer ต้องจัดการ Null เอง key ที่เรียงลง HotXLS จะกลับเครื่องหมายทุกอย่างที่ comparer คืน ซึ่งพาเซลล์ว่างขึ้นหัวไปด้วย ถ้า comparer ไม่จัดการเรื่องนี้เอง เตือนตัวเองไว้ว่าคอลัมน์ที่เรียงแบบนี้ไม่ได้อยู่ในลำดับที่ VLOOKUP ประมาณของ Excel หรือ XLOOKUP แบบ binary search คาดไว้อีกต่อไป กับดักของสองโหมดนี้กับข้อมูลที่เรียงคนละลำดับเล่าไว้ในคู่มือโหมด binary search ของ XLOOKUP และ XMATCH
ทำไม workbook เดียวกันถึงเรียงไม่เหมือนกันบนอีกเครื่อง
workbook เดียวกันเรียงไม่เหมือนกันบนอีกเครื่องได้ เพราะลำดับข้อความของ Excel ผูกกับ Windows user locale และ HotXLS ตั้งใจตามความผูกนี้ word sort ขึ้นกับภาษา: collation ของสวีเดน เช่น วาง ä ไว้หลัง z ขณะที่อังกฤษกับเยอรมันคงมันไว้ข้าง a Excel สืบทอดสิ่งนี้จาก locale ที่ตัวมันรันอยู่ workbook ที่เพื่อนนักที่สตอก์ฮ์ล์มคำนวณใหม่จึงคืน COUNTIF(...,">y") ต่างจากไฟล์เดียวกันบนเดสก์ท็อปที่ชิคาโกได้ HotXLS ส่ง LOCALE_USER_DEFAULT เพื่อให้ผลของมันเท่ากับของ Excel บนเครื่องเดียวกัน ถ้าตรึง locale ตายตัว HotXLS จะขัดกับ Excel บนทุกเครื่องที่ตั้งค่าต่างออกไป
ผลที่ตามมาทางปฏิบัติสามข้อสำหรับการผลิตฝั่งเซิร์ฟเวอร์:
- locale ที่นับคือของบัญชีที่ process รันอยู่ Windows service หรือ application pool ของ IIS อาจใช้รูปแบบภูมิภาคต่างจากเดสก์ท็อปของนักพัฒนา สิ่งที่เห็นใน IDE จึงไม่ใช่สิ่งที่ production คำนวณโดยอัตโนมัติ
- ผลคำนวณที่แคชไว้ในไฟล์สะท้อน locale ของเครื่องที่ผลิต Excel คำนวณใหม่ด้วย locale ของตัวเอง ค่าหนึ่งจึงเปลี่ยนได้เมื่อไฟล์ถูกเปิดที่อื่นแล้วคำนวณใหม่ นั่นคือพฤติกรรมของ Excel ไม่ใช่ของเสียจาก HotXLS
- locale ขัดกันเยอะที่ตัวอักษรมีวรรณยุกต์ กับกลุ่มอักษรที่บางภาษาถือเป็นตัวอักษรเดียว และสคริปต์ที่ไม่ใช่ละติน ข้อมูลทดสอบที่มีแต่คำอังกฤษธรรมดาจะไม่เผยปัญหานี้
เส้นแบ่งแพลตฟอร์มเรียบง่าย HotXLS เป็นไลบรารี Windows บิลด์สำหรับ Win32 กับ Win64 ด้วย Delphi กับ C++Builder และสำหรับเป้าหมาย win32 / win64 ด้วย Lazarus กับ Free Pascal ทุกบิลด์เรียก CompareStringW ตัวเดียวกัน ไม่มีเส้นทาง collation แยกสำหรับ non-Windows ของเดียวที่เหลือคือการ fallback เมื่อ API call ล้ม: ถ้า CompareStringW คืน 0 XlsCompareText จะเทียบสตริงที่ยกตัวพิมพ์ใหญ่แล้วตาม code unit แทนการ throw exception กลางการคำนวณใหม่ การคำนวณยังเดินต่อได้แต่ไม่ได้การันตีลำดับของ Excel อีก
สรุป: การเปรียบเทียบข้อความแบบ Excel ใน HotXLS
- กฎ: word sort ตาม locale ผู้ใช้พร้อม
NORM_IGNORECASEไม่มีSORT_STRINGSORTไม่มีNORM_IGNOREWIDTHใน HotXLS ตั้งแต่ v2.384.67 -กับ'แค่ตัดสินแพ้ชนะ:="a-b">"ab"เป็น TRUE และ="a-b"="ab"เป็น FALSE- เครื่องหมายวรรคตอนอื่นเรียงก่อนตัวเลข ตัวเลขก่อนตัวอักษร:
="a~b"<"ab"กับ="a0"<"ab"เป็น TRUE - ตัวพิมพ์ไม่มีวันมีผล:
="ABC"="abc"เป็น TRUE และVLOOKUP("ABC",...)หาabcเจอ - เส้นทางที่ครอบคลุม: operator เปรียบเทียบ การเทียบ array เกณฑ์
>/<,VLOOKUP/HLOOKUP, การจัดลำดับ dynamic-array,SortRangeในทั้งสองเอนจิน - ไม่อยู่ใต้กฎนี้: ชนิดผสม (ตัวเลข < ข้อความ < boolean) กับเกณฑ์ wildcard ซึ่งมีกฎของตัวเอง
- ในโค้ด Delphi:
CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, ...)เช็ก 0 ก่อน แล้วลบCSTR_EQUALเลี่ยงCompareText,CompareStrกับTComparer<string>.Defaultเมื่อผลต้องตรงกับ Excel - ผลลัพธ์ขึ้นกับ locale ของบัญชีที่รันโค้ด ทั้งใน Excel และ HotXLS เหมือนกัน
คำธรรมดาเรียงเหมือนกันใต้ทุกกฎ มีแต่รหัสที่มีขีด เครื่องหมายวรรคตอน และชื่อที่มีวรรณยุกต์เท่านั้นที่เผย collation ที่ผิด HotXLS ตอนนี้ให้คำตอบแบบ Excel กับทุกกรณีพวกนั้นทั้งเอนจิน XLS และ XLSX รายละเอียดลิขสิทธิ์ เวอร์ชัน Delphi กับ C++Builder ที่รองรับ และดาวน์โหลดรุ่นทดลองอยู่ที่หน้า HotXLS Delphi Excel component