From 4a1a99044bd17a219f0ee092f98e1d88f22bc70b Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Wed, 22 Oct 2014 23:25:26 +0000 Subject: [PATCH] fpspreadsheet: Fix circular unit reference bug (thanks, Michael). Add demo_sorting.pas unit missing from last commit. Some improvements with multi-key sorting, but still in error sometimes (--> sorting code is still experimental). git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3678 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../examples/other/demo_sorting.pas | 416 ++++++++++++++++++ components/fpspreadsheet/fpsexprparser.pas | 7 +- components/fpspreadsheet/fpsfunc.pas | 6 +- components/fpspreadsheet/fpspreadsheet.pas | 141 +++++- .../fpspreadsheet/tests/sortingtests.pas | 76 ++-- .../fpspreadsheet/tests/spreadtestgui.lpi | 5 +- 6 files changed, 610 insertions(+), 41 deletions(-) create mode 100644 components/fpspreadsheet/examples/other/demo_sorting.pas diff --git a/components/fpspreadsheet/examples/other/demo_sorting.pas b/components/fpspreadsheet/examples/other/demo_sorting.pas new file mode 100644 index 000000000..1bc158ea4 --- /dev/null +++ b/components/fpspreadsheet/examples/other/demo_sorting.pas @@ -0,0 +1,416 @@ +program demo_sorting; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + SysUtils, Classes + { you can add units after this }, + TypInfo, fpSpreadsheet, fpsutils; + +var + workbook: TsWorkbook; + worksheet: TsWorksheet; + s: String; + sortParams: TsSortParams; + + procedure SortSingleColumn; + var + i: Integer; + n: Double; + begin + WriteLn('Sorting of a single column'); + workbook := TsWorkbook.Create; + try + worksheet := workbook.AddWorksheet('Test'); + + worksheet.WriteNumber(0, 0, 10); // A1 + worksheet.WriteNumber(1, 0, 2); // A2 + worksheet.WriteNumber(2, 0, 5); // A3 + worksheet.WriteNumber(3, 0, 1); // A4 + + sortParams := InitSortParams(true, 1); + sortParams.Keys[0].ColRowIndex := 0; + sortParams.Keys[0].Order := ssoAscending; + + worksheet.Sort(sortParams, 0, 0, 3, 0); + + WriteLn(#9, 'A'); + for i:=0 to 3 do + begin + n := worksheet.ReadAsNumber(i, 0); + WriteLn(i, #9, FloatToStr(n)); + end; + WriteLn; + + finally + workbook.Free; + end; + end; + + procedure SortSingleRow; + var + i: Integer; + n: Double; + begin + WriteLn('Sorting of a single row'); + workbook := TsWorkbook.Create; + try + worksheet := workbook.AddWorksheet('Test'); + + worksheet.WriteNumber(0, 0, 10); // A1 + worksheet.WriteNumber(0, 1, 2); // B1 + worksheet.WriteNumber(0, 2, 5); // C1 + worksheet.WriteNumber(0, 3, 1); // D1 + + sortParams := InitSortParams(false, 1); + sortParams.Keys[0].ColRowIndex := 0; + sortParams.Keys[0].Order := ssoAscending; + + worksheet.Sort(sortParams, 0, 0, 0, 3); + + for i:=0 to 3 do + Write(char(ord('A')+i) + '1', #9); + WriteLn; + + for i:=0 to 3 do + begin + n := worksheet.ReadAsNumber(0, i); + Write(FloatToStr(n), #9); + end; + WriteLn; + WriteLn; + + finally + workbook.Free; + end; + end; + + procedure SortTwoColumns_OneKey; + var + i: Integer; + n1, n2: Double; + begin + WriteLn('Sorting of two columns using a single key column'); + WriteLn('(The 2nd column must be the negative of the 1st one)'); + workbook := TsWorkbook.Create; + try + worksheet := workbook.AddWorksheet('Test'); + + worksheet.WriteNumber(0, 0, 10); // A1 + worksheet.WriteNumber(1, 0, 2); // A2 + worksheet.WriteNumber(2, 0, 5); // A3 + worksheet.WriteNumber(3, 0, 1); // A4 + + worksheet.WriteNumber(0, 1, -10); // B1 + worksheet.WriteNumber(1, 1, -2); // B2 + worksheet.WriteNumber(2, 1, -5); // B3 + worksheet.WriteNumber(3, 1, -1); // B4 + + sortParams := InitSortParams(true, 1); + sortParams.Keys[0].ColRowIndex := 0; + sortParams.Keys[0].Order := ssoAscending; + + worksheet.Sort(sortParams, 0, 0, 3, 1); + + WriteLn(#9, 'A', #9, 'B'); + for i:=0 to 3 do + begin + n1 := worksheet.ReadAsNumber(i, 0); + n2 := worksheet.ReadAsNumber(i, 1); + WriteLn(i, #9, FloatToStr(n1), #9, FloatToStr(n2)); + end; + WriteLn; + + finally + workbook.Free; + end; + end; + + procedure SortTwoRows_OneKey; + var + i: Integer; + n1, n2: Double; + begin + WriteLn('Sorting of two rows using a single key column'); + WriteLn('(The 2nd row must be the negative of 1st row)'); + workbook := TsWorkbook.Create; + try + worksheet := workbook.AddWorksheet('Test'); + + worksheet.WriteNumber(0, 0, 10); // A1 + worksheet.WriteNumber(0, 1, 2); // B1 + worksheet.WriteNumber(0, 2, 5); // C1 + worksheet.WriteNumber(0, 3, 1); // D1 + + worksheet.WriteNumber(1, 0, -10); // A2 + worksheet.WriteNumber(1, 1, -2); // B2 + worksheet.WriteNumber(1, 2, -5); // C2 + worksheet.WriteNumber(1, 3, -1); // D2 + + sortParams := InitSortParams(false, 1); + sortParams.Keys[0].ColRowIndex := 0; + sortParams.Keys[0].Order := ssoAscending; + + worksheet.Sort(sortParams, 0, 0, 1, 3); + + Write(#9); + for i:=0 to 3 do + Write(char(ord('A')+i) + '1', #9); + WriteLn; + + Write('1', #9); + for i:=0 to 3 do begin + n1 := worksheet.ReadAsNumber(0, i); + Write(FloatToStr(n1), #9); + end; + WriteLn; + + Write('2', #9); + for i:=0 to 3 do begin + n1 := worksheet.ReadAsNumber(1, i); + Write(FloatToStr(n1), #9); + end; + WriteLn; + + WriteLn; + + finally + workbook.Free; + end; + end; + + procedure SortTwoColumns_TwoKeys; + var + i: Integer; + n1, n2: Double; + begin + WriteLn('Sorting of two columns on column "A" and "B"'); + workbook := TsWorkbook.Create; + try + worksheet := workbook.AddWorksheet('Test'); + + worksheet.WriteNumber(0, 0, 10); // A1 + worksheet.WriteNumber(1, 0, 1); // A2 + worksheet.WriteNumber(2, 0, 1); // A3 + worksheet.WriteNumber(3, 0, 1); // A4 + + worksheet.WriteNumber(0, 1, -10); // B1 + worksheet.WriteNumber(1, 1, -2); // B2 + worksheet.WriteNumber(2, 1, -5); // B3 + worksheet.WriteNumber(3, 1, -1); // B4 + + sortParams := InitSortParams(true, 2); + sortParams.Keys[0].ColRowIndex := 0; + sortParams.Keys[0].Order := ssoAscending; + sortParams.Keys[1].ColRowIndex := 1; + sortParams.Keys[1].Order := ssoAscending; + + worksheet.Sort(sortParams, 0, 0, 3, 1); + + WriteLn(#9, 'A', #9, 'B'); + for i:=0 to 3 do + begin + n1 := worksheet.ReadAsNumber(i, 0); + n2 := worksheet.ReadAsNumber(i, 1); + WriteLn(i, #9, FloatToStr(n1), #9, FloatToStr(n2)); + end; + WriteLn; + + finally + workbook.Free; + end; + end; + + procedure SortTwoRows_TwoKeys; + var + i: Integer; + n1, n2: Double; + begin + WriteLn('Sorting of two rows on row "1" and "2"'); + workbook := TsWorkbook.Create; + try + worksheet := workbook.AddWorksheet('Test'); + + worksheet.WriteNumber(0, 0, 10); // A1 + worksheet.WriteNumber(0, 1, 1); // B1 + worksheet.WriteNumber(0, 2, 1); // C1 + worksheet.WriteNumber(0, 3, 1); // D1 + + worksheet.WriteNumber(1, 0, -10); // A2 + worksheet.WriteNumber(1, 1, -2); // B2 + worksheet.WriteNumber(1, 2, -5); // C2 + worksheet.WriteNumber(1, 3, -1); // D2 + + sortParams := InitSortParams(false, 2); + sortParams.Keys[0].ColRowIndex := 0; + sortParams.Keys[0].Order := ssoAscending; + sortParams.Keys[1].ColRowIndex := 1; + sortParams.Keys[1].Order := ssoAscending; + + worksheet.Sort(sortParams, 0, 0, 1, 3); + + Write(#9); + for i:=0 to 3 do + Write(char(ord('A')+i) + '1', #9); + WriteLn; + + Write('1', #9); + for i:=0 to 3 do begin + n1 := worksheet.ReadAsNumber(0, i); + Write(FloatToStr(n1), #9); + end; + WriteLn; + + Write('2', #9); + for i:=0 to 3 do begin + n1 := worksheet.ReadAsNumber(1, i); + Write(FloatToStr(n1), #9); + end; + WriteLn; + + WriteLn; + + finally + workbook.Free; + end; + end; + + procedure SortTwoColumns_TwoKeys_1; + var + i: Integer; + n: Double; + s: String; + begin + WriteLn('Sorting of two columns on column "A" and "B"'); + WriteLn('(Expecting an ascending columns of characters and numbers)'); + workbook := TsWorkbook.Create; + try + worksheet := workbook.AddWorksheet('Test'); + + worksheet.WriteUTF8Text(0, 0, 'E'); + worksheet.WriteUTF8Text(1, 0, 'E'); + worksheet.WriteUTF8Text(2, 0, 'C'); + worksheet.WriteUTF8Text(3, 0, 'B'); + worksheet.WriteUTF8Text(4, 0, 'D'); + worksheet.WriteUTF8Text(5, 0, 'D'); + worksheet.WriteUTF8Text(6, 0, 'A'); + worksheet.WriteUTF8Text(7, 0, 'B'); + worksheet.WriteUTF8Text(8, 0, 'C'); + worksheet.WriteUTF8Text(9, 0, 'A'); + + worksheet.WriteNumber(0, 1, 9); // A2 --> E + worksheet.WriteNumber(1, 1, 8); // B2 --> E + worksheet.WriteNumber(2, 1, 5); // C2 --> C + worksheet.WriteNumber(3, 1, 2); // D2 --> B + worksheet.WriteNumber(4, 1, 6); // E2 --> D + worksheet.WriteNumber(5, 1, 7); // F2 --> D + worksheet.WriteNumber(6, 1, 1); // G2 --> A + worksheet.WriteNumber(7, 1, 3); // H2 --> B + worksheet.WriteNumber(8, 1, 4); // I2 --> C + worksheet.WriteNumber(9, 1, 0); // J2 --> A + + sortParams := InitSortParams(true, 2); + sortParams.Keys[0].ColRowIndex := 0; + sortParams.Keys[0].Order := ssoAscending; + sortParams.Keys[1].ColRowIndex := 1; + sortParams.Keys[1].Order := ssoAscending; + + worksheet.Sort(sortParams, 0, 0, 9, 1); + + WriteLn(#9, 'A', #9, 'B'); + for i:=0 to 9 do + begin + s := worksheet.ReadAsUTF8Text(i, 0); + n := worksheet.ReadAsNumber(i, 1); + WriteLn(i, #9, s, #9, FloatToStr(n)); + end; + + WriteLn; + + finally + workbook.Free; + end; + end; + + procedure SortTwoRows_TwoKeys_1; + var + i: Integer; + n1, n2: Double; + begin + WriteLn('Sorting of two rows on row "1" and "2"'); + WriteLn('(Expecting an ascending row of numbers)'); + workbook := TsWorkbook.Create; + try + worksheet := workbook.AddWorksheet('Test'); + + worksheet.WriteUTF8Text(0, 0, 'E'); + worksheet.WriteUTF8Text(0, 1, 'E'); + worksheet.WriteUTF8Text(0, 2, 'C'); + worksheet.WriteUTF8Text(0, 3, 'B'); + worksheet.WriteUTF8Text(0, 4, 'D'); + worksheet.WriteUTF8Text(0, 5, 'D'); + worksheet.WriteUTF8Text(0, 6, 'A'); + worksheet.WriteUTF8Text(0, 7, 'B'); + worksheet.WriteUTF8Text(0, 8, 'C'); + worksheet.WriteUTF8Text(0, 9, 'A'); + + worksheet.WriteNumber(1, 0, 9); // A2 --> E + worksheet.WriteNumber(1, 1, 8); // B2 --> E + worksheet.WriteNumber(1, 2, 5); // C2 --> C + worksheet.WriteNumber(1, 3, 2); // D2 --> B + worksheet.WriteNumber(1, 4, 6); // E2 --> D + worksheet.WriteNumber(1, 5, 7); // F2 --> D + worksheet.WriteNumber(1, 6, 1); // G2 --> A + worksheet.WriteNumber(1, 7, 3); // H2 --> B + worksheet.WriteNumber(1, 8, 4); // I2 --> C + worksheet.WriteNumber(1, 9, 0); // J2 --> A + + sortParams := InitSortParams(false, 2); + sortParams.Keys[0].ColRowIndex := 0; + sortParams.Keys[0].Order := ssoAscending; + sortParams.Keys[1].ColRowIndex := 1; + sortParams.Keys[1].Order := ssoAscending; + + worksheet.Sort(sortParams, 0, 0, 1, 9); + + Write(#9); + for i:=0 to 9 do + Write(char(ord('A')+i) + '1', #9); + WriteLn; + + Write('1', #9); + for i:=0 to 9 do + Write(worksheet.ReadAsUTF8Text(0, i), #9); + WriteLn; + + Write('2', #9); + for i:=0 to 9 do begin + n1 := worksheet.ReadAsNumber(1, i); + Write(FloatToStr(n1), #9); + end; + WriteLn; + + WriteLn; + + finally + workbook.Free; + end; + end; + +begin + SortSingleColumn; + SortSingleRow; + + SortTwoColumns_OneKey; + SortTwoRows_OneKey; + + SortTwoColumns_TwoKeys; + SortTwoRows_TwoKeys; + + SortTwoColumns_TwoKeys_1; + SortTwoRows_TwoKeys_1; +end. + diff --git a/components/fpspreadsheet/fpsexprparser.pas b/components/fpspreadsheet/fpsexprparser.pas index 5348c8bfa..2e5e8cddc 100644 --- a/components/fpspreadsheet/fpsexprparser.pas +++ b/components/fpspreadsheet/fpsexprparser.pas @@ -822,6 +822,9 @@ procedure RegisterFunction(const AName: ShortString; const AResultType: Char; procedure RegisterFunction(const AName: ShortString; const AResultType: Char; const AParamTypes: String; const AExcelCode: Integer; ACallBack: TsExprFunctionEvent); overload; +var + ExprFormatSettings: TFormatSettings; + const AllBuiltIns = [bcMath, bcStatistics, bcStrings, bcLogical, bcDateTime, bcLookup, bcInfo, bcUser]; @@ -830,7 +833,7 @@ const implementation uses - typinfo, math, lazutf8, dateutils, fpsutils, fpsfunc; + typinfo, math, lazutf8, dateutils, fpsutils; //, fpsfunc; const cNull = #0; @@ -4255,7 +4258,7 @@ initialization ExprFormatSettings.DecimalSeparator := '.'; ExprFormatSettings.ListSeparator := ','; - RegisterStdBuiltins(BuiltinIdentifiers); +// RegisterStdBuiltins(BuiltinIdentifiers); finalization FreeBuiltins; diff --git a/components/fpspreadsheet/fpsfunc.pas b/components/fpspreadsheet/fpsfunc.pas index 60aebdcfd..da74ddbe3 100644 --- a/components/fpspreadsheet/fpsfunc.pas +++ b/components/fpspreadsheet/fpsfunc.pas @@ -9,10 +9,7 @@ unit fpsfunc; interface uses - Classes, SysUtils, fpspreadsheet, fpsExprParser; - -var - ExprFormatSettings: TFormatSettings; + Classes, SysUtils, fpspreadsheet, fpsexprparser; procedure RegisterStdBuiltins(AManager : TsBuiltInExpressionManager); @@ -1895,5 +1892,6 @@ end; *) initialization + RegisterStdBuiltins(BuiltinIdentifiers); end. diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 93d3bb8bd..38db9d5b2 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -3341,11 +3341,87 @@ procedure TsWorksheet.Sort(const ASortParams: TsSortParams; repeat I := L; J := R; - P := (L+R) div 2; + P := (L + R) div 2; repeat + { original code from "grids.pas": + + if ColSorting then begin + while DoCompareCells(index, P, index, I)>0 do I:=I+1; + while DoCompareCells(index, P, index, J)<0 do J:=J-1; + end else begin + while DoCompareCells(P, index, I, index)>0 do I:=I+1; + while DoCompareCells(P, index, J, index)<0 do J:=J-1; + end; } + if ASortParams.SortByCols then begin + (* // Sorting by columns + // The next "while" loop corresponds to grid's: + // while DoCompareCells(index, P, index, I) > 0 do I:=I+1; + while true do + begin + cell1 := FindCell(P, ASortParams.Keys[0].ColRowIndex); + cell2 := FindCell(I, ASortParams.Keys[0].ColRowIndex); + compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[0].Order); + if compareResult < 0 then + break + else + if compareResult > 0 then + inc(I) + else + begin + // equal --> check next condition + K := 1; + while (K <= High(ASortParams.Keys)) do + begin + cell1 := FindCell(P, ASortParams.Keys[K].ColRowIndex); + cell2 := FindCell(I, ASortParams.Keys[K].ColRowIndex); + compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[K].Order); + if compareResult < 0 then + break + else + if compareResult > 0 then begin + inc(I); + break; + end else + inc(K); // Still equal --> try next condition + end; + if compareResult <= 0 then + break; + end; + end; + + // The next "while" loop corresponds to grid's: + // while DoCompareCells(index, P, index, J)<0 do J:=J-1; + while true do + begin + cell1 := FindCell(P, ASortParams.Keys[0].ColRowIndex); + cell2 := FindCell(J, ASortParams.Keys[0].ColRowIndex); + compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[0].Order); + if compareResult < 0 then + dec(J) + else + if compareResult > 0 then + break + else begin // equal --> check next condition + K := 1; + while (K <= High(ASortParams.Keys)) do + begin + cell1 := FindCell(P, ASortParams.Keys[K].ColRowIndex); + cell2 := FindCell(J, ASortParams.Keys[K].ColRowIndex); + compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[K].Order); + case abs(compareResult) of + -1: begin dec(J); break; end; + +1: break; + 0: inc(K); + end; + end; + if compareResult >= 0 then + break; + end; + end; + *) K := 0; while true do begin @@ -3355,9 +3431,10 @@ procedure TsWorksheet.Sort(const ASortParams: TsSortParams; case sign(compareResult) of -1: break; 0: if K <= High(ASortParams.Keys) then inc(K) else break; - +1: inc(I); + +1: begin inc(I); K:= 0; end; end; end; + K := 0; while true do begin @@ -3365,7 +3442,7 @@ procedure TsWorksheet.Sort(const ASortParams: TsSortParams; cell2 := FindCell(J, ASortParams.Keys[K].ColRowIndex); compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[K].Order); case sign(compareResult) of - -1: dec(J); + -1: begin dec(J); K := 0; end; 0: if K <= High(ASortParams.Keys) then inc(K) else break; +1: break; end; @@ -3382,7 +3459,7 @@ procedure TsWorksheet.Sort(const ASortParams: TsSortParams; case sign(compareResult) of -1: break; 0: if K <= High(ASortParams.Keys) then inc(K) else break; - +1: inc(I); + +1: begin inc(I); if K > 0 then K := 0; end; end; end; K := 0; @@ -3392,11 +3469,65 @@ procedure TsWorksheet.Sort(const ASortParams: TsSortParams; cell2 := FindCell(ASortParams.Keys[K].ColRowIndex, J); compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[K].Order); case sign(compareResult) of - -1: dec(J); + -1: begin dec(J); if K > 0 then K := 0; end; 0: if K <= High(ASortParams.Keys) then inc(K) else break; +1: break; end; end; + (* + while true do + begin + cell1 := FindCell(ASortParams.Keys[0].ColRowIndex, P); + cell2 := FindCell(ASortParams.Keys[0].ColRowIndex, I); + compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[0].Order); + case sign(compareresult) of + -1: break; + +1: inc(I); + 0: begin + K := 1; + while (compareResult=0) and (K <= High(ASortParams.Keys)) do + begin + cell1 := FindCell(ASortParams.Keys[K].ColRowIndex, P); + cell2 := FindCell(ASortParams.Keys[K].ColRowIndex, I); + compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[K].Order); + if compareResult = 0 then + continue + else begin + if compareresult > 0 then inc(I); + break; + end; + end; + if compareResult < 0 then break; + end; + end; + end; + while true do + begin + cell1 := FindCell(ASortParams.Keys[0].ColRowIndex, P); + cell2 := FindCell(ASortParams.Keys[0].ColRowIndex, J); + compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[0].Order); + case sign(compareResult) of + -1: dec(J); + +1: break; + 0: begin + K := 1; + while (compareResult=0) and (K <= High(ASortParams.Keys)) do + begin + cell1 := FindCell(ASortParams.Keys[0].ColRowIndex, P); + cell2 := FindCell(ASortParams.Keys[0].ColRowIndex, J); + compareResult := DoCompareCells(cell1, cell2, ASortParams.Keys[K].Order); + if compareResult = 0 then + continue + else begin + if compareResult < 0 then dec(J); + break; + end; + end; + if compareResult > 0 then break; + end; + end; + end; + *) end; if I <= J then diff --git a/components/fpspreadsheet/tests/sortingtests.pas b/components/fpspreadsheet/tests/sortingtests.pas index e634649b9..c0b5219b2 100644 --- a/components/fpspreadsheet/tests/sortingtests.pas +++ b/components/fpspreadsheet/tests/sortingtests.pas @@ -272,8 +272,10 @@ var begin sortParams := InitSortParams(ASortByCols, 2); - sortParams.Keys[0].ColRowIndex := 0; - sortParams.Keys[1].ColRowIndex := 1; + sortParams.Keys[0].ColRowIndex := 0; // col/row 0 is primary key + sortParams.Keys[1].ColRowIndex := 1; // col/row 1 is second key + + iLast := High(SollSortNumbers); TempFile := GetTempFileName; @@ -285,18 +287,22 @@ begin row := 0; if ASortByCols then begin - // Always 2 numbers in the first column are equal - for i:=0 to High(SollSortNumbers) do - MyWorksheet.WriteNumber(i, col, SollSortNumbers[(i mod 2)*2]); - // All strings in the second column are distinct - for i:=0 to High(SollSortStrings) do - MyWorksheet.WriteUTF8Text(i, col+1, SollSortStrings[i]); + // Write all randomized numbers to column B + for i:=0 to iLast do + MyWorksheet.WriteNumber(i, col+1, SollSortNumbers[i]); + // divide each number by 2 and calculate the character assigned to it + // and write it to column A + // We will sort primarily according to column A, and seconarily according + // to B. The construction allows us to determine if the sorting is correct. + for i:=0 to iLast do + MyWorksheet.WriteUTF8Text(i, col, char(ord('A')+round(SollSortNumbers[i div 2]))); end else begin - for i:=0 to High(SollSortNumbers) do - MyWorksheet.WriteNumber(row, i, SollSortNumbers[(i mod 2)*2]); - for i:=0 to High(SollSortStrings) do - MyWorksheet.WriteUTF8Text(row+1, i, SollSortStrings[i]); + // The same with the rows... + for i:=0 to iLast do + MyWorksheet.WriteNumber(row+1, i+1, SollSortNumbers[i]); + for i:=0 to iLast do + MyWorksheet.WriteUTF8Text(row, i, char(ord('A')+round(SollSortNumbers[i div 2]))); end; MyWorkBook.WriteToFile(TempFile, AFormat, true); @@ -319,7 +325,6 @@ begin fail('Error in test code. Failed to get named worksheet'); // ... and sort it. - iLast := High(SollSortNumbers); //must be the same as for SollSortStrings r1 := 0; c1 := 0; if ASortByCols then begin c2 := 1; @@ -338,31 +343,44 @@ begin for i:=0 to iLast do begin - row := 0; - col := 0; if ASortByCols then + begin + // Read the number first, they must be in order 0...9 (if ascending). + col := 1; case sortDir of ssoAscending : row := i; ssoDescending: row := iLast - i; - end - else + end; + actualNumber := MyWorksheet.ReadAsNumber(row, col); // col B is the number, must be 0...9 here + expectedNumber := i; + CheckEquals(expectednumber, actualnumber, + 'Sorted cell number mismatch, cell '+CellNotation(MyWorksheet, row, col)); + + // Now read the string. It must be the character corresponding to the + // half of the number + col := 0; + actualString := MyWorksheet.ReadAsUTF8Text(row, col); + expectedString := char(ord('A') + round(expectedNumber) div 2); + CheckEquals(expectedstring, actualstring, + 'Sorted cell string mismatch, cell '+CellNotation(MyWorksheet, row, col)); + end else + begin + row := 1; case sortDir of ssoAscending : col := i; ssoDescending: col := iLast - i; end; - actualNumber := MyWorksheet.ReadAsNumber(row, col); - expectedNumber := (i mod 2) * 2; - CheckEquals(expectednumber, actualnumber, - 'Sorted cell number mismatch, cell '+CellNotation(MyWorksheet, row, col)); + actualNumber := MyWorksheet.ReadAsNumber(row, col); + expectedNumber := i; + CheckEquals(expectednumber, actualnumber, + 'Sorted cell number mismatch, cell '+CellNotation(MyWorksheet, row, col)); - if ASortByCols then - inc(col) - else - inc(row); - actualString := MyWorksheet.ReadAsUTF8Text(row, col); - expectedString := char(ord('A') + i); - CheckEquals(expectedstring, actualstring, - 'Sorted cell string mismatch, cell '+CellNotation(MyWorksheet, row, col)); + row := 0; + actualstring := MyWorksheet.ReadAsUTF8Text(row, col); + expectedString := char(ord('A') + round(expectedNumber) div 2); + CheckEquals(expectedstring, actualstring, + 'Sorted cell string mismatch, cell '+CellNotation(MyWorksheet, row, col)); + end; end; finally MyWorkbook.Free; diff --git a/components/fpspreadsheet/tests/spreadtestgui.lpi b/components/fpspreadsheet/tests/spreadtestgui.lpi index fc62e2c66..fe7e6b7c0 100644 --- a/components/fpspreadsheet/tests/spreadtestgui.lpi +++ b/components/fpspreadsheet/tests/spreadtestgui.lpi @@ -48,7 +48,6 @@ - @@ -76,6 +75,7 @@ + @@ -84,6 +84,7 @@ + @@ -96,6 +97,7 @@ + @@ -105,6 +107,7 @@ +