You've already forked lazarus-ccr
fpspreadsheet: Add TDataset-descendant, TsWorksheetDataset, and related unit-tests.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8095 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
lazres ../../resource/fpsvisualreg.res @list_visual.txt
|
lazres ../../resource/fpsvisualreg.res @list_visual.txt
|
||||||
lazres ../../resource/fpsvisual.lrs cur_dragcopy.cur
|
lazres ../../resource/fpsvisual.lrs cur_dragcopy.cur
|
||||||
lazres ../../resource/fpsvisualexportreg.res @list_export.txt
|
lazres ../../resource/fpsvisualexportreg.res @list_export.txt
|
||||||
|
lazres ../../resource/fpsdatasetreg.res @list_dataset.txt
|
||||||
|
@ -11,3 +11,6 @@
|
|||||||
(4) If you need to unlock xls file protection
|
(4) If you need to unlock xls file protection
|
||||||
Make sure that the package dcpcrypt.lpk can be found by the IDE
|
Make sure that the package dcpcrypt.lpk can be found by the IDE
|
||||||
Open laz_fpspreadsheet_crypto.lpk -- > Compile
|
Open laz_fpspreadsheet_crypto.lpk -- > Compile
|
||||||
|
|
||||||
|
(5) If need database access to spreadsheets:
|
||||||
|
Open laz_fpsdataset.lpk --> Use --> Install
|
43
components/fpspreadsheet/laz_fpspreadsheet_dataset.lpk
Normal file
43
components/fpspreadsheet/laz_fpspreadsheet_dataset.lpk
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<CONFIG>
|
||||||
|
<Package Version="5">
|
||||||
|
<PathDelim Value="\"/>
|
||||||
|
<Name Value="laz_fpspreadsheet_dataset"/>
|
||||||
|
<Type Value="RunAndDesignTime"/>
|
||||||
|
<Author Value="Werner Pamler"/>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="11"/>
|
||||||
|
<PathDelim Value="\"/>
|
||||||
|
<SearchPaths>
|
||||||
|
<OtherUnitFiles Value="source/dataset"/>
|
||||||
|
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)\"/>
|
||||||
|
</SearchPaths>
|
||||||
|
</CompilerOptions>
|
||||||
|
<Description Value="Accesses a spreadsheet file like a database."/>
|
||||||
|
<License Value="LGPL with static linking exception. This is the same license as is used in the LCL (Lazarus Component Library)."/>
|
||||||
|
<Version Major="1" Minor="13"/>
|
||||||
|
<Files Count="1">
|
||||||
|
<Item1>
|
||||||
|
<Filename Value="source/dataset/fpsdataset.pas"/>
|
||||||
|
<HasRegisterProc Value="True"/>
|
||||||
|
<UnitName Value="fpsDataset"/>
|
||||||
|
</Item1>
|
||||||
|
</Files>
|
||||||
|
<CompatibilityMode Value="True"/>
|
||||||
|
<RequiredPkgs Count="2">
|
||||||
|
<Item1>
|
||||||
|
<PackageName Value="laz_fpspreadsheet"/>
|
||||||
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<PackageName Value="FCL"/>
|
||||||
|
</Item2>
|
||||||
|
</RequiredPkgs>
|
||||||
|
<UsageOptions>
|
||||||
|
<UnitPath Value="$(PkgOutDir)"/>
|
||||||
|
</UsageOptions>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<UseFileFilters Value="True"/>
|
||||||
|
</PublishOptions>
|
||||||
|
</Package>
|
||||||
|
</CONFIG>
|
BIN
components/fpspreadsheet/resource/fpsdatasetreg.res
Normal file
BIN
components/fpspreadsheet/resource/fpsdatasetreg.res
Normal file
Binary file not shown.
2231
components/fpspreadsheet/source/dataset/fpsdataset.pas
Normal file
2231
components/fpspreadsheet/source/dataset/fpsdataset.pas
Normal file
File diff suppressed because it is too large
Load Diff
132
components/fpspreadsheet/unit-tests/dataset/GuiTestProject.lpi
Normal file
132
components/fpspreadsheet/unit-tests/dataset/GuiTestProject.lpi
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<Version Value="12"/>
|
||||||
|
<PathDelim Value="\"/>
|
||||||
|
<General>
|
||||||
|
<Flags>
|
||||||
|
<CompatibilityMode Value="True"/>
|
||||||
|
</Flags>
|
||||||
|
<SessionStorage Value="InProjectDir"/>
|
||||||
|
<Title Value="GuiTestProject"/>
|
||||||
|
<ResourceType Value="res"/>
|
||||||
|
<UseXPManifest Value="True"/>
|
||||||
|
<Icon Value="0"/>
|
||||||
|
</General>
|
||||||
|
<BuildModes Count="1">
|
||||||
|
<Item1 Name="Default" Default="True"/>
|
||||||
|
</BuildModes>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<FormatVersion Value="2"/>
|
||||||
|
<Modes Count="1">
|
||||||
|
<Mode0 Name="default"/>
|
||||||
|
</Modes>
|
||||||
|
</RunParams>
|
||||||
|
<RequiredPackages Count="3">
|
||||||
|
<Item1>
|
||||||
|
<PackageName Value="laz_fpspreadsheet_dataset"/>
|
||||||
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<PackageName Value="fpcunittestrunner"/>
|
||||||
|
</Item2>
|
||||||
|
<Item3>
|
||||||
|
<PackageName Value="LCL"/>
|
||||||
|
</Item3>
|
||||||
|
</RequiredPackages>
|
||||||
|
<Units Count="8">
|
||||||
|
<Unit0>
|
||||||
|
<Filename Value="GuiTestProject.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit0>
|
||||||
|
<Unit1>
|
||||||
|
<Filename Value="readfieldstestunit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="ReadFieldsTestUnit"/>
|
||||||
|
</Unit1>
|
||||||
|
<Unit2>
|
||||||
|
<Filename Value="sorttestunit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="SortTestUnit"/>
|
||||||
|
</Unit2>
|
||||||
|
<Unit3>
|
||||||
|
<Filename Value="filtertestunit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="FilterTestUnit"/>
|
||||||
|
</Unit3>
|
||||||
|
<Unit4>
|
||||||
|
<Filename Value="posttestunit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="PostTestUnit"/>
|
||||||
|
</Unit4>
|
||||||
|
<Unit5>
|
||||||
|
<Filename Value="emptycolumnstestunit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="EmptyColumnsTestUnit"/>
|
||||||
|
</Unit5>
|
||||||
|
<Unit6>
|
||||||
|
<Filename Value="searchtestunit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="SearchTestUnit"/>
|
||||||
|
</Unit6>
|
||||||
|
<Unit7>
|
||||||
|
<Filename Value="copyfromdatasetunit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="CopyFromDatasetUnit"/>
|
||||||
|
</Unit7>
|
||||||
|
</Units>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="11"/>
|
||||||
|
<PathDelim Value="\"/>
|
||||||
|
<Target>
|
||||||
|
<Filename Value="GuiTestProject"/>
|
||||||
|
</Target>
|
||||||
|
<SearchPaths>
|
||||||
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||||
|
</SearchPaths>
|
||||||
|
<Parsing>
|
||||||
|
<SyntaxOptions>
|
||||||
|
<IncludeAssertionCode Value="True"/>
|
||||||
|
</SyntaxOptions>
|
||||||
|
</Parsing>
|
||||||
|
<CodeGeneration>
|
||||||
|
<Checks>
|
||||||
|
<IOChecks Value="True"/>
|
||||||
|
<RangeChecks Value="True"/>
|
||||||
|
<OverflowChecks Value="True"/>
|
||||||
|
<StackChecks Value="True"/>
|
||||||
|
</Checks>
|
||||||
|
<VerifyObjMethodCallValidity Value="True"/>
|
||||||
|
</CodeGeneration>
|
||||||
|
<Linking>
|
||||||
|
<Debugging>
|
||||||
|
<DebugInfoType Value="dsDwarf2Set"/>
|
||||||
|
</Debugging>
|
||||||
|
<Options>
|
||||||
|
<Win32>
|
||||||
|
<GraphicApplication Value="True"/>
|
||||||
|
</Win32>
|
||||||
|
</Options>
|
||||||
|
</Linking>
|
||||||
|
</CompilerOptions>
|
||||||
|
<Debugging>
|
||||||
|
<Exceptions Count="4">
|
||||||
|
<Item1>
|
||||||
|
<Name Value="EAbort"/>
|
||||||
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<Name Value="ECodetoolError"/>
|
||||||
|
</Item2>
|
||||||
|
<Item3>
|
||||||
|
<Name Value="EFOpenError"/>
|
||||||
|
</Item3>
|
||||||
|
<Item4>
|
||||||
|
<Name Value="EAssertionFailedError"/>
|
||||||
|
</Item4>
|
||||||
|
</Exceptions>
|
||||||
|
</Debugging>
|
||||||
|
</CONFIG>
|
@ -0,0 +1,17 @@
|
|||||||
|
program GuiTestProject;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
uses
|
||||||
|
Interfaces, Forms, GuiTestRunner,
|
||||||
|
ReadFieldsTestUnit, SortTestUnit, SearchTestUnit, FilterTestUnit, PostTestUnit,
|
||||||
|
EmptyColumnsTestUnit, CopyFromDatasetUnit;
|
||||||
|
|
||||||
|
{$R *.res}
|
||||||
|
|
||||||
|
begin
|
||||||
|
Application.Initialize;
|
||||||
|
Application.CreateForm(TGuiTestRunner, TestRunner);
|
||||||
|
Application.Run;
|
||||||
|
end.
|
||||||
|
|
@ -0,0 +1,219 @@
|
|||||||
|
unit CopyFromDatasetUnit;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testutils, testregistry,
|
||||||
|
DB, dbf,
|
||||||
|
fpspreadsheet, fpsDataset;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TCopyFromDatasetTest }
|
||||||
|
|
||||||
|
TCopyFromDatasetTest= class(TTestCase)
|
||||||
|
private
|
||||||
|
function CreateDbf: TDbf;
|
||||||
|
procedure CopyDatasetTest(ATestIndex: Integer);
|
||||||
|
protected
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
published
|
||||||
|
procedure CopyDatasetTest_FieldDefs;
|
||||||
|
procedure CopyDatasetTest_Fields;
|
||||||
|
procedure CopyDatasetTest_Records;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
TypInfo;
|
||||||
|
|
||||||
|
const
|
||||||
|
DBF_FILE_NAME = 'testdata.dbf';
|
||||||
|
FILE_NAME = 'testfile.xlsx';
|
||||||
|
SHEET_NAME = 'Sheet';
|
||||||
|
|
||||||
|
STRING_FIELD = 'StringCol';
|
||||||
|
INT_FIELD = 'IntegerCol';
|
||||||
|
FLOAT_FIELD = 'FloatCol';
|
||||||
|
|
||||||
|
NUM_RECORDS = 10;
|
||||||
|
|
||||||
|
var
|
||||||
|
DataFileName: String;
|
||||||
|
DbfPath: String;
|
||||||
|
|
||||||
|
|
||||||
|
function TCopyFromDatasetTest.CreateDbf: TDbf;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := TDbf.Create(nil);
|
||||||
|
Result.FilePathFull := DbfPath;
|
||||||
|
Result.TableName := DBF_FILE_NAME;
|
||||||
|
Result.FieldDefs.Add(STRING_FIELD, ftString, 20);
|
||||||
|
Result.FieldDefs.Add(INT_FIELD, ftInteger);
|
||||||
|
Result.FieldDefs.Add(FLOAT_FIELD, ftFloat);
|
||||||
|
Result.CreateTable;
|
||||||
|
Result.Open;
|
||||||
|
for i := 1 to NUM_RECORDS do
|
||||||
|
begin
|
||||||
|
Result.Append;
|
||||||
|
Result.FieldByName(STRING_FIELD).AsString := 'abc' + IntToStr(i);
|
||||||
|
Result.FieldByName(INT_FIELD).AsInteger := -5 + i;
|
||||||
|
Result.FieldByName(FLOAT_FIELD).AsFloat := -5.1 * (i + 5.1);
|
||||||
|
Result.Post;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCopyFromDatasetTest.CopyDatasetTest(ATestIndex: Integer);
|
||||||
|
const
|
||||||
|
DEBUG = false;
|
||||||
|
var
|
||||||
|
dbf: TDbf;
|
||||||
|
dataset: TsWorksheetDataset;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
dbf := CreateDbf;
|
||||||
|
|
||||||
|
if DEBUG then
|
||||||
|
begin
|
||||||
|
dbf.Close;
|
||||||
|
dbf.Open;
|
||||||
|
end;
|
||||||
|
|
||||||
|
dataset := TsWorksheetDataset.Create(nil);
|
||||||
|
try
|
||||||
|
dataset.CopyFromDataset(dbf, DataFileName, dbf.TableName);
|
||||||
|
|
||||||
|
// Save for debugging
|
||||||
|
if DEBUG then
|
||||||
|
begin
|
||||||
|
dataset.Close;
|
||||||
|
dataset.Open;
|
||||||
|
end;
|
||||||
|
|
||||||
|
case ATestIndex of
|
||||||
|
// FIELD DEFS
|
||||||
|
0: begin
|
||||||
|
CheckEquals( // Compare FieldDef count
|
||||||
|
dbf.FieldDefs.Count,
|
||||||
|
dataset.FieldDefs.Count,
|
||||||
|
'Mismatch in number of FieldDefs'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Compare FieldDefs
|
||||||
|
for i := 0 to dbf.FieldDefs.Count-1 do
|
||||||
|
begin
|
||||||
|
CheckEquals(
|
||||||
|
dbf.FieldDefs[i].Name,
|
||||||
|
dataset.FieldDefs[i].Name,
|
||||||
|
'Mismatch in FieldDefs[' + IntToStr(i) + '].Name'
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
GetEnumName(TypeInfo(TFieldType), integer(dbf.FieldDefs[i].DataType)),
|
||||||
|
GetEnumName(TypeInfo(TFieldType), integer(dataset.FieldDefs[i].DataType)),
|
||||||
|
'Mismatch in FieldDefs[' + IntToStr(i) + '].DataType'
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
dbf.FieldDefs[i].Size,
|
||||||
|
dataset.FieldDefs[i].Size,
|
||||||
|
'Mismatch in FieldDefs[' + IntToStr(i) + '].Size'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// FIELDS
|
||||||
|
1: begin
|
||||||
|
// Compare field count
|
||||||
|
CheckEquals(
|
||||||
|
dbf.FieldCount,
|
||||||
|
dataset.FieldCount,
|
||||||
|
'Mismatch in FieldCount'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Compare fields
|
||||||
|
for i := 0 to dbf.FieldCount-1 do
|
||||||
|
begin
|
||||||
|
CheckEquals(
|
||||||
|
dbf.Fields[i].FieldName,
|
||||||
|
dataset.Fields[i].FieldName,
|
||||||
|
'Mismatch in Fields[' + IntToStr(i) + '].FieldName'
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
GetEnumName(TypeInfo(TFieldType), integer(dbf.Fields[i].DataType)),
|
||||||
|
GetEnumName(TypeInfo(TFieldType), integer(dataset.Fields[i].DataType)),
|
||||||
|
'Mismatch in Fields[' + IntToStr(i) + '].DataType'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// RECORDS
|
||||||
|
2: begin
|
||||||
|
// Compare record count
|
||||||
|
CheckEquals(
|
||||||
|
dbf.RecordCount,
|
||||||
|
dataset.RecordCount,
|
||||||
|
'Mismatch in RecordCount'
|
||||||
|
);
|
||||||
|
|
||||||
|
dbf.First;
|
||||||
|
dataset.First;
|
||||||
|
while not dbf.EoF do
|
||||||
|
begin
|
||||||
|
for i := 0 to dbf.FieldCount-1 do
|
||||||
|
begin
|
||||||
|
CheckEquals(
|
||||||
|
dbf.Fields[i].AsString,
|
||||||
|
dataset.Fields[i].AsString,
|
||||||
|
'Record value mismatch, Field #[' + IntToStr(i) + '], RecNo ' + IntToStr(dbf.RecNo)
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
dbf.Next;
|
||||||
|
dataset.Next;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
finally
|
||||||
|
dataset.Free;
|
||||||
|
dbf.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCopyFromDatasetTest.CopyDatasetTest_FieldDefs;
|
||||||
|
begin
|
||||||
|
CopyDatasetTest(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCopyFromDatasetTest.CopyDatasetTest_Fields;
|
||||||
|
begin
|
||||||
|
CopyDatasetTest(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCopyFromDatasetTest.CopyDatasetTest_Records;
|
||||||
|
begin
|
||||||
|
CopyDatasetTest(2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCopyFromDatasetTest.SetUp;
|
||||||
|
begin
|
||||||
|
DataFileName := GetTempDir + FILE_NAME;
|
||||||
|
DbfPath := GetTempDir;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCopyFromDatasetTest.TearDown;
|
||||||
|
begin
|
||||||
|
if FileExists(DataFileName) then DeleteFile(DataFileName);
|
||||||
|
if FileExists(DbfPath + DBF_FILE_NAME) then DeleteFile(DbfPath + DBF_FILE_NAME);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
initialization
|
||||||
|
RegisterTest(TCopyFromDatasetTest);
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -0,0 +1,297 @@
|
|||||||
|
{ These tests check whether empty columns in the worksheet are ignored when
|
||||||
|
FieldDefs are determined. }
|
||||||
|
|
||||||
|
unit EmptyColumnsTestUnit;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testregistry,
|
||||||
|
DB,
|
||||||
|
fpSpreadsheet, fpsTypes, fpsDataset;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TEmptyColumnsTest = class(TTestCase)
|
||||||
|
private
|
||||||
|
function CreateAndOpenDataset(
|
||||||
|
ATestIndex: Integer; AutoFieldDefs: Boolean): TsWorksheetDataset;
|
||||||
|
procedure CreateWorksheet(ATestIndex: Integer);
|
||||||
|
protected
|
||||||
|
procedure TestFieldDefs(ATestIndex: Integer; AutoFieldDefs: Boolean);
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
published
|
||||||
|
procedure Test_0;
|
||||||
|
procedure Test_1;
|
||||||
|
procedure Test_2;
|
||||||
|
procedure Test_3;
|
||||||
|
procedure Test_4;
|
||||||
|
procedure Test_5;
|
||||||
|
procedure Test_6;
|
||||||
|
procedure Test_0_AutoFieldDefs;
|
||||||
|
procedure Test_1_AutoFieldDefs;
|
||||||
|
procedure Test_2_AutoFieldDefs;
|
||||||
|
procedure Test_3_AutoFieldDefs;
|
||||||
|
procedure Test_4_AutoFieldDefs;
|
||||||
|
procedure Test_5_AutoFieldDefs;
|
||||||
|
procedure Test_6_AutoFieldDefs;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
const
|
||||||
|
FILE_NAME = 'testfile.xlsx';
|
||||||
|
SHEET_NAME = 'Sheet';
|
||||||
|
|
||||||
|
var
|
||||||
|
DataFileName: String;
|
||||||
|
|
||||||
|
type
|
||||||
|
TDataRec = record
|
||||||
|
ColumnType: TFieldType;
|
||||||
|
FieldDefIndex: Integer;
|
||||||
|
end;
|
||||||
|
TTestData = array [0..3] of TDataRec; // colums 0..3 in worksheet
|
||||||
|
|
||||||
|
const
|
||||||
|
TestCases: array[0..6] of TTestData = (
|
||||||
|
( //0
|
||||||
|
(ColumnType:ftInteger; FieldDefIndex: 0),
|
||||||
|
(ColumnType:ftFloat; FieldDefIndex: 1),
|
||||||
|
(ColumnType:ftString; FieldDefIndex: 2),
|
||||||
|
(ColumnType:ftDate; FieldDefIndex: 3)
|
||||||
|
),
|
||||||
|
( // 1
|
||||||
|
(ColumnType:ftInteger; FieldDefIndex: 0),
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1),
|
||||||
|
(ColumnType:ftFloat; FieldDefIndex: 1),
|
||||||
|
(ColumnType:ftDate; FieldDefIndex: 2)
|
||||||
|
),
|
||||||
|
( // 2
|
||||||
|
(ColumnType:ftInteger; FieldDefIndex: 0),
|
||||||
|
(ColumnType:ftFloat; FieldDefIndex: 1),
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1),
|
||||||
|
(ColumnType:ftString; FieldDefIndex: 2)
|
||||||
|
),
|
||||||
|
( // 3
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1),
|
||||||
|
(ColumnType:ftInteger; FieldDefIndex: 0),
|
||||||
|
(ColumnType:ftFloat; FieldDefIndex: 1),
|
||||||
|
(ColumnType:ftString; FieldDefIndex: 2)
|
||||||
|
),
|
||||||
|
( // 4
|
||||||
|
(ColumnType:ftInteger; FieldDefIndex: 0),
|
||||||
|
(ColumnType:ftString; FieldDefIndex: 1),
|
||||||
|
(ColumnType:ftDate; FieldDefIndex: 2),
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1)
|
||||||
|
),
|
||||||
|
( // 5
|
||||||
|
(ColumnType:ftInteger; FieldDefIndex: 0),
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1),
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1),
|
||||||
|
(ColumnType:ftFloat; FieldDefIndex: 1)
|
||||||
|
),
|
||||||
|
( // 6
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1),
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1),
|
||||||
|
(ColumnType:ftUnknown; FieldDefIndex:-1),
|
||||||
|
(ColumnType:ftInteger; FieldDefIndex: 0)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
function TEmptyColumnsTest.CreateAndOpenDataset(
|
||||||
|
ATestIndex: Integer; AutoFieldDefs: Boolean): TsWorksheetDataset;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := TsWorksheetDataset.Create(nil);
|
||||||
|
Result.FileName := DataFileName;
|
||||||
|
Result.SheetName := SHEET_NAME;
|
||||||
|
Result.AutoFieldDefs := AutoFieldDefs;
|
||||||
|
if not AutoFieldDefs then
|
||||||
|
begin
|
||||||
|
for i := 0 to Length(TTestData)-1 do
|
||||||
|
begin
|
||||||
|
case TestCases[ATestIndex][i].ColumnType of
|
||||||
|
ftUnknown: ;
|
||||||
|
ftInteger: Result.AddFieldDef('IntCol', ftInteger, 0, i);
|
||||||
|
ftFloat: Result.AddFieldDef('FloatCol', ftFloat, 0, i);
|
||||||
|
ftString: Result.AddFieldDef('StringCol', ftString, 20, i);
|
||||||
|
ftDate: Result.AddFieldDef('DateCol', ftDate, 0, i);
|
||||||
|
else raise Exception.Create('Field type not expected in this test.');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result.CreateTable;
|
||||||
|
end;
|
||||||
|
Result.Open;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Creates a worksheet with columns as defined by the TestColumns.
|
||||||
|
ftUnknown will become an empty column. }
|
||||||
|
procedure TEmptyColumnsTest.CreateWorksheet(ATestIndex: Integer);
|
||||||
|
const
|
||||||
|
NumRows = 10;
|
||||||
|
var
|
||||||
|
r, c: Integer;
|
||||||
|
s: String;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
worksheet: TsWorksheet;
|
||||||
|
begin
|
||||||
|
// Create test spreadsheet file
|
||||||
|
workbook := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
// Create worksheet
|
||||||
|
worksheet := workbook.AddWorkSheet(SHEET_NAME);
|
||||||
|
// Write headers (= field names) and record values
|
||||||
|
for c := 0 to Length(TTestData)-1 do
|
||||||
|
begin
|
||||||
|
case TestCases[ATestIndex][c].ColumnType of
|
||||||
|
ftUnknown: ;
|
||||||
|
ftInteger:
|
||||||
|
begin
|
||||||
|
worksheet.WriteText(0, c, 'IntCol');
|
||||||
|
for r := 1 to NumRows do
|
||||||
|
worksheet.WriteNumber(r, c, Random(100));
|
||||||
|
end;
|
||||||
|
ftFloat:
|
||||||
|
begin
|
||||||
|
worksheet.WriteText(0, c, 'FloatCol');
|
||||||
|
for r := 1 to NumRows do
|
||||||
|
worksheet.WriteNumber(r, c, Random*100);
|
||||||
|
end;
|
||||||
|
ftString:
|
||||||
|
begin
|
||||||
|
worksheet.WriteText(0, c, 'StringCol');
|
||||||
|
for r := 1 to NumRows do
|
||||||
|
worksheet.WriteText(r, c, char(ord('a') + random(26)));
|
||||||
|
end;
|
||||||
|
ftDate:
|
||||||
|
begin
|
||||||
|
worksheet.WriteText(0, c, 'DateCol');
|
||||||
|
for r := 1 to NumRows do
|
||||||
|
worksheet.WriteDateTime(r, c, EncodeDate(2000,1,1) + Random(1000), nfShortDate);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Save
|
||||||
|
workbook.WriteToFile(DataFileName, true);
|
||||||
|
finally
|
||||||
|
workbook.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.TestFieldDefs(ATestIndex: Integer; AutoFieldDefs: Boolean);
|
||||||
|
var
|
||||||
|
dataset: TsWorksheetDataset;
|
||||||
|
c, i: Integer;
|
||||||
|
expectedFieldDefIndex, actualFieldDefIndex: Integer;
|
||||||
|
begin
|
||||||
|
CreateWorksheet(ATestIndex);
|
||||||
|
dataset := CreateAndOpenDataset(ATestIndex, AutoFieldDefs);
|
||||||
|
try
|
||||||
|
for i := 0 to dataset.FieldDefs.Count-1 do
|
||||||
|
begin
|
||||||
|
c := TsFieldDef(dataset.FieldDefs[i]).ColIndex;
|
||||||
|
expectedFieldDefIndex := TestCases[ATestIndex][c].FieldDefIndex;
|
||||||
|
actualFieldDefIndex := i;
|
||||||
|
CheckEquals(
|
||||||
|
expectedFieldDefIndex,
|
||||||
|
actualFieldDefIndex,
|
||||||
|
'FieldDef index mismatch, fieldDef #' + IntToStr(i)
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
dataset.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_0;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(0, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_1;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(1, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_2;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(2, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_3;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(3, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_4;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(4, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_5;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(5, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_6;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(6, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_0_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(0, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_1_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(1, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_2_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(2, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_3_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(3, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_4_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(4, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_5_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(5, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.Test_6_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
TestFieldDefs(6, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.SetUp;
|
||||||
|
begin
|
||||||
|
DataFileName := GetTempDir + FILE_NAME;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEmptyColumnsTest.TearDown;
|
||||||
|
begin
|
||||||
|
if FileExists(DataFileName) then DeleteFile(DataFileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
|
||||||
|
RegisterTest(TEmptyColumnsTest);
|
||||||
|
end.
|
||||||
|
|
370
components/fpspreadsheet/unit-tests/dataset/filtertestunit.pas
Normal file
370
components/fpspreadsheet/unit-tests/dataset/filtertestunit.pas
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
unit FilterTestUnit;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testregistry,
|
||||||
|
DB,
|
||||||
|
fpspreadsheet, fpstypes, fpsutils, fpsdataset;
|
||||||
|
|
||||||
|
type
|
||||||
|
TFilterTest= class(TTestCase)
|
||||||
|
private
|
||||||
|
function CreateAndOpenDataset: TsWorksheetDataset;
|
||||||
|
procedure Filter_01(Dataset: TDataset; var Accept: Boolean); // 'IntCol < 2'
|
||||||
|
procedure Filter_10(Dataset: TDataset; var Accept: Boolean); // 'StringCol = 'abc
|
||||||
|
procedure Filter_11(Dataset: TDataset; var Accept: Boolean); // 'UPPER(StringCol) = 'ABC'
|
||||||
|
procedure Filter_12(Dataset: TDataset; var Accept: Boolean); // 'StringCol = 'ä'
|
||||||
|
procedure Filter_13(Dataset: TDataset; var Accept: Boolean); // 'StringCol > 'α'
|
||||||
|
procedure Filter_20(Dataset: TDataset; var Accept: Boolean); // 'WideStringCol = 'wABC'
|
||||||
|
procedure Filter_21(Dataset: TDataset; var Accept: Boolean); // 'UPPER(WideStringCol) = 'WABC'
|
||||||
|
procedure Filter_22(Dataset: TDataset; var Accept: Boolean); // 'WideStringCol = 'wä'
|
||||||
|
protected
|
||||||
|
procedure FilterTest(TestIndex: Integer);
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
published
|
||||||
|
procedure FilterTest_01_Int;
|
||||||
|
procedure FilterTest_10_String;
|
||||||
|
procedure FilterTest_11_UpperString;
|
||||||
|
procedure FilterTest_12_StringUTF8;
|
||||||
|
procedure FilterTest_13_StringUTF8;
|
||||||
|
|
||||||
|
procedure FilterTest_ByEvent_101_Int;
|
||||||
|
procedure FilterTest_ByEvent_110_String;
|
||||||
|
procedure FilterTest_ByEvent_111_UpperString;
|
||||||
|
procedure FilterTest_ByEvent_112_String_UTF8;
|
||||||
|
procedure FilterTest_ByEvent_113_String_UTF8;
|
||||||
|
procedure FilterTest_ByEvent_120_WideString;
|
||||||
|
procedure FilterTest_ByEvent_121_UpperWideString;
|
||||||
|
procedure FilterTest_ByEvent_122_WideString_UTF8;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
const
|
||||||
|
FILE_NAME = 'testfile.xlsx';
|
||||||
|
SHEET_NAME = 'Sheet';
|
||||||
|
INT_COL = 0;
|
||||||
|
STRING_COL = 1;
|
||||||
|
WIDESTRING_COL = 2;
|
||||||
|
INT_FIELD = 'IntCol';
|
||||||
|
STRING_FIELD = 'StringCol';
|
||||||
|
WIDESTRING_FIELD = 'WideStringCol';
|
||||||
|
|
||||||
|
var
|
||||||
|
DataFileName: String;
|
||||||
|
|
||||||
|
type
|
||||||
|
TTestRow = record
|
||||||
|
IntValue: Integer;
|
||||||
|
StringValue: String;
|
||||||
|
WideStringValue: Widestring;
|
||||||
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
// Unfiltered test values
|
||||||
|
UNFILTERED: array[0..7] of TTestRow = ( // Index
|
||||||
|
(IntValue: 10; StringValue: 'abc'; WideStringValue: 'wabc'), // 0
|
||||||
|
(IntValue: 1; StringValue: 'ABC'; WideStringvalue: 'wABC'), // 1
|
||||||
|
(IntValue: 1; StringValue: 'a'; WideStringValue: 'wa'), // 2
|
||||||
|
(IntValue: 2; StringValue: 'A'; WideStringValue: 'wA'), // 3
|
||||||
|
(IntValue: -1; StringValue: 'xyz'; WideStringValue: 'wxyz'), // 4
|
||||||
|
(IntValue: 25; StringValue: 'ä'; WideStringValue: 'wä'), // 5
|
||||||
|
(IntValue: 30; StringValue: 'Äöü'; WideStringValue: 'wÄöü'), // 6
|
||||||
|
(IntValue: 5; StringValue: 'αβγä';WideStringValue: 'wαβγä') // 7
|
||||||
|
);
|
||||||
|
|
||||||
|
// These are the indexes into the UNFILTERED array after filtering
|
||||||
|
FILTERED_01: array[0..2] of Integer = (1, 2, 4); // 'IntCol < 2'
|
||||||
|
FILTERED_10: array[0..0] of Integer = (0); // 'StringCol = 'abc'
|
||||||
|
FILTERED_11: array[0..1] of Integer = (0, 1); // 'UPPER(StringCol) = 'ABC'
|
||||||
|
FILTERED_12: array[0..0] of Integer = (5); // StringCol = 'ä'
|
||||||
|
FILTERED_13: array[0..0] of Integer = (7); // StringCol >= 'α'
|
||||||
|
FILTERED_20: array[0..0] of Integer = (1); // 'WideStringCol = 'wABC'
|
||||||
|
FILTERED_21: array[0..1] of Integer = (0, 1); // 'UPPER(WideStringCol) = 'WABC'
|
||||||
|
FILTERED_22: array[0..0] of Integer = (5); // WideStringCol = 'wä'
|
||||||
|
|
||||||
|
EXPRESSION_01 = 'IntCol < 2';
|
||||||
|
EXPRESSION_10 = 'StringCol = "abc"';
|
||||||
|
EXPRESSION_11 = 'UPPER(StringCol) = "ABC"';
|
||||||
|
EXPRESSION_12 = 'StringCol = "ä"';
|
||||||
|
EXPRESSION_13 = 'StringCol >= "α"';
|
||||||
|
EXPRESSION_20 = 'WideStringCol = "wABC"';
|
||||||
|
EXPRESSION_21 = 'UPPER(WideStringCol) = "WABC"';
|
||||||
|
EXPRESSION_22 = 'WideStringCol = "wä"';
|
||||||
|
|
||||||
|
|
||||||
|
procedure TFilterTest.Filter_01(Dataset: TDataset; var Accept: Boolean);
|
||||||
|
begin
|
||||||
|
Accept := Dataset.FieldByName(INT_FIELD).AsInteger < 2;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.Filter_10(Dataset: TDataset; var Accept: Boolean);
|
||||||
|
begin
|
||||||
|
Accept := Dataset.FieldByName(STRING_FIELD).AsString = 'abc';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.Filter_11(Dataset: TDataset; var Accept: Boolean);
|
||||||
|
begin
|
||||||
|
Accept := UpperCase(Dataset.FieldByName(STRING_FIELD).AsString) = 'ABC';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.Filter_12(Dataset: TDataset; var Accept: Boolean);
|
||||||
|
begin
|
||||||
|
Accept := Dataset.FieldByName(STRING_FIELD).AsString = 'ä';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.Filter_13(Dataset: TDataset; var Accept: Boolean);
|
||||||
|
begin
|
||||||
|
Accept := Dataset.FieldByName(STRING_FIELD).AsString >= 'α';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.Filter_20(Dataset: TDataset; var Accept: Boolean);
|
||||||
|
begin
|
||||||
|
Accept := Dataset.FieldByName(WIDESTRING_FIELD).AsWideString = WideString('wABC');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.Filter_21(Dataset: TDataset; var Accept: Boolean);
|
||||||
|
begin
|
||||||
|
Accept := Uppercase(Dataset.FieldByName(WIDESTRING_FIELD).AsWideString) = WideString('WABC');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.Filter_22(Dataset: TDataset; var Accept: Boolean);
|
||||||
|
begin
|
||||||
|
Accept := Dataset.FieldByName(WIDESTRING_FIELD).AsWideString = WideString('wä');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFilterTest.CreateAndOpenDataset: TsWorksheetDataset;
|
||||||
|
begin
|
||||||
|
Result := TsWorksheetDataset.Create(nil);
|
||||||
|
Result.FileName := DataFileName;
|
||||||
|
Result.SheetName := SHEET_NAME;
|
||||||
|
Result.AutoFieldDefs := false;
|
||||||
|
Result.AddFieldDef(INT_FIELD, ftInteger);
|
||||||
|
Result.AddFieldDef(STRING_FIELD, ftString, 20);
|
||||||
|
Result.AddFieldDef(WIDESTRING_FIELD, ftWideString, 20);
|
||||||
|
Result.CreateTable;
|
||||||
|
Result.Open;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest(TestIndex: Integer);
|
||||||
|
var
|
||||||
|
dataset: TsWorksheetDataset;
|
||||||
|
intField: TField;
|
||||||
|
stringField: TField;
|
||||||
|
widestringField: TField;
|
||||||
|
actualInt: Integer;
|
||||||
|
actualString: String;
|
||||||
|
actualWideString: WideString;
|
||||||
|
expectedInt: Integer;
|
||||||
|
expectedString: String;
|
||||||
|
expectedWideString: WideString;
|
||||||
|
expectedRecordCount: Integer;
|
||||||
|
i, idx: Integer;
|
||||||
|
begin
|
||||||
|
dataset := CreateAndOpenDataset;
|
||||||
|
try
|
||||||
|
dataset.Filter := '';
|
||||||
|
dataset.OnFilterRecord := nil;
|
||||||
|
case TestIndex of
|
||||||
|
// Tests using the Filter property
|
||||||
|
1: dataset.Filter := EXPRESSION_01; // Integer test
|
||||||
|
10: dataset.Filter := EXPRESSION_10; // String tests
|
||||||
|
11: dataset.Filter := EXPRESSION_11;
|
||||||
|
12: dataset.Filter := EXPRESSION_12;
|
||||||
|
13: dataset.Filter := EXPRESSION_13;
|
||||||
|
20: dataset.Filter := EXPRESSION_20; // widestring tests
|
||||||
|
21: dataset.Filter := EXPRESSION_21;
|
||||||
|
22: dataset.Filter := EXPRESSION_22;
|
||||||
|
// Tests using the OnFilterRecord event
|
||||||
|
101: dataset.OnFilterRecord := @Filter_01;
|
||||||
|
110: dataset.OnFilterRecord := @Filter_10;
|
||||||
|
111: dataset.OnFilterRecord := @Filter_11;
|
||||||
|
112: dataset.OnFilterRecord := @Filter_12;
|
||||||
|
113: dataset.OnFilterRecord := @Filter_13;
|
||||||
|
120: dataset.OnFilterRecord := @Filter_20;
|
||||||
|
121: dataset.OnFilterRecord := @Filter_21;
|
||||||
|
122: dataset.OnFilterRecord := @Filter_22;
|
||||||
|
end;
|
||||||
|
dataset.Filtered := true;
|
||||||
|
|
||||||
|
case (TestIndex mod 100) of
|
||||||
|
1: expectedRecordCount := Length(FILTERED_01);
|
||||||
|
10: expectedRecordCount := Length(FILTERED_10);
|
||||||
|
11: expectedRecordCount := Length(FILTERED_11);
|
||||||
|
12: expectedRecordCount := Length(FILTERED_12);
|
||||||
|
13: expectedRecordCount := Length(FILTERED_13);
|
||||||
|
20: expectedRecordCount := Length(FILTERED_20);
|
||||||
|
21: expectedRecordCount := Length(FILTERED_21);
|
||||||
|
22: expectedRecordCount := Length(FILTERED_22);
|
||||||
|
end;
|
||||||
|
|
||||||
|
intField := dataset.FieldByName(INT_FIELD);
|
||||||
|
stringField := dataset.FieldByName(STRING_FIELD);
|
||||||
|
wideStringField := dataset.FieldByName(WIDESTRING_FIELD);
|
||||||
|
|
||||||
|
dataset.First;
|
||||||
|
i := 0;
|
||||||
|
while not dataset.EOF do
|
||||||
|
begin
|
||||||
|
CheckEquals(true, i < expectedRecordCount, 'Record count mismatch.');
|
||||||
|
|
||||||
|
case TestIndex mod 100 of
|
||||||
|
1: idx := FILTERED_01[i];
|
||||||
|
10: idx := FILTERED_10[i];
|
||||||
|
11: idx := FILTERED_11[i];
|
||||||
|
12: idx := FILTERED_12[i];
|
||||||
|
13: idx := FILTERED_13[i];
|
||||||
|
20: idx := FILTERED_20[i];
|
||||||
|
21: idx := FILTERED_21[i];
|
||||||
|
22: idx := FILTERED_22[i];
|
||||||
|
end;
|
||||||
|
|
||||||
|
actualInt := intField.AsInteger;
|
||||||
|
actualString := stringField.AsString;
|
||||||
|
actualWideString := wideStringField.AsWideString;
|
||||||
|
|
||||||
|
expectedInt := UNFILTERED[idx].IntValue;
|
||||||
|
expectedString := UNFILTERED[idx].StringValue;
|
||||||
|
expectedWideString := UNFILTERED[idx].WideStringValue;
|
||||||
|
|
||||||
|
CheckEquals(
|
||||||
|
expectedInt,
|
||||||
|
actualInt,
|
||||||
|
'Integer field value mismatch in row ' + IntToStr(i)
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
expectedString,
|
||||||
|
actualString,
|
||||||
|
'String field value mismatch in row ' + IntToStr(i)
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
expectedWideString,
|
||||||
|
actualWideString,
|
||||||
|
'Widestring field value mismatch in row ' + IntToStr(i)
|
||||||
|
);
|
||||||
|
|
||||||
|
inc(i);
|
||||||
|
dataset.Next;
|
||||||
|
end;
|
||||||
|
|
||||||
|
CheckEquals(true, i = expectedRecordCount, 'Record count mismatch.');
|
||||||
|
|
||||||
|
finally
|
||||||
|
dataset.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_01_Int;
|
||||||
|
begin
|
||||||
|
FilterTest(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_10_String;
|
||||||
|
begin
|
||||||
|
FilterTest(10);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_11_UpperString;
|
||||||
|
begin
|
||||||
|
FilterTest(11);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_12_StringUTF8;
|
||||||
|
begin
|
||||||
|
FilterTest(12);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_13_StringUTF8;
|
||||||
|
begin
|
||||||
|
FilterTest(13);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_ByEvent_101_Int;
|
||||||
|
begin
|
||||||
|
FilterTest(101);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_ByEvent_110_String;
|
||||||
|
begin
|
||||||
|
FilterTest(110);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_ByEvent_111_UpperString;
|
||||||
|
begin
|
||||||
|
FilterTest(111);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_ByEvent_112_String_UTF8;
|
||||||
|
begin
|
||||||
|
FilterTest(112);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_ByEvent_113_String_UTF8;
|
||||||
|
begin
|
||||||
|
FilterTest(113);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_ByEvent_120_WideString;
|
||||||
|
begin
|
||||||
|
FilterTest(120);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_ByEvent_121_UpperWideString;
|
||||||
|
begin
|
||||||
|
FilterTest(121);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.FilterTest_ByEvent_122_WideString_UTF8;
|
||||||
|
begin
|
||||||
|
FilterTest(122);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.SetUp;
|
||||||
|
var
|
||||||
|
i, r: Integer;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
worksheet: TsWorksheet;
|
||||||
|
begin
|
||||||
|
// Create test spreadsheet file
|
||||||
|
workbook := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
// Create worksheet
|
||||||
|
worksheet := workbook.AddWorkSheet(SHEET_NAME);
|
||||||
|
|
||||||
|
// Write headers (= field names)
|
||||||
|
worksheet.WriteText(0, INT_COL, INT_FIELD);
|
||||||
|
worksheet.WriteText(0, STRING_COL, STRING_FIELD);
|
||||||
|
worksheet.WriteText(0, WIDESTRING_COL, WIDESTRING_FIELD);
|
||||||
|
|
||||||
|
// Write values
|
||||||
|
for i := Low(UNFILTERED) to High(UNFILTERED) do
|
||||||
|
begin
|
||||||
|
r := 1 + (i - Low(UNFILTERED));
|
||||||
|
worksheet.WriteNumber(r, INT_COL, UNFILTERED[i].IntValue, nfFixed, 0);
|
||||||
|
worksheet.WriteText(r, STRING_COL, UNFILTERED[i].StringValue);
|
||||||
|
worksheet.WriteText(r, WIDESTRING_COL, UNFILTERED[i].WideStringValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Save
|
||||||
|
DataFileName := GetTempDir + FILE_NAME;
|
||||||
|
workbook.WriteToFile(DataFileName, true);
|
||||||
|
finally
|
||||||
|
workbook.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFilterTest.TearDown;
|
||||||
|
begin
|
||||||
|
if FileExists(DataFileName) then DeleteFile(DataFileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
initialization
|
||||||
|
RegisterTest(TFilterTest);
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
216
components/fpspreadsheet/unit-tests/dataset/posttestunit.pas
Normal file
216
components/fpspreadsheet/unit-tests/dataset/posttestunit.pas
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
{ - Creates a new WorksheetDataset with a variety of fields
|
||||||
|
- Appends a record and posts the dataset
|
||||||
|
- Opens the created spreadsheet file and compares its cells with the
|
||||||
|
posted data.
|
||||||
|
}
|
||||||
|
|
||||||
|
unit PostTestUnit;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testregistry,
|
||||||
|
DB,
|
||||||
|
fpsdataset, fpspreadsheet, fpstypes, fpsutils;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TPostTest= class(TTestCase)
|
||||||
|
protected
|
||||||
|
procedure RunPostTest(ADataType: TFieldType; ASize: Integer = 0);
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
published
|
||||||
|
procedure PostTest_Int;
|
||||||
|
procedure PostTest_String_20;
|
||||||
|
procedure PostTest_String_10;
|
||||||
|
procedure PostTest_Widestring_20;
|
||||||
|
procedure PostTest_Widestring_10;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
LazUTF8, LazUTF16;
|
||||||
|
|
||||||
|
const
|
||||||
|
FILE_NAME = 'testfile.xls';
|
||||||
|
SHEET_NAME = 'Sheet';
|
||||||
|
COL_NAME = 'TestCol';
|
||||||
|
|
||||||
|
var
|
||||||
|
DataFileName: String;
|
||||||
|
|
||||||
|
type
|
||||||
|
TTestRecord = record
|
||||||
|
IntValue: Integer;
|
||||||
|
StringValue: String;
|
||||||
|
WideStringValue: WideString;
|
||||||
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
TestData: Array[0..5] of TTestRecord = (
|
||||||
|
(IntValue: 10; StringValue: 'abc'; WideStringValue: 'abc'), // 0
|
||||||
|
(IntValue: -20; StringValue: 'äöüαβγ'; WideStringvalue: 'äöüαβγ'), // 1
|
||||||
|
(IntValue: 100; StringValue: 'a234567890'; WideStringvalue: 'a234567890'), // 2
|
||||||
|
(IntValue: 0; StringValue: 'a234567890123'; WideStringvalue: 'a234567890123'), // 3
|
||||||
|
(IntValue: 501; StringValue: 'äα34567890'; WideStringValue: 'äα34567890'), // 4
|
||||||
|
(IntValue: 502; StringValue: 'äα34567890123'; WideStringValue: 'äα34567890123') // 5
|
||||||
|
);
|
||||||
|
|
||||||
|
procedure TPostTest.RunPostTest(ADataType: TFieldType; ASize: Integer = 0);
|
||||||
|
var
|
||||||
|
dataset: TsWorksheetDataset;
|
||||||
|
field: TField;
|
||||||
|
i: Integer;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
worksheet: TsWorksheet;
|
||||||
|
row, lastRow: Integer;
|
||||||
|
actualIntValue: Integer;
|
||||||
|
actualStringValue: String;
|
||||||
|
actualWideStringValue: WideString;
|
||||||
|
expectedIntValue: Integer;
|
||||||
|
expectedStringValue: String;
|
||||||
|
expectedWideStringValue: WideString;
|
||||||
|
begin
|
||||||
|
dataset := TsWorksheetDataset.Create(nil);
|
||||||
|
try
|
||||||
|
dataset.FileName := DataFileName;
|
||||||
|
dataset.SheetName := SHEET_NAME;
|
||||||
|
dataset.AddFieldDef(COL_NAME, ADataType, ASize);
|
||||||
|
dataset.CreateTable;
|
||||||
|
dataset.Open;
|
||||||
|
|
||||||
|
field := dataset.FieldByName(COL_NAME);
|
||||||
|
for i := 0 to High(TestData) do
|
||||||
|
begin
|
||||||
|
dataset.Append;
|
||||||
|
case ADataType of
|
||||||
|
ftInteger : field.AsInteger := TestData[i].IntValue;
|
||||||
|
ftString : field.AsString := TestData[i].StringValue;
|
||||||
|
ftWideString : field.AsString := UTF8Decode(TestData[i].WideStringValue);
|
||||||
|
end;
|
||||||
|
dataset.Post;
|
||||||
|
end;
|
||||||
|
dataset.Close;
|
||||||
|
finally
|
||||||
|
dataset.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
CheckEquals(
|
||||||
|
true,
|
||||||
|
FileExists(DatafileName),
|
||||||
|
'Spreadsheet data file not found'
|
||||||
|
);
|
||||||
|
|
||||||
|
workbook := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
workbook.ReadFromFile(DataFileName);
|
||||||
|
worksheet := workbook.GetWorksheetByName(SHEET_NAME);
|
||||||
|
CheckEquals(
|
||||||
|
true,
|
||||||
|
worksheet <> nil,
|
||||||
|
'Worksheet not found'
|
||||||
|
);
|
||||||
|
|
||||||
|
lastRow := worksheet.GetLastRowIndex(true);
|
||||||
|
CheckEquals(
|
||||||
|
Length(TestData),
|
||||||
|
lastRow,
|
||||||
|
'Row count mismatch in worksheet'
|
||||||
|
);
|
||||||
|
|
||||||
|
actualStringValue := worksheet.ReadAsText(0, 0);
|
||||||
|
CheckEquals(
|
||||||
|
COL_NAME,
|
||||||
|
actualStringValue,
|
||||||
|
'Column name mismatch'
|
||||||
|
);
|
||||||
|
|
||||||
|
i := 0;
|
||||||
|
for row := 1 to lastRow do
|
||||||
|
begin
|
||||||
|
case ADataType of
|
||||||
|
ftInteger:
|
||||||
|
begin
|
||||||
|
expectedIntValue := TestData[i].IntValue;
|
||||||
|
actualIntValue := Round(worksheet.ReadAsNumber(row, 0));
|
||||||
|
CheckEquals(
|
||||||
|
expectedIntValue,
|
||||||
|
actualIntValue,
|
||||||
|
'Integer field mismatch, row ' + IntToStr(row)
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
ftString:
|
||||||
|
begin
|
||||||
|
expectedStringValue := UTF8Copy(TestData[i].StringValue, 1, ASize);
|
||||||
|
actualStringValue := worksheet.ReadAsText(row, 0);
|
||||||
|
CheckEquals(
|
||||||
|
expectedStringValue,
|
||||||
|
actualStringValue,
|
||||||
|
'String field mismatch, Row ' + IntToStr(row)
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
ftWideString:
|
||||||
|
begin
|
||||||
|
expectedWideStringValue := UTF16Copy(TestData[i].WideStringValue, 1, ASize);
|
||||||
|
actualWideStringValue := UTF8Decode(worksheet.ReadAsText(row, 0));
|
||||||
|
CheckEquals(
|
||||||
|
expectedWidestringValue,
|
||||||
|
actualWideStringValue,
|
||||||
|
'Widestring field mismatch, row ' + IntToStr(row)
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
raise Exception.Create('Field type not tested here.');
|
||||||
|
end;
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
workbook.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPostTest.PostTest_Int;
|
||||||
|
begin
|
||||||
|
RunPostTest(ftInteger);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPostTest.PostTest_String_20;
|
||||||
|
begin
|
||||||
|
RunPostTest(ftString, 20);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPostTest.PostTest_String_10;
|
||||||
|
begin
|
||||||
|
RunPostTest(ftString, 10);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPostTest.PostTest_WideString_20;
|
||||||
|
begin
|
||||||
|
RunPostTest(ftWideString, 20);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPostTest.PostTest_WideString_10;
|
||||||
|
begin
|
||||||
|
RunPostTest(ftWideString, 10);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPostTest.SetUp;
|
||||||
|
begin
|
||||||
|
DataFileName := GetTempDir + FILE_NAME;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPostTest.TearDown;
|
||||||
|
begin
|
||||||
|
if FileExists(DataFileName) then DeleteFile(DataFileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
initialization
|
||||||
|
RegisterTest(TPostTest);
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -0,0 +1,442 @@
|
|||||||
|
unit ReadFieldsTestUnit;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
{$IF FPC_FullVersion >= 30300}
|
||||||
|
{$DEFINE TEST_BYTE_FIELD}
|
||||||
|
{$IFEND}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testutils, testregistry,
|
||||||
|
DB,
|
||||||
|
fpspreadsheet, fpstypes, fpsdataset;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TReadFieldsTest= class(TTestCase)
|
||||||
|
private
|
||||||
|
function CreateAndOpenDataset(AutoFieldDefs: Boolean): TsWorksheetDataset;
|
||||||
|
procedure ReadFieldTest(Col: Integer; FieldName: String; AutoFieldDefs: Boolean);
|
||||||
|
protected
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
published
|
||||||
|
procedure ReadIntegerField;
|
||||||
|
{$IFDEF TEST_BYTE_FIELD}
|
||||||
|
procedure ReadByteField;
|
||||||
|
{$IFEND}
|
||||||
|
procedure ReadWordField;
|
||||||
|
procedure ReadFloatField;
|
||||||
|
procedure ReadCurrencyField;
|
||||||
|
procedure ReadBCDField;
|
||||||
|
procedure ReadFmtBCDField;
|
||||||
|
procedure ReadStringField;
|
||||||
|
procedure ReadMemoField;
|
||||||
|
procedure ReadBoolField;
|
||||||
|
procedure ReadDateField;
|
||||||
|
procedure ReadTimeField;
|
||||||
|
procedure ReadDateTimeField;
|
||||||
|
|
||||||
|
procedure ReadIntegerField_AutoFieldDefs;
|
||||||
|
procedure ReadByteField_AutoFieldDefs;
|
||||||
|
procedure ReadWordField_AutoFieldDefs;
|
||||||
|
procedure ReadFloatField_AutoFieldDefs;
|
||||||
|
procedure ReadCurrencyField_AutoFieldDefs;
|
||||||
|
procedure ReadStringField_AutoFieldDefs;
|
||||||
|
procedure ReadMemoField_AutoFieldDefs;
|
||||||
|
procedure ReadBoolField_AutoFieldDefs;
|
||||||
|
procedure ReadDateField_AutoFieldDefs;
|
||||||
|
procedure ReadTimeField_AutoFieldDefs;
|
||||||
|
procedure ReadDateTimeField_AutoFieldDefs;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
const
|
||||||
|
FILE_NAME = 'testfile.xlsx';
|
||||||
|
SHEET_NAME = 'Sheet';
|
||||||
|
|
||||||
|
INT_COL = 0;
|
||||||
|
BYTE_COL = 1;
|
||||||
|
WORD_COL = 2;
|
||||||
|
FLOAT_COL = 3;
|
||||||
|
CURRENCY_COL = 4;
|
||||||
|
BCD_COL = 5;
|
||||||
|
FMTBCD_COL = 6;
|
||||||
|
STRING_COL = 7;
|
||||||
|
BOOL_COL = 8;
|
||||||
|
DATE_COL = 9;
|
||||||
|
TIME_COL = 10;
|
||||||
|
DATETIME_COL = 11;
|
||||||
|
MEMO_COL = 12;
|
||||||
|
|
||||||
|
TestText: array[0..3] of string = (
|
||||||
|
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua',
|
||||||
|
'At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet',
|
||||||
|
'Статья 1 Все люди рождаются свободными и равными в своем достоинстве и правах.',
|
||||||
|
'ϰαὶ τότ'' ἐγὼ Κύϰλωπα προσηύδων ἄγχι παραστάς, '
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
var
|
||||||
|
DataFileName: String;
|
||||||
|
|
||||||
|
function TReadFieldsTest.CreateAndOpenDataset(AutoFieldDefs: Boolean): TsWorksheetDataset;
|
||||||
|
begin
|
||||||
|
Result := TsWorksheetDataset.Create(nil);
|
||||||
|
Result.AutoFieldDefs:= true;
|
||||||
|
Result.FileName := DataFileName;
|
||||||
|
Result.SheetName := SHEET_NAME;
|
||||||
|
Result.AutoFieldDefs := AutoFieldDefs;
|
||||||
|
if not AutoFieldDefs then
|
||||||
|
begin
|
||||||
|
Result.AddFieldDef('IntCol', ftInteger);
|
||||||
|
{$IFDEF TEST_BYTE_FIELD}
|
||||||
|
Result.AddFieldDef('ByteCol', ftByte);
|
||||||
|
{$ELSE}
|
||||||
|
Result.AddFieldDef('ByteCol', ftInteger); // No ftByte in too old FPC
|
||||||
|
{$ENDIF}
|
||||||
|
Result.AddFieldDef('WordCol', ftWord);
|
||||||
|
Result.AddFieldDef('FloatCol', ftFloat);
|
||||||
|
Result.AddFieldDef('CurrencyCol', ftCurrency);
|
||||||
|
Result.AddFieldDef('BCDCol', ftBCD);
|
||||||
|
Result.AddFieldDef('FmtBCDCol', ftFmtBCD);
|
||||||
|
Result.AddFieldDef('StringCol', ftString, 30);
|
||||||
|
Result.AddFieldDef('BoolCol', ftBoolean);
|
||||||
|
Result.AddFieldDef('DateCol', ftDate);
|
||||||
|
Result.AddFieldDef('TimeCol', ftTime);
|
||||||
|
Result.AddFieldDef('DateTimeCol', ftDateTime);
|
||||||
|
Result.AddFieldDef('MemoCol', ftMemo);
|
||||||
|
Result.CreateTable;
|
||||||
|
end;
|
||||||
|
Result.Open;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.SetUp;
|
||||||
|
const
|
||||||
|
NumRows = 10;
|
||||||
|
var
|
||||||
|
r: Integer;
|
||||||
|
s: String;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
worksheet: TsWorksheet;
|
||||||
|
begin
|
||||||
|
// Create test spreadsheet file
|
||||||
|
workbook := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
// Create worksheet
|
||||||
|
worksheet := workbook.AddWorkSheet(SHEET_NAME);
|
||||||
|
// Write headers (= field names)
|
||||||
|
worksheet.WriteText(0, INT_COL, 'IntCol');
|
||||||
|
worksheet.WriteText(0, BYTE_COL, 'ByteCol');
|
||||||
|
worksheet.WriteText(0, WORD_COL, 'WordCol');
|
||||||
|
worksheet.WriteText(0, FLOAT_COL, 'FloatCol');
|
||||||
|
worksheet.WriteText(0, CURRENCY_COL, 'CurrencyCol');
|
||||||
|
worksheet.WriteText(0, BCD_COL, 'BCDCol');
|
||||||
|
worksheet.WriteText(0, FMTBCD_Col, 'FmtBCDCol');
|
||||||
|
worksheet.WriteText(0, STRING_COL, 'StringCol');
|
||||||
|
worksheet.WriteText(0, BOOL_COL, 'BoolCol');
|
||||||
|
worksheet.WriteText(0, DATE_COL, 'DateCol');
|
||||||
|
worksheet.WriteText(0, TIME_COL, 'TimeCol');
|
||||||
|
worksheet.WriteText(0, DATETIME_COL, 'DateTimeCol');
|
||||||
|
worksheet.Writetext(0, MEMO_COL, 'MemoCol');
|
||||||
|
for r := 1 to NumRows do begin
|
||||||
|
// Write values to IntCol
|
||||||
|
worksheet.WriteNumber(r, INT_COL, r*120- 50, nfFixed, 0);
|
||||||
|
// Write values to ByteCol
|
||||||
|
worksheet.WriteNumber(r, BYTE_COL, r*2, nfFixed, 0);
|
||||||
|
//Write values to WordCol
|
||||||
|
worksheet.WriteNumber(r, WORD_COL, r*3, nfFixed, 0);
|
||||||
|
// Write values to FloatCol
|
||||||
|
worksheet.WriteNumber(r, FLOAT_COL, r*1.1-5.1, nfFixed, 2);
|
||||||
|
// Write values to CurrencyCol
|
||||||
|
worksheet.WriteCurrency(r, CURRENCY_COL, r*1000, nfCurrency);
|
||||||
|
// Write values to BCDcol
|
||||||
|
worksheet.WriteNumber(r, BCD_COL, r*1.2-3);
|
||||||
|
// Write values to FmtBCDCol
|
||||||
|
worksheet.WriteNumber(r, FMTBCD_COL, r*12.3-60);
|
||||||
|
// Write values to StringCol
|
||||||
|
case r of
|
||||||
|
1: s := 'Статья';
|
||||||
|
2: s := 'Λορεμ ιπσθμ δολορ σιτ αμετ';
|
||||||
|
else s := char(ord('A') + r-1) + char(ord('b') + r-1) + char(ord('c') + r-1);
|
||||||
|
end;
|
||||||
|
worksheet.WriteText(r, STRING_COL, s);
|
||||||
|
// Write values to BoolCol
|
||||||
|
worksheet.WriteBoolValue(r, BOOL_COL, odd(r));
|
||||||
|
// Write values to DateCol
|
||||||
|
worksheet.WriteDateTime(r, DATE_COL, EncodeDate(2021, 8, 1) + r-1, nfShortDate);
|
||||||
|
// Write values to TimeCol
|
||||||
|
worksheet.WriteDateTime(r, TIME_COL, EncodeTime(8, 0, 0, 0) + (r-1) / (24*60), nfShortTime);
|
||||||
|
// Write value to DateTimeCol
|
||||||
|
worksheet.WriteDateTime(r, DATETIME_COL, EncodeDate(2021, 8, 1) + EncodeTime(8, 0, 0, 0) + (r-1) + (r-1)/24, nfShortDateTime);
|
||||||
|
// Write value to MemoCol
|
||||||
|
worksheet.WriteText(r, MEMO_COL, TestText[r mod Length(TestText)]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Save
|
||||||
|
DataFileName := GetTempDir + FILE_NAME;
|
||||||
|
workbook.WriteToFile(DataFileName, true);
|
||||||
|
finally
|
||||||
|
workbook.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.TearDown;
|
||||||
|
begin
|
||||||
|
if FileExists(DataFileName) then DeleteFile(DataFileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadFieldTest(Col: Integer; FieldName: String;
|
||||||
|
AutoFieldDefs: Boolean);
|
||||||
|
const
|
||||||
|
FLOAT_EPS = 1E-9;
|
||||||
|
var
|
||||||
|
dataset: TDataset;
|
||||||
|
row: Integer;
|
||||||
|
f: TField;
|
||||||
|
dt: TDateTime;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
worksheet: TsWorksheet;
|
||||||
|
n: Integer;
|
||||||
|
begin
|
||||||
|
dataset := CreateAndOpenDataset(AutoFieldDefs);
|
||||||
|
try
|
||||||
|
workbook := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
workbook.ReadFromFile(DataFileName);
|
||||||
|
worksheet := workbook.GetFirstWorksheet;
|
||||||
|
|
||||||
|
f := dataset.FieldByName(FieldName);
|
||||||
|
|
||||||
|
CheckEquals(
|
||||||
|
worksheet.ReadAsText(0, col),
|
||||||
|
f.FieldName,
|
||||||
|
'Column header / FieldName mismatch'
|
||||||
|
);
|
||||||
|
|
||||||
|
CheckEquals(
|
||||||
|
col,
|
||||||
|
f.FieldNo-1,
|
||||||
|
'Field number mismatch'
|
||||||
|
);
|
||||||
|
|
||||||
|
CheckEquals(
|
||||||
|
worksheet.GetLastRowIndex(true),
|
||||||
|
dataset.RecordCount,
|
||||||
|
'Row count / record count mismatch'
|
||||||
|
);
|
||||||
|
|
||||||
|
dataset.First;
|
||||||
|
row := 1;
|
||||||
|
while not dataset.EoF do
|
||||||
|
begin
|
||||||
|
if (f.DataType in [ftString, ftWideString, ftMemo]) then
|
||||||
|
CheckEquals(
|
||||||
|
worksheet.ReadAsText(row, col),
|
||||||
|
f.AsString,
|
||||||
|
'Text mismatch in row ' + IntToStr(row)
|
||||||
|
)
|
||||||
|
else
|
||||||
|
if (f.DataType in [
|
||||||
|
ftInteger, {$IFDEF TEST_BYTE_FIELD}ftByte, {$ENDIF}
|
||||||
|
ftWord, ftSmallInt, ftLargeInt])
|
||||||
|
then
|
||||||
|
CheckEquals(
|
||||||
|
round(worksheet.ReadAsNumber(row, col)),
|
||||||
|
f.AsInteger,
|
||||||
|
'Integer value mismatch in row ' + IntToStr(row)
|
||||||
|
)
|
||||||
|
else if (f.DataType in [ftFloat, ftCurrency, ftBCD, ftFmtBCD]) then
|
||||||
|
CheckEquals(
|
||||||
|
worksheet.ReadAsNumber(row, col),
|
||||||
|
f.AsFloat,
|
||||||
|
FLOAT_EPS,
|
||||||
|
'Float value mismatch in row ' + IntToStr(row)
|
||||||
|
)
|
||||||
|
else if (f.DataType = ftDate) then
|
||||||
|
begin
|
||||||
|
CheckEquals(
|
||||||
|
true,
|
||||||
|
worksheet.ReadAsDateTime(row, col, dt),
|
||||||
|
'Invalid date in row ' + IntToStr(row)
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
dt,
|
||||||
|
f.AsDateTime,
|
||||||
|
FLOAT_EPS,
|
||||||
|
'Date value mismatch in row ' + IntToStr(row)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
else if (f.DataType = ftTime) then
|
||||||
|
begin
|
||||||
|
CheckEquals(
|
||||||
|
true,
|
||||||
|
worksheet.ReadAsDateTime(row, col, dt),
|
||||||
|
'Invalid time in row ' + IntToStr(row)
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
dt,
|
||||||
|
f.AsDateTime,
|
||||||
|
FLOAT_EPS,
|
||||||
|
'Time value mismatch in row ' + IntToStr(row)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
else if (f.DataType = ftDateTime) then
|
||||||
|
begin
|
||||||
|
CheckEquals(
|
||||||
|
true,
|
||||||
|
worksheet.ReadAsDateTime(row, col, dt),
|
||||||
|
'Invalid date/time in row ' + IntToStr(row)
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
dt,
|
||||||
|
f.AsDateTime,
|
||||||
|
FLOAT_EPS,
|
||||||
|
'Date/time value mismatch in row ' + IntToStr(row)
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
inc(row);
|
||||||
|
dataset.Next;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
workbook.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
dataset.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadIntegerField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(INT_COL, 'IntCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadByteField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(BYTE_COL, 'ByteCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadWordField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(WORD_COL, 'WordCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadFloatField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(FLOAT_COL, 'FloatCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadCurrencyField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(CURRENCY_COL, 'CurrencyCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadStringField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(STRING_COL, 'StringCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadMemoField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(MEMO_COL, 'MemoCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadBoolField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(BOOL_COL, 'BoolCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadDateField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(DATE_COL, 'DateCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadTimeField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(TIME_COL, 'TimeCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadDateTimeField_AutoFieldDefs;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(DATETIME_COL, 'DateTimeCol', true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadIntegerField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(INT_COL, 'IntCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$IFDEF TEST_BYTE_FIELD}
|
||||||
|
procedure TReadFieldsTest.ReadByteField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(BYTE_COL, 'ByteCol', false);
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadWordField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(WORD_COL, 'WordCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadFloatField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(FLOAT_COL, 'FloatCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadCurrencyField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(CURRENCY_COL, 'CurrencyCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadBCDField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(BCD_COL, 'BCDCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadFmtBCDField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(FMTBCD_COL, 'FmtBCDCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadStringField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(STRING_COL, 'StringCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadMemoField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(MEMO_COL, 'MemoCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadBoolField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(BOOL_COL, 'BoolCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadDateField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(DATE_COL, 'DateCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadTimeField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(TIME_COL, 'TimeCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TReadFieldsTest.ReadDateTimeField;
|
||||||
|
begin
|
||||||
|
ReadFieldTest(DATETIME_COL, 'DateTimeCol', false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
initialization
|
||||||
|
RegisterTest(TReadFieldsTest);
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
456
components/fpspreadsheet/unit-tests/dataset/searchtestunit.pas
Normal file
456
components/fpspreadsheet/unit-tests/dataset/searchtestunit.pas
Normal file
@ -0,0 +1,456 @@
|
|||||||
|
unit SearchTestUnit;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testutils, testregistry,
|
||||||
|
DB,
|
||||||
|
fpspreadsheet, fpsTypes, fpsDataset;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TSearchTest = class(TTestCase)
|
||||||
|
private
|
||||||
|
function CreateAndOpenDataset: TsWorksheetDataset;
|
||||||
|
procedure LocateTest(SearchInField: String; SearchValue: Variant;
|
||||||
|
ExpectedRecNo: Integer; Options: TLocateOptions = []);
|
||||||
|
procedure LookupTest(SearchInField: String; SearchValue: Variant;
|
||||||
|
ResultFields: String; ExpectedValues: Variant);
|
||||||
|
|
||||||
|
protected
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
|
||||||
|
published
|
||||||
|
procedure LocateTest_Int_Found;
|
||||||
|
procedure LocateTest_Int_NotFound;
|
||||||
|
procedure LocateTest_String_Found;
|
||||||
|
procedure LocateTest_String_Found_CaseInsensitive;
|
||||||
|
procedure LocateTest_String_NotFound;
|
||||||
|
procedure LocateTest_NonASCIIString_Found;
|
||||||
|
procedure LocateTest_NonASCIIString_Found_CaseInsensitive;
|
||||||
|
procedure LocateTest_NonASCIIString_NotFound;
|
||||||
|
procedure LocateTest_WideString_Found;
|
||||||
|
procedure LocateTest_WideString_Found_CaseInsensitive;
|
||||||
|
procedure LocateTest_WideString_NotFound;
|
||||||
|
procedure LocateTest_NonASCIIWideString_Found;
|
||||||
|
procedure LocateTest_NonASCIIWideString_Found_CaseInsensitive;
|
||||||
|
procedure LocateTest_NonASCIIWideString_NotFound;
|
||||||
|
|
||||||
|
procedure LookupTest_Int_Found;
|
||||||
|
procedure LookupTest_Int_NotFound;
|
||||||
|
procedure LookupTest_String_Found;
|
||||||
|
procedure LookupTest_String_NotFound;
|
||||||
|
procedure LookupTest_NonASCIIString_Found;
|
||||||
|
procedure LookupTest_NonASCIIString_NotFound;
|
||||||
|
procedure LookupTest_WideString_Found;
|
||||||
|
procedure LookupTest_WideString_NotFound;
|
||||||
|
procedure LookupTest_NonASCIIWideString_Found;
|
||||||
|
procedure LookupTest_NonASCIIWideString_NotFound;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
Variants, LazUTF8;
|
||||||
|
|
||||||
|
const
|
||||||
|
FILE_NAME = 'testfile.xlsx';
|
||||||
|
SHEET_NAME = 'Sheet';
|
||||||
|
INT_COL = 0;
|
||||||
|
STRING_COL = 1;
|
||||||
|
WIDESTRING_COL = 2;
|
||||||
|
INT_FIELD = 'IntCol';
|
||||||
|
STRING_FIELD = 'StringCol';
|
||||||
|
WIDESTRING_FIELD = 'WideStringCol';
|
||||||
|
|
||||||
|
var
|
||||||
|
DataFileName: String;
|
||||||
|
|
||||||
|
const
|
||||||
|
NUM_ROWS = 5;
|
||||||
|
var
|
||||||
|
INT_VALUES: array[1..NUM_ROWS] of Integer = (
|
||||||
|
12, 20, -10, 83, 3
|
||||||
|
);
|
||||||
|
STRING_VALUES: array[1..NUM_ROWS] of String = (
|
||||||
|
'abc', 'a', 'Hallo', 'ijk', 'äöüαβγ'
|
||||||
|
);
|
||||||
|
WIDESTRING_VALUES: array[1..NUM_ROWS] of String = ( // Strings are converted to wide at runtime
|
||||||
|
'ABC', 'A', 'Test', 'ÄöüΓ', 'xyz'
|
||||||
|
);
|
||||||
|
|
||||||
|
function TSearchTest.CreateAndOpenDataset: TsWorksheetDataset;
|
||||||
|
begin
|
||||||
|
Result := TsWorksheetDataset.Create(nil);
|
||||||
|
Result.FileName := DataFileName;
|
||||||
|
Result.SheetName := SHEET_NAME;
|
||||||
|
Result.AutoFieldDefs := false;
|
||||||
|
Result.AddFieldDef(INT_FIELD, ftInteger);
|
||||||
|
Result.AddFieldDef(STRING_FIELD, ftString, 20);
|
||||||
|
Result.AddFieldDef(WIDESTRING_FIELD, ftWideString, 20);
|
||||||
|
Result.Open;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest(SearchInField: String; SearchValue: Variant;
|
||||||
|
ExpectedRecNo: Integer; Options: TLocateOptions = []);
|
||||||
|
var
|
||||||
|
dataset: TsWorksheetDataset;
|
||||||
|
actualRecNo: Integer;
|
||||||
|
found: Boolean;
|
||||||
|
f: TField;
|
||||||
|
begin
|
||||||
|
dataset := CreateAndOpenDataset;
|
||||||
|
try
|
||||||
|
found := dataset.Locate(SearchInField, SearchValue, options);
|
||||||
|
|
||||||
|
if ExpectedRecNo = -1 then
|
||||||
|
CheckEquals(
|
||||||
|
false,
|
||||||
|
found,
|
||||||
|
'Record found unexpectedly.'
|
||||||
|
)
|
||||||
|
else
|
||||||
|
CheckEquals(
|
||||||
|
true,
|
||||||
|
found,
|
||||||
|
'Existing record not found.'
|
||||||
|
);
|
||||||
|
|
||||||
|
if found then
|
||||||
|
begin
|
||||||
|
actualRecNo := dataset.RecNo;
|
||||||
|
CheckEquals(
|
||||||
|
ExpectedRecNo,
|
||||||
|
actualRecNo,
|
||||||
|
'Mismatch of found RecNo.'
|
||||||
|
);
|
||||||
|
|
||||||
|
for f in dataset.Fields do
|
||||||
|
case f.FieldName of
|
||||||
|
INT_FIELD:
|
||||||
|
CheckEquals(
|
||||||
|
INT_VALUES[actualRecNo],
|
||||||
|
f.AsInteger,
|
||||||
|
'Value mismatch in integer field'
|
||||||
|
);
|
||||||
|
STRING_FIELD:
|
||||||
|
CheckEquals(
|
||||||
|
STRING_VALUES[actualRecNo],
|
||||||
|
f.AsString,
|
||||||
|
'Value mismatch in string field'
|
||||||
|
);
|
||||||
|
WIDESTRING_FIELD:
|
||||||
|
CheckEquals(
|
||||||
|
UTF8ToUTF16(WIDESTRING_VALUES[actualRecNo]),
|
||||||
|
f.AsWideString,
|
||||||
|
'Value mismatch in widestring field'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
dataset.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_Int_Found;
|
||||||
|
begin
|
||||||
|
LocateTest(INT_FIELD, -10, 3);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_Int_NotFound;
|
||||||
|
begin
|
||||||
|
LocateTest(INT_FIELD, 1000, -1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_String_Found;
|
||||||
|
begin
|
||||||
|
LocateTest(STRING_FIELD, 'a', 2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_String_Found_CaseInsensitive;
|
||||||
|
begin
|
||||||
|
LocateTest(STRING_FIELD, 'ABC', 1, [loCaseInsensitive]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_String_NotFound;
|
||||||
|
begin
|
||||||
|
LocateTest(STRING_FIELD, 'ttt', -1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_NonASCIIString_Found;
|
||||||
|
begin
|
||||||
|
LocateTest(STRING_FIELD, 'äöüαβγ', 5);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_NonASCIIString_Found_CaseInsensitive;
|
||||||
|
begin
|
||||||
|
LocateTest(STRING_FIELD, 'ÄöÜαβΓ', 5, [loCaseInsensitive]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_NonASCIIString_NotFound;
|
||||||
|
begin
|
||||||
|
LocateTest(STRING_FIELD, 'ä', -1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_WideString_Found;
|
||||||
|
begin
|
||||||
|
LocateTest(WIDESTRING_FIELD, WideString('ABC'), 1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_WideString_Found_CaseInsensitive;
|
||||||
|
begin
|
||||||
|
LocateTest(WIDESTRING_FIELD, WideString('Abc'), 1, [loCaseInsensitive]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_WideString_NotFound;
|
||||||
|
begin
|
||||||
|
LocateTest(WIDESTRING_FIELD, WideString('abc'), -1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_NonASCIIWideString_Found;
|
||||||
|
var
|
||||||
|
ws: WideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16('ÄöüΓ');
|
||||||
|
LocateTest(WIDESTRING_FIELD, ws, 4);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_NonASCIIWideString_Found_CaseInsensitive;
|
||||||
|
var
|
||||||
|
ws: Widestring;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16('Äöüγ');
|
||||||
|
LocateTest(WIDESTRING_FIELD, ws, 4, [loCaseInsensitive]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LocateTest_NonASCIIWideString_NotFound;
|
||||||
|
var
|
||||||
|
ws: WideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16('ä-α');
|
||||||
|
LocateTest(WIDESTRING_FIELD, ws, -1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest(SearchInField: String; SearchValue: Variant;
|
||||||
|
ResultFields: String; ExpectedValues: Variant);
|
||||||
|
var
|
||||||
|
dataset: TsWorksheetDataset;
|
||||||
|
savedRecNo: Integer;
|
||||||
|
i, j: Integer;
|
||||||
|
actualValues: Variant;
|
||||||
|
expectedInt, actualInt: Integer;
|
||||||
|
expectedStr, actualStr: String;
|
||||||
|
expectedWideStr, actualWideStr: WideString;
|
||||||
|
L: TStringList;
|
||||||
|
begin
|
||||||
|
dataset := CreateAndOpenDataset;
|
||||||
|
try
|
||||||
|
savedRecNo := dataset.RecNo;
|
||||||
|
actualValues := dataset.Lookup(SearchInField, SearchValue, ResultFields);
|
||||||
|
|
||||||
|
// The active record position must not be changed
|
||||||
|
CheckEquals(
|
||||||
|
savedRecNo,
|
||||||
|
dataset.RecNo,
|
||||||
|
'Lookup must not move the active record.'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Compare count of elements in value arrays
|
||||||
|
CheckEquals(
|
||||||
|
VarArrayDimCount(ExpectedValues),
|
||||||
|
VarArrayDimCount(actualValues),
|
||||||
|
'Mismatch in found field values.'
|
||||||
|
);
|
||||||
|
|
||||||
|
if VarIsNull(ExpectedValues) then
|
||||||
|
begin
|
||||||
|
CheckEquals(
|
||||||
|
true,
|
||||||
|
varIsNull(actualValues),
|
||||||
|
'Record found but not expected.'
|
||||||
|
);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not VarIsNull(ExpectedValues) then
|
||||||
|
CheckEquals(
|
||||||
|
false,
|
||||||
|
varIsNull(actualValues),
|
||||||
|
'Record expected but not found.'
|
||||||
|
);
|
||||||
|
|
||||||
|
L := TStringList.Create;
|
||||||
|
L.StrictDelimiter := true;
|
||||||
|
L.Delimiter := ';';
|
||||||
|
L.DelimitedText := ResultFields;
|
||||||
|
|
||||||
|
// Compare lookup values with expected values
|
||||||
|
for i := 0 to dataset.Fields.Count-1 do
|
||||||
|
begin
|
||||||
|
j := L.IndexOf(dataset.Fields[i].FieldName);
|
||||||
|
if j = -1 then
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case dataset.Fields[i].DataType of
|
||||||
|
ftInteger:
|
||||||
|
begin
|
||||||
|
expectedInt := ExpectedValues[j];
|
||||||
|
actualInt := actualvalues[j];
|
||||||
|
CheckEquals(
|
||||||
|
expectedInt,
|
||||||
|
actualInt,
|
||||||
|
'Integer field lookup value mismatch'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
ftString:
|
||||||
|
begin
|
||||||
|
expectedStr := VarToStr(ExpectedValues[j]);
|
||||||
|
actualStr := VarToStr(actualValues[j]);
|
||||||
|
CheckEquals(
|
||||||
|
expectedStr,
|
||||||
|
actualStr,
|
||||||
|
'String field lookup value mismatch'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
ftWideString:
|
||||||
|
begin
|
||||||
|
expectedWideStr := VarToWideStr(ExpectedValues[j]);
|
||||||
|
actualWideStr := VarToWideStr(actualValues[j]);
|
||||||
|
CheckEquals(
|
||||||
|
ExpectedWideStr,
|
||||||
|
actualWideStr,
|
||||||
|
'Widestring field lookup value mismatch'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
raise Exception.Create('Unsupported field type in LookupTest');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
L.Free;
|
||||||
|
finally
|
||||||
|
dataset.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_Int_Found;
|
||||||
|
var
|
||||||
|
ws: wideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16(WIDESTRING_VALUES[2]);
|
||||||
|
LookupTest(INT_FIELD, 20, STRING_FIELD+';'+WIDESTRING_FIELD, VarArrayOf(['a', ws]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_Int_NotFound;
|
||||||
|
begin
|
||||||
|
LookupTest(INT_FIELD, 200, STRING_FIELD+';'+WIDESTRING_FIELD, Null);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_String_Found;
|
||||||
|
var
|
||||||
|
ws: wideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16(WIDESTRING_VALUES[3]);
|
||||||
|
LookupTest(STRING_FIELD, 'Hallo', INT_FIELD+';'+WIDESTRING_FIELD, VarArrayOf([-10, ws]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_String_NotFound;
|
||||||
|
begin
|
||||||
|
LookupTest(STRING_FIELD, 'Halloooo', INT_FIELD+';'+WIDESTRING_FIELD, Null);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_NonASCIIString_Found;
|
||||||
|
var
|
||||||
|
ws: wideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16('xyz');
|
||||||
|
LookupTest(STRING_FIELD, 'äöüαβγ', INT_FIELD+';'+WIDESTRING_FIELD, VarArrayOf([3, ws]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_NonASCIIString_NotFound;
|
||||||
|
begin
|
||||||
|
LookupTest(STRING_FIELD, 'ÄÄÄÄα', INT_FIELD+';'+WIDESTRING_FIELD, Null);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_WideString_Found;
|
||||||
|
var
|
||||||
|
ws: wideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16('ABC');
|
||||||
|
LookupTest(WIDESTRING_FIELD, ws, INT_FIELD+';'+STRING_FIELD, VarArrayOf([12, 'abc']));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_WideString_NotFound;
|
||||||
|
var
|
||||||
|
ws: wideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16('ABCD');
|
||||||
|
LookupTest(WIDESTRING_FIELD, ws, INT_FIELD+';'+STRING_FIELD, null);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_NonASCIIWideString_Found;
|
||||||
|
var
|
||||||
|
ws: wideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16('ÄöüΓ');
|
||||||
|
LookupTest(WIDESTRING_FIELD, ws, INT_FIELD+';'+STRING_FIELD, VarArrayOf([83, 'ijk']));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.LookupTest_NonASCIIWideString_NotFound;
|
||||||
|
var
|
||||||
|
ws: wideString;
|
||||||
|
begin
|
||||||
|
ws := UTF8ToUTF16('Äöαβ');
|
||||||
|
LookupTest(WIDESTRING_FIELD, ws, INT_FIELD+';'+STRING_FIELD, null);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
procedure TSearchTest.SetUp;
|
||||||
|
var
|
||||||
|
r: Integer;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
worksheet: TsWorksheet;
|
||||||
|
begin
|
||||||
|
// Create test spreadsheet file
|
||||||
|
workbook := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
// Create worksheet
|
||||||
|
worksheet := workbook.AddWorkSheet(SHEET_NAME);
|
||||||
|
|
||||||
|
// Write headers (= field names)
|
||||||
|
worksheet.WriteText(0, INT_COL, INT_FIELD);
|
||||||
|
worksheet.WriteText(0, STRING_COL, STRING_FIELD);
|
||||||
|
worksheet.WriteText(0, WIDESTRING_COL, WIDESTRING_FIELD);
|
||||||
|
|
||||||
|
// Write values
|
||||||
|
for r := 1 to NUM_ROWS do
|
||||||
|
begin
|
||||||
|
worksheet.WriteNumber(r, INT_COL, INT_VALUES[r], nfFixed, 0);
|
||||||
|
worksheet.WriteText(r, STRING_COL, STRING_VALUES[r]);
|
||||||
|
worksheet.WriteText(r, WIDESTRING_COL, WIDESTRING_VALUES[r]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Save
|
||||||
|
DataFileName := GetTempDir + FILE_NAME;
|
||||||
|
workbook.WriteToFile(DataFileName, true);
|
||||||
|
finally
|
||||||
|
workbook.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSearchTest.TearDown;
|
||||||
|
begin
|
||||||
|
if FileExists(DataFileName) then DeleteFile(DataFileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
RegisterTest(TSearchTest);
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
231
components/fpspreadsheet/unit-tests/dataset/sorttestunit.pas
Normal file
231
components/fpspreadsheet/unit-tests/dataset/sorttestunit.pas
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
unit SortTestUnit;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testregistry,
|
||||||
|
DB,
|
||||||
|
fpspreadsheet, fpstypes, fpsutils, fpsdataset;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TSortTest= class(TTestCase)
|
||||||
|
private
|
||||||
|
function CreateAndOpenDataset: TsWorksheetDataset;
|
||||||
|
protected
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
procedure SortTest(SortField: String; Descending, CaseInsensitive: Boolean);
|
||||||
|
published
|
||||||
|
procedure SortTest_IntField_Ascending;
|
||||||
|
procedure SortTest_IntField_Descending;
|
||||||
|
procedure SortTest_TextField_Ascending_CaseSensitive;
|
||||||
|
procedure SortTest_TextField_Descending_CaseSensitive;
|
||||||
|
procedure SortTest_TextField_Ascending_CaseInsensitive;
|
||||||
|
procedure SortTest_TextField_Descending_CaseInsensitive;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
const
|
||||||
|
FILE_NAME = 'testfile.xlsx';
|
||||||
|
SHEET_NAME = 'Sheet';
|
||||||
|
INT_COL = 0;
|
||||||
|
TEXT_COL = 1;
|
||||||
|
INT_FIELD = 'IntCol';
|
||||||
|
TEXT_FIELD = 'TextCol';
|
||||||
|
|
||||||
|
var
|
||||||
|
DataFileName: String;
|
||||||
|
|
||||||
|
type
|
||||||
|
TTestRow = record
|
||||||
|
IntValue: Integer;
|
||||||
|
TextValue: String;
|
||||||
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
// Unsorted test values
|
||||||
|
UNSORTED: array[0..4] of TTestRow = ( // Index
|
||||||
|
(IntValue: 10; TextValue: 'abc'), // 0
|
||||||
|
(IntValue: 1; TextValue: 'ABC'), // 1
|
||||||
|
(IntValue: 1; TextValue: 'a'), // 2
|
||||||
|
(IntValue: 2; TextValue: 'A'), // 3
|
||||||
|
(IntValue: -1; TextValue: 'xyz') // 4
|
||||||
|
);
|
||||||
|
|
||||||
|
// These are the indexes into the UNSORTED array after sorting
|
||||||
|
SORTED_BY_INT_ASCENDING: array[0..4] of Integer = (4, 1, 2, 3, 0);
|
||||||
|
SORTED_BY_INT_DESCENDING: array[0..4] of Integer = (0, 3, 2, 1, 4);
|
||||||
|
SORTED_BY_TEXT_ASCENDING_CASESENS: array[0..4] of Integer = (2, 0, 3, 1, 4);
|
||||||
|
SORTED_BY_TEXT_DESCENDING_CASESENS: array[0..4] of Integer = (4, 1, 3, 0, 2);
|
||||||
|
SORTED_BY_TEXT_ASCENDING_CASEINSENS: array[0..4] of Integer = (3, 2, 1, 0, 4);
|
||||||
|
SORTED_BY_TEXT_DESCENDING_CASEINSENS: array[0..4] of Integer = (4, 1, 0, 3, 2);
|
||||||
|
// Note on case-insensitive sorting: Depending on implementation of the
|
||||||
|
// sorting algorithms different results can be obtained for which the
|
||||||
|
// uppercased texts are the same. Therefore, Excel yields different result
|
||||||
|
// than FPSpreadsheet. Above indices are for FPSpreadsheet.
|
||||||
|
|
||||||
|
|
||||||
|
function TSortTest.CreateAndOpenDataset: TsWorksheetDataset;
|
||||||
|
begin
|
||||||
|
Result := TsWorksheetDataset.Create(nil);
|
||||||
|
Result.FileName := DataFileName;
|
||||||
|
Result.SheetName := SHEET_NAME;
|
||||||
|
Result.Open;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSortTest.SortTest(SortField: String; Descending, CaseInsensitive: Boolean);
|
||||||
|
var
|
||||||
|
dataset: TsWorksheetDataset;
|
||||||
|
options: TsSortOptions;
|
||||||
|
intField: TField;
|
||||||
|
textField: TField;
|
||||||
|
actualInt: Integer;
|
||||||
|
actualText: String;
|
||||||
|
expectedInt: Integer;
|
||||||
|
expectedText: String;
|
||||||
|
i, sortedIdx: Integer;
|
||||||
|
begin
|
||||||
|
options := [];
|
||||||
|
if Descending then Include(options, ssoDescending);
|
||||||
|
if CaseInsensitive then Include(options, ssoCaseInsensitive);
|
||||||
|
|
||||||
|
dataset := CreateAndOpenDataset;
|
||||||
|
try
|
||||||
|
dataset.SortOnField(SortField, options);
|
||||||
|
|
||||||
|
// For debugging
|
||||||
|
dataset.Close; // to write the worksheet to file
|
||||||
|
dataset.Open;
|
||||||
|
|
||||||
|
intField := dataset.FieldByName(INT_FIELD);
|
||||||
|
textField := dataset.FieldByName(TEXT_FIELD);
|
||||||
|
|
||||||
|
dataset.First;
|
||||||
|
i := 0;
|
||||||
|
while not dataset.EOF do
|
||||||
|
begin
|
||||||
|
if SortField = INT_FIELD then
|
||||||
|
begin
|
||||||
|
if Descending then
|
||||||
|
sortedIdx := SORTED_BY_INT_DESCENDING[i]
|
||||||
|
else
|
||||||
|
sortedIdx := SORTED_BY_INT_ASCENDING[i];
|
||||||
|
end else
|
||||||
|
if SortField = TEXT_FIELD then
|
||||||
|
begin
|
||||||
|
if Descending then
|
||||||
|
begin
|
||||||
|
if CaseInsensitive then
|
||||||
|
sortedIdx := SORTED_BY_TEXT_DESCENDING_CASEINSENS[i]
|
||||||
|
else
|
||||||
|
sortedIdx := SORTED_BY_TEXT_DESCENDING_CASESENS[i];
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
if CaseInsensitive then
|
||||||
|
sortedIdx := SORTED_BY_TEXT_ASCENDING_CASEINSENS[i]
|
||||||
|
else
|
||||||
|
sortedIdx := SORTED_BY_TEXT_ASCENDING_CASESENS[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
expectedInt := UNSORTED[sortedIdx].IntValue;
|
||||||
|
expectedText := UNSORTED[sortedIdx].TextValue;
|
||||||
|
actualInt := intField.AsInteger;
|
||||||
|
actualText := textField.AsString;
|
||||||
|
|
||||||
|
CheckEquals(
|
||||||
|
expectedInt,
|
||||||
|
actualInt,
|
||||||
|
'Integer field value mismatch in row ' + IntToStr(i)
|
||||||
|
);
|
||||||
|
CheckEquals(
|
||||||
|
expectedText,
|
||||||
|
actualText,
|
||||||
|
'Text field value mismatch in row ' + IntToStr(i)
|
||||||
|
);
|
||||||
|
|
||||||
|
inc(i);
|
||||||
|
dataset.Next;
|
||||||
|
end;
|
||||||
|
|
||||||
|
finally
|
||||||
|
dataset.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSortTest.SortTest_IntField_Ascending;
|
||||||
|
begin
|
||||||
|
SortTest(INT_FIELD, false, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSortTest.SortTest_IntField_Descending;
|
||||||
|
begin
|
||||||
|
SortTest(INT_FIELD, true, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSortTest.SortTest_TextField_Ascending_CaseSensitive;
|
||||||
|
begin
|
||||||
|
SortTest(TEXT_FIELD, false, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSortTest.SortTest_TextField_Descending_CaseSensitive;
|
||||||
|
begin
|
||||||
|
SortTest(TEXT_FIELD, true, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSortTest.SortTest_TextField_Ascending_CaseInsensitive;
|
||||||
|
begin
|
||||||
|
SortTest(TEXT_FIELD, false, true);
|
||||||
|
end;
|
||||||
|
procedure TSortTest.SortTest_TextField_Descending_CaseInsensitive;
|
||||||
|
begin
|
||||||
|
SortTest(TEXT_FIELD, true, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSortTest.SetUp;
|
||||||
|
var
|
||||||
|
i, r: Integer;
|
||||||
|
workbook: TsWorkbook;
|
||||||
|
worksheet: TsWorksheet;
|
||||||
|
begin
|
||||||
|
// Create test spreadsheet file
|
||||||
|
workbook := TsWorkbook.Create;
|
||||||
|
try
|
||||||
|
// Create worksheet
|
||||||
|
worksheet := workbook.AddWorkSheet(SHEET_NAME);
|
||||||
|
|
||||||
|
// Write headers (= field names)
|
||||||
|
worksheet.WriteText(0, INT_COL, INT_FIELD);
|
||||||
|
worksheet.WriteText(0, TEXT_COL, TEXT_FIELD);
|
||||||
|
|
||||||
|
// Write values
|
||||||
|
for i := Low(UNSORTED) to High(UNSORTED) do
|
||||||
|
begin
|
||||||
|
r := 1 + (i - Low(UNSORTED));
|
||||||
|
worksheet.WriteNumber(r, INT_COL, UNSORTED[i].IntValue, nfFixed, 0);
|
||||||
|
worksheet.WriteText(r, TEXT_COL, UNSORTED[i].TextValue);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Save
|
||||||
|
DataFileName := GetTempDir + FILE_NAME;
|
||||||
|
workbook.WriteToFile(DataFileName, true);
|
||||||
|
finally
|
||||||
|
workbook.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSortTest.TearDown;
|
||||||
|
begin
|
||||||
|
if FileExists(DataFileName) then DeleteFile(DataFileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
initialization
|
||||||
|
RegisterTest(TSortTest);
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
Reference in New Issue
Block a user