Move unit tests into folder unit-tests/common

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8094 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2021-09-24 08:45:28 +00:00
parent 271084dbe6
commit 4585269bdb
55 changed files with 0 additions and 0 deletions

View File

@ -0,0 +1,214 @@
unit celltypetests;
{$mode objfpc}{$H+}
interface
{ Cell type tests
This unit tests writing the various cell data types out to and reading them
back from files.
}
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
type
{ TSpreadWriteReadCellTypeTests }
// Write cell types to xls/xml file and read back
TSpreadWriteReadCellTypeTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteRead_Bool(AFormat: TsSpreadsheetFormat);
published
// BIFF2 test cases
procedure TestWriteRead_Bool_BIFF2;
// BIFF5 test cases
procedure TestWriteRead_Bool_BIFF5;
// BIFF8 test cases
procedure TestWriteRead_Bool_BIFF8;
// ODS test cases
procedure TestWriteRead_Bool_ODS;
// OOXML test cases
procedure TestWriteRead_Bool_OOXML;
// Excel2003/XML test cases
procedure TestWriteRead_Bool_XML;
// CSV test cases
procedure TestWriteRead_Bool_CSV;
end;
implementation
uses
TypInfo;
const
SheetName = 'CellTypes';
{ TSpreadWriteReadCellTypeTests }
procedure TSpreadWriteReadCellTypeTests.SetUp;
begin
inherited SetUp;
end;
procedure TSpreadWriteReadCellTypeTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadCellTypeTests.TestWriteRead_Bool(AFormat: TsSpreadsheetFormat);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col: Integer;
MyCell: PCell;
value: Boolean;
TempFile: string; //write xls/xml to this file and read back from it
begin
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving];
MyWorkSheet:= MyWorkBook.AddWorksheet(SheetName);
row := 0;
// direct cells with TRUE and FALSE
MyWorksheet.WriteBoolValue(row, 0, false); // A1
Myworksheet.WriteBoolValue(row, 1, true); // B1
inc(row);
// cells with TRUE and FALSE as formula results
MyWorksheet.WriteFormula(row, 0, '=FALSE()'); // A2
MyWorksheet.WriteFormula(row, 1, '=TRUE()'); // B2
inc(row);
// Merged cells with TRUE and FALSE
MyWorksheet.MergeCells(row, 0, row+1, 0); // A3
Myworksheet.WriteBoolValue(row, 0, false);
MyWorksheet.MergeCells(row, 1, row+1, 1); // B3
MyWorksheet.WriteBoolValue(row, 1, true);
inc(row, 2);
// Merged cells with TRUE and FALSE function results
MyWorksheet.MergeCells(row, 0, row+1, 0); // A5
MyWorksheet.WriteFormula(row, 0, '=FALSE()');
MyWorksheet.MergeCells(row, 1, row+1, 1); // B5
MyWorksheet.WriteFormula(row, 1, '=TRUE()');
TempFile := NewTempFile;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boReadFormulas];
MyWorkbook.ReadFromFile(TempFile, AFormat);
MyWorkbook.CalcFormulas;
if AFormat in [sfExcel2, sfCSV] then
MyWorksheet := MyWorkbook.GetFirstWorksheet // only 1 sheet for BIFF2
else
MyWorksheet := GetWorksheetByName(MyWorkBook, SheetName);
if MyWorksheet = nil then
fail('Error in test code. Failed to get named worksheet');
// Try to read cell
row := 0;
repeat
for col:=0 to 1 do
begin
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
fail('Error in test code. Failed to get cell '+CellNotation(MyWorksheet, row, col));
CheckEquals(
GetEnumName(TypeInfo(TCellContentType), ord(cctBool)),
GetEnumName(TypeInfo(TCellContentType), ord(MyCell^.ContentType)),
'Test saved content type mismatch, cell '+CellNotation(MyWorksheet, row, col)
);
value := MyCell^.BoolValue;
CheckEquals(
Boolean(col),
MyCell^.BoolValue,
'Test saved boolean value mismatch, cell '+CellNotation(MyWorksheet, row, col));
end;
case row of
0, 1: inc(row);
2 : inc(row, 2);
else break;
end;
until false;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ BIFF2 }
procedure TSpreadWriteReadCellTypeTests.TestWriteRead_Bool_BIFF2;
begin
TestWriteRead_Bool(sfExcel2);
end;
{ BIFF5 }
procedure TSpreadWriteReadCellTypeTests.TestWriteRead_Bool_BIFF5;
begin
TestWriteRead_Bool(sfExcel5);
end;
{ BIFF8 }
procedure TSpreadWriteReadCellTypeTests.TestWriteRead_Bool_BIFF8;
begin
TestWriteRead_Bool(sfExcel8);
end;
{ ODS }
procedure TSpreadWriteReadCellTypeTests.TestWriteRead_Bool_ODS;
begin
TestWriteRead_Bool(sfOpenDocument);
end;
{ OOXML }
procedure TSpreadWriteReadCellTypeTests.TestWriteRead_Bool_OOXML;
begin
TestWriteRead_Bool(sfOOXML);
end;
{ XML }
procedure TSpreadWriteReadCellTypeTests.TestWriteRead_Bool_XML;
begin
TestWriteRead_Bool(sfExcelXML);
end;
{ CSV }
procedure TSpreadWriteReadCellTypeTests.TestWriteRead_Bool_CSV;
begin
TestWriteRead_Bool(sfCSV);
end;
initialization
RegisterTest(TSpreadWriteReadCellTypeTests);
end.

View File

@ -0,0 +1,589 @@
{ Color tests
--------------------------------------------------------------------------------
This unit tests writing out to and reading back from files.
}
unit colortests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
type
{ TSpreadWriteReadColorTests }
//Write to xls/xml file and read back
TSpreadWriteReadColorTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteReadBackgroundColors(AFormat: TsSpreadsheetFormat; WhichPalette: Integer);
procedure TestWriteReadFontColors(AFormat: TsSpreadsheetFormat; WhichPalette: Integer);
procedure TestWriteReadTabColor(AFormat: TsSpreadsheetFormat; ATabColor: TsColor);
published
// Writes out colors & reads back.
{ BIFF2 file format tests }
procedure TestWriteRead_BIFF2_Font_InternalPal; // internal palette for BIFF2 file format
{ BIFF5 file format tests }
// Background colors...
procedure TestWriteRead_BIFF5_Background_InternalPal; // internal palette
procedure TestWriteRead_BIFF5_Background_Biff5Pal; // official biff5 palette
procedure TestWriteRead_BIFF5_Background_Biff8Pal; // official biff8 palette
procedure TestWriteRead_BIFF5_Background_RandomPal; // palette 64, top 56 entries random
// Font colors...
procedure TestWriteRead_BIFF5_Font_InternalPal; // internal palette for BIFF8 file format
procedure TestWriteRead_BIFF5_Font_Biff5Pal; // official biff5 palette in BIFF8 file format
procedure TestWriteRead_BIFF5_Font_Biff8Pal; // official biff8 palette in BIFF8 file format
procedure TestWriteRead_BIFF5_Font_RandomPal; // palette 64, top 56 entries random
{ BIFF8 file format tests }
// Background colors...
procedure TestWriteRead_BIFF8_Background_InternalPal; // internal palette
procedure TestWriteRead_BIFF8_Background_Biff5Pal; // official biff5 palette
procedure TestWriteRead_BIFF8_Background_Biff8Pal; // official biff8 palette
procedure TestWriteRead_BIFF8_Background_RandomPal; // palette 64, top 56 entries random
// Font colors...
procedure TestWriteRead_BIFF8_Font_InternalPal; // internal palette for BIFF8 file format
procedure TestWriteRead_BIFF8_Font_Biff5Pal; // official biff5 palette in BIFF8 file format
procedure TestWriteRead_BIFF8_Font_Biff8Pal; // official biff8 palette in BIFF8 file format
procedure TestWriteRead_BIFF8_Font_RandomPal; // palette 64, top 56 entries random
// Tab color
procedure TestWriteRead_BIFF8_TabColor;
{ OpenDocument file format tests }
// Background colors...
procedure TestWriteRead_ODS_Background_InternalPal; // internal palette
procedure TestWriteRead_ODS_Background_Biff5Pal; // official biff5 palette
procedure TestWriteRead_ODS_Background_Biff8Pal; // official biff8 palette
procedure TestWriteRead_ODS_Background_RandomPal; // palette 64, top 56 entries random
// Font colors...
procedure TestWriteRead_ODS_Font_InternalPal; // internal palette for BIFF8 file format
procedure TestWriteRead_ODS_Font_Biff5Pal; // official biff5 palette in BIFF8 file format
procedure TestWriteRead_ODS_Font_Biff8Pal; // official biff8 palette in BIFF8 file format
procedure TestWriteRead_ODS_Font_RandomPal; // palette 64, top 56 entries random
// Tab color
procedure TestWriteRead_ODS_TabColor;
{ OOXML file format tests }
// Background colors...
procedure TestWriteRead_OOXML_Background_InternalPal; // internal palette
procedure TestWriteRead_OOXML_Background_Biff5Pal; // official biff5 palette
procedure TestWriteRead_OOXML_Background_Biff8Pal; // official biff8 palette
procedure TestWriteRead_OOXML_Background_RandomPal; // palette 64, top 56 entries random
// Font colors...
procedure TestWriteRead_OOXML_Font_InternalPal; // internal palette for BIFF8 file format
procedure TestWriteRead_OOXML_Font_Biff5Pal; // official biff5 palette in BIFF8 file format
procedure TestWriteRead_OOXML_Font_Biff8Pal; // official biff8 palette in BIFF8 file format
procedure TestWriteRead_OOXML_Font_RandomPal; // palette 64, top 56 entries random
// Tab color
procedure TestWriteRead_OOXML_TabColor;
{ Excel 2003/XML file format tests }
// Background colors...
procedure TestWriteRead_XML_Background_InternalPal; // internal palette
procedure TestWriteRead_XML_Background_Biff5Pal; // official biff5 palette
procedure TestWriteRead_XML_Background_Biff8Pal; // official biff8 palette
procedure TestWriteRead_XML_Background_RandomPal; // palette 64, top 56 entries random
// Font colors...
procedure TestWriteRead_XML_Font_InternalPal; // internal palette for BIFF8 file format
procedure TestWriteRead_XML_Font_Biff5Pal; // official biff5 palette in BIFF8 file format
procedure TestWriteRead_XML_Font_Biff8Pal; // official biff8 palette in BIFF8 file format
procedure TestWriteRead_XML_Font_RandomPal; // palette 64, top 56 entries random
end;
implementation
uses
fpsPalette;
const
ColorsSheet = 'Colors';
{ TSpreadWriteReadColorTests }
procedure TSpreadWriteReadColorTests.SetUp;
begin
inherited SetUp;
end;
procedure TSpreadWriteReadColorTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadColorTests.TestWriteReadBackgroundColors(AFormat: TsSpreadsheetFormat;
WhichPalette: Integer);
// WhichPalette = 5: BIFF5 palette
// 8: BIFF8 palette
// else internal palette
// see also "manualtests".
const
CELLTEXT = 'Color test';
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col: Integer;
MyCell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
expectedRGB: DWord;
currentRGB: DWord;
palette: TsPalette;
i: Integer;
begin
TempFile:=GetTempFileName;
// Define palette
palette := TsPalette.Create;
try
case whichPalette of
5: palette.UseColors(PALETTE_BIFF5);
8: palette.UseColors(PALETTE_BIFF8);
999: begin // random palette: testing of color replacement
palette.UseColors(PALETTE_BIFF8);
// Loop begins at 16 because the first 8 colors must not be changed
// and the next 8 are duplicates for editingy in Excel
for i:=16 to 63 do
palette[i] := random(256) + random(256) shr 8 + random(256) shr 16;
end;
else palette.AddBuiltinColors;
end;
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(ColorsSheet);
// Write out all colors
row := 0;
col := 0;
for i := 0 to palette.Count-1 do begin
MyWorksheet.WriteUTF8Text(row, col, CELLTEXT);
MyCell := MyWorksheet.WriteBackgroundColor(row, col, palette[i]);
if MyCell = nil then
fail('Error in test code. Failed to get cell.');
currentRGB := MyWorksheet.ReadBackgroundColor(MyCell);
expectedRGB := palette[i];
CheckEquals(expectedRGB, currentRGB,
'Test unsaved background color, cell ' + CellNotation(MyWorksheet,0,0));
inc(row);
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, ColorsSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
for row := 0 to MyWorksheet.GetLastRowIndex do begin
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
fail('Error in test code. Failed to get cell.');
currentRGB := MyWorksheet.ReadBackgroundColor(MyCell);
expectedRGB := palette[row];
CheckEquals(expectedRGB, currentRGB,
'Test saved background color, cell '+CellNotation(MyWorksheet,Row,Col));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
finally
palette.Free
end;
end;
procedure TSpreadWriteReadColorTests.TestWriteReadFontColors(AFormat: TsSpreadsheetFormat;
WhichPalette: Integer);
// WhichPalette = 5: BIFF5 palette
// 8: BIFF8 palette
// else internal palette
// see also "manualtests".
const
CELLTEXT = 'Color test';
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col: Integer;
MyCell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
expectedRGB, currentRGB: DWord;
palette: TsPalette;
i: Integer;
begin
TempFile:=GetTempFileName;
// Define palette
palette := TsPalette.Create;
try
case whichPalette of
5: palette.UseColors(PALETTE_BIFF5);
8: palette.UseColors(PALETTE_BIFF8);
999: begin // random palette: testing of color replacement
palette.UseColors(PALETTE_BIFF8);
// Loop begins at 16 because the first 8 colors must not be changed
// and the next 8 are duplicates for editingy in Excel
for i:=16 to 63 do
palette[i] := random(256) + random(256) shr 8 + random(256) shr 16;
end;
else palette.AddBuiltinColors;
end;
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(ColorsSheet);
// Write out all colors
row := 0;
col := 0;
for i := 0 to palette.Count-1 do begin
MyWorksheet.WriteUTF8Text(row, col, CELLTEXT);
MyWorksheet.WriteFontColor(row, col, palette[i]);
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
fail('Error in test code. Failed to get cell.');
currentRGB := MyWorksheet.ReadCellFont(MyCell).Color;
expectedRGB := palette[i];
CheckEquals(expectedRGB, currentRGB,
'Test unsaved font color, cell ' + CellNotation(MyWorksheet,row, col));
inc(row);
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, ColorsSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
col := 0;
for row := 0 to MyWorksheet.GetLastRowIndex do begin
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
fail('Error in test code. Failed to get cell.');
expectedRGB := palette[row];
currentRGB := MyWorksheet.ReadCellFont(MyCell).Color;
// Excel2 cannot write the entire palette. We have to look for the
// closest color.
if (AFormat = sfExcel2) then
expectedRGB := palette[palette.FindClosestColorIndex(expectedRGB, BIFF2_MAX_PALETTE_SIZE)];
CheckEquals(expectedRGB, currentRGB,
'Test saved font color, cell '+CellNotation(MyWorksheet,Row,Col));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
finally
palette.Free;
end;
end;
procedure TSpreadWriteReadColorTests.TestWriteReadTabColor(
AFormat: TsSpreadsheetFormat; ATabColor: TsColor);
const
CELLTEXT = 'Color test';
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col: Integer;
MyCell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
expectedRGB: DWord;
currentRGB: DWord;
i: Integer;
begin
if not (AFormat in [sfOOXML, sfExcel8, sfOpenDocument]) then
exit;
TempFile:=GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(ColorsSheet);
MyWorkSheet.TabColor := scRed;
currentRGB := MyWorksheet.TabColor;
expectedRGB := ATabColor;
CheckEquals(expectedRGB, currentRGB, 'Test unsaved tab color');
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
MyWorksheet := GetWorksheetByName(MyWorkBook, ColorsSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
currentRGB := MyWorksheet.TabColor;
expectedRGB := ATabColor;
CheckEquals(expectedRGB, currentRGB, 'Test saved tab color');
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ Tests for BIFF2 file format }
{ BIFF2 supports only a fixed palette, and no background color --> test only
internal palette for font color }
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF2_Font_InternalPal;
begin
TestWriteReadFontColors(sfExcel2, 0);
end;
{ Tests for BIFF5 file format }
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF5_Background_InternalPal;
begin
TestWriteReadBackgroundColors(sfExcel5, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF5_Background_Biff5Pal;
begin
TestWriteReadBackgroundColors(sfExcel5, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF5_Background_Biff8Pal;
begin
TestWriteReadBackgroundColors(sfExcel5, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF5_Background_RandomPal;
begin
TestWriteReadBackgroundColors(sfExcel5, 999);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF5_Font_InternalPal;
begin
TestWriteReadFontColors(sfExcel5, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF5_Font_Biff5Pal;
begin
TestWriteReadFontColors(sfExcel5, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF5_Font_Biff8Pal;
begin
TestWriteReadFontColors(sfExcel5, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF5_Font_RandomPal;
begin
TestWriteReadFontColors(sfExcel5, 999);
end;
{ Tests for BIFF8 file format }
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_Background_InternalPal;
begin
TestWriteReadBackgroundColors(sfExcel8, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_Background_Biff5Pal;
begin
TestWriteReadBackgroundColors(sfExcel8, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_Background_Biff8Pal;
begin
TestWriteReadBackgroundColors(sfExcel8, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_Background_RandomPal;
begin
TestWriteReadBackgroundColors(sfExcel8, 999);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_Font_InternalPal;
begin
TestWriteReadFontColors(sfExcel8, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_Font_Biff5Pal;
begin
TestWriteReadFontColors(sfExcel8, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_Font_Biff8Pal;
begin
TestWriteReadFontColors(sfExcel8, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_Font_RandomPal;
begin
TestWriteReadFontColors(sfExcel8, 999);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_BIFF8_TabColor;
begin
TestWriteReadTabColor(sfExcel8, scRed);
end;
{ Tests for Open Document file format }
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_Background_InternalPal;
begin
TestWriteReadBackgroundColors(sfOpenDocument, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_Background_Biff5Pal;
begin
TestWriteReadBackgroundColors(sfOpenDocument, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_Background_Biff8Pal;
begin
TestWriteReadBackgroundColors(sfOpenDocument, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_Background_RandomPal;
begin
TestWriteReadBackgroundColors(sfOpenDocument, 999);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_Font_InternalPal;
begin
TestWriteReadFontColors(sfOpenDocument, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_Font_Biff5Pal;
begin
TestWriteReadFontColors(sfOpenDocument, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_Font_Biff8Pal;
begin
TestWriteReadFontColors(sfOpenDocument, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_Font_RandomPal;
begin
TestWriteReadFontColors(sfOpenDocument, 999);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_ODS_TabColor;
begin
TestWriteReadTabColor(sfOpenDocument, scRed);
end;
{ Tests for OOXML file format }
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_Background_InternalPal;
begin
TestWriteReadBackgroundColors(sfOOXML, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_Background_Biff5Pal;
begin
TestWriteReadBackgroundColors(sfOOXML, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_Background_Biff8Pal;
begin
TestWriteReadBackgroundColors(sfOOXML, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_Background_RandomPal;
begin
TestWriteReadBackgroundColors(sfOOXML, 999);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_Font_InternalPal;
begin
TestWriteReadFontColors(sfOOXML, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_Font_Biff5Pal;
begin
TestWriteReadFontColors(sfOOXML, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_Font_Biff8Pal;
begin
TestWriteReadFontColors(sfOOXML, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_Font_RandomPal;
begin
TestWriteReadFontColors(sfOOXML, 999);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_OOXML_TabColor;
begin
TestWriteReadTabColor(sfOOXML, scRed);
end;
{ Tests for Excel 2003/XML file format }
procedure TSpreadWriteReadColorTests.TestWriteRead_XML_Background_InternalPal;
begin
TestWriteReadBackgroundColors(sfExcelXML, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_XML_Background_Biff5Pal;
begin
TestWriteReadBackgroundColors(sfExcelXML, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_XML_Background_Biff8Pal;
begin
TestWriteReadBackgroundColors(sfExcelXML, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_XML_Background_RandomPal;
begin
TestWriteReadBackgroundColors(sfExcelXML, 999);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_XML_Font_InternalPal;
begin
TestWriteReadFontColors(sfExcelXML, 0);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_XML_Font_Biff5Pal;
begin
TestWriteReadFontColors(sfExcelXML, 5);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_XML_Font_Biff8Pal;
begin
TestWriteReadFontColors(sfExcelXML, 8);
end;
procedure TSpreadWriteReadColorTests.TestWriteRead_XML_Font_RandomPal;
begin
TestWriteReadFontColors(sfExcelXML, 999);
end;
initialization
RegisterTest(TSpreadWriteReadColorTests);
end.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,320 @@
{ Comment tests
These unit tests are writing out to and reading back from file.
}
unit commenttests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
type
{ TSpreadWriteReadCommemtTests }
//Write to xls/xml file and read back
TSpreadWriteReadCommentTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteRead_Comment(AFormat: TsSpreadsheetFormat;
const ACommentText: String);
published
// Writes out comments & reads back.
{ BIFF2 comment tests }
procedure TestWriteRead_BIFF2_Standard_Comment;
procedure TestWriteRead_BIFF2_NonAscii_Comment;
procedure TestWriteRead_BIFF2_NonXMLChar_Comment;
procedure TestWriteRead_BIFF2_VeryLong_Standard_Comment;
procedure TestWriteRead_BIFF2_VeryLong_NonAscii_Comment;
{ BIFF5 comment tests }
procedure TestWriteRead_BIFF5_Standard_Comment;
procedure TestWriteRead_BIFF5_NonAscii_Comment;
procedure TestWriteRead_BIFF5_NonXMLChar_Comment;
procedure TestWriteRead_BIFF5_VeryLong_Standard_Comment;
procedure TestWriteRead_BIFF5_VeryLong_NonAscii_Comment;
{ BIFF8 comment tests }
// writing is currently not supported
//procedure TestWriteRead_BIFF8_Standard_Comment;
//procedure TestWriteRead_BIFF8_NonAscii_Comment;
//procedure TestWriteRead_BIFF8_NonXMLChar_Comment;
{ OpenDocument comment tests }
procedure TestWriteRead_ODS_Standard_Comment;
procedure TestWriteRead_ODS_NonAscii_Comment;
procedure TestWriteRead_ODS_NonXMLChar_Comment;
procedure TestWriteRead_ODS_VeryLong_Comment;
{ OOXML comment tests }
procedure TestWriteRead_OOXML_Standard_Comment;
procedure TestWriteRead_OOXML_NonAscii_Comment;
procedure TestWriteRead_OOXML_NonXMLChar_Comment;
procedure TestWriteRead_OOXML_VeryLong_Comment;
{ XML comment tests }
procedure TestWriteRead_XML_Standard_Comment;
procedure TestWriteRead_XML_NonAscii_Comment;
procedure TestWriteRead_XML_NonXMLChar_Comment;
procedure TestWriteRead_XML_VeryLong_Comment;
end;
implementation
const
CommentSheet = 'Comments';
STANDARD_COMMENT = 'This is a comment';
COMMENT_UTF8 = 'Comment with non-standard characters: ÄÖÜß café au lait'; // водка wódka';
COMMENT_XML = 'Comment with characters not allowed by XML: <, >';
var
VERY_LONG_COMMENT: String;
VERY_LONG_NONASCII_COMMENT: String;
{ TSpreadWriteReadCommentTests }
procedure TSpreadWriteReadCommentTests.SetUp;
var
i: Integer;
begin
inherited SetUp;
// In BIFF2-5, comments longer than 2048 characters are split into several
// NOTE records.
VERY_LONG_COMMENT := '';
repeat
VERY_LONG_COMMENT := VERY_LONG_COMMENT + '1234567890 ';
until Length(VERY_LONG_COMMENT) > 3000;
VERY_LONG_NONASCII_COMMENT := '';
repeat
VERY_LONG_NONASCII_COMMENT := VERY_LONG_NONASCII_COMMENT + 'ÄÖÜäöü ';
until Length(VERY_LONG_NONASCII_COMMENT) > 3000;
end;
procedure TSpreadWriteReadCommentTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_Comment(
AFormat: TsSpreadsheetFormat; const ACommentText: String);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col, lastCol: Integer;
expected, actual: String;
MyCell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
begin
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(CommentSheet);
// Comment in empty cell
row := 0;
col := 0;
Myworksheet.WriteComment(row, col, ACommentText);
// Comment in label cell
col := 1;
MyWorksheet.WriteText(row, col, 'Cell with comment');
Myworksheet.WriteComment(row, col, ACommentText);
// Comment in number cell
col := 2;
MyWorksheet.WriteNumber(row, col, 123.456);
Myworksheet.WriteComment(row, col, ACommentText);
// Comment in formula cell
col := 3;
Myworksheet.WriteFormula(row, col, '1+1');
Myworksheet.WriteComment(row, col, ACommentText);
// Comment in boolean cell
col := 4;
MyWorksheet.WriteBoolValue(row, col, true);
Myworksheet.WriteComment(row, col, ACommentText);
// Comment in error cell
// Error cell must be the last cell because ODS does not support error cell
// and the test is to be omitted.
col := 5;
Myworksheet.WriteErrorValue(row, col, errWrongType);
Myworksheet.WriteComment(row, col, ACommentText);
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, CommentSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
row := 0;
lastCol := MyWorksheet.GetLastColIndex;
if AFormat = sfOpenDocument then dec(lastCol); // No error cells supported in ODS --> skip the last test which is for error cells
for col := 0 to lastCol do
begin
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
fail('Failure to find cell ' + CellNotation(MyWorksheet, row, col));
actual := MyWorksheet.ReadComment(MyCell);
expected := ACommentText;
CheckEquals(expected, actual,
'Test saved comment mismatch, cell '+CellNotation(MyWorksheet, row, col));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ Tests for BIFF2 file format }
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF2_Standard_Comment;
begin
TestWriteRead_Comment(sfExcel2, STANDARD_COMMENT);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF2_NonAscii_Comment;
begin
TestWriteRead_Comment(sfExcel2, COMMENT_UTF8);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF2_NonXMLChar_Comment;
begin
TestWriteRead_Comment(sfExcel2, COMMENT_XML);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF2_VeryLong_Standard_Comment;
begin
TestWriteRead_Comment(sfExcel2, VERY_LONG_COMMENT);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF2_VeryLong_NonAscii_Comment;
begin
TestWriteRead_Comment(sfExcel2, VERY_LONG_NONASCII_COMMENT);
end;
{ Tests for BIFF5 file format }
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF5_Standard_Comment;
begin
TestWriteRead_Comment(sfExcel5, STANDARD_COMMENT);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF5_NonAscii_Comment;
begin
TestWriteRead_Comment(sfExcel5, COMMENT_UTF8);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF5_NonXMLChar_Comment;
begin
TestWriteRead_Comment(sfExcel5, COMMENT_XML);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF5_VeryLong_Standard_Comment;
begin
TestWriteRead_Comment(sfExcel5, VERY_LONG_COMMENT);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_BIFF5_VeryLong_NonAscii_Comment;
begin
TestWriteRead_Comment(sfExcel5, VERY_LONG_NONASCII_COMMENT);
end;
{ Tests for BIFF8 file format }
{ Writing is currently not support --> the test does not make sense! }
{ Tests for Open Document file format }
procedure TSpreadWriteReadCommentTests.TestWriteRead_ODS_Standard_Comment;
begin
TestWriteRead_Comment(sfOpenDocument, STANDARD_COMMENT);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_ODS_NonAscii_Comment;
begin
TestWriteRead_Comment(sfOpenDocument, COMMENT_UTF8);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_ODS_NonXMLChar_Comment;
begin
TestWriteRead_Comment(sfOpenDocument, COMMENT_XML);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_ODS_VeryLong_Comment;
begin
TestWriteRead_Comment(sfOpenDocument, VERY_LONG_COMMENT);
end;
{ Tests for OOXML file format }
procedure TSpreadWriteReadCommentTests.TestWriteRead_OOXML_Standard_Comment;
begin
TestWriteRead_Comment(sfOOXML, STANDARD_COMMENT);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_OOXML_NonAscii_Comment;
begin
TestWriteRead_Comment(sfOOXML, COMMENT_UTF8);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_OOXML_NonXMLChar_Comment;
begin
TestWriteRead_Comment(sfOOXML, COMMENT_XML);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_OOXML_VeryLong_Comment;
begin
TestWriteRead_Comment(sfOOXML, VERY_LONG_COMMENT);
end;
{ Tests for Excel 2003/XML file format }
procedure TSpreadWriteReadCommentTests.TestWriteRead_XML_Standard_Comment;
begin
TestWriteRead_Comment(sfExcelXML, STANDARD_COMMENT);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_XML_NonAscii_Comment;
begin
TestWriteRead_Comment(sfExcelXML, COMMENT_UTF8);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_XML_NonXMLChar_Comment;
begin
TestWriteRead_Comment(sfExcelXML, COMMENT_XML);
end;
procedure TSpreadWriteReadCommentTests.TestWriteRead_XML_VeryLong_Comment;
begin
TestWriteRead_Comment(sfExcelXML, VERY_LONG_COMMENT);
end;
initialization
RegisterTest(TSpreadWriteReadCommentTests);
end.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,490 @@
unit copytests;
{$mode objfpc}{$H+}
interface
{ Tests for copying cells
NOTE: The code in these tests is very fragile because the test results are
hard-coded. Any modification in "InitCopyData" must be carefully verified!
}
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8, fpsopendocument, {and a project requirement for lclbase for utf8 handling}
testsutility;
type
PCellRecord = ^TCellRecord;
TCellRecord = record
ContentType: TCellContentType;
Numbervalue: Double;
UTF8StringValue: String;
FormulaValue: String;
UsedFormattingFields: TsUsedFormattingFields;
SharedFormulaBase: PCellRecord;
BackgroundColor: TsColor;
end;
var
SourceCells: Array[0..8] of TCellRecord;
procedure InitCopyData;
type
{ TSpreadCopyTests }
TSpreadCopyTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure Test_Copy(ATestKind: Integer);
published
procedure Test_CopyValuesToEmptyCells;
procedure Test_CopyValuesToOccupiedCells;
procedure Test_CopyFormatsToEmptyCells;
procedure Test_CopyFormatsToOccupiedCells;
procedure Test_CopyFormulasToEmptyCells;
procedure Test_CopyFormulasToOccupiedCells;
end;
implementation
uses
TypInfo, fpsutils;
const
CopyTestSheet = 'Copy';
procedure MyInitCellRecord(out ACell: TCellRecord);
begin
ACell.ContentType := cctEmpty;
ACell.NumberValue := 0.0;
ACell.UTF8StringValue := '';
ACell.FormulaValue := '';
ACell.UsedformattingFields := [];
ACell.BackgroundColor := scTransparent;
ACell.SharedFormulaBase := nil;
end;
function MyHasFormula(ACell: PCellRecord): Boolean;
begin
Result := Assigned(ACell) and (
(ACell^.SharedFormulaBase <> nil) or (Length(ACell^.FormulaValue) > 0)
);
end;
function InitNumber(ANumber: Double; ABkColor: TsColor): TCellRecord;
begin
MyInitCellRecord(Result);
Result.ContentType := cctNumber;
Result.Numbervalue := ANumber;
if (ABkColor <> scTransparent) then begin
Result.UsedFormattingFields := Result.UsedFormattingFields + [uffBackground];
Result.BackgroundColor := ABkColor;
end;
end;
function InitString(AString: String; ABkColor: TsColor): TCellRecord;
begin
MyInitCellRecord(Result);
Result.ContentType := cctUTF8String;
Result.UTF8StringValue := AString;
if (ABkColor <> scTransparent) then begin
Result.UsedFormattingFields := Result.usedFormattingFields + [uffBackground];
Result.BackgroundColor := ABkColor;
end;
end;
function InitFormula(AFormula: String; ANumberResult: Double;
ABkColor: TsColor): TCellRecord;
begin
MyInitCellRecord(Result);
Result.FormulaValue := AFormula;
Result.NumberValue := ANumberResult;
Result.ContentType := cctNumber;
if (ABkColor <> scTransparent) then begin
Result.UsedFormattingFields := Result.usedFormattingFields + [uffBackground];
Result.BackgroundColor := ABkColor;
end;
end;
{ IMPORTANT: Carefully check the Test_Copy method if anything is changed here.
The expected test results are hard-coded in this method! }
procedure InitCopyData;
begin
SourceCells[0] := InitNumber(1.0, scTransparent); // will be in A1
SourceCells[1] := InitNumber(2.0, scTransparent);
SourceCells[2] := InitNumber(3.0, scYellow);
SourceCells[3] := InitString('Lazarus', scRed);
SourceCells[4] := InitFormula('A1+1', 2.0, scTransparent);
SourceCells[5] := InitFormula('$A1+1', 2.0, scTransparent);
SourceCells[6] := InitFormula('A$1+1', 2.0, scTransparent);
SourceCells[7] := InitFormula('$A$1+1', 2.0, scGray);
MyInitCellRecord(SourceCells[8]); // empty but existing
end;
{ TSpreadCopyTests }
procedure TSpreadCopyTests.SetUp;
begin
inherited SetUp;
InitCopyData;
end;
procedure TSpreadCopyTests.TearDown;
begin
inherited TearDown;
end;
{ This test prepares a worksheet and copies Values (ATestKind = 1 or 2), Formats
(ATestKind = 3 or 4), or Formulas (ATestKind = 5 or 6).
The odd ATestKind numbers copy the data to the empty column C,
the even ATestKind numbers copy them to the occupied column B which contains
the source data (those from column A), but shifted down by 1 cell.
The worksheet is saved, reloaded and compared to expectated data }
procedure TSpreadCopyTests.Test_Copy(ATestKind: Integer);
const
AFormat = sfExcel8;
var
TempFile: string;
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
i, row, col: Integer;
cell: PCell;
expectedFormula: String;
expectedStr, actualStr: String;
begin
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving]; //boAutoCalc];
MyWorkSheet:= MyWorkBook.AddWorksheet(CopyTestSheet);
// Prepare the worksheet in which cells are copied:
// Store the SourceCells to column A and B; in B shifted down by 1 cell
{ A B C
1 1.0
2 2.0 1.0
3 3.0 (yellow) 2.0
4 Lazarus (red) 3.0
5 A1+1 Lazarus
6 $A1+1 A1+1
7 A$1+1 $A1+1
8 $A$1+1 (gray) A$1+1
9 (empty) $A$1+1 (gray)
10 (empty)
}
for col := 0 to 1 do
for row := 0 to High(SourceCells) do
begin
// Adding the col to the row index shifts the data in the second column
// down. Offsetting the second column is done to avoid that the "copy"
// action operates on cells having a different content afterwards.
case SourceCells[row].ContentType of
cctNumber:
cell := MyWorksheet.WriteNumber(row+col, col, SourceCells[row].NumberValue);
cctUTF8String:
cell := Myworksheet.WriteText(row+col, col, SourceCells[row].UTF8StringValue);
cctEmpty:
cell := MyWorksheet.WriteBlank(row+col, col);
end;
if SourceCells[row].FormulaValue <> '' then
Myworksheet.WriteFormula(row+col, col, SourceCells[row].FormulaValue);
if SourceCells[row].BackgroundColor <> scTransparent then
MyWorksheet.WriteBackgroundColor(cell, SourceCells[row].BackgroundColor);
end;
MyWorksheet.CalcFormulas;
// Now perform the "copy" operations
for row := 0 to High(SourceCells) do
begin
cell := Myworksheet.FindCell(row, 0);
case ATestKind of
// 0: ; // don't copy, just write the original file for debugging
1: MyWorksheet.CopyValue(cell, row, 2);
2: MyWorksheet.CopyValue(cell, row, 1);
3: MyWorksheet.CopyFormat(cell, row, 2);
4: MyWorksheet.CopyFormat(cell, row, 1);
5: MyWorksheet.CopyFormula(cell, row, 2);
6: MyWorksheet.CopyFormula(cell, row, 1);
end;
end;
// Write to file
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boAutoCalc, boReadFormulas];
// Read spreadsheet file...
MyWorkbook.ReadFromFile(TempFile, AFormat);
MyWorksheet := MyWorkbook.GetFirstWorksheet;
MyWorksheet.CalcFormulas;
if odd(ATestKind) then col := 2 else col := 1;
for i:=0 to Length(SourceCells) do // the "-1" is dropped to catch the down-shifted column!
begin
row := i;
cell := MyWorksheet.FindCell(row, col);
// (1) -- Compare values ---
case ATestKind of
1, 2: // Copied values
if (cell <> nil) and (row <= High(SourceCells)) then
begin
// Check formula results
if MyHasFormula(@SourceCells[row]) then
CheckEquals(
SourceCells[0].NumberValue + 1, // +1 because that's what the formula does...
cell^.NumberValue,
'Result of copied formula mismatch, cell ' + CellNotation(MyWorksheet, row, col)
)
else
if (SourceCells[row].ContentType in [cctNumber, cctUTF8String, cctEmpty]) then
CheckEquals(
GetEnumName(TypeInfo(TCellContentType), Integer(SourceCells[row].ContentType)),
GetEnumName(TypeInfo(TCellContentType), Integer(cell^.ContentType)),
'Content type mismatch, cell '+CellNotation(MyWorksheet, row, col)
);
case SourceCells[row].ContentType of
cctNumber:
CheckEquals(
SourceCells[row].NumberValue,
cell^.NumberValue,
'Number value mismatch, cell ' + CellNotation(MyWorksheet, row, col)
);
cctUTF8String:
CheckEquals(
SourceCells[row].UTF8StringValue,
cell^.UTF8StringValue,
'String value mismatch, cell ' + CellNotation(MyWorksheet, row, col)
);
end;
end;
3: // Copied formats to empty column -> there must not be any content
if (cell <> nil) and (cell^.ContentType <> cctEmpty) then
CheckEquals(
true, // true = "the cell has no content"
(cell = nil) or (cell^.ContentType = cctEmpty),
'No content mismatch, cell ' + CellNotation(MyWorksheet, row,col)
);
4: // Copied formats to occupied column --> data must be equal to source
// cells, but offset by 1 cell
if (row = 0) then
CheckEquals(
true, // true = "the cell has no content"
(cell = nil) or (cell^.ContentType = cctEmpty),
'No content mismatch, cell ' + CellNotation(MyWorksheet, row, col)
)
else begin
if (SourceCells[i+col-2].ContentType in [cctNumber, cctUTF8String, cctEmpty]) then
CheckEquals(
GetEnumName(TypeInfo(TCellContentType), Integer(SourceCells[i+col-2].ContentType)),
GetEnumName(TypeInfo(TCellContentType), Integer(cell^.ContentType)),
'Content type mismatch, cell '+CellNotation(MyWorksheet, row, col)
);
case SourceCells[i+col-2].ContentType of
cctNumber:
CheckEquals(
SourceCells[i+col-2].NumberValue,
cell^.NumberValue,
'Number value mismatch, cell ' + CellNotation(MyWorksheet, row, col)
);
cctUTF8String:
CheckEquals(
SourceCells[i+col-2].UTF8StringValue,
cell^.UTF8StringValue,
'String value mismatch, cell ' + CellNotation(MyWorksheet, row, col)
);
end;
end;
end;
// (2) -- Compare formatting ---
case ATestKind of
1, 5:
CheckEquals(
true,
(cell = nil) or (MyWorksheet.ReadUsedFormatting(cell) = []),
'Default formatting mismatch, cell ' + CellNotation(MyWorksheet, row, col)
);
2, 6:
if (row = 0) then
CheckEquals(
true,
(cell = nil) or (MyWorksheet.ReadUsedFormatting(cell) = []),
'Default formatting mismatch, cell ' + CellNotation(MyWorksheet, row, col)
)
else
begin
expectedStr := SetToString(PTypeInfo(TypeInfo(TsUsedFormattingFields)),
integer(Sourcecells[i+col-2].UsedformattingFields), true);
actualStr := SetToString(PTypeInfo(TypeInfo(TsUsedFormattingFields)),
integer(MyWorksheet.ReadUsedFormatting(cell)), true);
CheckEquals(
expectedStr, actualStr,
'Used formatting fields mismatch, cell ' + CellNotation(myWorksheet, row, col)
);
if (uffBackground in SourceCells[i+(col-2)].UsedFormattingFields) then
CheckEquals(
SourceCells[i+(col-2)].BackgroundColor,
MyWorksheet.ReadBackgroundColor(cell),
'Background color mismatch, cell ' + CellNotation(Myworksheet, row, col)
);
end;
3, 4:
if (i = Length(SourceCells)) and (ATestKind = 4) then
CheckEquals(
true,
(cell = nil) or (MyWorksheet.ReadUsedFormatting(cell) = []),
'Default formatting mismatch, cell ' + CellNotation(MyWorksheet, row, col)
)
else
if (cell <> nil) then
begin
CheckEquals(
true,
SourceCells[i].UsedFormattingFields = MyWorksheet.ReadUsedFormatting(cell),
'Used formatting fields mismatch, cell ' + CellNotation(MyWorksheet, row, col)
);
if (uffBackground in SourceCells[i].UsedFormattingFields) then
CheckEquals(
SourceCells[i].BackgroundColor,
MyWorksheet.ReadBackgroundColor(cell),
'Background color mismatch, cell ' + CellNotation(Myworksheet, row, col)
);
end;
end;
// (3) --- Check formula ---
case ATestKind of
1, 2, 3:
CheckEquals(
false,
HasFormula(cell),
'No formula mismatch, cell ' + CellNotation(MyWorksheet, row, col)
);
4:
if (row = 0) then
CheckEquals(
false,
(cell <> nil) and HasFormula(cell),
'No formula mismatch, cell ' + CellNotation(Myworksheet, row, col)
)
else
CheckEquals(
SourceCells[i+col-2].FormulaValue,
MyWorksheet.ReadFormula(cell),
// cell^.Formulavalue,
'Formula mismatch, cell ' + CellNotation(MyWorksheet, row, col)
);
5:
if cell <> nil then
begin
case SourceCells[i].FormulaValue of
'A1+1' : expectedFormula := 'C1+1';
'A$1+1': expectedFormula := 'C$1+1';
else expectedFormula := SourceCells[i].FormulaValue;
end;
CheckEquals(
expectedFormula,
MyWorksheet.ReadFormula(cell),
// cell^.FormulaValue,
'Formula mismatch, cell ' + Cellnotation(Myworksheet, row, col)
);
end;
6:
begin
if (row = 0) or (i >= Length(SourceCells)) then
expectedFormula := ''
else
begin
case SourceCells[i].FormulaValue of
'A1+1' : expectedFormula := 'B1+1';
'A$1+1': expectedFormula := 'B$1+1';
'$A1+1': expectedFormula := '$A1+1';
else expectedFormula := SourceCells[i].FormulaValue;
end;
CheckEquals(
expectedFormula,
MyWorksheet.ReadFormula(cell),
// cell^.FormulaValue,
'Formula mismatch, cell ' + Cellnotation(Myworksheet, row, col)
);
end;
end;
end;
end; // For
finally
MyWorkbook.Free;
end;
DeleteFile(TempFile);
end;
{ Copy given cell values to empty cells }
procedure TSpreadCopyTests.Test_CopyValuesToEmptyCells;
begin
Test_Copy(1);
end;
{ Copy given cell values to occupied cells }
procedure TSpreadCopyTests.Test_CopyValuesToOccupiedCells;
begin
Test_Copy(2);
end;
{ Copy given cell formats to empty cells }
procedure TSpreadCopyTests.Test_CopyFormatsToEmptyCells;
begin
Test_Copy(3);
end;
{ Copy given cell formats to occupied cells }
procedure TSpreadCopyTests.Test_CopyFormatsToOccupiedCells;
begin
Test_Copy(4);
end;
{ Copy given cell formulas to empty cells }
procedure TSpreadCopyTests.Test_CopyFormulasToEmptyCells;
begin
Test_Copy(5);
end;
{ Copy given cell formulas to occupied cells }
procedure TSpreadCopyTests.Test_CopyFormulasToOccupiedCells;
begin
Test_Copy(6);
end;
initialization
RegisterTest(TSpreadCopyTests);
InitCopyData;
end.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
unit dbexporttests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testutils, testregistry,
fpstypes, fpsallformats, fpspreadsheet,
testsutility, db, bufdataset, fpsexport;
type
TExportTestData=record
id: integer;
Name: string;
DOB: TDateTime;
end;
var
ExportTestData: array[0..4] of TExportTestData;
procedure InitExportTestData;
type
{ TSpreadExportTests }
TSpreadExportTests = class(TTestCase)
private
FDataset: TBufDataset;
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
published
procedure TestExport;
end;
implementation
procedure InitExportTestData;
begin
with ExportTestData[0] do
begin
id:=1;
name:='Elvis Wesley';
dob:=encodedate(1912,12,31);
end;
with ExportTestData[1] do
begin
id:=2;
name:='Kingsley Dill';
dob:=encodedate(1918,11,11);
end;
with ExportTestData[2] do
begin
id:=3;
name:='Joe Snort';
dob:=encodedate(1988,8,4);
end;
with ExportTestData[3] do
begin
id:=4;
//> may give problems with character encoding
//http://forum.lazarus.freepascal.org/index.php/topic,26471.0.html
name:='Hagen > Dit';
dob:=encodedate(1944,2,24);
end;
with ExportTestData[4] do
begin
id:=5;
name:='';
dob:=encodedate(2112,4,12);
end;
end;
{ TSpreadExportTests }
procedure TSpreadExportTests.SetUp;
var
i:integer;
begin
inherited SetUp;
InitExportTestData;
FDataset:=TBufDataset.Create(nil);
with FDataset.FieldDefs do
begin
Add('id',ftAutoinc);
Add('name',ftString,40);
Add('dob',ftDateTime);
end;
FDataset.CreateDataset;
for i:=low(ExportTestData) to high(ExportTestData) do
begin
FDataset.Append;
//autoinc field should be filled by bufdataset
FDataSet.Fields.FieldByName('name').AsString:=ExportTestData[i].Name;
FDataSet.Fields.FieldByName('dob').AsDateTime:=ExportTestData[i].dob;
FDataSet.Post;
end;
end;
procedure TSpreadExportTests.TearDown;
begin
FDataset.Free;
inherited TearDown;
end;
procedure TSpreadExportTests.TestExport;
var
Exp: TFPSExport;
ExpSettings: TFPSExportFormatSettings;
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
Row: cardinal;
TempFile: string;
TheDate: TDateTime;
begin
Exp := TFPSExport.Create(nil);
ExpSettings := TFPSExportFormatSettings.Create(true);
try
ExpSettings.ExportFormat := efXLS;
ExpSettings.HeaderRow := true;
Exp.FormatSettings := ExpSettings;
Exp.Dataset:=FDataset;
Exp.FromCurrent:=false; //export from beginning
TempFile := NewTempFile;
Exp.FileName := TempFile;
CheckEquals(length(ExportTestData),Exp.Execute,'Number of exported records');
CheckTrue(FileExists(TempFile),'Export file must exist');
// Open the workbook for verification
MyWorkbook := TsWorkbook.Create;
try
// Format must match ExpSettings.ExportFormat above
MyWorkbook.ReadFromFile(TempFile, sfExcel8);
MyWorksheet := MyWorkbook.GetFirstWorksheet;
// ignore header row for now
for Row := 1 to length(ExportTestData) do
begin
// cell 0 is id
CheckEquals(ExportTestData[Row-1].id,MyWorkSheet.ReadAsNumber(Row,0),'Cell data: id');
CheckEquals(ExportTestData[Row-1].name,MyWorkSheet.ReadAsUTF8Text(Row,1),'Cell data: name');
MyWorkSheet.ReadAsDateTime(Row,2,TheDate);
CheckEquals(ExportTestData[Row-1].dob,TheDate,'Cell data: dob');
end;
finally
MyWorkBook.Free;
end;
finally
Exp.Free;
ExpSettings.Free;
DeleteFile(TempFile);
end;
end;
initialization
// Register so these tests are included in a full run
RegisterTest(TSpreadExportTests);
InitExportTestData; //useful to have norm data if other code want to use this unit
end.
end.

View File

@ -0,0 +1,972 @@
unit emptycelltests;
{$mode objfpc}{$H+}
interface
{ Tests for correct location of empty cells
This unit test is writing out to and reading back from files.
}
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8, fpsopendocument, {and a project requirement for lclbase for utf8 handling}
testsutility;
var
// Norm to test against - list of strings that show the layout of empty and occupied cells
SollLayoutStrings: array[0..9] of string;
procedure InitSollLayouts;
type
{ TSpreadWriteReadEmptyCellTests }
//Write to xls/xml file and read back
TSpreadWriteReadEmptyCellTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteReadEmptyCells(AFormat: TsSpreadsheetFormat;
ALayout: Integer; AInverted: Boolean);
published
// Writes out cell layouts
{ BIFF2 file format tests }
procedure TestWriteReadEmptyCells_BIFF2_0;
procedure TestWriteReadEmptyCells_BIFF2_0_inv;
procedure TestWriteReadEmptyCells_BIFF2_1;
procedure TestWriteReadEmptyCells_BIFF2_1_inv;
procedure TestWriteReadEmptyCells_BIFF2_2;
procedure TestWriteReadEmptyCells_BIFF2_2_inv;
procedure TestWriteReadEmptyCells_BIFF2_3;
procedure TestWriteReadEmptyCells_BIFF2_3_inv;
procedure TestWriteReadEmptyCells_BIFF2_4;
procedure TestWriteReadEmptyCells_BIFF2_4_inv;
procedure TestWriteReadEmptyCells_BIFF2_5;
procedure TestWriteReadEmptyCells_BIFF2_5_inv;
procedure TestWriteReadEmptyCells_BIFF2_6;
procedure TestWriteReadEmptyCells_BIFF2_6_inv;
procedure TestWriteReadEmptyCells_BIFF2_7;
procedure TestWriteReadEmptyCells_BIFF2_7_inv;
procedure TestWriteReadEmptyCells_BIFF2_8;
procedure TestWriteReadEmptyCells_BIFF2_8_inv;
procedure TestWriteReadEmptyCells_BIFF2_9;
procedure TestWriteReadEmptyCells_BIFF2_9_inv;
{ BIFF5 file format tests }
procedure TestWriteReadEmptyCells_BIFF5_0;
procedure TestWriteReadEmptyCells_BIFF5_0_inv;
procedure TestWriteReadEmptyCells_BIFF5_1;
procedure TestWriteReadEmptyCells_BIFF5_1_inv;
procedure TestWriteReadEmptyCells_BIFF5_2;
procedure TestWriteReadEmptyCells_BIFF5_2_inv;
procedure TestWriteReadEmptyCells_BIFF5_3;
procedure TestWriteReadEmptyCells_BIFF5_3_inv;
procedure TestWriteReadEmptyCells_BIFF5_4;
procedure TestWriteReadEmptyCells_BIFF5_4_inv;
procedure TestWriteReadEmptyCells_BIFF5_5;
procedure TestWriteReadEmptyCells_BIFF5_5_inv;
procedure TestWriteReadEmptyCells_BIFF5_6;
procedure TestWriteReadEmptyCells_BIFF5_6_inv;
procedure TestWriteReadEmptyCells_BIFF5_7;
procedure TestWriteReadEmptyCells_BIFF5_7_inv;
procedure TestWriteReadEmptyCells_BIFF5_8;
procedure TestWriteReadEmptyCells_BIFF5_8_inv;
procedure TestWriteReadEmptyCells_BIFF5_9;
procedure TestWriteReadEmptyCells_BIFF5_9_inv;
{ BIFF8 file format tests }
procedure TestWriteReadEmptyCells_BIFF8_0;
procedure TestWriteReadEmptyCells_BIFF8_0_inv;
procedure TestWriteReadEmptyCells_BIFF8_1;
procedure TestWriteReadEmptyCells_BIFF8_1_inv;
procedure TestWriteReadEmptyCells_BIFF8_2;
procedure TestWriteReadEmptyCells_BIFF8_2_inv;
procedure TestWriteReadEmptyCells_BIFF8_3;
procedure TestWriteReadEmptyCells_BIFF8_3_inv;
procedure TestWriteReadEmptyCells_BIFF8_4;
procedure TestWriteReadEmptyCells_BIFF8_4_inv;
procedure TestWriteReadEmptyCells_BIFF8_5;
procedure TestWriteReadEmptyCells_BIFF8_5_inv;
procedure TestWriteReadEmptyCells_BIFF8_6;
procedure TestWriteReadEmptyCells_BIFF8_6_inv;
procedure TestWriteReadEmptyCells_BIFF8_7;
procedure TestWriteReadEmptyCells_BIFF8_7_inv;
procedure TestWriteReadEmptyCells_BIFF8_8;
procedure TestWriteReadEmptyCells_BIFF8_8_inv;
procedure TestWriteReadEmptyCells_BIFF8_9;
procedure TestWriteReadEmptyCells_BIFF8_9_inv;
{ OpenDocument file format tests }
procedure TestWriteReadEmptyCells_ODS_0;
procedure TestWriteReadEmptyCells_ODS_0_inv;
procedure TestWriteReadEmptyCells_ODS_1;
procedure TestWriteReadEmptyCells_ODS_1_inv;
procedure TestWriteReadEmptyCells_ODS_2;
procedure TestWriteReadEmptyCells_ODS_2_inv;
procedure TestWriteReadEmptyCells_ODS_3;
procedure TestWriteReadEmptyCells_ODS_3_inv;
procedure TestWriteReadEmptyCells_ODS_4;
procedure TestWriteReadEmptyCells_ODS_4_inv;
procedure TestWriteReadEmptyCells_ODS_5;
procedure TestWriteReadEmptyCells_ODS_5_inv;
procedure TestWriteReadEmptyCells_ODS_6;
procedure TestWriteReadEmptyCells_ODS_6_inv;
procedure TestWriteReadEmptyCells_ODS_7;
procedure TestWriteReadEmptyCells_ODS_7_inv;
procedure TestWriteReadEmptyCells_ODS_8;
procedure TestWriteReadEmptyCells_ODS_8_inv;
procedure TestWriteReadEmptyCells_ODS_9;
procedure TestWriteReadEmptyCells_ODS_9_inv;
{ OOXML file format tests }
procedure TestWriteReadEmptyCells_OOXML_0;
procedure TestWriteReadEmptyCells_OOXML_0_inv;
procedure TestWriteReadEmptyCells_OOXML_1;
procedure TestWriteReadEmptyCells_OOXML_1_inv;
procedure TestWriteReadEmptyCells_OOXML_2;
procedure TestWriteReadEmptyCells_OOXML_2_inv;
procedure TestWriteReadEmptyCells_OOXML_3;
procedure TestWriteReadEmptyCells_OOXML_3_inv;
procedure TestWriteReadEmptyCells_OOXML_4;
procedure TestWriteReadEmptyCells_OOXML_4_inv;
procedure TestWriteReadEmptyCells_OOXML_5;
procedure TestWriteReadEmptyCells_OOXML_5_inv;
procedure TestWriteReadEmptyCells_OOXML_6;
procedure TestWriteReadEmptyCells_OOXML_6_inv;
procedure TestWriteReadEmptyCells_OOXML_7;
procedure TestWriteReadEmptyCells_OOXML_7_inv;
procedure TestWriteReadEmptyCells_OOXML_8;
procedure TestWriteReadEmptyCells_OOXML_8_inv;
procedure TestWriteReadEmptyCells_OOXML_9;
procedure TestWriteReadEmptyCells_OOXML_9_inv;
{ §xcel/XML file format tests }
procedure TestWriteReadEmptyCells_XML_0;
procedure TestWriteReadEmptyCells_XML_0_inv;
procedure TestWriteReadEmptyCells_XML_1;
procedure TestWriteReadEmptyCells_XML_1_inv;
procedure TestWriteReadEmptyCells_XML_2;
procedure TestWriteReadEmptyCells_XML_2_inv;
procedure TestWriteReadEmptyCells_XML_3;
procedure TestWriteReadEmptyCells_XML_3_inv;
procedure TestWriteReadEmptyCells_XML_4;
procedure TestWriteReadEmptyCells_XML_4_inv;
procedure TestWriteReadEmptyCells_XML_5;
procedure TestWriteReadEmptyCells_XML_5_inv;
procedure TestWriteReadEmptyCells_XML_6;
procedure TestWriteReadEmptyCells_XML_6_inv;
procedure TestWriteReadEmptyCells_XML_7;
procedure TestWriteReadEmptyCells_XML_7_inv;
procedure TestWriteReadEmptyCells_XML_8;
procedure TestWriteReadEmptyCells_XML_8_inv;
procedure TestWriteReadEmptyCells_XML_9;
procedure TestWriteReadEmptyCells_XML_9_inv;
end;
implementation
const
EmptyCellsSheet = 'EmptyCells';
procedure InitSollLayouts;
begin
SollLayoutStrings[0] := 'x x|'+
' |'+
' ox |'+
' |'+
'x x|';
SollLayoutStrings[1] := 'xx xx |'+
' xx xx|'+
'xx xx |';
SollLayoutStrings[2] := 'xxooxxoo|'+
'ooxxooxx|'+
'xxooxxoo|';
SollLayoutStrings[3] := ' |'+
'xxxxxxxx|'+
' |';
SollLayoutStrings[4] := ' |'+
'xxxxxxxx';
SollLayoutStrings[5] := 'xxxxxxxx|'+
' |'+
' ';
SollLayoutStrings[6] := 'xxxxxxxx|'+
' x x |'+
' |';
SollLayoutStrings[7] := ' |'+
' |'+
' xx |'+
' xx |';
SollLayoutStrings[8] := ' |'+
' |'+
' x x |'+
' x x |';
SollLayoutStrings[9] := 'oooooooo|'+
'oooooooo|'+
'oooxoxoo|'+
' x x |';
end;
{ TSpreadWriteReadEmptyCellTests }
procedure TSpreadWriteReadEmptyCellTests.SetUp;
begin
inherited SetUp;
InitSollLayouts;
end;
procedure TSpreadWriteReadEmptyCellTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells(
AFormat: TsSpreadsheetFormat; ALayout: Integer; AInverted: Boolean);
const
CELLTEXT = 'x';
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col: Integer;
MyCell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
L: TStringList;
s: String;
function FixODS(s: String): String;
// In this test, ODS cannot distinguish between a blank and a nonexisting cell
var
i: Integer;
begin
Result := s;
for i := 1 to Length(Result) do
if Result[i] = 'o' then begin
if AInverted then Result[i] := 'x' else Result[i] := ' ';
end;
end;
begin
TempFile := GetTempFileName;
L := TStringList.Create;
try
L.Delimiter := '|';
L.StrictDelimiter := true;
L.DelimitedText := SollLayoutStrings[ALayout];
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(EmptyCellsSheet);
// Write out cells
// 'x' --> write label cell
// 'o' --> write blank cell
// ' ' --> do not write a cell
for row := 0 to L.Count-1 do begin
s := L[row];
for col := 0 to Length(s)-1 do begin
if AInverted then begin
if s[col+1] = ' ' then s[col+1] := 'x'
else
if s[col+1] = 'x' then s[col+1] := ' ';
end;
if s[col+1] = 'x' then
MyWorksheet.WriteText(row, col, CELLTEXT)
else
if s[col+1] = 'o' then
MyWorksheet.WriteBlank(row, col);
end;
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, EmptyCellsSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
for row := 0 to MyWorksheet.GetLastRowIndex do begin
SetLength(s, MyWorksheet.GetLastColIndex + 1);
for col := 0 to MyWorksheet.GetLastColIndex do begin
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
s[col+1] := ' '
else
if MyCell^.ContentType = cctEmpty then
s[col+1] := 'o'
else
s[col+1] := 'x';
if AInverted then begin
if s[col+1] = ' ' then s[col+1] := 'x'
else
if s[col+1] = 'x' then s[col+1] := ' ';
end;
end;
if AInverted then
while Length(s) < Length(L[row]) do s := s + 'x'
else
while Length(s) < Length(L[row]) do s := s + ' ';
if AFormat = sfOpenDocument then
CheckEquals(FixODS(L[row]), s,
'Test empty cell layout mismatch, cell '+CellNotation(MyWorksheet, Row, Col))
else
CheckEquals(L[row], s,
'Test empty cell layout mismatch, cell '+CellNotation(MyWorksheet, Row, Col));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
finally
L.Free;
end;
end;
{ BIFF2 tests }
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_0;
begin
TestWriteReadEmptyCells(sfExcel2, 0, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_0_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 0, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_1;
begin
TestWriteReadEmptyCells(sfExcel2, 1, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_1_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 1, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_2;
begin
TestWriteReadEmptyCells(sfExcel2, 2, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_2_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 2, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_3;
begin
TestWriteReadEmptyCells(sfExcel2, 3, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_3_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 3, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_4;
begin
TestWriteReadEmptyCells(sfExcel2, 4, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_4_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 4, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_5;
begin
TestWriteReadEmptyCells(sfExcel2, 5, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_5_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 5, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_6;
begin
TestWriteReadEmptyCells(sfExcel2, 6, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_6_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 6, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_7;
begin
TestWriteReadEmptyCells(sfExcel2, 7, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_7_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 7, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_8;
begin
TestWriteReadEmptyCells(sfExcel2, 8, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_8_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 8, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_9;
begin
TestWriteReadEmptyCells(sfExcel2, 9, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF2_9_inv;
begin
TestWriteReadEmptyCells(sfExcel2, 9, true);
end;
{ BIFF5 tests }
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_0;
begin
TestWriteReadEmptyCells(sfExcel5, 0, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_0_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 0, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_1;
begin
TestWriteReadEmptyCells(sfExcel5, 1, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_1_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 1, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_2;
begin
TestWriteReadEmptyCells(sfExcel5, 2, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_2_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 2, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_3;
begin
TestWriteReadEmptyCells(sfExcel5, 3, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_3_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 3, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_4;
begin
TestWriteReadEmptyCells(sfExcel5, 4, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_4_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 4, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_5;
begin
TestWriteReadEmptyCells(sfExcel5, 5, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_5_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 5, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_6;
begin
TestWriteReadEmptyCells(sfExcel5, 6, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_6_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 6, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_7;
begin
TestWriteReadEmptyCells(sfExcel5, 7, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_7_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 7, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_8;
begin
TestWriteReadEmptyCells(sfExcel5, 8, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_8_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 8, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_9;
begin
TestWriteReadEmptyCells(sfExcel5, 9, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF5_9_inv;
begin
TestWriteReadEmptyCells(sfExcel5, 9, true);
end;
{ BIFF8 tests }
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_0;
begin
TestWriteReadEmptyCells(sfExcel8, 0, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_0_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 0, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_1;
begin
TestWriteReadEmptyCells(sfExcel8, 1, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_1_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 1, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_2;
begin
TestWriteReadEmptyCells(sfExcel8, 2, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_2_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 2, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_3;
begin
TestWriteReadEmptyCells(sfExcel8, 3, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_3_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 3, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_4;
begin
TestWriteReadEmptyCells(sfExcel8, 4, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_4_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 4, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_5;
begin
TestWriteReadEmptyCells(sfExcel8, 5, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_5_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 5, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_6;
begin
TestWriteReadEmptyCells(sfExcel8, 6, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_6_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 6, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_7;
begin
TestWriteReadEmptyCells(sfExcel8, 7, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_7_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 7, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_8;
begin
TestWriteReadEmptyCells(sfExcel8, 8, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_8_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 8, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_9;
begin
TestWriteReadEmptyCells(sfExcel8, 9, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_BIFF8_9_inv;
begin
TestWriteReadEmptyCells(sfExcel8, 9, true);
end;
{ OpenDocument tests }
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_0;
begin
TestWriteReadEmptyCells(sfOpenDocument, 0, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_0_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 0, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_1;
begin
TestWriteReadEmptyCells(sfOpenDocument, 1, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_1_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 1, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_2;
begin
TestWriteReadEmptyCells(sfOpenDocument, 2, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_2_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 2, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_3;
begin
TestWriteReadEmptyCells(sfOpenDocument, 3, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_3_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 3, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_4;
begin
TestWriteReadEmptyCells(sfOpenDocument, 4, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_4_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 4, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_5;
begin
TestWriteReadEmptyCells(sfOpenDocument, 5, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_5_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 5, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_6;
begin
TestWriteReadEmptyCells(sfOpenDocument, 6, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_6_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 6, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_7;
begin
TestWriteReadEmptyCells(sfOpenDocument, 7, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_7_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 7, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_8;
begin
TestWriteReadEmptyCells(sfOpenDocument, 8, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_8_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 8, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_9;
begin
TestWriteReadEmptyCells(sfOpenDocument, 9, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_ODS_9_inv;
begin
TestWriteReadEmptyCells(sfOpenDocument, 9, true);
end;
{ OOXML tests }
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_0;
begin
TestWriteReadEmptyCells(sfOOXML, 0, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_0_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 0, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_1;
begin
TestWriteReadEmptyCells(sfOOXML, 1, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_1_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 1, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_2;
begin
TestWriteReadEmptyCells(sfOOXML, 2, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_2_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 2, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_3;
begin
TestWriteReadEmptyCells(sfOOXML, 3, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_3_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 3, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_4;
begin
TestWriteReadEmptyCells(sfOOXML, 4, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_4_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 4, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_5;
begin
TestWriteReadEmptyCells(sfOOXML, 5, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_5_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 5, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_6;
begin
TestWriteReadEmptyCells(sfOOXML, 6, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_6_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 6, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_7;
begin
TestWriteReadEmptyCells(sfOOXML, 7, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_7_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 7, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_8;
begin
TestWriteReadEmptyCells(sfOOXML, 8, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_8_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 8, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_9;
begin
TestWriteReadEmptyCells(sfOOXML, 9, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_OOXML_9_inv;
begin
TestWriteReadEmptyCells(sfOOXML, 9, true);
end;
{ Excel2003 / XML tests }
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_0;
begin
TestWriteReadEmptyCells(sfExcelXML, 0, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_0_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 0, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_1;
begin
TestWriteReadEmptyCells(sfExcelXML, 1, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_1_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 1, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_2;
begin
TestWriteReadEmptyCells(sfExcelXML, 2, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_2_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 2, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_3;
begin
TestWriteReadEmptyCells(sfExcelXML, 3, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_3_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 3, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_4;
begin
TestWriteReadEmptyCells(sfExcelXML, 4, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_4_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 4, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_5;
begin
TestWriteReadEmptyCells(sfExcelXML, 5, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_5_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 5, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_6;
begin
TestWriteReadEmptyCells(sfExcelXML, 6, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_6_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 6, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_7;
begin
TestWriteReadEmptyCells(sfExcelXML, 7, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_7_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 7, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_8;
begin
TestWriteReadEmptyCells(sfExcelXML, 8, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_8_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 8, true);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_9;
begin
TestWriteReadEmptyCells(sfExcelXML, 9, false);
end;
procedure TSpreadWriteReadEmptyCellTests.TestWriteReadEmptyCells_XML_9_inv;
begin
TestWriteReadEmptyCells(sfExcelXML, 9, true);
end;
initialization
RegisterTest(TSpreadWriteReadEmptyCellTests);
InitSollLayouts;
end.

View File

@ -0,0 +1,363 @@
{ Tests for iteration through cells by means of the enumerator of the cells tree.
This unit test is not writing anything to file.
}
unit enumeratortests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, fpsclasses, {and a project requirement for lclbase for utf8 handling}
testsutility;
type
{ TSpreadEnumeratorTests }
TSpreadEnumeratorTests = class(TTestCase)
private
protected
procedure SetUp; override;
procedure TearDown; override;
procedure Test_EnumCells(what: Integer; reverse, withGaps: Boolean);
procedure Test_EnumComments(what: Integer; withGaps: Boolean);
published
procedure Test_Enum_Cells_All;
procedure Test_Enum_Cells_All_Reverse;
procedure Test_Enum_Cells_FullRow;
procedure Test_Enum_Cells_FullRow_Reverse;
procedure Test_Enum_Cells_FullCol;
procedure Test_Enum_Cells_FullCol_Reverse;
procedure Test_Enum_Cells_PartialRow;
procedure Test_Enum_Cells_PartialRow_Reverse;
procedure Test_Enum_Cells_PartialCol;
procedure Test_Enum_Cells_PartialCol_Reverse;
procedure Test_Enum_Cells_Range;
procedure Test_Enum_Cells_Range_Reverse;
procedure Test_Enum_Cells_WithGaps_All;
procedure Test_Enum_Cells_WithGaps_All_Reverse;
procedure Test_Enum_Cells_WithGaps_FullRow;
procedure Test_Enum_Cells_WithGaps_FullRow_Reverse;
procedure Test_Enum_Cells_WithGaps_FullCol;
procedure Test_Enum_Cells_WithGaps_FullCol_Reverse;
procedure Test_Enum_Cells_WithGaps_PartialRow;
procedure Test_Enum_Cells_WithGaps_PartialRow_Reverse;
procedure Test_Enum_Cells_WithGaps_PartialCol;
procedure Test_Enum_Cells_WithGaps_PartialCol_Reverse;
procedure Test_Enum_Cells_WithGaps_Range;
procedure Test_Enum_Cells_WithGaps_Range_Reverse;
procedure Test_Enum_Comments_All;
procedure Test_Enum_Comments_Range;
procedure Test_Enum_Comments_WithGaps_All;
procedure Test_Enum_Comments_WithGaps_Range;
end;
implementation
const
NUM_ROWS = 100;
NUM_COLS = 100;
TEST_ROW = 10;
TEST_COL = 20;
TEST_ROW1 = 20;
TEST_ROW2 = 50;
TEST_COL1 = 30;
TEST_COL2 = 60;
procedure TSpreadEnumeratorTests.Setup;
begin
end;
procedure TSpreadEnumeratorTests.TearDown;
begin
end;
procedure TSpreadEnumeratorTests.Test_EnumCells(what: Integer; reverse: Boolean;
withGaps: Boolean);
{ what = 1 ---> iterate through entire worksheet
what = 2 ---> iterate along full row
what = 3 ---> iterate along full column
what = 4 ---> iterate along partial row
what = 5 ---> iterate along partial column
what = 6 ---> iterate through rectangular cell range
The test writes numbers into the worksheet calculated by <row>*10000 + <col>.
Then the test iterates through the designed range (according to "what") and
compares the read number with the soll values.
If "withGaps" is true then numbers are only written at cells where
<col>+<row> is odd. }
var
row, col: Cardinal;
cell: PCell;
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
expected, actual: Double;
enumerator: TsCellEnumerator;
begin
MyWorkbook := TsWorkbook.Create;
try
MyWorksheet := MyWorkbook.AddWorksheet('Sheet1');
for row := 0 to NUM_ROWS-1 do
for col := 0 to NUM_COLS-1 do
if (withGaps and odd(row + col)) or (not withGaps) then
MyWorksheet.WriteNumber(row, col, row*10000.0 + col);
if reverse then
case what of
1: enumerator := MyWorksheet.Cells.GetReverseRangeEnumerator(0, 0, $7FFFFFFF, $7FFFFFFF);
2: enumerator := Myworksheet.Cells.GetReverseRowEnumerator(TEST_ROW);
3: enumerator := MyWorksheet.Cells.GetReverseColEnumerator(TEST_COL);
4: enumerator := MyWorksheet.Cells.GetReverseRowEnumerator(TEST_ROW, TEST_COL1, TEST_COL2);
5: enumerator := Myworksheet.Cells.GetReverseColEnumerator(TEST_COL, TEST_ROW1, TEST_ROW2);
6: enumerator := MyWorksheet.Cells.GetReverseRangeEnumerator(TEST_ROW1, TEST_COL1, TEST_ROW2, TEST_COL2);
end
else
case what of
1: enumerator := MyWorksheet.Cells.GetEnumerator;
2: enumerator := Myworksheet.Cells.GetRowEnumerator(TEST_ROW);
3: enumerator := MyWorksheet.Cells.GetColEnumerator(TEST_COL);
4: enumerator := MyWorksheet.Cells.GetRowEnumerator(TEST_ROW, TEST_COL1, TEST_COL2);
5: enumerator := Myworksheet.Cells.GetColEnumerator(TEST_COL, TEST_ROW1, TEST_ROW2);
6: enumerator := MyWorksheet.Cells.GetRangeEnumerator(TEST_ROW1, TEST_COL1, TEST_ROW2, TEST_COL2);
end;
for cell in enumerator do
begin
row := cell^.Row;
col := cell^.Col;
if (withgaps and odd(row + col)) or (not withgaps) then
expected := row * 10000.0 + col
else
expected := 0.0;
actual := MyWorksheet.ReadAsNumber(cell);
CheckEquals(expected, actual,
'Enumerated cell value mismatch, cell '+CellNotation(MyWorksheet, row, col));
end;
// for debugging, to see the data file
// MyWorkbook.WriteToFile('enumerator-test.xlsx', sfOOXML, true);
finally
MyWorkbook.Free;
end;
end;
procedure TSpreadEnumeratorTests.Test_EnumComments(what: Integer;
withGaps: Boolean);
{ what = 1 ---> iterate through entire worksheet
what = 2 ---> iterate through rectangular cell range
The test writes comments into the worksheet calculated by <row>*10000 + <col>.
Then the test iterates through the designed range (according to "what") and
compares the read comments with the soll values.
if "withGaps" is true then comments are only written at cells where
<col>+<row> is odd. }
var
row, col: Cardinal;
comment: PsComment;
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
expected, actual: string;
enumerator: TsCommentEnumerator;
begin
MyWorkbook := TsWorkbook.Create;
try
MyWorksheet := MyWorkbook.AddWorksheet('Sheet1');
for row := 0 to NUM_ROWS-1 do
for col := 0 to NUM_COLS-1 do
if (withGaps and odd(row + col)) or (not withGaps) then
MyWorksheet.WriteComment(row, col, IntToStr(row*10000 + col));
case what of
1: enumerator := MyWorksheet.Comments.GetEnumerator;
2: enumerator := MyWorksheet.Comments.GetRangeEnumerator(TEST_ROW1, TEST_COL1, TEST_ROW2, TEST_COL2);
end;
for comment in enumerator do
begin
row := comment^.Row;
col := comment^.Col;
if (withgaps and odd(row + col)) or (not withgaps) then
expected := IntToStr(row * 10000 + col)
else
expected := '';
actual := MyWorksheet.ReadComment(row, col);
CheckEquals(expected, actual,
'Enumerated comment mismatch, cell '+CellNotation(MyWorksheet, row, col));
end;
// for debugging, to see the data file
// MyWorkbook.WriteToFile('enumerator-test.xlsx', sfOOXML, true);
finally
MyWorkbook.Free;
end;
end;
{ Fully filled worksheet }
procedure TSpreadEnumeratorTests.Test_Enum_Cells_All;
begin
Test_Enumcells(1, false, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_All_Reverse;
begin
Test_EnumCells(1, true, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_FullRow;
begin
Test_EnumCells(2, false, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_FullRow_Reverse;
begin
Test_EnumCells(2, true, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_FullCol;
begin
Test_EnumCells(3, false, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_FullCol_Reverse;
begin
Test_EnumCells(3, true, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_PartialRow;
begin
Test_EnumCells(4, false, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_PartialRow_Reverse;
begin
Test_EnumCells(4, true, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_PartialCol;
begin
Test_EnumCells(5, false, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_PartialCol_Reverse;
begin
Test_EnumCells(5, true, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_Range;
begin
Test_EnumCells(6, false, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_Range_Reverse;
begin
Test_EnumCells(6, true, false);
end;
{ Worksheet with gaps}
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_All;
begin
Test_Enumcells(1, false, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_All_Reverse;
begin
Test_EnumCells(1, true, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_FullRow;
begin
Test_EnumCells(2, false, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_FullRow_Reverse;
begin
Test_EnumCells(2, true, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_FullCol;
begin
Test_EnumCells(3, false, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_FullCol_Reverse;
begin
Test_EnumCells(3, true, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_PartialRow;
begin
Test_EnumCells(4, false, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_PartialRow_Reverse;
begin
Test_EnumCells(4, true, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_PartialCol;
begin
Test_EnumCells(5, false, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_PartialCol_Reverse;
begin
Test_EnumCells(5, true, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_Range;
begin
Test_EnumCells(6, false, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Cells_WithGaps_Range_Reverse;
begin
Test_EnumCells(6, true, true);
end;
{ Fully filled worksheet }
procedure TSpreadEnumeratorTests.Test_Enum_Comments_All;
begin
Test_EnumComments(1, false);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Comments_Range;
begin
Test_EnumComments(2, false);
end;
{ Every other cell empty }
procedure TSpreadEnumeratorTests.Test_Enum_Comments_WithGaps_All;
begin
Test_EnumComments(1, true);
end;
procedure TSpreadEnumeratorTests.Test_Enum_Comments_WithGaps_Range;
begin
Test_EnumComments(2, true);
end;
initialization
RegisterTest(TSpreadEnumeratorTests);
end.

View File

@ -0,0 +1,268 @@
unit errortests;
{$mode objfpc}{$H+}
{ Tests for error logging by readers / writers }
interface
uses
// Not using lazarus package as the user may be working with multiple versions
// Instead, add ".." to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet {and a project requirement for lclbase for utf8 handling},
fpsutils, testsutility;
type
{ TSpreadErrorTests }
TSpreadErrorTests= class(TTestCase)
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteErrorMessages(AFormat: TsSpreadsheetFormat);
published
// Tests collection of error messages during writing
procedure TestWriteErrorMessages_BIFF2;
procedure TestWriteErrorMessages_BIFF5;
procedure TestWriteErrorMessages_BIFF8;
procedure TestWriteErrorMessages_ODS;
procedure TestWriteErrorMessages_OOXML;
procedure TestWriteErrorMessages_XML;
end;
implementation
uses
StrUtils, fpsPalette, fpsRPN, xlsbiff5;
const
ERROR_SHEET = 'ErrorTest'; //worksheet name
procedure TSpreadErrorTests.SetUp;
begin
end;
procedure TSpreadErrorTests.TearDown;
begin
end;
procedure TSpreadErrorTests.TestWriteErrorMessages(AFormat: TsSpreadsheetFormat);
type
TTestParam = record
Format: TsSpreadsheetFormat;
MaxRowCount: Cardinal;
MaxColCount: Cardinal;
MaxCellLen: Cardinal;
end;
const
TestParams: array[0..5] of TTestParam = (
(Format: sfExcel2; MaxRowCount: 65536; MaxColCount: 256; MaxCellLen: 255),
(Format: sfExcel5; MaxRowCount: 65536; MaxColCount: 256; MaxCellLen: 255),
(Format: sfExcel8; MaxRowCount: 65536; MaxColCount: 256; MaxCellLen: 32767),
(Format: sfExcelXML; MaxRowCount: 65536; MaxColCount: 256; MaxCellLen: 32767),
(Format: sfOOXML; MaxRowCount: 1048576; MaxColCount: 16384; MaxCellLen: $FFFFFFFF),
(Format: sfOpenDocument; MaxRowCount: 1048576; MaxColCount: 1024; MaxCellLen: $FFFFFFFF)
);
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
row, col: Cardinal;
row1, row2: Cardinal;
col1, col2: Cardinal;
formula: string;
s: String;
TempFile: String;
ErrList: TStringList;
newColor: TsColor;
expected: integer;
palette: TsPalette;
i: Integer;
testIndex: Integer;
begin
formula := '=A1';
testIndex := -1;
for i:=0 to High(TestParams) do
if TestParams[i].Format = AFormat then begin
testIndex := i;
break;
end;
if testIndex = -1 then
raise Exception.CreateFmt('[TSpreadErrorTests.TestWriteErrorMessages] File format %d not found.', [AFormat]);
ErrList := TStringList.Create;
try
// Test 1: Too many rows
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(ERROR_SHEET);
row1 := Testparams[testIndex].MaxRowCount - 5;
row2 := Testparams[testIndex].MaxRowCount + 5;
for row := row1 to row2 do begin
MyWorksheet.WriteBlank(row, 0);
MyWorksheet.WriteNumber(row, 1, 1.0);
MyWorksheet.WriteText(row, 2, 'A');
MyWorksheet.WriteFormula(Row, 3, formula);
MyWorksheet.WriteRPNFormula(row, 4, CreateRPNFormula(
RPNCellValue('A1', nil)));
end;
TempFile:=NewTempFile;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
ErrList.Text := MyWorkbook.ErrorMsg;
CheckEquals(1, ErrList.Count, 'Error count mismatch in test 1');
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
// Test 2: Too many columns
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(ERROR_SHEET);
col1 := TestParams[testIndex].MaxColCount - 5;
col2 := TestParams[testIndex].MaxColCount + 5;
for col := col1 to col2 do begin
MyWorksheet.WriteBlank(0, col);
MyWorksheet.WriteNumber(1, col, 1.0);
MyWorksheet.WriteText(2, col, 'A');
MyWorksheet.WriteFormula(3, col, formula);
MyWorksheet.WriteRPNFormula(4, col, CreateRPNFormula(
RPNCellValue('A1', nil)));
end;
TempFile:=NewTempFile;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
ErrList.Text := MyWorkbook.ErrorMsg;
CheckEquals(1, ErrList.Count, 'Error count mismatch in test 2');
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
// Test 3: Too many colors
MyWorkbook := TsWorkbook.Create;
try
// Prepare a full palette
palette := TsPalette.Create;
try
// Create random palette of 65 unique entries -> 1 too many for Excel5/8
// and a lot too many for BIFF2
palette.AddBuiltinColors;
for i:=palette.Count to 65 do
begin
repeat
newColor := random(256) + random(256) shl 8 + random(256) shl 16;
until palette.FindColor(newColor) = -1;
palette.AddColor(newColor);
end;
MyWorkSheet:= MyWorkBook.AddWorksheet(ERROR_SHEET);
// Use all colors in order to have them in the palette to be written
// to file.
for row := 0 to palette.Count-1 do
begin
MyWorksheet.WriteText(row, 0, s);
MyWorksheet.WriteFontColor(row, 0, palette[row]);
end;
TempFile:=NewTempFile;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
ErrList.Text := MyWorkbook.ErrorMsg;
// Palette usage in biff --> expecting error due to too large palette
if (AFormat in [sfExcel2, sfExcel5, sfExcel8]) then
expected := 1
else
// no palette in xml --> no error expected
expected := 0;
CheckEquals(expected, ErrList.Count, 'Error count mismatch in test 3');
finally
palette.Free;
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
// Test 4: Too long cell label
if TestParams[testIndex].MaxCellLen <> Cardinal(-1) then begin
s := DupeString('A', TestParams[testIndex].MaxCellLen + 10);
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(ERROR_SHEET);
MyWorksheet.WriteText(0, 0, s);
TempFile:=NewTempFile;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
ErrList.Text := MyWorkbook.ErrorMsg;
CheckEquals(1, ErrList.Count, 'Error count mismatch in test 4');
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
// Test 5: cell text contains forbidden XML character
if (AFormat in [sfOOXML, sfOpenDocument]) then begin
s := #19'Standard';
MyWorkbook := TsWorkbook.Create;
try
MyWorksheet := MyWorkbook.AddWorksheet(ERROR_SHEET);
Myworksheet.WriteText(0, 0, s);
TempFile := NewTempFile;
Myworkbook.WriteToFile(TempFile, AFormat, true);
ErrList.Text := MyWorkbook.ErrorMsg;
CheckEquals(1, ErrList.Count, 'Error count mismatch in test 5');
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end else
Ignore('Test 5 is no error condition for this format');
finally
ErrList.Free;
end;
end;
procedure TSpreadErrorTests.TestWriteErrorMessages_BIFF2;
begin
TestWriteErrorMessages(sfExcel2);
end;
procedure TSpreadErrorTests.TestWriteErrorMessages_BIFF5;
begin
TestWriteErrorMessages(sfExcel5);
end;
procedure TSpreadErrorTests.TestWriteErrorMessages_BIFF8;
begin
TestWriteErrorMessages(sfExcel8);
end;
procedure TSpreadErrorTests.TestWriteErrorMessages_ODS;
begin
TestWriteErrorMessages(sfOpenDocument);
end;
procedure TSpreadErrorTests.TestWriteErrorMessages_OOXML;
begin
TestWriteErrorMessages(sfOOXML);
end;
procedure TSpreadErrorTests.TestWriteErrorMessages_XML;
begin
TestWriteErrorMessages(sfExcelXML);
end;
initialization
// Register so these tests are included in a full run
RegisterTest(TSpreadErrorTests);
end.

View File

@ -0,0 +1,397 @@
unit exceltests;
{$mode objfpc}{$H+}
interface
{ Tests which require Excel.
Will be skipped if Excel is not available.
}
{$ifdef windows}
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
type
{ TSpreadExcelTests }
// Write "something" to Excel file and open it in Excel
TSpreadExcelTests = class(TTestCase)
private
FExcelApp: OleVariant;
FExcelAvail: Boolean;
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
// Comments in several sheets (index of sheets specified)
procedure Test_Comments(const ASheets: array of Integer; AFormat: TsSpreadsheetFormat);
// Header/footer images in several sheets
procedure Test_HeaderFooterImages(const ASheets: array of Integer;
AddToFooter: Boolean; AFormat: TsSpreadsheetFormat);
// Images in several sheets
procedure Test_Images(const ASheets: array of Integer;
AFormat: TsSpreadsheetFormat);
// Comments, images, header/footer images, and hyperlinks
procedure Test_All(const ASheets: array of Integer;
AFormat: TsSpreadsheetFormat);
published
// OOXML test cases
procedure Test_Comments0_OOXML;
procedure Test_Comments01_OOXML;
procedure Test_Comments02_OOXML;
procedure Test_HeaderImages0_OOXML;
procedure Test_HeaderImages01_OOXML;
procedure Test_HeaderImages12_OOXML;
procedure Test_FooterImages0_OOXML;
procedure Test_FooterImages01_OOXML;
procedure Test_FooterImages12_OOXML;
procedure Test_Images0_OOXML;
procedure Test_Images01_OOXML;
procedure Test_Images12_OOXML;
procedure Test_All0_OOXML;
procedure Test_All01_OOXML;
procedure Test_All12_OOXML;
end;
{$endif}
implementation
{$ifdef windows}
uses
TypInfo, comobj;
const
SheetName = 'Excel-Test';
{ TSpreadExcelTexts }
procedure TSpreadExcelTests.SetUp;
begin
inherited SetUp;
try
FExcelApp := CreateOleObject('Excel.Application'); // creates an Excel Object
FExcelApp.Visible := False; // hides Excel window
FExcelApp.ScreenUpdating := False; // turns off screen updating of Excel
FExcelApp.DisplayAlerts := False; // no excel warnings and error messages
FExcelAvail := true;
except
FExcelAvail := false;
end;
end;
procedure TSpreadExcelTests.TearDown;
begin
FExcelApp.Quit;
FExcelApp := UnAssigned;
inherited TearDown;
end;
procedure TSpreadExcelTests.Test_Comments(
const ASheets: array of Integer; AFormat: TsSpreadsheetFormat);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
TempFile: string; //write xls/xml to this file and read back from it
varFile: variant; // filename as variant for Excel
i, j: Integer;
book: OleVariant;
begin
if not FExcelAvail then
begin
exit;
end;
TempFile := NewTempFile;
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving];
for i:=0 to ASheets[High(ASheets)] do
begin
MyWorkSheet:= MyWorkBook.AddWorksheet(SheetName + IntToStr(i+1));
for j:=0 to High(ASheets) do
if ASheets[j] = i then
begin
MyWorksheet.WriteText(0, 0, 'This is a text');
MyWorksheet.WriteComment(0, 0, 'This is a comment');
end;
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet in Excel
try
varFile := TempFile;
book := FExcelApp.Workbooks.Open(varFile);
book.Close;
except
Fail('Excel fails to open the file.');
end;
DeleteFile(TempFile);
end;
procedure TSpreadExcelTests.Test_HeaderFooterImages(
const ASheets: array of Integer; AddToFooter: Boolean;
AFormat: TsSpreadsheetFormat);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
TempFile: string; // write xls/xml to this file and read back from it
varFile: variant; // filename as variants for Excel
i, j: Integer;
book: OleVariant;
begin
if not FExcelAvail then
begin
exit;
end;
TempFile := NewTempFile;
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving];
for i:=0 to ASheets[High(ASheets)] do
begin
MyWorkSheet:= MyWorkBook.AddWorksheet(SheetName + IntToStr(i+1));
for j:=0 to High(ASheets) do
if ASheets[j] = i then
begin
MyWorksheet.WriteText(0, 0, 'This is a text');
if AddToFooter then
MyWorksheet.PageLayout.AddFooterImage(1, hfsCenter, 'lazarus32x32.png')
else
MyWorksheet.PageLayout.AddHeaderImage(1, hfsCenter, 'lazarus32x32.png');
end;
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet in Excel
try
varFile := TempFile;
book := FExcelApp.Workbooks.Open(varFile);
book.Close;
except
Fail(Format('Excel fails to open file "%s".', [TempFile]));
end;
DeleteFile(TempFile);
end;
procedure TSpreadExcelTests.Test_Images(const ASheets: array of Integer;
AFormat: TsSpreadsheetFormat);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
TempFile: string; // write xls/xml to this file and read back from it
varFile: variant; // filename as variants for Excel
i, j: Integer;
book: OleVariant;
begin
if not FExcelAvail then
begin
exit;
end;
TempFile := NewTempFile;
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving];
for i:=0 to ASheets[High(ASheets)] do
begin
MyWorkSheet:= MyWorkBook.AddWorksheet(SheetName + IntToStr(i+1));
for j:=0 to High(ASheets) do
if ASheets[j] = i then
begin
MyWorksheet.WriteText(0, 0, 'This is a text');
MyWorksheet.WriteImage(0, 1, 'lazarus32x32.png')
end;
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet in Excel
try
varFile := TempFile;
book := FExcelApp.Workbooks.Open(varFile);
book.Close;
except
Fail(Format('Excel fails to open file "%s".', [TempFile]));
end;
DeleteFile(TempFile);
end;
procedure TSpreadExcelTests.Test_All(const ASheets: array of Integer;
AFormat: TsSpreadsheetFormat);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
TempFile: string; // write xls/xml to this file and read back from it
varFile: variant; // filename as variants for Excel
i, j: Integer;
book: OleVariant;
begin
if not FExcelAvail then
begin
exit;
end;
TempFile := NewTempFile;
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving];
for i:=0 to ASheets[High(ASheets)] do
begin
MyWorkSheet:= MyWorkBook.AddWorksheet(SheetName + IntToStr(i+1));
for j:=0 to High(ASheets) do
if ASheets[j] = i then
begin
MyWorksheet.WriteText(0, 0, 'This is a text');
MyWorksheet.WriteComment(0, 0, 'This is a comment');
MyWorksheet.WriteHyperlink(0, 0, 'http://www.lazarus-ide.org/');
MyWorksheet.WriteImage(0, 1, 'lazarus32x32.png');
MyWorksheet.PageLayout.AddFooterImage(1, hfsCenter, 'lazarus32x32.png');
MyWorksheet.PageLayout.AddHeaderImage(1, hfsCenter, 'lazarus32x32.png');
end;
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet in Excel
try
varFile := TempFile;
book := FExcelApp.Workbooks.Open(varFile);
book.Close;
except
Fail(Format('Excel fails to open file "%s".', [TempFile]));
end;
DeleteFile(TempFile);
end;
{ OOXML }
procedure TSpreadExcelTests.Test_Comments0_OOXML;
begin
Test_Comments([0], sfOOXML);
end;
procedure TSpreadExcelTests.Test_Comments01_OOXML;
begin
Test_Comments([0,1], sfOOXML);
end;
procedure TSpreadExcelTests.Test_Comments02_OOXML;
begin
Test_Comments([0,2], sfOOXML);
end;
procedure TSpreadExcelTests.Test_HeaderImages0_OOXML;
begin
Test_HeaderFooterImages([0], false, sfOOXML);
end;
procedure TSpreadExcelTests.Test_HeaderImages01_OOXML;
begin
Test_HeaderFooterImages([0,1], false, sfOOXML);
end;
procedure TSpreadExcelTests.Test_HeaderImages12_OOXML;
begin
Test_HeaderFooterImages([1,2], false, sfOOXML);
end;
procedure TSpreadExcelTests.Test_FooterImages0_OOXML;
begin
Test_HeaderFooterImages([0], true, sfOOXML);
end;
procedure TSpreadExcelTests.Test_FooterImages01_OOXML;
begin
Test_HeaderFooterImages([0,1], true, sfOOXML);
end;
procedure TSpreadExcelTests.Test_FooterImages12_OOXML;
begin
Test_HeaderFooterImages([1,2], true, sfOOXML);
end;
procedure TSpreadExcelTests.Test_Images0_OOXML;
begin
Test_Images([0], sfOOXML);
end;
procedure TSpreadExcelTests.Test_Images01_OOXML;
begin
Test_Images([0,1], sfOOXML);
end;
procedure TSpreadExcelTests.Test_Images12_OOXML;
begin
Test_Images([1,2], sfOOXML);
end;
procedure TSpreadExcelTests.Test_All0_OOXML;
begin
Test_All([0], sfOOXML);
end;
procedure TSpreadExcelTests.Test_All01_OOXML;
begin
Test_All([0,1], sfOOXML);
end;
procedure TSpreadExcelTests.Test_All12_OOXML;
begin
Test_All([1,2], sfOOXML);
end;
initialization
RegisterTest(TSpreadExcelTests);
{$endif}
end.

View File

@ -0,0 +1,149 @@
unit fileformattests;
{$mode objfpc}{$H+}
interface
{ Cell type tests
This unit tests writing the various cell data types out to and reading them
back from files.
}
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet,
xlsbiff2, xlsbiff5, xlsbiff8, fpsOpenDocument,
testsutility;
type
{ TSpreadFileFormatTests }
// Write cell types to xls/xml file and read back
TSpreadFileFormatTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestAutoDetect(AFormat: TsSpreadsheetFormat);
published
procedure TestAutoDetect_BIFF2;
procedure TestAutoDetect_BIFF5;
procedure TestAutoDetect_BIFF8;
procedure TestAutoDetect_OOXML;
procedure TestAutoDetect_XML;
procedure TestAutoDetect_ODS;
end;
implementation
uses
fpsReaderWriter;
const
SheetName = 'FileFormat';
{ TSpreadFileFormatTests }
procedure TSpreadFileFormatTests.SetUp;
begin
inherited SetUp;
end;
procedure TSpreadFileFormatTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadFileFormatTests.TestAutoDetect(AFormat: TsSpreadsheetFormat);
const
EXPECTED_TEXT = 'abcefg';
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col: Integer;
MyCell: PCell;
value: Boolean;
TempFile: string; //write xls/xml to this file and read back from it
actualText: String;
begin
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(SheetName);
// write any content to the file
MyWorksheet.WriteText(0, 0, EXPECTED_TEXT);
// Write workbook to file using format specified, but with wrong extension
TempFile := ChangeFileExt(NewTempFile, '.abc');
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
// Try to read file and detect format automatically
try
MyWorkbook.ReadFromFile(TempFile);
// If the tests gets here the format was detected correctly.
// Quickly check the cell content
MyWorksheet := MyWorkbook.GetFirstWorksheet;
actualText := MyWorksheet.ReadAsUTF8Text(0, 0);
CheckEquals(EXPECTED_TEXT, actualText, 'Cell mismatch in A1');
except
fail('Cannot read file with format ' + GetSpreadFormatName(ord(AFormat)));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ BIFF2 }
procedure TSpreadFileFormatTests.TestAutoDetect_BIFF2;
begin
TestAutoDetect(sfExcel2);
end;
{ BIFF5 }
procedure TSpreadFileFormatTests.TestAutoDetect_BIFF5;
begin
TestAutoDetect(sfExcel5);
end;
{ BIFF8 }
procedure TSpreadFileFormatTests.TestAutoDetect_BIFF8;
begin
TestAutoDetect(sfExcel8);
end;
{ OOXML }
procedure TSpreadFileFormatTests.TestAutoDetect_OOXML;
begin
TestAutoDetect(sfOOXML);
end;
{ Excel 2003/XML }
procedure TSpreadFileFormatTests.TestAutoDetect_XML;
begin
TestAutoDetect(sfExcelXML);
end;
{ ODS }
procedure TSpreadFileFormatTests.TestAutoDetect_ODS;
begin
TestAutoDetect(sfOpenDocument);
end;
initialization
RegisterTest(TSpreadFileFormatTests);
end.

View File

@ -0,0 +1,333 @@
unit fonttests;
{$mode objfpc}{$H+}
//{$mode Delphi}{$H+}
interface
{ Font tests
This unit tests writing out to and reading back from files.
}
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
var
// Norm to test against - list of font sizes that should occur in spreadsheet
SollSizes: array[0..12] of single; //"Soll" is a German word in Dutch accountancy jargon meaning "normative value to check against". There ;)
SollStyles: array[0..15] of TsFontStyles;
// Initializes Soll*/normative variables.
// Useful in test setup procedures to make sure the norm is correct.
procedure InitSollSizes;
procedure InitSollStyles;
type
{ TSpreadWriteReadFontTests }
// Write to xls/xml file and read back
TSpreadWriteReadFontTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
// procedure TestWriteReadBold(AFormat: TsSpreadsheetFormat);
procedure TestWriteReadFont(AFormat: TsSpreadsheetFormat; AFontName: String);
published
// BIFF2 test cases
// procedure TestWriteRead_BIFF2_Bold;
procedure TestWriteRead_BIFF2_Font_Arial;
procedure TestWriteRead_BIFF2_Font_TimesNewRoman;
procedure TestWriteRead_BIFF2_Font_CourierNew;
// BIFF5 test cases
// procedure TestWriteRead_BIFF5_Bold;
procedure TestWriteRead_BIFF5_Font_Arial;
procedure TestWriteRead_BIFF5_Font_TimesNewRoman;
procedure TestWriteRead_BIFF5_Font_CourierNew;
// BIFF8 test cases
// procedure TestWriteRead_BIFF8_Bold;
procedure TestWriteRead_BIFF8_Font_Arial;
procedure TestWriteRead_BIFF8_Font_TimesNewRoman;
procedure TestWriteRead_BIFF8_Font_CourierNew;
// ODS test cases
// procedure TestWriteRead_ODS_Bold;
procedure TestWriteRead_ODS_Font_Arial;
procedure TestWriteRead_ODS_Font_TimesNewRoman;
procedure TestWriteRead_ODS_Font_CourierNew;
// OOXML test cases
// procedure TestWriteRead_OOXML_Bold;
procedure TestWriteRead_OOXML_Font_Arial;
procedure TestWriteRead_OOXML_Font_TimesNewRoman;
procedure TestWriteRead_OOXML_Font_CourierNew;
// Excel2003/XML test cases
// procedure TestWriteRead_XML_Bold;
procedure TestWriteRead_XML_Font_Arial;
procedure TestWriteRead_XML_Font_TimesNewRoman;
procedure TestWriteRead_XML_Font_CourierNew;
end;
implementation
uses
TypInfo;
const
FontSheet = 'Font';
// When adding tests, add values to this array
// and increase array size in variable declaration
procedure InitSollSizes;
begin
// Set up norm - MUST match spreadsheet cells exactly
SollSizes[0]:=8.0;
SollSizes[1]:=9.0;
SollSizes[2]:=10.0;
SollSizes[3]:=11.0;
SollSizes[4]:=12.0;
SollSizes[5]:=13.0;
SollSizes[6]:=14.0;
SollSizes[7]:=16.0;
SollSizes[8]:=18.0;
SollSizes[9]:=20.0;
SollSizes[10]:=24.0;
SollSizes[11]:=32.0;
SollSizes[12]:=48.0;
end;
procedure InitSollStyles;
begin
SollStyles[0] := [];
SollStyles[1] := [fssBold];
SolLStyles[2] := [fssItalic];
SollStyles[3] := [fssBold, fssItalic];
SollStyles[4] := [fssUnderline];
SollStyles[5] := [fssUnderline, fssBold];
SollStyles[6] := [fssUnderline, fssItalic];
SollStyles[7] := [fssUnderline, fssBold, fssItalic];
SollStyles[8] := [fssStrikeout];
SollStyles[9] := [fssStrikeout, fssBold];
SolLStyles[10] := [fssStrikeout, fssItalic];
SollStyles[11] := [fssStrikeout, fssBold, fssItalic];
SollStyles[12] := [fssStrikeout, fssUnderline];
SollStyles[13] := [fssStrikeout, fssUnderline, fssBold];
SollStyles[14] := [fssStrikeout, fssUnderline, fssItalic];
SollStyles[15] := [fssStrikeout, fssUnderline, fssBold, fssItalic];
end;
{ TSpreadWriteReadFontTests }
procedure TSpreadWriteReadFontTests.SetUp;
begin
inherited SetUp;
InitSollSizes;
InitSollStyles;
end;
procedure TSpreadWriteReadFontTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadFontTests.TestWriteReadFont(AFormat: TsSpreadsheetFormat;
AFontName: String);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col: Integer;
MyCell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
cellText: String;
font: TsFont;
currValue: String;
expectedValue: String;
counter: Integer;
begin
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(FontSheet);
// Write out all font styles at various sizes
for row := 0 to High(SollSizes) do
begin
for col := 0 to High(SollStyles) do
begin
cellText := Format('%s, %.1f-pt', [AFontName, SollSizes[row]]);
MyWorksheet.WriteUTF8Text(row, col, celltext);
MyWorksheet.WriteFont(row, col, AFontName, SollSizes[row], SollStyles[col], scBlack);
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
fail('Error in test code. Failed to get cell.');
font := MyWorksheet.ReadCellFont(MyCell);
CheckEquals(SollSizes[row], font.Size,
'Test unsaved font size, cell ' + CellNotation(MyWorksheet,0,0));
currValue := SetToString(PTypeInfo(TypeInfo(TsFontStyles)), integer(font.Style), false);
expectedValue := SetToString(PTypeInfo(TypeInfo(TsFontStyles)), integer(SollStyles[col]), false);
CheckEquals(currValue, expectedValue,
'Test unsaved font style, cell ' + CellNotation(MyWorksheet,0,0));
end;
end;
TempFile := NewTempFile;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet // only 1 sheet for BIFF2
else
MyWorksheet := GetWorksheetByName(MyWorkBook, FontSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
counter := 0;
for row := 0 to MyWorksheet.GetLastRowIndex do
for col := 0 to MyWorksheet.GetLastColIndex do
begin
if (AFormat = sfExcel2) and (counter = 4) then
break; // Excel 2 allows only 4 fonts
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
fail('Error in test code. Failed to get cell.');
font := MyWorksheet.ReadCellFont(MyCell);
if abs(SollSizes[row] - font.Size) > 1e-6 then // safe-guard against rounding errors
CheckEquals(SollSizes[row], font.Size,
'Test saved font size, cell '+CellNotation(MyWorksheet,Row,Col));
currValue := SetToString(PTypeInfo(TypeInfo(TsFontStyles)), integer(font.Style), false);
expectedValue := SetToString(PTypeInfo(TypeInfo(TsFontStyles)), integer(SollStyles[col]), false);
CheckEquals(currValue, expectedValue,
'Test unsaved font style, cell ' + CellNotation(MyWorksheet,0,0));
inc(counter);
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ BIFF2 }
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF2_Font_Arial;
begin
TestWriteReadFont(sfExcel2, 'Arial');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF2_Font_TimesNewRoman;
begin
TestWriteReadFont(sfExcel2, 'Times New Roman');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF2_Font_CourierNew;
begin
TestWriteReadFont(sfExcel2, 'Courier New');
end;
{ BIFF5 }
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF5_Font_Arial;
begin
TestWriteReadFont(sfExcel5, 'Arial');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF5_Font_TimesNewRoman;
begin
TestWriteReadFont(sfExcel5, 'Times New Roman');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF5_Font_CourierNew;
begin
TestWriteReadFont(sfExcel5, 'Courier New');
end;
{ BIFF8 }
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF8_Font_Arial;
begin
TestWriteReadFont(sfExcel8, 'Arial');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF8_Font_TimesNewRoman;
begin
TestWriteReadFont(sfExcel8, 'Times New Roman');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_BIFF8_Font_CourierNew;
begin
TestWriteReadFont(sfExcel8, 'Courier New');
end;
{ ODS }
procedure TSpreadWriteReadFontTests.TestWriteRead_ODS_Font_Arial;
begin
TestWriteReadFont(sfOpenDocument, 'Arial');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_ODS_Font_TimesNewRoman;
begin
TestWriteReadFont(sfOpenDocument, 'Times New Roman');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_ODS_Font_CourierNew;
begin
TestWriteReadFont(sfOpenDocument, 'Courier New');
end;
{ OOXML }
procedure TSpreadWriteReadFontTests.TestWriteRead_OOXML_Font_Arial;
begin
TestWriteReadFont(sfOOXML, 'Arial');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_OOXML_Font_TimesNewRoman;
begin
TestWriteReadFont(sfOOXML, 'Times New Roman');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_OOXML_Font_CourierNew;
begin
TestWriteReadFont(sfOOXML, 'Courier New');
end;
{ Excel 2003/XML }
procedure TSpreadWriteReadFontTests.TestWriteRead_XML_Font_Arial;
begin
TestWriteReadFont(sfExcelXML, 'Arial');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_XML_Font_TimesNewRoman;
begin
TestWriteReadFont(sfExcelXML, 'Times New Roman');
end;
procedure TSpreadWriteReadFontTests.TestWriteRead_XML_Font_CourierNew;
begin
TestWriteReadFont(sfExcelXML, 'Courier New');
end;
initialization
RegisterTest(TSpreadWriteReadFontTests);
end.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,634 @@
{ Hyperlink tests
These unit tests are writing out to and reading back from file.
}
unit hyperlinktests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
type
{ TSpreadWriteReadHyperlinkTests }
//Write to xls/xml file and read back
TSpreadWriteReadHyperlinkTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteRead_Hyperlink(AFormat: TsSpreadsheetFormat;
ATestMode, ATooltipMode: Integer);
published
{ BIFF2 hyperlink tests - nothing to do: BIFF2 does not support hyperlinks }
{ BIFF5 hyperlink tests - nothing to do: BIFF5 does not support hyperlinks }
{ BIFF8 hyperlink tests }
procedure TestWriteRead_Hyperlink_BIFF8_HTTPLink1;
procedure TestWriteRead_Hyperlink_BIFF8_HTTPLink1_Tooltip1;
procedure TestWriteRead_Hyperlink_BIFF8_HTTPLink1_Tooltip2;
procedure TestWriteRead_Hyperlink_BIFF8_HTTPLink2;
procedure TestWriteRead_Hyperlink_BIFF8_HTTPLink2_Tooltip1;
procedure TestWriteRead_Hyperlink_BIFF8_HTTPLink2_Tooltip2;
procedure TestWriteRead_Hyperlink_BIFF8_FileLink;
procedure TestWriteRead_Hyperlink_BIFF8_FileLink_Tooltip1;
procedure TestWriteRead_Hyperlink_BIFF8_FileLink_Tooltip2;
procedure TestWriteRead_Hyperlink_BIFF8_RelFileLink1;
procedure TestWriteRead_Hyperlink_BIFF8_RelFileLink1_Tooltip1;
procedure TestWriteRead_Hyperlink_BIFF8_RelFileLink1_Tooltip2;
procedure TestWriteRead_Hyperlink_BIFF8_RelFileLink2;
procedure TestWriteRead_Hyperlink_BIFF8_RelFileLink2_Tooltip1;
procedure TestWriteRead_Hyperlink_BIFF8_RelFileLink2_Tooltip2;
procedure TestWriteRead_Hyperlink_BIFF8_InternalLink;
procedure TestWriteRead_Hyperlink_BIFF8_InternalLink_Tooltip1;
procedure TestWriteRead_Hyperlink_BIFF8_InternalLink_Tooltip2;
{ OpenDocument hyperlink tests }
procedure TestWriteRead_Hyperlink_ODS_HTTPLink1;
procedure TestWriteRead_Hyperlink_ODS_HTTPLink1_Tooltip1;
procedure TestWriteRead_Hyperlink_ODS_HTTPLink1_Tooltip2;
procedure TestWriteRead_Hyperlink_ODS_HTTPLink2;
procedure TestWriteRead_Hyperlink_ODS_HTTPLink2_Tooltip1;
procedure TestWriteRead_Hyperlink_ODS_HTTPLink2_Tooltip2;
procedure TestWriteRead_Hyperlink_ODS_FileLink;
procedure TestWriteRead_Hyperlink_ODS_FileLink_Tooltip1;
procedure TestWriteRead_Hyperlink_ODS_FileLink_Tooltip2;
procedure TestWriteRead_Hyperlink_ODS_RelFileLink1;
procedure TestWriteRead_Hyperlink_ODS_RelFileLink1_Tooltip1;
procedure TestWriteRead_Hyperlink_ODS_RElFileLink1_Tooltip2;
procedure TestWriteRead_Hyperlink_ODS_RelFileLink2;
procedure TestWriteRead_Hyperlink_ODS_RelFileLink2_Tooltip1;
procedure TestWriteRead_Hyperlink_ODS_RelFileLink2_Tooltip2;
procedure TestWriteRead_Hyperlink_ODS_InternalLink;
procedure TestWriteRead_Hyperlink_ODS_InternalLink_Tooltip1;
procedure TestWriteRead_Hyperlink_ODS_InternalLink_Tooltip2;
{ OOXML hyperlink tests }
procedure TestWriteRead_Hyperlink_OOXML_HTTPLink1;
procedure TestWriteRead_Hyperlink_OOXML_HTTPLink1_Tooltip1;
procedure TestWriteRead_Hyperlink_OOXML_HTTPLink1_Tooltip2;
procedure TestWriteRead_Hyperlink_OOXML_HTTPLink2;
procedure TestWriteRead_Hyperlink_OOXML_HTTPLink2_Tooltip1;
procedure TestWriteRead_Hyperlink_OOXML_HTTPLink2_Tooltip2;
procedure TestWriteRead_Hyperlink_OOXML_FileLink;
procedure TestWriteRead_Hyperlink_OOXML_FileLink_Tooltip1;
procedure TestWriteRead_Hyperlink_OOXML_FileLink_Tooltip2;
procedure TestWriteRead_Hyperlink_OOXML_RelFileLink1;
procedure TestWriteRead_Hyperlink_OOXML_RelFileLink1_Tooltip1;
procedure TestWriteRead_Hyperlink_OOXML_RelFileLink1_Tooltip2;
procedure TestWriteRead_Hyperlink_OOXML_RelFileLink2;
procedure TestWriteRead_Hyperlink_OOXML_RelFileLink2_Tooltip1;
procedure TestWriteRead_Hyperlink_OOXML_RelFileLink2_Tooltip2;
procedure TestWriteRead_Hyperlink_OOXML_InternalLink;
procedure TestWriteRead_Hyperlink_OOXML_InternalLink_Tooltip1;
procedure TestWriteRead_Hyperlink_OOXML_InternalLink_Tooltip2;
{ Excel2003/XML hyperlink tests }
procedure TestWriteRead_Hyperlink_XML_HTTPLink1;
procedure TestWriteRead_Hyperlink_XML_HTTPLink1_Tooltip1;
procedure TestWriteRead_Hyperlink_XML_HTTPLink1_Tooltip2;
procedure TestWriteRead_Hyperlink_XML_HTTPLink2;
procedure TestWriteRead_Hyperlink_XML_HTTPLink2_Tooltip1;
procedure TestWriteRead_Hyperlink_XML_HTTPLink2_Tooltip2;
procedure TestWriteRead_Hyperlink_XML_FileLink;
procedure TestWriteRead_Hyperlink_XML_FileLink_Tooltip1;
procedure TestWriteRead_Hyperlink_XML_FileLink_Tooltip2;
procedure TestWriteRead_Hyperlink_XML_RelFileLink1;
procedure TestWriteRead_Hyperlink_XML_RelFileLink1_Tooltip1;
procedure TestWriteRead_Hyperlink_XML_RelFileLink1_Tooltip2;
procedure TestWriteRead_Hyperlink_XML_RelFileLink2;
procedure TestWriteRead_Hyperlink_XML_RelFileLink2_Tooltip1;
procedure TestWriteRead_Hyperlink_XML_RelFileLink2_Tooltip2;
procedure TestWriteRead_Hyperlink_XML_InternalLink;
procedure TestWriteRead_Hyperlink_XML_InternalLink_Tooltip1;
procedure TestWriteRead_Hyperlink_XML_InternalLink_Tooltip2;
end;
implementation
uses
uriparser, lazfileutils, fpsutils, fpsreaderWriter;
const
HyperlinkSheet = 'Hyperlinks';
var
SollLinks: array[0..5] of String = (
'http://wiki.lazarus.freepascal.org/Lazarus_Documentation',
'http://wiki.lazarus.freepascal.org/Lazarus_Documentation#The_Lazarus_User_Guides',
'file:///', // file link: path of test file will be added
'testbiff8_1899.xls',
'testbiff8_1899.xls#Texts!A2',
'#A10'
);
SollCellContent: array[0..3] of string = (
'',
'Label', // Label cell
'1', // Number cell
'12:00:00' // Date/time cell
);
SollTooltip: array[0..2] of String = (
'', // no tooltip
'This is the tooltip for a hyperlink.',
'<< Special characters äöüÄÖÜ >>'
);
{ TSpreadWriteReadHyperlinkTests }
procedure TSpreadWriteReadHyperlinkTests.SetUp;
var
i: Integer;
fn: String;
begin
inherited SetUp;
for i:=Low(SollLinks) to High(SollLinks) do
if SollLinks[i] = 'file:///' then
begin
fn := ExpandFileName('testbiff8_1899.xls');
FilenameToURI(fn);
SollLinks[i] := fn;
exit;
end;
end;
procedure TSpreadWriteReadHyperlinkTests.TearDown;
begin
inherited TearDown;
end;
{ Tests differ by "TestMode" (http link, file link, internal link) and usage of
tooltip (no tooltip, tootip with "normal" characters, tooltip with special
characters - "ToolTipMode"). All cells have hyperlinks based on the same
combination of TestMode and ToolTipMode, but they differ in their content
(SollCellContent): blank, string, number, date/time. }
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink(
AFormat: TsSpreadsheetFormat; ATestMode, ATooltipMode: Integer);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
row, col: Integer;
hyperlink: TsHyperlink;
expected, actual: String;
cell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
begin
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(HyperlinkSheet);
col := 0;
for row := 0 to High(SollCellContent) do
begin
Myworksheet.WriteHyperlink(row, col, SollLinks[ATestMode], SollTooltip[AToolTipMode]);
if SollCellContent[row] <> '' then
MyWorksheet.WriteCellValueAsString(row, col, SollCellContent[row]);
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
// To see the file in the test folder uncomment the next line
// MyWorkBook.WriteToFile(Format('hyperlink_Test_%d_%d%s', [ATestMode, AToolTipMode, GetSpreadFormatExt(ord(AFormat))]), AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
MyWorksheet := GetWorksheetByName(MyWorkBook, HyperlinkSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
col := 0;
for row := 0 to High(SollCellContent) do
begin
cell := MyWorksheet.FindCell(row, col);
// Open document can attach hyperlinks only to label cells --> skip this test
if (AFormat = sfOpenDocument) and (cell^.ContentType <> cctUTF8String) then
continue;
hyperlink := MyWorksheet.ReadHyperlink(cell);
actual := hyperlink.Target;
expected := SollLinks[ATestMode];
// Make sure that the same path delimiter is used in the comparison (fps accepts both)
FixHyperlinkPathDelims(actual);
FixHyperlinkPathDelims(expected);
CheckEquals(expected, actual,
'Test saved hyperlink target, cell '+CellNotation(MyWorksheet, row, col));
actual := MyWorksheet.ReadAsText(cell);
if row = 0 then begin
// An originally blank cell shows the hyperlink.Target.
// But Worksheet.WriteHyperlink removes the "file:///" protocol
expected := hyperlink.Target;
if pos('file:', SollLinks[ATestMode])=1 then
Delete(expected, 1, Length('file:///'))
else if expected[1] = '#' then // ... and internal links are displayed without #
Delete(expected, 1, 1);
end else
expected := SollCellContent[row];
FixHyperlinkPathDelims(expected);
FixHyperlinkPathDelims(actual);
CheckEquals(expected, actual,
'Test saved hyperlink cell text, cell '+ CellNotation(MyWorksheet, row, col));
// Tooltips are not supported by ODS --> don't check
if AFormat <> sfOpenDocument then
CheckEquals(SollToolTip[AToolTipMode], hyperlink.Tooltip,
'Test saved hyperlink tooltip, cell ' + CellNotation(MyWorksheet, row, col));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ Tests for BIFF8 file format }
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_HttpLink1;
begin
TestWriteRead_Hyperlink(sfExcel8, 0, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_HttpLink1_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcel8, 0, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_HttpLink1_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcel8, 0, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_HttpLink2;
begin
TestWriteRead_Hyperlink(sfExcel8, 1, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_HttpLink2_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcel8, 1, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_HttpLink2_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcel8, 1, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_FileLink;
begin
TestWriteRead_Hyperlink(sfExcel8, 2, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_FileLink_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcel8, 2, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_FileLink_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcel8, 2, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_RelFileLink1;
begin
TestWriteRead_Hyperlink(sfExcel8, 3, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_RelFileLink1_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcel8, 3, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_RelFileLink1_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcel8, 3, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_RelFileLink2;
begin
TestWriteRead_Hyperlink(sfExcel8, 4, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_RelFileLink2_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcel8, 4, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_RelFileLink2_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcel8, 4, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_InternalLink;
begin
TestWriteRead_Hyperlink(sfExcel8, 5, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_InternalLink_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcel8, 5, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_BIFF8_InternalLink_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcel8, 5, 2);
end;
{ Tests for Open Document file format }
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_HttpLink1;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 0, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_HttpLink1_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 0, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_HttpLink1_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 0, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_HttpLink2;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 1, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_HttpLink2_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 1, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_HttpLink2_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 1, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_FileLink;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 2, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_FileLink_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 2, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_FileLink_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 2, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_RelFileLink1;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 3, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_RelFileLink1_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 3, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_RelFileLink1_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 3, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_RelFileLink2;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 4, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_RelFileLink2_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 4, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_RelFileLink2_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 4, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_InternalLink;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 5, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_InternalLink_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 5, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_ODS_InternalLink_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOpenDocument, 5, 2);
end;
{ Tests for OOXML file format }
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_HttpLink1;
begin
TestWriteRead_Hyperlink(sfOOXML, 0, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_HttpLink1_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOOXML, 0, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_HttpLink1_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOOXML, 0, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_HttpLink2;
begin
TestWriteRead_Hyperlink(sfOOXML, 1, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_HttpLink2_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOOXML, 1, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_HttpLink2_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOOXML, 1, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_FileLink;
begin
TestWriteRead_Hyperlink(sfOOXML, 2, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_FileLink_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOOXML, 2, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_FileLink_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOOXML, 2, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_RelFileLink1;
begin
TestWriteRead_Hyperlink(sfOOXML, 3, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_RelFileLink1_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOOXML, 3, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_RelFileLink1_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOOXML, 3, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_RelFileLink2;
begin
TestWriteRead_Hyperlink(sfOOXML, 4, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_RelFileLink2_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOOXML, 4, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_RelFileLink2_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOOXML, 4, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_InternalLink;
begin
TestWriteRead_Hyperlink(sfOOXML, 5, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_InternalLink_ToolTip1;
begin
TestWriteRead_Hyperlink(sfOOXML, 5, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_OOXML_InternalLink_ToolTip2;
begin
TestWriteRead_Hyperlink(sfOOXML, 5, 2);
end;
{ Hyperlink tests for Excel2003/XML file format }
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_HttpLink1;
begin
TestWriteRead_Hyperlink(sfExcelXML, 0, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_HttpLink1_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcelXML, 0, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_HttpLink1_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcelXML, 0, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_HttpLink2;
begin
TestWriteRead_Hyperlink(sfExcelXML, 1, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_HttpLink2_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcelXML, 1, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_HttpLink2_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcelXML, 1, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_FileLink;
begin
TestWriteRead_Hyperlink(sfExcelXML, 2, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_FileLink_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcelXML, 2, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_FileLink_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcelXML, 2, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_RelFileLink1;
begin
TestWriteRead_Hyperlink(sfExcelXML, 3, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_RelFileLink1_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcelXML, 3, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_RelFileLink1_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcelXML, 3, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_RelFileLink2;
begin
TestWriteRead_Hyperlink(sfExcelXML, 4, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_RelFileLink2_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcelXML, 4, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_RelFileLink2_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcelXML, 4, 2);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_InternalLink;
begin
TestWriteRead_Hyperlink(sfExcelXML, 5, 0);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_InternalLink_ToolTip1;
begin
TestWriteRead_Hyperlink(sfExcelXML, 5, 1);
end;
procedure TSpreadWriteReadHyperlinkTests.TestWriteRead_Hyperlink_XML_InternalLink_ToolTip2;
begin
TestWriteRead_Hyperlink(sfExcelXML, 5, 2);
end;
initialization
RegisterTest(TSpreadWriteReadHyperlinkTests);
end.

View File

@ -0,0 +1,946 @@
unit internaltests;
{ Other units test file read/write capability.
This unit tests functions, procedures and properties that fpspreadsheet provides.
}
{$mode objfpc}{$H+}
interface
{
Adding tests/test data:
- just add your new test procedure
}
uses
// Not using lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testutils, testregistry,
fpstypes, fpsallformats, fpspreadsheet, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
fpsutils, fpsstreams, fpshtmlutils, testsutility, md5;
type
{ TSpreadReadInternalTests }
// Tests fpspreadsheet functionality, especially internal functions
// Excel/LibreOffice/OpenOffice import/export compatibility should *NOT* be tested here
{ TSpreadInternalTests }
TSpreadInternalTests= class(TTestCase)
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure FractionTest(AMaxDigits: Integer);
procedure HtmlToRichTextTest(ATestIndex: Integer);
procedure RichTextToHtmlTest(ATestIndex: Integer);
procedure WriteToStreamTest(AFormat: TsSpreadsheetFormat);
procedure InvalidSheetName(AFormat: TsSpreadsheetFormat);
published
// Tests getting Excel style A1 cell locations from row/column based locations.
// Bug 26447
procedure TestCellString;
// Tests cell references given in the "R1C1" syntax.
procedure TestCellString_R1C1;
procedure TestCellRangeString_R1C1;
// Tests row and column string names
procedure TestRowString;
procedure TestColString;
//todo: add more calls, rename sheets, try to get sheets with invalid indexes etc
//(see strings tests for how to deal with expected exceptions)
procedure GetSheetByIndex;
// Verify GetSheetByName returns the correct sheet number
// GetSheetByName was implemented in SVN revision 2857
procedure GetSheetByName;
// Test for invalid sheet names
procedure InvalidSheetName_BIFF8;
procedure InvalidSheetName_XLSX;
procedure InvalidSheetName_XML;
procedure InvalidSheetName_ODS;
// Tests whether overwriting existing file works
procedure OverwriteExistingFile;
// Write out date cell and try to read as UTF8; verify if contents the same
procedure ReadDateAsUTF8;
// Test buffered stream
procedure TestReadBufStream;
procedure TestWriteBufStream;
// Test write to stream
procedure TestWriteToStream_Biff8;
procedure TestWriteToStream_Biff5;
// Test fractions
// procedure FractionTest_0;
procedure FractionTest_1;
procedure FractionTest_2;
procedure FractionTest_3;
// Test HTML-Richtext conversion
procedure HtmlToRichTextTest_0;
procedure HtmlToRichTextTest_1;
procedure HtmlToRichTextTest_2;
procedure HtmlToRichTextTest_3;
procedure RichTextToHtmlTest_0;
procedure RichTextToHtmlTest_1;
procedure RichTextToHtmlTest_2;
procedure RichTextToHtmlTest_3;
end;
implementation
uses
Math;
const
InternalSheet = 'Internal'; //worksheet name
procedure TSpreadInternalTests.GetSheetByIndex;
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
begin
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:=MyWorkBook.AddWorksheet(InternalSheet);
MyWorkSheet:=nil;
MyWorkSheet:=MyWorkBook.GetWorksheetByIndex(0);
CheckFalse((MyWorksheet=nil),'GetWorksheetByIndex should return a valid index');
finally
MyWorkbook.Free;
end;
end;
procedure TSpreadInternalTests.GetSheetByName;
const
AnotherSheet='AnotherSheet';
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
begin
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:=MyWorkBook.AddWorksheet(InternalSheet);
MyWorkSheet:=MyWorkBook.AddWorksheet(AnotherSheet);
MyWorkSheet:=nil;
MyWorkSheet:=MyWorkBook.GetWorksheetByName(InternalSheet);
CheckFalse((MyWorksheet=nil),'GetWorksheetByName should return a valid index');
CheckEquals(MyWorksheet.Name,InternalSheet,'GetWorksheetByName should return correct name.');
finally
MyWorkbook.Free;
end;
end;
procedure TSpreadInternalTests.InvalidSheetName(AFormat: TsSpreadsheetFormat);
type
TSheetNameCheck = record
Valid: Boolean;
SheetName: String;
end;
var
TempFile: String;
const
TestCases: array[0..10] of TSheetNameCheck = (
(Valid: true; SheetName:'Sheet'),
(Valid: true; SheetName:'äöü'), // UFt8-characters are ok
(Valid: true; SheetName:'<sheet>'), // forbidden xml characters
(Valid: true; SheetName:'sheet 1'), // space in name
(Valid: false; SheetName:'Test'), // duplicate
(Valid: false; SheetName:'TEST'), // duplicate since case is ignored
(Valid: false; SheetName:''), // empty string
(Valid: false; SheetName:'[sheet]'), // forbidden characters in following cases
(Valid: false; SheetName:'/sheet/'),
(Valid: false; SheetName:'\sheet\'),
(Valid: false; SheetName:'***sheet***')
);
var
i: Integer;
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
ok: Boolean;
begin
TempFile := NewTempFile;
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.AddWorksheet('Test');
for i:=0 to High(TestCases) do
begin
ok := MyWorkbook.ValidWorksheetName(TestCases[i].SheetName);
CheckEquals(TestCases[i].Valid, ok, 'Sheet name validity check mismatch: ' + TestCases[i].SheetName);
if TestCases[i].Valid then
MyWorksheet := MyWorkbook.AddWorksheet(TestCases[i].SheetName);
end;
MyWorkbook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
for i:=0 to High(TestCases) do
if TestCases[i].Valid then
begin
MyWorksheet := MyWorkbook.GetWorksheetByName(TestCases[i].SheetName);
if MyWorksheet = nil then
fail('Test case '+IntToStr(i) + ': Worksheet not found after reading. '+
'Expected sheet name: '+TestCases[i].SheetName);
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
procedure TSpreadInternalTests.InvalidSheetName_BIFF8;
begin
InvalidSheetname(sfExcel8);
end;
procedure TSpreadInternalTests.InvalidSheetName_XLSX;
begin
InvalidSheetname(sfOOXML);
end;
procedure TSpreadInternalTests.InvalidSheetName_XML;
begin
InvalidSheetname(sfExcelXML);
end;
procedure TSpreadInternalTests.InvalidSheetName_ODS;
begin
InvalidSheetname(sfOpenDocument);
end;
procedure TSpreadInternalTests.OverwriteExistingFile;
const
FirstFileCellText='Old version';
SecondFileCellText='New version';
var
FirstFileHash: string;
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
TempFile: string;
begin
// Write out first file
MyWorkbook:=TsWorkbook.Create;
try
MyWorkSheet:=MyWorkBook.AddWorksheet(InternalSheet);
MyWorkSheet.WriteUTF8Text(0,0,FirstFileCellText);
TempFile:=NewTempFile;
MyWorkBook.WriteToFile(TempFile, sfExcel8, false);
finally
MyWorkbook.Free;
end;
if not(FileExists(TempFile)) then
fail('Trying to write first file did not work.');
FirstFileHash:=MD5Print(MD5File(TempFile));
// Now overwrite with second file
MyWorkbook:=TsWorkbook.Create;
try
MyWorkSheet:=MyWorkBook.AddWorksheet(InternalSheet);
MyWorkSheet.WriteUTF8Text(0,0,SecondFileCellText);
MyWorkBook.WriteToFile(TempFile,sfExcel8,true);
finally
MyWorkbook.Free;
end;
if FirstFileHash=MD5Print(MD5File(TempFile)) then
fail('File contents are still those of the first file.');
DeleteFile(TempFile);
end;
procedure TSpreadInternalTests.ReadDateAsUTF8;
var
ActualDT: TDateTime;
ActualDTString: string; //Result from ReadAsUTF8Text
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
Row,Column: Cardinal;
TestDT: TDateTime;
begin
Row:=0;
Column:=0;
TestDT:=EncodeDate(1969,7,21)+EncodeTime(2,56,0,0);
MyWorkbook:=TsWorkbook.Create;
try
MyWorkSheet:=MyWorkBook.AddWorksheet(InternalSheet);
MyWorkSheet.WriteDateTime(Row,Column,TestDT); //write date
// Reading as date/time should just work
if not(MyWorksheet.ReadAsDateTime(Row,Column,ActualDT)) then
Fail('Could not read date time for cell '+CellNotation(MyWorkSheet,Row,Column));
CheckEquals(TestDT,ActualDT,'Test date/time value mismatch '
+'cell '+CellNotation(MyWorkSheet,Row,Column));
//Check reading as string, convert to date & compare
ActualDTString:=MyWorkSheet.ReadAsUTF8Text(Row,Column);
ActualDT:=StrToDateTimeDef(ActualDTString,EncodeDate(1906,1,1));
CheckEquals(TestDT,ActualDT,'Date/time mismatch using ReadAsUTF8Text');
finally
MyWorkbook.Free;
end;
end;
procedure TSpreadInternalTests.TestReadBufStream;
const
BUF_SIZE = 1024;
FILE_SIZE = 2000;
var
tempFileName: String;
stream: TStream;
writedata: array of Byte;
readdata: array of Byte;
i, n, nread: Integer;
begin
RandSeed := 0;
// Create a test file
tempFileName := GetTempFileName;
stream := TFileStream.Create(tempFileName, fmCreate);
try
SetLength(writedata, FILE_SIZE);
for i:=0 to High(writedata) do
writedata[i] := random(256);
stream.WriteBuffer(writedata[0], Length(writedata));
finally
stream.Free;
end;
// Use a TBufStream to read parts of the file back
stream := TBufStream.Create(tempFilename, fmOpenRead, BUF_SIZE);
try
// Check stream size
CheckEquals(FILE_SIZE, stream.Size, 'Size mismatch');
// Read first 100 bytes and compare with data
nread := 100;
SetLength(readdata, nread);
n := stream.Read(readdata[0], nread);
CheckEquals(nread, n, 'Bytes count mismatch');
for i:=0 to nread-1 do
CheckEquals(writedata[i], readdata[i], Format('Read mismatch at position %d', [i]));
// Check stream size
CheckEquals(FILE_SIZE, stream.Size, 'Size mismatch');
// Read next 100 bytes and compare
stream.ReadBuffer(readdata[0], nread);
for i:=0 to nread-1 do
CheckEquals(writedata[i+nread], readdata[i], Format('Read mismatch at position %d', [i+nread]));
// Go to position 1000, this is 24 bytes to the end of the buffer, and read
// 100 bytes again - this process will require to refresh the buffer
stream.Position := 1000;
stream.ReadBuffer(readdata[0], nread);
for i:=0 to nread-1 do
CheckEquals(writedata[i+1000], readdata[i], Format('Read mismatch at position %d', [i+1000]));
// Check stream size
CheckEquals(FILE_SIZE, stream.Size, 'Size mismatch');
// Read next 100 bytes
stream.ReadBuffer(readdata[0], nread);
for i:=0 to nread-1 do
CheckEquals(writedata[i+1000+nread], readdata[i], Format('Read mismatch at position %d', [i+1000+nread]));
// Go back to start and fill the memory stream again with bytes 0..1023
stream.Position := 0;
stream.ReadBuffer(readdata[0], nread);
// Now read 100 bytes which are not in the buffer
stream.Position := 1500; // this is past the buffered range
stream.ReadBuffer(readdata[0], 100);
for i:=0 to nread-1 do
CheckEquals(writedata[i+1500], readdata[i], Format('Read mismatch at position %d', [i+1500]));
// Go back to start and fill the memory stream again with bytes 0..1023
stream.Position := 0;
stream.ReadBuffer(readdata[0], 100);
// Read last 100 bytes
stream.Seek(nread, soFromEnd);
stream.ReadBuffer(readdata[0], nread);
for i:=0 to nread-1 do
CheckEquals(writedata[i+FILE_SIZE-nread], readdata[i],
Format('Read mismatch at position %d', [i+FILE_SIZE-nread]));
finally
stream.Free;
DeleteFile(tempFileName);
end;
end;
procedure TSpreadInternalTests.TestWriteBufStream;
const
BUFSIZE = 1024;
var
stream: TBufStream;
readBuf, writeBuf1, writeBuf2: array of byte;
nRead, nWrite1, nWrite2: Integer;
i: Integer;
begin
stream := TBufStream.Create(BUFSIZE);
try
// Write 100 random bytes. They fit into the BUFSIZE of the memory buffer
nWrite1 := 100;
SetLength(writeBuf1, nWrite1);
for i:=0 to nWrite1-1 do writeBuf1[i] := Random(255);
stream.WriteBuffer(writeBuf1[0], nWrite1);
// Check stream size - must be equal to nWrite
CheckEquals(nWrite1, stream.Size, 'Stream size mismatch (#1)');
// Check stream position must be equal to nWrite
CheckEquals(nWrite1, stream.Position, 'Stream position mismatch (#2)');
// Bring stream pointer back to start
stream.Position := 0;
CheckEquals(0, stream.Position, 'Stream position mismatch (#3)');
// Read the first 10 bytes just written and compare
nRead := 10;
SetLength(readBuf, nRead);
nRead := stream.Read(readBuf[0], nRead);
CheckEquals(10, nRead, 'Read/write size mismatch (#4)');
for i:=0 to 9 do
CheckEquals(writeBuf1[i], readBuf[i], Format('Read/write mismatch at position %d (#5)', [i]));
// Back to start, and read the entire stream
stream.Position := 0;
nRead := stream.Size;
Setlength(readBuf, nRead);
nRead := stream.Read(readBuf[0], stream.Size);
CheckEquals(nWrite1, nRead, 'Stream read size mismatch (#6)');
for i:=0 to nWrite1-1 do
CheckEquals(writeBuf1[i], readBuf[i], Format('Read/write mismatch at position %d (#7)', [i]));
// Now put stream pointer to end and write another 2000 bytes. This crosses
// the size of the memory buffer, and the stream must swap to file.
stream.Seek(0, soFromEnd);
CheckEquals(stream.Size, stream.Position, 'Stream position not at end (#8)');
nWrite2 := 2000;
SetLength(writeBuf2, nWrite2);
for i:=0 to nWrite2-1 do writeBuf2[i] := Random(255);
stream.WriteBuffer(writeBuf2[0], nWrite2);
// The stream pointer must be at 100+2000, same for the size
CheckEquals(nWrite1+nWrite2, stream.Position, 'Stream position mismatch (#9)');
CheckEquals(nWrite1+nWrite2, stream.Size, 'Stream size mismatch (#10)');
// Read the last 10 bytes and compare
Stream.Seek(10, soFromEnd);
SetLength(readBuf, 10);
Stream.ReadBuffer(readBuf[0], 10);
for i:=0 to 9 do
CheckEquals(writeBuf2[nWrite2-10+i], readBuf[i], Format('Read/write mismatch at position %d from end (#11)', [i]));
// Now read all from beginning
Stream.Position := 0;
SetLength(readBuf, stream.Size);
nRead := Stream.Read(readBuf[0], stream.Size);
CheckEquals(nWrite1+nWrite2, nRead, 'Read/write size mismatch (#4)');
for i:=0 to nRead-1 do
if i < nWrite1 then
CheckEquals(writeBuf1[i], readBuf[i], Format('Read/write mismatch at position %d (#11)', [i]))
else
CheckEquals(writeBuf2[i-nWrite1], readBuf[i], Format('Read/write mismatch at position %d (#11)', [i]));
finally
stream.Free;
end;
end;
procedure TSpreadInternalTests.WriteToStreamTest(AFormat: TsSpreadsheetFormat);
var
myworkbook: TsWorkbook;
myworksheet: TsWorksheet;
memstream: TMemoryStream;
filestream: TMemoryStream;
tempFile: String;
pf, pm: Pointer;
i, p: Integer;
begin
tempFile := GetTempFileName;
myworkbook := TsWorkbook.Create;
myworksheet := myworkbook.AddWorksheet('Test');
memstream := TMemoryStream.Create;
filestream := TMemoryStream.Create;
try
myworksheet.WriteText(0, 0, 'Text');
myworksheet.WriteNumber(0, 1, 12.345);
myworksheet.WriteDateTime(0, 2, now() );
// Write to file
myworkbook.WriteToFile(tempfile, AFormat);
// Write to memory stream
myworkbook.WriteToStream(memstream, AFormat);
// Determine length of "used" data, there seems to be scap at the end
memstream.Position := 0;
myworkbook.ReadFromStream(memstream, AFormat);
p := memstream.Position;
// Read file back into memory stream
filestream.LoadFromFile(tempfile);
// Compare both streams
CheckEquals(filestream.Size, memstream.Size, 'Stream size mismatch');
pf := filestream.Memory;
pm := memStream.Memory;
for i:=0 to p-1 do
begin
CheckEquals(PByte(pf)^, PByte(pm)^, 'Stream mismatch at position ' + IntToStr(i));
inc(pf);
inc(pm);
end;
finally
filestream.Free;
memstream.Free;
myworkbook.Free;
end;
DeleteFile(tempFile);
end;
procedure TSpreadInternalTests.TestWriteToStream_Biff5;
begin
WriteToStreamTest(sfExcel5);
end;
procedure TSpreadInternalTests.TestWriteToStream_Biff8;
begin
WriteToStreamTest(sfExcel8);
end;
procedure TSpreadInternalTests.TestCellString;
var
r,c: Cardinal;
s: String;
flags: TsRelFlags;
begin
CheckEquals('$A$1',GetCellString(0,0,[]));
CheckEquals('$Z$1',GetCellString(0,25,[])); //bug 26447
CheckEquals('$AA$2',GetCellString(1,26,[])); //just past the last letter
CheckEquals('$GW$5',GetCellString(4,204,[])); //some big value
CheckEquals('$IV$1',GetCellString(0,255,[])); //the last column of xls
CheckEquals('$IW$1',GetCellString(0,256,[])); //the first column beyond xls
CheckEquals('$XFD$1',GetCellString(0,16383,[])); // the last column of xlsx
CheckEquals('$XFE$1',GetCellString(0,16384,[])); // the first column beyond xlsx
// Something VERY big, beyond xlsx
// s := 'ZZZZ1'; // this is case is no longer possible because max column count has been cut down to 65536
s := 'CRAA1';
ParseCellString(s, r, c, flags);
CheckEquals(s, GetCellString(r, c, flags));
end;
{ Tests cell references given in the "R1C1" syntax. }
procedure TSpreadInternalTests.TestCellString_R1C1;
var
r,c: Cardinal;
s: String;
flags: TsRelFlags;
res: Boolean;
begin
// (1) Absolute reference of the cell at row=0 col=0
res := ParseCellString_R1C1('R1C1', 10, 10, r, c, flags);
CheckEquals(res, true, 'Result mismatch in test 1');
CheckEquals(r, 0, 'Row mismatch in test 1'); // base cell coordinates are ignored with absolute refs!
CheckEquals(c, 0, 'Col mismatch in test 1');
CheckEquals(true, flags = [], 'Flags mismatch in test 1');
// (2) Relative reference of the cell left of col 10 and above row 10
res := ParseCellString_R1C1('R[-1]C[-1]', 10, 10, r, c, flags);
CheckEquals(res, true, 'Result mismatch in test 2');
CheckEquals(r, 9, 'Row mismatch in test 2');
CheckEquals(c, 9, 'Col mismatch in test 2');
CheckEquals(true, flags = [rfRelRow, rfRelCol], 'Flags mismatch in test 2');
// (3) Relative reference of the cell in row 10 and 2 cols at the right of col 10
res := ParseCellString_R1C1('RC[2]', 10, 10, r, c, flags);
CheckEquals(res, true, 'Result mismatch in test 3');
CheckEquals(r, 10, 'Row mismatch in test 3');
CheckEquals(c, 12, 'Col mismatch in test 3');
CheckEquals(true, flags = [rfRelRow, rfRelCol], 'Flags mismatch in test 3');
// (4) Relative reference of the cell in col 10 and 2 rows below row 10
res := ParseCellString_R1C1('R[2]C', 10, 10, r, c, flags);
CheckEquals(res, true, 'Result mismatch in test 4');
CheckEquals(r, 12, 'Row mismatch in test 4');
CheckEquals(c, 10, 'Col mismatch in test 4');
CheckEquals(true, flags = [rfRelRow, rfRelCol], 'Flags mismatch in test 4');
// (5) Relative reference of the cell 3 rows above row 10 and 2 cols left of col 10
res := ParseCellString_R1C1('R[-3]C[-2]', 10, 10, r, c, flags);
CheckEquals(res, true, 'Result mismatch in test 5');
CheckEquals(r, 7, 'Row mismatch in test 5');
CheckEquals(c, 8, 'Col mismatch in test 5');
CheckEquals(true, flags = [rfRelRow, rfRelCol], 'Flags mismatch in test 5');
// (6) Mixed reference: base cell in row10/col10 (note: zero-based!).
// Absolute reference to row, relative reference to 10 columns to the right
res := ParseCellString_R1C1('R11C[10]', 10, 10, r, c, flags);
CheckEquals(res, true, 'Result mismatch in test 6');
CheckEquals(r, 10, 'Row mismatch in test 6');
CheckEquals(c, 20, 'Col mismatch in test 6');
CheckEquals(true, flags = [rfRelCol], 'Flags mismatch in test 6');
// (7) Mixed reference: base cell in row10/col10 (note: zero-based!).
// Relative reference to 10 rows below, absolute reference to this col
res := ParseCellString_R1C1('R[10]C11', 10, 10, r, c, flags);
CheckEquals(res, true, 'Result mismatch in test 7');
CheckEquals(r, 20, 'Row mismatch in test 7');
CheckEquals(c, 10, 'Col mismatch in test 7');
CheckEquals(true, flags = [rfRelRow], 'Flags mismatch in test 7');
// Error tests
// (E1) Relative reference of the cell 30 rows above row 10 and 2 cols left of col 10
res := ParseCellString_R1C1('R[-30]C[-2]', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E1');
// (E2) Relative reference of the cell 30 rows to the left of row 10
res := ParseCellString_R1C1('R[-30]C', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E2');
// (E3) Illegal "R" character
res := ParseCellString_R1C1('x1C2', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E3');
// (E4) Illegal "C" character
res := ParseCellString_R1C1('R1x2', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E4');
// (E5) Illegal row number character
res := ParseCellString_R1C1('R10.1C2', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E5');
// (E6) Illegal row number character
res := ParseCellString_R1C1('R1C10.1', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E6');
// (E7) Illegal opening row bracket
res := ParseCellString_R1C1('R(1]C1', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E7');
// (E8 Illegal closing row bracket
res := ParseCellString_R1C1('R[1)C1', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E8');
// (E9) Illegal opening col bracket
res := ParseCellString_R1C1('R1C(1]', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E9');
// (E10) Illegal closing col bracket
res := ParseCellString_R1C1('RC[1)', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E10');
// (E11) Missing opening row bracket
res := ParseCellString_R1C1('R1]C1', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E11');
// (E12) Missing closing row bracket
res := ParseCellString_R1C1('R[1C1', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E12');
// (E13) Missing opening col bracket
res := ParseCellString_R1C1('R1C1]', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E13');
// (E14) Missing closing col bracket
res := ParseCellString_R1C1('R1C[1', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E14');
// (E15) RC interchanged
res := ParseCellString_R1C1('C1R1', 10, 10, r, c, flags);
CheckEquals(res, false, 'Result mismatch in test E15');
end;
{ Tests cell range references given in the "R1C1" syntax. }
procedure TSpreadInternalTests.TestCellRangeString_R1C1;
var
r1,c1,r2,c2: Cardinal;
s: String;
flags: TsRelFlags;
res: Boolean;
begin
// (1) Absolute reference of the range between cells row0/cell0 and row2/col1
res := ParseCellRangeString_R1C1('R1C1:R3C2', 10, 10, r1, c1, r2, c2, flags);
CheckEquals(res, true, 'Result mismatch in test 1');
CheckEquals(r1, 0, 'Row1 mismatch in test 1'); // base cell coordinates are ignored with absolute refs!
CheckEquals(c1, 0, 'Col1 mismatch in test 1');
CheckEquals(r2, 2, 'Row2 mismatch in test 1'); // base cell coordinates are ignored with absolute refs!
CheckEquals(c2, 1, 'Col2 mismatch in test 1');
CheckEquals(true, flags = [], 'Flags mismatch in test 1');
// (2) Relative reference of the cell left of col 10 and above row 10
res := ParseCellRangeString_R1C1('R[-1]C[-1]:R[1]C[1]', 10, 10, r1, c1, r2, c2, flags);
CheckEquals(res, true, 'Result mismatch in test 2');
CheckEquals(r1, 9, 'Row mismatch in test 2');
CheckEquals(c1, 9, 'Col mismatch in test 2');
CheckEquals(r2, 11, 'Row mismatch in test 2');
CheckEquals(c2, 11, 'Col mismatch in test 2');
CheckEquals(true, flags = [rfRelRow, rfRelCol, rfRelRow2, rfRelCol2], 'Flags mismatch in test 2');
// (3) Absolute reference of first cell (row0/col0), Relative reference of second cell
res := ParseCellRangeString_R1C1('R1C1:R[1]C[1]', 10, 10, r1, c1, r2, c2, flags);
CheckEquals(res, true, 'Result mismatch in test 2');
CheckEquals(r1, 0, 'Row mismatch in test 3');
CheckEquals(c1, 0, 'Col mismatch in test 3');
CheckEquals(r2, 11, 'Row mismatch in test 3');
CheckEquals(c2, 11, 'Col mismatch in test 3');
CheckEquals(true, flags = [rfRelRow2, rfRelCol2], 'Flags mismatch in test 3');
// (4) Relative reference of first cell, absolute reference of second cell
res := ParseCellRangeString_R1C1('R[-1]C[-1]:R20C20', 10, 10, r1, c1, r2, c2, flags);
CheckEquals(res, true, 'Result mismatch in test 4');
CheckEquals(r1, 9, 'Row mismatch in test 4');
CheckEquals(c1, 9, 'Col mismatch in test 4');
CheckEquals(r2, 19, 'Row mismatch in test 4');
CheckEquals(c2, 19, 'Col mismatch in test 4');
CheckEquals(true, flags = [rfRelRow, rfRelCol], 'Flags mismatch in test 4');
end;
procedure TSpreadInternalTests.TestColString;
var
res: Boolean;
c: Cardinal;
begin
// (1) Check column 0 ("A")
res := ParseCellColString('A', c);
CheckEquals(res, true, 'Result mismatch in test 1');
CheckEquals(res, true, 'Col mismatch in test 1');
// (2) Check column 25 ("Z")
res := ParseCellColString('Z', c);
CheckEquals(res, true, 'Result mismatch in test 2');
CheckEquals(c, 25, 'Col mismatch in test 2');
// (3) Check column 26 ("AA")
res := ParseCellColString('AA', c);
CheckEquals(res, true, 'Result mismatch in test 3');
CheckEquals(c, 26, 'Col mismatch in test 3');
// (3) Check column 26 ("$AA") with $
res := ParseCellColString('$AA', c);
CheckEquals(res, true, 'Result mismatch in test 4');
CheckEquals(c, 26, 'Col mismatch in test 4');
end;
procedure TSpreadInternalTests.TestRowString;
var
res: Boolean;
r: Cardinal;
begin
// (1) Check row 0 ("1")
res := ParseCellRowString('1', r);
CheckEquals(res, true, 'Result mismatch in test 1');
CheckEquals(r, 0, 'Row mismatch in test 1');
// (2) Check row 99 ("100")
res := ParseCellRowString('100', r);
CheckEquals(res, true, 'Result mismatch in test 2');
CheckEquals(r, 99, 'Row mismatch in test 2');
// (2) Check row 99 ("100") with $
res := ParseCellRowString('$100', r);
CheckEquals(res, true, 'Result mismatch in test 3');
CheckEquals(r, 99, 'Row mismatch in test 3');
end;
procedure TSpreadInternalTests.FractionTest(AMaxDigits: Integer);
const
N = 300;
var
j: Integer;
sollNum, sollDenom: Integer;
sollValue: Double;
actualNum, actualDenom: Int64;
max: Integer;
prec: Double;
begin
max := Round(IntPower(10, AMaxDigits));
prec := 0.001/max;
for sollDenom := 1 to max-1 do
for sollNum := 1 to sollDenom-1 do begin
sollValue := StrToFloat(FormatFloat('0.000000000', sollNum/sollDenom));
FloatToFraction(sollValue, max, actualNum, actualDenom);
//FloatToFraction(sollValue, prec, max, max, actualNum, actualDenom);
if (actualnum*solldenom div actualdenom <> sollnum) then
fail(Format('Conversion error: %g = %d/%d turns to %d/%d (=%g)', [sollValue, sollNum, sollDenom, actualNum, actualDenom, actualNum/actualdenom]));
end;
end;
procedure TSpreadInternalTests.FractionTest_1;
begin
FractionTest(1);
end;
procedure TSpreadInternalTests.FractionTest_2;
begin
FractionTest(2);
end;
procedure TSpreadInternalTests.FractionTest_3;
begin
FractionTest(3);
end;
{------------------------------------------------------------------------------}
{ HTML-to-RichText conversion }
{------------------------------------------------------------------------------}
type
THtmlRichTextParam = record
HTML: String;
PlainText: String;
NumRichTextParams: 0..2;
RichTextParams: array[0..1] of TsRichTextParam;
end;
const
HtmlRTParams: array[0..3] of THtmlRichTextParam = (
(HTML: 'ABC'; PlainText: 'ABC';
NumRichTextParams: 0),
(HTML: 'ABC<b>abc</b>'; PlainText: 'ABCabc';
NumRichTextParams: 1;
RichTextParams: (
(FirstIndex:4; FontIndex:2; HyperlinkIndex:-1),
(FirstIndex:0; FontIndex:0; HyperlinkIndex:-1)
)
),
(HTML: 'ABC<b>abc</b>ABC'; PlainText: 'ABCabcABC';
NumRichTextParams: 2;
RichTextParams: (
(FirstIndex:4; FontIndex:2; HyperlinkIndex:-1),
(FirstIndex:7; FontIndex:0; HyperlinkIndex:-1)
)
),
(HTML: '<b>abc</b>ABC'; PlainText: 'abcABC';
NumRichTextParams: 2;
RichTextParams: (
(FirstIndex:1; FontIndex:2; HyperlinkIndex:-1),
(FirstIndex:4; FontIndex:0; HyperlinkIndex:-1)
)
)
);
procedure TSpreadInternalTests.HtmlToRichTextTest(ATestIndex: Integer);
var
book: TsWorkbook;
fnt: TsFont;
rtparams: TsRichTextParams;
plain: String;
i: Integer;
begin
book := TsWorkbook.Create;
try
fnt := book.GetDefaultFont;
HTMLToRichText(book, fnt, HTMLRtParams[ATestIndex].HTML, plain, rtParams);
CheckEquals(HtmlRTParams[ATestIndex].PlainText, plain, 'Plain text mismatch');
CheckEquals(HtmlRTParams[ATestIndex].NumRichTextParams, Length(rtParams),
'Count of rich-text params mismatch');
for i:=0 to HtmlRTParams[ATestIndex].NumRichTextParams-1 do begin
CheckEquals(HtmlRTParams[ATestIndex].RichTextParams[i].FirstIndex, rtParams[i].FirstIndex,
'RichTextParam['+IntToStr(i)+'].FirstIndex mismatch');
CheckEquals(HtmlRTParams[ATestIndex].RichTextParams[i].FontIndex, rtParams[i].FontIndex,
'RichTextParam['+IntToStr(i)+'].FontIndex mismatch');
end;
finally
book.Free;
end;
end;
procedure TSpreadInternalTests.RichTextToHtmlTest(ATestIndex: Integer);
var
book: TsWorkbook;
fnt: TsFont;
rtparams: TsRichTextParams;
html: String;
i: Integer;
begin
book := TsWorkbook.Create;
try
fnt := book.GetDefaultFont;
SetLength(rtParams, HTMLRtParams[ATestIndex].NumRichTextParams);
for i:=0 to HtmlRtParams[ATestindex].NumRichTextParams-1 do begin
rtParams[i].FirstIndex := HtmlRTParams[ATestIndex].RichTextParams[i].FirstIndex;
rtParams[i].FontIndex := HtmlRTParams[ATestIndex].RichTextParams[i].FontIndex;
end;
RichTextToHTML(book, fnt, HTMLRtParams[ATestIndex].PlainText, rtParams, html);
CheckEquals(HtmlRTParams[ATestIndex].HTML, html, 'HTML text mismatch');
finally
book.Free;
end;
end;
procedure TSpreadInternalTests.HtmlToRichTextTest_0;
begin
HtmlToRichTextTest(0);
end;
procedure TSpreadInternalTests.HtmlToRichTextTest_1;
begin
HtmlToRichTextTest(1);
end;
procedure TSpreadInternalTests.HtmlToRichTextTest_2;
begin
HtmlToRichTextTest(2);
end;
procedure TSpreadInternalTests.HtmlToRichTextTest_3;
begin
HtmlToRichTextTest(3);
end;
procedure TSpreadInternalTests.RichTextToHtmlTest_0;
begin
RichTextToHtmlTest(0);
end;
procedure TSpreadInternalTests.RichTextToHtmlTest_1;
begin
RichTextToHtmlTest(1);
end;
procedure TSpreadInternalTests.RichTextToHtmlTest_2;
begin
RichTextToHtmlTest(2);
end;
procedure TSpreadInternalTests.RichTextToHtmlTest_3;
begin
RichTextToHtmlTest(3);
end;
procedure TSpreadInternalTests.SetUp;
begin
end;
procedure TSpreadInternalTests.TearDown;
begin
end;
initialization
// Register so these tests are included in a full run
RegisterTest(TSpreadInternalTests);
end.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,307 @@
unit manualtests;
{
Tests that can be run but need a human to check results.
Examples are color output, rotation, bold etc
Of course, you could write Excel macros to do this for you; patches welcome ;)
}
{$mode objfpc}{$H+}
{
Adding tests/test data:
1. Increase Soll* array size
2. Add desired normative value InitNormVariables so you can test against it
3. Add your write test(s) including instructions for the humans check the resulting file
}
interface
uses
// Not using lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, testutils, testregistry, testdecorator, fpcunit,
fpsallformats, fpspreadsheet, fpscell,
xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
{
var
// Norm to test against - list of dates/times that should occur in spreadsheet
SollColors: array[0..16] of tsColor; //"Soll" is a German word in Dutch accountancy jargon meaning "normative value to check against". There ;)
SollColorNames: array[0..16] of string; //matching names for SollColors
// Initializes Soll*/normative variables.
// Useful in test setup procedures to make sure the norm is correct.
procedure InitSollColors;
}
type
{ TSpreadManualSetup }
TSpreadManualSetup= class(TTestSetup)
protected
procedure OneTimeSetup; override;
procedure OneTimeTearDown; override;
end;
{ TSpreadManualTests }
// Writes to file and let humans figure out if the correct output was generated
TSpreadManualTests= class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
published
// Current fpspreadsheet does not yet have support for new RPN formulas
{$DEFINE FPSPREAD_HAS_NEWRPNSUPPORT}
{$IFDEF FPSPREAD_HAS_NEWRPNSUPPORT}
// As described in bug 25718: Feature request & patch: Implementation of writing more functions
// Writes all rpn formulas. Use Excel or Open/LibreOffice to check validity.
procedure TestRPNFormula;
// Dto, but writes string formulas.
// procedure TestStringFormula;
{$ENDIF}
// For BIFF8 format, writes all background colors in A1..A16
procedure TestBiff8CellBackgroundColor;
procedure TestNumberFormats;
end;
implementation
uses
fpstypes, fpsUtils, fpsPalette, rpnFormulaUnit;
const
COLORSHEETNAME='color_sheet'; //for background color tests
RPNSHEETNAME='rpn_formula_sheet'; //for rpn formula tests
FORMULASHEETNAME='formula_sheet'; // for string formula tests
NUMBERFORMATSHEETNAME='number format sheet'; // for number format tests
OUTPUT_FORMAT = sfExcel8; //change manually if you want to test different formats. To do: automatically output all formats
var
Workbook: TsWorkbook = nil;
(*
// Initialize array with variables that represent the values
// we expect to be in the test spreadsheet files.
//
// When adding tests, add values to this array
// and increase array size in variable declaration
procedure InitSollColors;
begin
// Set up norm - MUST match spreadsheet cells exactly
// Follows fpspreadsheet.TsColor, except custom colors
SollColors[0]:=scBlack;
SollColors[1]:=scWhite;
SollColors[2]:=scRed;
SollColors[3]:=scGREEN;
SollColors[4]:=scBLUE;
SollColors[5]:=scYELLOW;
SollColors[6]:=scMAGENTA;
SollColors[7]:=scCYAN;
SollColors[8]:=scDarkRed;
SollColors[9]:=scDarkGreen;
SollColors[10]:=scDarkBlue;
SollColors[11]:=scOLIVE;
SollColors[12]:=scPURPLE;
SollColors[13]:=scTEAL;
SollColors[14]:=scSilver;
SollColors[15]:=scGrey;
SollColors[16]:=scOrange;
{
SollColors[16]:=scGrey10pct;
SollColors[17]:=scGrey20pct;
SollColors[18]:=scOrange;
SollColors[19]:=scDarkBrown;
SollColors[20]:=scBrown;
SollColors[21]:=scBeige;
SollColors[22]:=scWheat;
}
// Corresponding names for display in cells:
SollColorNames[0]:='scBlack';
SollColorNames[1]:='scWhite';
SollColorNames[2]:='scRed';
SollColorNames[3]:='scGREEN';
SollColorNames[4]:='scBLUE';
SollColorNames[5]:='scYELLOW';
SollColorNames[6]:='scMAGENTA';
SollColorNames[7]:='scCYAN';
SollColorNames[8]:='scDarkRed';
SollColorNames[9]:='scDarkGreen';
SollColorNames[10]:='scDarkBlue';
SollColorNames[11]:='scOLIVE';
SollColorNames[12]:='scPURPLE';
SollColorNames[13]:='scTEAL';
SollColorNames[14]:='scSilver';
SollColorNames[15]:='scGrey';
SollColorNames[16]:='scOrange';
{
SollColorNames[16]:='scGrey10pct';
SollColorNames[17]:='scGrey20pct';
SollColorNames[18]:='scOrange';
SollColorNames[19]:='scDarkBrown';
SollColorNames[20]:='scBrown';
SollColorNames[21]:='scBeige';
SollColorNames[22]:='scWheat';
}
end;
*)
{ TSpreadManualSetup }
procedure TSpreadManualSetup.OneTimeSetup;
begin
// One time setup for entire suite: nothing needed here yet
end;
procedure TSpreadManualSetup.OneTimeTearDown;
begin
if Workbook <> nil then begin
// In Ubuntu explicit deletion of the existing file is needed.
// Otherwise an error would occur and a defective file would be written }
if FileExists(TestFileManual) then DeleteFile(TestFileManual);
Workbook.WriteToFile(TestFileManual, OUTPUT_FORMAT, TRUE);
Workbook.Free;
Workbook := nil;
end;
end;
{ TSpreadManualTests }
procedure TSpreadManualTests.SetUp;
begin
// InitSollColors;
end;
procedure TSpreadManualTests.TearDown;
begin
// nothing to do here, yet
end;
procedure TSpreadManualTests.TestBiff8CellBackgroundColor();
// source: forum post
// http://forum.lazarus.freepascal.org/index.php/topic,19887.msg134114.html#msg134114
// possible fix for values there too
var
Worksheet: TsWorksheet;
Cell : PCell;
i: cardinal;
RowOffset: cardinal;
palette: TsPalette;
begin
if OUTPUT_FORMAT <> sfExcel8 then
Ignore('This test only applies to BIFF8 XLS output format.');
// No worksheets in BIFF2. Since main interest is here in formulas we just jump
// off here - need to change this in the future...
if OUTPUT_FORMAT = sfExcel2 then
Ignore('BIFF2 does not support worksheets. Ignoring manual tests for now');
if Workbook = nil then
Workbook := TsWorkbook.Create;
palette := TsPalette.Create;
try
palette.AddBuiltinColors;
palette.AddExcelColors;
Worksheet := Workbook.AddWorksheet(COLORSHEETNAME);
WorkSheet.WriteUTF8Text(0, 1, 'TSpreadManualTests.TestBiff8CellBackgroundColor');
RowOffset := 1;
for i:=0 to palette.Count-1 do begin
cell := WorkSheet.WriteUTF8Text(i+RowOffset,0,'BACKGROUND COLOR TEST');
Worksheet.WriteBackgroundColor(Cell, palette[i]);
Worksheet.WriteFontColor(cell, HighContrastColor(palette[i]));
WorkSheet.WriteUTF8Text(i+RowOffset,1,'Cell to the left should be '+GetColorName(palette[i])+'. Please check.');
end;
Worksheet.WriteColWidth(0, 30);
Worksheet.WriteColWidth(1, 60);
finally
palette.Free;
end;
end;
procedure TSpreadManualTests.TestNumberFormats();
// source: forum post
// http://forum.lazarus.freepascal.org/index.php/topic,19887.msg134114.html#msg134114
// possible fix for values there too
const
Values: Array[0..4] of Double = (12000.34, -12000.34, 0.0001234, -0.0001234, 0.0);
FormatStrings: array[0..24] of String = (
'General',
'0', '0.00', '0.0000',
'#,##0', '#,##0.00', '#,##0.0000',
'0%', '0.00%', '0.0000%',
'0,', '0.00,', '0.0000,',
'0E+00', '0.00E+00', '0.0000E+00',
'0E-00', '0.00E-00', '0.0000E-00',
'# ?/?', '# ??/??', '# ????/????',
'?/?', '??/??', '????/????'
);
var
Worksheet: TsWorksheet;
Cell : PCell;
i: cardinal;
r, c: Cardinal;
palette: TsPalette;
nfs: String;
begin
if OUTPUT_FORMAT <> sfExcel8 then
Ignore('This test only applies to BIFF8 XLS output format.');
// No worksheets in BIFF2. Since main interest is here in formulas we just jump
// off here - need to change this in the future...
if OUTPUT_FORMAT = sfExcel2 then
Ignore('BIFF2 does not support worksheets. Ignoring manual tests for now');
if Workbook = nil then
Workbook := TsWorkbook.Create;
Worksheet := Workbook.AddWorksheet(NUMBERFORMATSHEETNAME);
WorkSheet.WriteUTF8Text(0, 1, 'Number format tests');
for r:=0 to High(FormatStrings) do
begin
Worksheet.WriteUTF8Text(r+2, 0, FormatStrings[r]);
for c:=0 to High(Values) do
Worksheet.WriteNumber(r+2, c+1, values[c], nfCustom, FormatStrings[r]);
end;
Worksheet.WriteColWidth(0, 20);
end;
{$IFDEF FPSPREAD_HAS_NEWRPNSUPPORT}
// As described in bug 25718: Feature request & patch: Implementation of writing more functions
procedure TSpreadManualTests.TestRPNFormula;
var
Worksheet: TsWorksheet;
begin
if Workbook = nil then
Workbook := TsWorkbook.Create;
Worksheet := Workbook.AddWorksheet(RPNSHEETNAME);
WriteRPNFormulaSamples(Worksheet, OUTPUT_FORMAT, false);
end;
(*
procedure TSpreadManualTests.TestStringFormula;
var
Worksheet: TsWorksheet;
begin
if Workbook = nil then
Workbook := TsWorkbook.Create;
Worksheet := Workbook.AddWorksheet(FORMULASHEETNAME);
WriteRPNFormulaSamples(Worksheet, OUTPUT_FORMAT, false, false);
end;
*)
{$ENDIF}
initialization
// Register one time setup/teardown and associated test class to actually run the tests
RegisterTestDecorator(TSpreadManualSetup,TSpreadManualTests);
// Initialize the norm variables in case other units want to use it:
// InitSollColors;
end.

View File

@ -0,0 +1,87 @@
{-------------------------------------------------------------------------------
Tests for some dedicated math routines which are specific to spreadsheets.
-------------------------------------------------------------------------------}
unit mathtests;
{$mode objfpc}{$H+}
{$modeswitch advancedrecords}
interface
uses
{$IFDEF Unix}
//required for formatsettings
clocale,
{$ENDIF}
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testutils, testregistry, testsutility,
fpstypes, fpspreadsheet, fpsutils;
type
{ TSpreadMathTests }
//Write to xls/xml file and read back
TSpreadMathTests = class(TTestCase)
private
protected
procedure TestRound(InputValue: Double; Expected: Integer);
published
// Test whether "round" avoids Banker's rounding
procedure TestRound_plus15;
procedure Testround_minus15;
procedure TestRound_plus25;
procedure TestRound_minus25;
end;
implementation
{ TSpreadMathTests }
procedure TSpreadMathTests.TestRound(InputValue: Double; Expected: Integer);
var
book: TsWorkbook;
sheet: TsWorksheet;
readValue: String;
begin
book := TsWorkbook.Create;
try
sheet := book.AddWorksheet('Math');
sheet.WriteNumber(1, 1, InputValue, nfFixed, 0);
readValue := sheet.ReadAsText(1, 1);
CheckEquals(Expected, StrToInt(readValue),
'Rounding error, sheet "' + sheet.Name + '"')
finally
book.Free;
end;
end;
procedure TSpreadMathTests.TestRound_plus15;
begin
TestRound(1.5, 2);
end;
procedure TSpreadMathTests.TestRound_minus15;
begin
Testround(-1.5, -2);
end;
procedure TSpreadMathTests.TestRound_plus25;
begin
TestRound(2.5, 3);
end;
procedure TSpreadMathTests.Testround_minus25;
begin
TestRound(-2.5, -3);
end;
initialization
RegisterTest(TSpreadMathTests);
end.

View File

@ -0,0 +1,815 @@
unit numberstests;
{$mode objfpc}{$H+}
interface
{
Adding tests/test data:
1. Add a new value to column A in the relevant worksheet, and save the spreadsheet read-only
(for dates, there are 2 files, with different datemodes. Use them both...)
2. Increase SollNumbers array size
3. Add value from 1) to InitNormVariables so you can test against it
4. Add your read test(s), read and check read value against SollDates[<added number>]
}
uses
// Not using lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testutils, testregistry,
fpstypes, fpsallformats, fpspreadsheet, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
var
// Norm to test against - list of numbers/times that should occur in spreadsheet
SollNumbers: array[0..22] of double; //"Soll" is a German word in Dutch accountancy jargon meaning "normative value to check against". There ;)
// Initializes Soll*/normative variables.
// Useful in test setup procedures to make sure the norm is correct.
procedure InitSollNumbers;
type
{ TSpreadReadNumberTests }
// Read from xls/xml file with known values
TSpreadReadNumberTests= class(TTestCase)
private
// Tries to read number in column A, specified (0-based) row
procedure TestReadNumber(FileName: string; Row: integer);
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
published
// Reads numbers values from spreadsheet and checks against list
// One cell per test so some tests can fail and those further below may still work
procedure TestReadNumber0; //number tests for biff8 file format
procedure TestReadNumber1; //number and time
procedure TestReadNumber2;
procedure TestReadNumber3;
procedure TestReadNumber4; //time only tests start here
procedure TestReadNumber5;
procedure TestReadNumber6;
procedure TestReadNumber7;
procedure TestReadNumber8;
procedure TestReadNumber9;
procedure TestReadNumber10;
procedure TestReadNumber11;
procedure TestReadNumber12;
procedure TestReadNumber13;
procedure TestReadNumber14;
procedure TestReadNumber15;
procedure TestReadNumber16;
procedure TestReadNumber17;
procedure TestReadNumber18;
procedure TestReadNumber19;
procedure TestReadNumber20;
procedure TestReadNumber21;
procedure TestReadNumber22;
procedure TestReadODFNumber0; //number tests using ODF/LibreOffice file format
procedure TestReadODFNumber1; //number and time
procedure TestReadODFNumber2;
procedure TestReadODFNumber3;
procedure TestReadODFNumber4; //time only tests start here
procedure TestReadODFNumber5;
procedure TestReadODFNumber6;
procedure TestReadODFNumber7;
procedure TestReadODFNumber8;
procedure TestReadODFNumber9;
procedure TestReadODFNumber10;
procedure TestReadODFNumber11;
procedure TestReadODFNumber12;
procedure TestReadODFNumber13;
procedure TestReadODFNumber14;
procedure TestReadODFNumber15;
procedure TestReadODFNumber16;
procedure TestReadODFNumber17;
procedure TestReadODFNumber18;
procedure TestReadODFNumber19;
procedure TestReadODFNumber20;
procedure TestReadODFNumber21;
procedure TestReadODFNumber22;
procedure TestReadOOXMLNumber0; //number tests using Excel XLSX file format
procedure TestReadOOXMLNumber1; //number and time
procedure TestReadOOXMLNumber2;
procedure TestReadOOXMLNumber3;
procedure TestReadOOXMLNumber4; //time only tests start here
procedure TestReadOOXMLNumber5;
procedure TestReadOOXMLNumber6;
procedure TestReadOOXMLNumber7;
procedure TestReadOOXMLNumber8;
procedure TestReadOOXMLNumber9;
procedure TestReadOOXMLNumber10;
procedure TestReadOOXMLNumber11;
procedure TestReadOOXMLNumber12;
procedure TestReadOOXMLNumber13;
procedure TestReadOOXMLNumber14;
procedure TestReadOOXMLNumber15;
procedure TestReadOOXMLNumber16;
procedure TestReadOOXMLNumber17;
procedure TestReadOOXMLNumber18;
procedure TestReadOOXMLNumber19;
procedure TestReadOOXMLNumber20;
procedure TestReadOOXMLNumber21;
procedure TestReadOOXMLNumber22;
procedure TestReadXMLNumber0; //number tests using Wxcel2003/XML file format
procedure TestReadXMLNumber1; //number and time
procedure TestReadXMLNumber2;
procedure TestReadXMLNumber3;
procedure TestReadXMLNumber4; //time only tests start here
procedure TestReadXMLNumber5;
procedure TestReadXMLNumber6;
procedure TestReadXMLNumber7;
procedure TestReadXMLNumber8;
procedure TestReadXMLNumber9;
procedure TestReadXMLNumber10;
procedure TestReadXMLNumber11;
procedure TestReadXMLNumber12;
procedure TestReadXMLNumber13;
procedure TestReadXMLNumber14;
procedure TestReadXMLNumber15;
procedure TestReadXMLNumber16;
procedure TestReadXMLNumber17;
procedure TestReadXMLNumber18;
procedure TestReadXMLNumber19;
procedure TestReadXMLNumber20;
procedure TestReadXMLNumber21;
procedure TestReadXMLNumber22;
end;
{ TSpreadWriteReadNumberTests }
//Write to xls/xml file and read back
TSpreadWriteReadNumberTests= class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
// Reads numbers values from spreadsheet and checks against list
// One cell per test so some tests can fail and those further below may still work
procedure TestWriteReadNumbers(AFormat: TsSpreadsheetFormat);
published
procedure TestWriteReadNumbers_BIFF2;
procedure TestWriteReadNumbers_BIFF5;
procedure TestWriteReadNumbers_BIFF8;
procedure TestWriteReadNumbers_ODS;
procedure TestWriteReadNumbers_OOXML;
end;
implementation
var
TestWorksheet: TsWorksheet = nil;
TestWorkbook: TsWorkbook = nil;
TestFileName: String = '';
// Initialize array with variables that represent the values
// we expect to be in the test spreadsheet files.
//
// When adding tests, add values to this array
// and increase array size in variable declaration
procedure InitSollNumbers;
begin
// Set up norm - MUST match spreadsheet cells exactly
SollNumbers[0]:=-59000000; //minus 59 million
SollNumbers[1]:=-988;
SollNumbers[2]:=-124.23432;
SollNumbers[3]:=-81.9028508730274;
SollNumbers[4]:=-15;
SollNumbers[5]:=-0.002934; //minus small fraction
SollNumbers[6]:=-0; //minus zero
SollNumbers[7]:=0; //zero
SollNumbers[8]:=0.000000005; //small fraction
SollNumbers[9]:=0.982394; //almost 1
SollNumbers[10]:=3.14159265358979; //some parts of pi
SollNumbers[11]:=59000000; //59 million
SollNumbers[12]:=59000000.1; //same + a tenth
SollNumbers[13]:=0.3536; // 0.3536 formatted as percentage, no decimals
SollNumbers[14]:=0.3536; // 0.3536 formatted as percentage, 2 decimals
SollNumbers[15]:=59000000.1234; // 59 million + 0.1234 formatted with thousand separator, no decimals
SollNumbers[16]:=59000000.1234; // 59 million + 0.1234 formatted with thousand separator, 2 decimals
SollNumbers[17]:=-59000000.1234; // minus 59 million + 0.1234, formatted as "exp" with 2 decimals
SollNumbers[18]:=59000000.1234; // 59 million + 0.1234 formatted as currrency (EUROs, at end), 2 decimals
SollNumbers[19]:=59000000.1234; // 59 million + 0.1234 formatted as currrency (Dollars, at end), 2 decimals
SollNumbers[20]:=-59000000.1234; // minus 59 million + 0.1234 formatted as currrency (EUROs, at end), 2 decimals
SollNumbers[21]:=-59000000.1234; // minus 59 million + 0.1234 formatted as currrency (Dollars, at end), 2 decimals
SollNumbers[22]:=-59000000.1234; // minus 59 million + 0.1234 formatted as currrency (Dollars, at end, neg red), 2 decimals
end;
{ TSpreadWriteReadNumberTests }
procedure TSpreadWriteReadNumberTests.SetUp;
begin
inherited SetUp;
InitSollNumbers;
end;
procedure TSpreadWriteReadNumberTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadNumberTests.TestWriteReadNumbers(AFormat: TsSpreadsheetFormat);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
ActualNumber: double;
Row: Cardinal;
TempFile: string; //write xls/xml to this file and read back from it
begin
{// Not needed: use workbook.writetofile with overwrite=true
if fileexists(TempFile) then
DeleteFile(TempFile);
}
// Write out all test values
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet := MyWorkBook.AddWorksheet(NumbersSheet);
for Row := Low(SollNumbers) to High(SollNumbers) do
begin
MyWorkSheet.WriteNumber(Row,0,SollNumbers[Row]);
// Some checks inside worksheet itself
ActualNumber:=MyWorkSheet.ReadAsNumber(Row,0);
CheckEquals(SollNumbers[Row],ActualNumber,'Test value mismatch cell '+CellNotation(MyWorkSheet,Row));
end;
TempFile:=NewTempFile;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet, as biff8
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook,NumbersSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
// Read test data from A column & compare if written=original
for Row := Low(SollNumbers) to High(SollNumbers) do
begin
ActualNumber:=MyWorkSheet.ReadAsNumber(Row,0);
CheckEquals(SollNumbers[Row],ActualNumber,'Test value mismatch cell '+CellNotation(MyWorkSheet,Row));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
procedure TSpreadWriteReadNumberTests.TestWriteReadNumbers_BIFF2;
begin
TestWriteReadNumbers(sfExcel2);
end;
procedure TSpreadWriteReadNumberTests.TestWriteReadNumbers_BIFF5;
begin
TestWriteReadNumbers(sfExcel5);
end;
procedure TSpreadWriteReadNumberTests.TestWriteReadNumbers_BIFF8;
begin
TestWriteReadNumbers(sfExcel8);
end;
procedure TSpreadWriteReadNumberTests.TestWriteReadNumbers_ODS;
begin
TestWriteReadNumbers(sfOpenDocument);
end;
procedure TSpreadWriteReadNumberTests.TestWriteReadNumbers_OOXML;
begin
TestWriteReadNumbers(sfOOXML);
end;
{ TSpreadReadNumberTests }
procedure TSpreadReadNumberTests.TestReadNumber(FileName: string; Row: integer);
var
ActualNumber: double;
begin
if Row>High(SollNumbers) then
fail('Error in test code: array bounds overflow. Check array size is correct.');
// Load the file only if is the file name changes.
if (FileName <> TestFileName) then begin
if TestWorkbook <> nil then
TestWorkbook.Free;
// Open the spreadsheet
TestWorkbook := TsWorkbook.Create;
case UpperCase(ExtractFileExt(FileName)) of
'.XLSX': TestWorkbook.ReadFromFile(FileName, sfOOXML);
'.XML' : TestWorkbook.ReadFromFile(FileName, sfExcelXML);
'.ODS' : TestWorkbook.ReadFromFile(FileName, sfOpenDocument);
// Excel XLS/BIFF
else TestWorkbook.ReadFromFile(FileName, sfExcel8);
end;
TestWorksheet:=GetWorksheetByName(TestWorkBook,NumbersSheet);
if TestWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
TestFileName := FileName;
end;
ActualNumber := TestWorkSheet.ReadAsNumber(Row, 0);
CheckEquals(SollNumbers[Row], ActualNumber,'Test value mismatch, '
+'cell '+CellNotation(TestWorkSheet,Row));
// Don't free the workbook here - it will be reused. It is destroyed at finalization.
end;
procedure TSpreadReadNumberTests.SetUp;
begin
InitSollNumbers;
end;
procedure TSpreadReadNumberTests.TearDown;
begin
end;
procedure TSpreadReadNumberTests.TestReadNumber0;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,0);
end;
procedure TSpreadReadNumberTests.TestReadNumber1;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,1);
end;
procedure TSpreadReadNumberTests.TestReadNumber2;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,2);
end;
procedure TSpreadReadNumberTests.TestReadNumber3;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,3);
end;
procedure TSpreadReadNumberTests.TestReadNumber4;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,4);
end;
procedure TSpreadReadNumberTests.TestReadNumber5;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,5);
end;
procedure TSpreadReadNumberTests.TestReadNumber6;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,6);
end;
procedure TSpreadReadNumberTests.TestReadNumber7;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,7);
end;
procedure TSpreadReadNumberTests.TestReadNumber8;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,8);
end;
procedure TSpreadReadNumberTests.TestReadNumber9;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,9);
end;
procedure TSpreadReadNumberTests.TestReadNumber10;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,10);
end;
procedure TSpreadReadNumberTests.TestReadNumber11;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,11);
end;
procedure TSpreadReadNumberTests.TestReadNumber12;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,12);
end;
procedure TSpreadReadNumberTests.TestReadNumber13;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,13);
end;
procedure TSpreadReadNumberTests.TestReadNumber14;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,14);
end;
procedure TSpreadReadNumberTests.TestReadNumber15;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,15);
end;
procedure TSpreadReadNumberTests.TestReadNumber16;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,16);
end;
procedure TSpreadReadNumberTests.TestReadNumber17;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,17);
end;
procedure TSpreadReadNumberTests.TestReadNumber18;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,18);
end;
procedure TSpreadReadNumberTests.TestReadNumber19;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,19);
end;
procedure TSpreadReadNumberTests.TestReadNumber20;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,20);
end;
procedure TSpreadReadNumberTests.TestReadNumber21;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,21);
end;
procedure TSpreadReadNumberTests.TestReadNumber22;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,22);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber0;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,0);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber1;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,1);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber2;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,2);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber3;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,3);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber4;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,4);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber5;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,5);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber6;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,6);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber7;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,7);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber8;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,8);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber9;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,9);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber10;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,10);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber11;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,11);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber12;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,12);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber13;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,13);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber14;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,14);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber15;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,15);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber16;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,16);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber17;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,17);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber18;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,18);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber19;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,19);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber20;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,20);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber21;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,21);
end;
procedure TSpreadReadNumberTests.TestReadODFNumber22;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileODF,22);
end;
{ OOXML Tests }
procedure TSpreadReadNumberTests.TestReadOOXMLNumber0;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,0);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber1;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,1);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber2;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,2);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber3;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,3);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber4;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,4);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber5;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,5);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber6;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,6);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber7;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,7);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber8;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,8);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber9;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,9);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber10;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,10);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber11;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,11);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber12;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,12);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber13;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,13);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber14;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,14);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber15;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,15);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber16;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,16);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber17;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,17);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber18;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,18);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber19;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,19);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber20;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,20);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber21;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,21);
end;
procedure TSpreadReadNumberTests.TestReadOOXMLNumber22;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,22);
end;
{ Excel2003/XML Tests }
procedure TSpreadReadNumberTests.TestReadXMLNumber0;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,0);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber1;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,1);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber2;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,2);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber3;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,3);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber4;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,4);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber5;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,5);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber6;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,6);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber7;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,7);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber8;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,8);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber9;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,9);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber10;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,10);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber11;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,11);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber12;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,12);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber13;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,13);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber14;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,14);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber15;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,15);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber16;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,16);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber17;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,17);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber18;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,18);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber19;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,19);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber20;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,20);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber21;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,21);
end;
procedure TSpreadReadNumberTests.TestReadXMLNumber22;
begin
TestReadNumber(ExtractFilePath(ParamStr(0)) + TestFileOOXML,22);
end;
initialization
// Register so these tests are included in a full run
RegisterTest(TSpreadReadNumberTests);
RegisterTest(TSpreadWriteReadNumberTests);
InitSollNumbers; //useful to have norm data if other code wants to use this unit
finalization
FreeAndNil(TestWorkbook);
end.

View File

@ -0,0 +1,420 @@
unit numformatparsertests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, fpsnumformat
{and a project requirement for lclbase for utf8 handling},
testsutility;
type
TParserTestData = record
FormatString: String;
SollFormatString: String;
SollNumFormat: TsNumberFormat;
SollSectionCount: Integer;
SollDecimals: Byte;
SollFactor: Double;
SollNumeratorDigits: Integer;
SollDenominatorDigits: Integer;
SollCurrencySymbol: String;
SollSection2Color: TsColor;
end;
TRoundingTestData = record
FormatString: String;
Number: Double;
SollString: String;
end;
var
ParserTestData: Array[0..13] of TParserTestData;
RoundingTestData: Array[0..65] of TRoundingTestData = (
// 0
(FormatString: '0'; Number: 1.2; SollString: '1'),
(FormatString: '0'; Number: 1.9; SollString: '2'),
(FormatString: '0'; Number: -1.2; SollString: '-1'),
(FormatString: '0'; Number: -1.9; SollString: '-2'),
(FormatString: '0'; Number: 1234.2; SollString: '1234'),
(FormatString: '0'; Number: 1234.9; SollString: '1235'),
(FormatString: '0'; Number: -1234.2; SollString: '-1234'),
(FormatString: '0'; Number: -1234.9; SollString: '-1235'),
// 8
(FormatString: '0.00'; Number: 1.2; SollString: '1.20'),
(FormatString: '0.00'; Number: 1.9; SollString: '1.90'),
(FormatString: '0.00'; Number: -1.2; SollString: '-1.20'),
(FormatString: '0.00'; Number: -1.9; SollString: '-1.90'),
(FormatString: '0.00'; Number: 1234.2; SollString: '1234.20'),
(FormatString: '0.00'; Number: 1234.9; SollString: '1234.90'),
(FormatString: '0.00'; Number: -1234.2; SollString: '-1234.20'),
(FormatString: '0.00'; Number: -1234.9; SollString: '-1234.90'),
(FormatString: '0.00'; Number: 1234.21; SollString: '1234.21'),
(FormatString: '0.00'; Number: 1234.99; SollString: '1234.99'),
(FormatString: '0.00'; Number: -1234.21; SollString: '-1234.21'),
(FormatString: '0.00'; Number: -1234.99; SollString: '-1234.99'),
(FormatString: '0.00'; Number: 1234.2123; SollString: '1234.21'),
(FormatString: '0.00'; Number: 1234.2999; SollString: '1234.30'),
(FormatString: '0.00'; Number: 1234.9123; SollString: '1234.91'),
(FormatString: '0.00'; Number: 1234.9993; SollString: '1235.00'),
(FormatString: '0.00'; Number: -1234.2123; SollString: '-1234.21'),
(FormatString: '0.00'; Number: -1234.2999; SollString: '-1234.30'),
(FormatString: '0.00'; Number: -1234.9123; SollString: '-1234.91'),
(FormatString: '0.00'; Number: -1234.9993; SollString: '-1235.00'),
// 28
(FormatString: '#,##0.00'; Number: 1.2; SollString: '1.20'),
(FormatString: '#,##0.00'; Number: 1.9; SollString: '1.90'),
(FormatString: '#,##0.00'; Number: -1.2; SollString: '-1.20'),
(FormatString: '#,##0.00'; Number: -1.9; SollString: '-1.90'),
(FormatString: '#,##0.00'; Number: 1234.2; SollString: '1,234.20'),
(FormatString: '#,##0.00'; Number: 1234.9; SollString: '1,234.90'),
(FormatString: '#,##0.00'; Number: -1234.2; SollString: '-1,234.20'),
(FormatString: '#,##0.00'; Number: -1234.9; SollString: '-1,234.90'),
(FormatString: '#,##0.00'; Number: 1234.2123; SollString: '1,234.21'),
(FormatString: '#,##0.00'; Number: 1234.2999; SollString: '1,234.30'),
(FormatString: '#,##0.00'; Number: 1234.9123; SollString: '1,234.91'),
(FormatString: '#,##0.00'; Number: 1234.9993; SollString: '1,235.00'),
(FormatString: '#,##0.00'; Number: -1234.2123; SollString: '-1,234.21'),
(FormatString: '#,##0.00'; Number: -1234.2999; SollString: '-1,234.30'),
(FormatString: '#,##0.00'; Number: -1234.9123; SollString: '-1,234.91'),
(FormatString: '#,##0.00'; Number: -1234.9993; SollString: '-1,235.00'),
// 44
(FormatString: '00.00'; Number: 1.2; SollString: '01.20'),
(FormatString: '00.00'; Number: 1.9; SollString: '01.90'),
(FormatString: '00.00'; Number: -1.2; SollString: '-01.20'),
(FormatString: '00.00'; Number: -1.9; SollString: '-01.90'),
(FormatString: '00.00'; Number: 1234.2; SollString: '1234.20'),
(FormatString: '00.00'; Number: 1234.9; SollString: '1234.90'),
(FormatString: '00.00'; Number: -1234.2; SollString: '-1234.20'),
(FormatString: '00.00'; Number: -1234.9; SollString: '-1234.90'),
// 52
(FormatString: '#.00'; Number: 0.2; SollString: '.20'),
(FormatString: '#.00'; Number: 0.9; SollString: '.90'),
(FormatString: '#.00'; Number: -0.2; SollString: '-.20'),
(FormatString: '#.00'; Number: -0.9; SollString: '-.90'),
(FormatString: '#.00'; Number: 1.2; SollString: '1.20'),
(FormatString: '#.00'; Number: -1.9; SollString: '-1.90'),
// 58
(FormatString: '0.0##'; Number: 1.2; SollString: '1.2'),
(FormatString: '0.0##'; Number: 1.21; SollString: '1.21'),
(FormatString: '0.0##'; Number: 1.212; SollString: '1.212'),
(FormatString: '0.0##'; Number: 1.2134; SollString: '1.213'),
(FormatString: '0.0##'; Number: 1.2135; SollString: '1.214'),
// 63
(FormatString: '#'; Number: 0; SollString: ''),
(FormatString: '#'; Number: 1.2; SollString: '1'),
(FormatString: '#'; Number: -1.2; SollString: '-1')
);
procedure InitParserTestData;
type
TSpreadNumFormatParserTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
// Reads numbers values from spreadsheet and checks against list
// One cell per test so some tests can fail and those further below may still work
published
procedure TestNumFormatParser;
procedure TestRounding;
end;
implementation
uses
TypInfo;
{ The test will use Excel strings and convert them to fpc dialect }
procedure InitParserTestData;
begin
// Tests with 1 format section only
with ParserTestData[0] do begin
FormatString := '0';
SollFormatString := '0';
SollNumFormat := nfFixed;
SollSectionCount := 1;
SollDecimals := 0;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[1] do begin
FormatString := '0.000';
SollFormatString := '0.000';
SollNumFormat := nfFixed;
SollSectionCount := 1;
SollDecimals := 3;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[2] do begin
FormatString := '#,##0.000';
SollFormatString := '#,##0.000';
SollNumFormat := nfFixedTh;
SollSectionCount := 1;
SollDecimals := 3;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[3] do begin
FormatString := '0.000%';
SollFormatString := '0.000%';
SollNumFormat := nfPercentage;
SollSectionCount := 1;
SollDecimals := 3;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[4] do begin
FormatString := 'hh:mm:ss';
SollFormatString := 'hh:mm:ss';
SollNumFormat := nfLongTime;
SollSectionCount := 1;
SollDecimals := 0;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[5] do begin
FormatString := 'hh:mm:ss AM/PM';
SollFormatString := 'hh:mm:ss AM/PM';
SollNumFormat := nfLongTimeAM;
SollSectionCount := 1;
SollDecimals := 0;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[6] do begin
FormatString := '[$-409]hh:mm:ss\ AM/PM;@';
SollFormatString := 'hh:mm:ss\ AM/PM;@';
SollNumFormat := nfCustom;
SollSectionCount := 2;
SollDecimals := 0;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[7] do begin
FormatString := '[$-F400]dd.mm.yy\ hh:mm';
SollFormatString := 'dd.mm.yy\ hh:mm';
SollNumFormat := nfCustom;
SollSectionCount := 1;
SollDecimals := 0;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[8] do begin
FormatString := '[$€] #,##0.00;-[$€] #,##0.00;[$€] 0.00';
SollFormatString := '[$€] #,##0.00;-[$€] #,##0.00;[$€] 0.00';
SollNumFormat := nfCurrency;
SollSectionCount := 3;
SollDecimals := 2;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '€';
SollSection2Color := scBlack;
end;
with ParserTestData[9] do begin
FormatString := '[$€] #,##0.00;[red]-[$€] #,##0.00;[$€] 0.00';
SollFormatString := '[$€] #,##0.00;[red]-[$€] #,##0.00;[$€] 0.00';
SollNumFormat := nfCurrencyRed;
SollSectionCount := 3;
SollDecimals := 2;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '€';
SollSection2Color := scRed;
end;
with ParserTestData[10] do begin
FormatString := '0.00,,';
SollFormatString := '0.00,,';
SollNumFormat := nfCustom;
SollSectionCount := 1;
SollDecimals := 2;
SollFactor := 1e-6;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[11] do begin
FormatString := '# ??/??';
SollFormatString := '# ??/??';
SollNumFormat := nfFraction;
SollSectionCount := 1;
SollDecimals := 0;
SollFactor := 0;
SollNumeratorDigits := 2;
SollDenominatorDigits := 2;
SollCurrencySymbol := '';
end;
with ParserTestData[12] do begin
FormatString := 'General;[Red]-General';
SollFormatString := 'General;[red]-General';
SollNumFormat := nfCustom;
SollSectionCount := 2;
SollDecimals := 0;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
SollSection2Color := scRed;
end;
with ParserTestData[13] do begin
FormatString := 'General';
SollFormatString := 'General';
SollNumFormat := nfGeneral;
SollSectionCount := 1;
SollDecimals := 0;
SollFactor := 0;
SollNumeratorDigits := 0;
SollDenominatorDigits := 0;
SollCurrencySymbol := '';
end;
{
with ParserTestData[5] do begin
FormatString := '#,##0.00 "$";-#,##0.00 "$";-';
SollFormatString := '#,##0.00 "$";-#,##0.00 "$";-';
SollNumFormat := nfCurrencyDash;
SollSectionCount := 3;
SollDecimals := 2;
SollCurrencySymbol := '$';
end; }
{
// This case will report a mismatching FormatString because of the [RED] --> ignore
with ParserTestData[6] do begin
FormatString := '#,##0.00 "$";[RED]-#,##0.00 "$";-';
SollFormatString := '#,##0.00 "$";-#,##0.00 "$";-';
SollNumFormat := nfCurrencyDashRed;
SollSectionCount := 3;
SollDecimals := 2;
SollCurrencySymbol := '$';
end;
}
end;
{ TSpreadNumFormatParserTests }
procedure TSpreadNumFormatParserTests.SetUp;
begin
inherited SetUp;
InitParserTestData;
end;
procedure TSpreadNumFormatParserTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadNumFormatParserTests.TestNumFormatParser;
var
i: Integer;
parser: TsNumFormatParser;
MyWorkbook: TsWorkbook;
actual: String;
begin
MyWorkbook := TsWorkbook.Create; // needed to provide the FormatSettings for the parser
try
for i:=0 to High(ParserTestData) do begin
parser := TsNumFormatParser.Create(ParserTestData[i].FormatString, MyWorkbook.FormatSettings);
try
actual := parser.FormatString;
CheckEquals(ParserTestData[i].SollFormatString, actual,
'Test format string ' + ParserTestData[i].SollFormatString + ' construction mismatch');
CheckEquals(
GetEnumName(TypeInfo(TsNumberFormat), ord(ParserTestData[i].SollNumFormat)),
GetEnumName(TypeInfo(TsNumberformat), ord(parser.ParsedSections[0].NumFormat)),
'Test format (' + ParserTestData[i].FormatString + ') detection mismatch');
CheckEquals(ParserTestData[i].SollDecimals, parser.ParsedSections[0].Decimals,
'Test format (' + ParserTestData[i].FormatString + ') decimal detection mismatch');
CheckEquals(ParserTestData[i].SollCurrencySymbol, parser.ParsedSections[0].CurrencySymbol,
'Test format (' + ParserTestData[i].FormatString + ') currency symbol detection mismatch');
CheckEquals(ParserTestData[i].SollSectionCount, parser.ParsedSectionCount,
'Test format (' + ParserTestData[i].FormatString + ') section count mismatch');
CheckEquals(ParserTestData[i].SollFactor, parser.ParsedSections[0].Factor,
'Test format (' + ParserTestData[i].FormatString + ') factor mismatch');
CheckEquals(ParserTestData[i].SollNumeratorDigits, parser.ParsedSections[0].FracNumerator,
'Test format (' + ParserTestData[i].FormatString + ') numerator digits mismatch');
CheckEquals(ParserTestData[i].SollDenominatorDigits, parser.ParsedSections[0].FracDenominator,
'Test format (' + ParserTestData[i].FormatString + ') denominator digits mismatch');
if ParserTestData[i].SollSectionCount > 1 then
CheckEquals(ParserTestData[i].SollSection2Color, parser.ParsedSections[1].Color,
'Test format (' + ParserTestData[i].FormatString + ') section 2 color mismatch');
finally
parser.Free;
end;
end;
finally
MyWorkbook.Free;
end;
end;
procedure TSpreadNumFormatParserTests.TestRounding;
var
i: Integer;
parser: TsNumFormatParser;
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
actual: String;
fs: TFormatSettings;
begin
MyWorkbook := TsWorkbook.Create;
try
fs := DefaultFormatSettings;
fs.DecimalSeparator := '.';
fs.ThousandSeparator := ',';
MyWorkbook.FormatSettings := fs;
MyWorksheet := MyWorkbook.AddWorksheet('Test');
for i:=0 to High(RoundingTestData) do begin
MyWorksheet.WriteNumber(0, 0,
RoundingTestData[i].Number, nfCustom, RoundingTestData[i].FormatString);
actual := MyWorksheet.ReadAsText(0, 0);
CheckEquals(RoundingTestData[i].SollString, actual,
'Rounding mismatch in test #' + IntToStr(i));
end;
finally
MyWorkbook.Free;
end;
end;
initialization
// Register so these tests are included in a full run
RegisterTest(TSpreadNumFormatParserTests);
InitParserTestData; //useful to have norm data if other code want to use this unit
end.
end.

View File

@ -0,0 +1,562 @@
unit optiontests;
{$mode objfpc}{$H+}
interface
{ Tests for spreadsheet options
This unit tests writing out to and reading back from files.
}
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
type
{ TSpreadWriteReadOptionTests }
//Write to xls/xml file and read back
TSpreadWriteReadOptionsTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteReadPanes(AFormat: TsSpreadsheetFormat;
ALeftPaneWidth, ATopPaneHeight: Integer);
procedure TestWriteReadGridHeaders(AFormat: TsSpreadsheetFormat;
AShowGridLines, AShowHeaders: Boolean);
procedure TestWriteReadHiddenSheet(AFormat: TsSpreadsheetFormat);
published
// Writes out sheet options & reads back.
{ BIFF2 tests }
procedure TestWriteRead_BIFF2_ShowGridLines_ShowHeaders;
procedure TestWriteRead_BIFF2_ShowGridLines_HideHeaders;
procedure TestWriteRead_BIFF2_HideGridLines_ShowHeaders;
procedure TestWriteRead_BIFF2_HideGridLines_HideHeaders;
procedure TestWriteRead_BIFF2_Panes_HorVert;
procedure TestWriteRead_BIFF2_Panes_Hor;
procedure TestWriteRead_BIFF2_Panes_Vert;
procedure TestWriteRead_BIFF2_Panes_None;
{ BIFF5 tests }
procedure TestWriteRead_BIFF5_ShowGridLines_ShowHeaders;
procedure TestWriteRead_BIFF5_ShowGridLines_HideHeaders;
procedure TestWriteRead_BIFF5_HideGridLines_ShowHeaders;
procedure TestWriteRead_BIFF5_HideGridLines_HideHeaders;
procedure TestWriteRead_BIFF5_Panes_HorVert;
procedure TestWriteRead_BIFF5_Panes_Hor;
procedure TestWriteRead_BIFF5_Panes_Vert;
procedure TestWriteRead_BIFF5_Panes_None;
procedure TestWriteRead_BIFF5_HiddenSheet;
{ BIFF8 tests }
procedure TestWriteRead_BIFF8_ShowGridLines_ShowHeaders;
procedure TestWriteRead_BIFF8_ShowGridLines_HideHeaders;
procedure TestWriteRead_BIFF8_HideGridLines_ShowHeaders;
procedure TestWriteRead_BIFF8_HideGridLines_HideHeaders;
procedure TestWriteRead_BIFF8_Panes_HorVert;
procedure TestWriteRead_BIFF8_Panes_Hor;
procedure TestWriteRead_BIFF8_Panes_Vert;
procedure TestWriteRead_BIFF8_Panes_None;
procedure TestWriteRead_BIFF8_HiddenSheet;
{ ODS tests }
procedure TestWriteRead_ODS_ShowGridLines_ShowHeaders;
procedure TestWriteRead_ODS_ShowGridLines_HideHeaders;
procedure TestWriteRead_ODS_HideGridLines_ShowHeaders;
procedure TestWriteRead_ODS_HideGridLines_HideHeaders;
procedure TestWriteRead_ODS_Panes_HorVert;
procedure TestWriteRead_ODS_Panes_Hor;
procedure TestWriteRead_ODS_Panes_Vert;
procedure TestWriteRead_ODS_Panes_None;
procedure TestWriteRead_ODS_HiddenSheet;
{ OOXML tests }
procedure TestWriteRead_OOXML_ShowGridLines_ShowHeaders;
procedure TestWriteRead_OOXML_ShowGridLines_HideHeaders;
procedure TestWriteRead_OOXML_HideGridLines_ShowHeaders;
procedure TestWriteRead_OOXML_HideGridLines_HideHeaders;
procedure TestWriteRead_OOXML_Panes_HorVert;
procedure TestWriteRead_OOXML_Panes_Hor;
procedure TestWriteRead_OOXML_Panes_Vert;
procedure TestWriteRead_OOXML_Panes_None;
procedure TestWriteRead_OOXML_HiddenSheet;
{ Excel 2003/XML tests }
procedure TestWriteRead_XML_ShowGridLines_ShowHeaders;
procedure TestWriteRead_XML_ShowGridLines_HideHeaders;
procedure TestWriteRead_XML_HideGridLines_ShowHeaders;
procedure TestWriteRead_XML_HideGridLines_HideHeaders;
procedure TestWriteRead_XML_Panes_HorVert;
procedure TestWriteRead_XML_Panes_Hor;
procedure TestWriteRead_XML_Panes_Vert;
procedure TestWriteRead_XML_Panes_None;
procedure TestWriteRead_XML_HiddenSheet;
end;
implementation
const
OptionsSheet = 'Options';
{ TSpreadWriteReadOptions }
procedure TSpreadWriteReadOptionsTests.SetUp;
begin
inherited SetUp;
end;
procedure TSpreadWriteReadOptionsTests.TearDown;
begin
inherited TearDown;
end;
{ Test for grid lines and sheet headers }
procedure TSpreadWriteReadOptionsTests.TestWriteReadGridHeaders(AFormat: TsSpreadsheetFormat;
AShowGridLines, AShowHeaders: Boolean);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
TempFile: string; //write xls/xml to this file and read back from it
begin
TempFile := GetTempFileName;
{// Not needed: use workbook.writetofile with overwrite=true
if fileexists(TempFile) then
DeleteFile(TempFile);
}
// Write out show/hide grid lines/sheet headers
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(OptionsSheet);
if AShowGridLines then
MyWorksheet.Options := MyWorksheet.Options + [soShowGridLines]
else
MyWorksheet.Options := MyWorksheet.Options - [soShowGridLines];
if AShowHeaders then
MyWorksheet.Options := MyWorksheet.Options + [soShowHeaders]
else
MyWorksheet.Options := MyWorksheet.Options - [soShowHeaders];
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Read back presence of grid lines/sheet headers
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, OptionsSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
CheckEquals(soShowGridLines in MyWorksheet.Options, AShowGridLines,
'Test saved show grid lines mismatch');
CheckEquals(soShowHeaders in MyWorksheet.Options, AShowHeaders,
'Test saved show headers mismatch');
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ Tests for BIFF2 grid lines and/or headers }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF2_ShowGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfExcel2, true, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF2_ShowGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfExcel2, true, false);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF2_HideGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfExcel2, false, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF2_HideGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfExcel2, false, false);
end;
{ Tests for BIFF5 grid lines and/or headers }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_ShowGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfExcel5, true, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_ShowGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfExcel5, true, false);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_HideGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfExcel5, false, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_HideGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfExcel5, false, false);
end;
{ Tests for BIFF8 grid lines and/or headers }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_ShowGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfExcel8, true, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_ShowGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfExcel8, true, false);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_HideGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfExcel8, false, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_HideGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfExcel8, false, false);
end;
{ Tests for ODS grid lines and/or headers }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_ShowGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfOpenDocument, true, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_ShowGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfOpenDocument, true, false);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_HideGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfOpenDocument, false, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_HideGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfOpenDocument, false, false);
end;
{ Tests for OOXML grid lines and/or headers }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_ShowGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfOOXML, true, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_ShowGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfOOXML, true, false);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_HideGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfOOXML, false, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_HideGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfOOXML, false, false);
end;
{ Tests for Excel2003/XML grid lines and/or headers }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_ShowGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfExcelXML, true, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_ShowGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfExcelXML, true, false);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_HideGridLines_ShowHeaders;
begin
TestWriteReadGridHeaders(sfExcelXML, false, true);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_HideGridLines_HideHeaders;
begin
TestWriteReadGridHeaders(sfExcelXML, false, false);
end;
{ Test for frozen panes }
procedure TSpreadWriteReadOptionsTests.TestWriteReadPanes(AFormat: TsSpreadsheetFormat;
ALeftPaneWidth, ATopPaneHeight: Integer);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
TempFile: string; //write xls/xml to this file and read back from it
begin
TempFile := GetTempFileName;
{// Not needed: use workbook.writetofile with overwrite=true
if fileexists(TempFile) then
DeleteFile(TempFile);
}
// Write out pane sizes
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(OptionsSheet);
MyWorksheet.LeftPaneWidth := ALeftPaneWidth;
MyWorksheet.TopPaneHeight := ATopPaneHeight;
MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes];
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Read back pane sizes
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, OptionsSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
CheckEquals(
(AleftPaneWidth > 0) or (ATopPaneHeight > 0),
(soHasFrozenPanes in MyWorksheet.Options)
and ((MyWorksheet.LeftPaneWidth > 0) or (MyWorksheet.TopPaneHeight > 0)),
'Test saved frozen panes mismatch');
CheckEquals(ALeftPaneWidth, MyWorksheet.LeftPaneWidth,
'Test saved left pane width mismatch');
CheckEquals(ATopPaneHeight, MyWorksheet.TopPaneHeight,
'Test save top pane height mismatch');
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ Tests for BIFF2 frozen panes }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF2_Panes_HorVert;
begin
TestWriteReadPanes(sfExcel2, 1, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF2_Panes_Hor;
begin
TestWriteReadPanes(sfExcel2, 1, 0);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF2_Panes_Vert;
begin
TestWriteReadPanes(sfExcel2, 0, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF2_Panes_None;
begin
TestWriteReadPanes(sfExcel2, 0, 0);
end;
{ Tests for BIFF5 frozen panes }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_Panes_HorVert;
begin
TestWriteReadPanes(sfExcel5, 1, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_Panes_Hor;
begin
TestWriteReadPanes(sfExcel5, 1, 0);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_Panes_Vert;
begin
TestWriteReadPanes(sfExcel5, 0, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_Panes_None;
begin
TestWriteReadPanes(sfExcel5, 0, 0);
end;
{ Tests for BIFF8 frozen panes }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_Panes_HorVert;
begin
TestWriteReadPanes(sfExcel8, 1, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_Panes_Hor;
begin
TestWriteReadPanes(sfExcel8, 1, 0);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_Panes_Vert;
begin
TestWriteReadPanes(sfExcel8, 0, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_Panes_None;
begin
TestWriteReadPanes(sfExcel8, 0, 0);
end;
{ Tests for ODS frozen panes }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_Panes_HorVert;
begin
TestWriteReadPanes(sfOpenDocument, 1, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_Panes_Hor;
begin
TestWriteReadPanes(sfOpenDocument, 1, 0);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_Panes_Vert;
begin
TestWriteReadPanes(sfOpenDocument, 0, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_Panes_None;
begin
TestWriteReadPanes(sfOpenDocument, 0, 0);
end;
{ Tests for OOXML frozen panes }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_Panes_HorVert;
begin
TestWriteReadPanes(sfOOXML, 1, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_Panes_Hor;
begin
TestWriteReadPanes(sfOOXML, 1, 0);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_Panes_Vert;
begin
TestWriteReadPanes(sfOOXML, 0, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_Panes_None;
begin
TestWriteReadPanes(sfOOXML, 0, 0);
end;
{ Tests for Excel 2003/XML frozen panes }
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_Panes_HorVert;
begin
TestWriteReadPanes(sfExcelXML, 1, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_Panes_Hor;
begin
TestWriteReadPanes(sfExcelXML, 1, 0);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_Panes_Vert;
begin
TestWriteReadPanes(sfExcelXML, 0, 2);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_Panes_None;
begin
TestWriteReadPanes(sfExcelXML, 0, 0);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteReadHiddenSheet(
AFormat: TsSpreadsheetFormat);
const
RESULTS: array[0..1] of Boolean = (false, true);
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
TempFile: string; //write xls/xml to this file and read back from it
i: Integer;
begin
TempFile := GetTempFileName;
// Write out pane sizes
MyWorkbook := TsWorkbook.Create;
try
MyWorkBook.AddWorksheet(OptionsSheet);
MyWorkSheet := MyWorkBook.AddWorksheet(OptionsSheet + '-hidden');
MyWorksheet.Options := myWorksheet.Options + [soHidden];
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Read back pane sizes
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
for i:=0 to MyWorkbook.GetWorksheetCount-1 do begin
MyWorksheet := MyWorkbook.GetWorksheetByIndex(i);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet #' + IntToStr(i));
CheckEquals(RESULTS[i], soHidden in MyWorksheet.Options,
'Test saved hidden state mismatch, sheet #' + IntToStr(i));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF5_HiddenSheet;
begin
TestWriteReadHiddenSheet(sfExcel5);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_BIFF8_HiddenSheet;
begin
TestWriteReadHiddenSheet(sfExcel8);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_OOXML_HiddenSheet;
begin
TestWriteReadHiddenSheet(sfOOXML);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_ODS_HiddenSheet;
begin
TestWriteReadHiddenSheet(sfOpenDocument);
end;
procedure TSpreadWriteReadOptionsTests.TestWriteRead_XML_HiddenSheet;
begin
TestWriteReadHiddenSheet(sfExcelXML);
end;
initialization
RegisterTest(TSpreadWriteReadOptionsTests);
end.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,840 @@
{ Protection tests
These unit tests are writing out to and reading back from file.
}
unit protectiontests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, //xlsbiff2, xlsbiff5, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
type
{ TSpreadWriteReadProtectionTests }
//Write to xls/xml file and read back
TSpreadWriteReadProtectionTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteRead_WorkbookProtection(AFormat: TsSpreadsheetFormat;
ACondition: Integer);
procedure TestWriteRead_WorksheetProtection(AFormat: TsSpreadsheetFormat;
ACondition: Integer);
procedure TestWriteRead_CellProtection(AFormat: TsSpreadsheetFormat);
procedure TestWriteRead_Passwords(AFormat: TsSpreadsheetFormat);
published
// Writes out protection & reads back.
{ BIFF2 protection tests }
procedure TestWriteRead_BIFF2_WorkbookProtection_None;
procedure TestWriteRead_BIFF2_WorkbookProtection_Struct;
procedure TestWriteRead_BIFF2_WorkbookProtection_Win;
procedure TestWriteRead_BIFF2_WorkbookProtection_StructWin;
procedure TestWriteRead_BIFF2_WorksheetProtection_Default;
procedure TestWriteRead_BIFF2_WorksheetProtection_Objects;
procedure TestWriteRead_BIFF2_CellProtection;
procedure TestWriteRead_BIFF2_Passwords;
{ BIFF5 protection tests }
procedure TestWriteRead_BIFF5_WorkbookProtection_None;
procedure TestWriteRead_BIFF5_WorkbookProtection_Struct;
procedure TestWriteRead_BIFF5_WorkbookProtection_Win;
procedure TestWriteRead_BIFF5_WorkbookProtection_StructWin;
procedure TestWriteRead_BIFF5_WorksheetProtection_Default;
procedure TestWriteRead_BIFF5_WorksheetProtection_SelectLockedCells;
procedure TestWriteRead_BIFF5_WorksheetProtection_SelectUnlockedCells;
procedure TestWriteRead_BIFF5_WorksheetProtection_Objects;
procedure TestWriteRead_BIFF5_CellProtection;
procedure TestWriteRead_BIFF5_Passwords;
{ BIFF8 protection tests }
procedure TestWriteRead_BIFF8_WorkbookProtection_None;
procedure TestWriteRead_BIFF8_WorkbookProtection_Struct;
procedure TestWriteRead_BIFF8_WorkbookProtection_Win;
procedure TestWriteRead_BIFF8_WorkbookProtection_StructWin;
procedure TestWriteRead_BIFF8_WorksheetProtection_Default;
procedure TestWriteRead_BIFF8_WorksheetProtection_SelectLockedCells;
procedure TestWriteRead_BIFF8_WorksheetProtection_SelectUnlockedCells;
procedure TestWriteRead_BIFF8_WorksheetProtection_Objects;
procedure TestWriteRead_BIFF8_CellProtection;
procedure TestWriteRead_BIFF8_Passwords;
{ OOXML protection tests }
procedure TestWriteRead_OOXML_WorkbookProtection_None;
procedure TestWriteRead_OOXML_WorkbookProtection_Struct;
procedure TestWriteRead_OOXML_WorkbookProtection_Win;
procedure TestWriteRead_OOXML_WorkbookProtection_StructWin;
procedure TestWriteRead_OOXML_WorksheetProtection_Default;
procedure TestWriteRead_OOXML_WorksheetProtection_FormatCells;
procedure TestWriteRead_OOXML_WorksheetProtection_FormatColumns;
procedure TestWriteRead_OOXML_WorksheetProtection_FormatRows;
procedure TestWriteRead_OOXML_WorksheetProtection_DeleteColumns;
procedure TestWriteRead_OOXML_WorksheetProtection_DeleteRows;
procedure TestWriteRead_OOXML_WorksheetProtection_InsertColumns;
procedure TestWriteRead_OOXML_WorksheetProtection_InsertHyperlinks;
procedure TestWriteRead_OOXML_WorksheetProtection_InsertRows;
procedure TestWriteRead_OOXML_WorksheetProtection_Sort;
procedure TestWriteRead_OOXML_WorksheetProtection_SelectLockedCells;
procedure TestWriteRead_OOXML_WorksheetProtection_SelectUnlockedCells;
procedure TestWriteRead_OOXML_WorksheetProtection_Objects;
procedure TestWriteRead_OOXML_CellProtection;
procedure TestWriteRead_OOXML_Passwords;
{ Excedl2003/XML protection tests }
procedure TestWriteRead_XML_WorkbookProtection_None;
procedure TestWriteRead_XML_WorkbookProtection_Struct;
procedure TestWriteRead_XML_WorkbookProtection_Win;
procedure TestWriteRead_XML_WorkbookProtection_StructWin;
procedure TestWriteRead_XML_WorksheetProtection_Default;
procedure TestWriteRead_XML_WorksheetProtection_FormatCells;
procedure TestWriteRead_XML_WorksheetProtection_FormatColumns;
procedure TestWriteRead_XML_WorksheetProtection_FormatRows;
procedure TestWriteRead_XML_WorksheetProtection_DeleteColumns;
procedure TestWriteRead_XML_WorksheetProtection_DeleteRows;
procedure TestWriteRead_XML_WorksheetProtection_InsertColumns;
procedure TestWriteRead_XML_WorksheetProtection_InsertHyperlinks;
procedure TestWriteRead_XML_WorksheetProtection_InsertRows;
procedure TestWriteRead_XML_WorksheetProtection_Sort;
procedure TestWriteRead_XML_WorksheetProtection_SelectLockedCells;
procedure TestWriteRead_XML_WorksheetProtection_SelectUnlockedCells;
procedure TestWriteRead_XML_WorksheetProtection_Objects;
procedure TestWriteRead_XML_CellProtection;
//procedure TestWriteRead_XML_Passwords; // not allowed
{ ODS protection tests }
procedure TestWriteRead_ODS_WorkbookProtection_None;
procedure TestWriteRead_ODS_WorkbookProtection_Struct;
//procedure TestWriteRead_ODS_WorkbookProtection_Win;
//procedure TestWriteRead_ODS_WorkbookProtection_StructWin;
procedure TestWriteRead_ODS_WorksheetProtection_Default;
procedure TestWriteRead_ODS_WorksheetProtection_SelectLockedCells;
procedure TestWriteRead_ODS_WorksheetProtection_SelectUnlockedCells;
procedure TestWriteRead_ODS_CellProtection;
procedure TestWriteRead_ODS_Passwords;
end;
implementation
uses
fpsUtils;
const
ProtectionSheet = 'Protection';
{ TSpreadWriteReadProtectionTests }
procedure TSpreadWriteReadProtectionTests.SetUp;
begin
inherited SetUp;
end;
procedure TSpreadWriteReadProtectionTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_WorkbookProtection(
AFormat: TsSpreadsheetFormat; ACondition: Integer);
var
MyWorkbook: TsWorkbook;
TempFile: string; //write xls/xml to this file and read back from it
expected, actual: TsWorkbookProtections;
msg: String;
begin
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorkBook.AddWorksheet(ProtectionSheet);
case ACondition of
0: expected := [];
1: expected := [bpLockStructure];
2: expected := [bpLockWindows];
3: expected := [bpLockStructure, bpLockWindows];
end;
MyWorkbook.Protection := expected;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
actual := MyWorkbook.Protection;
if actual <> expected then begin
msg := 'Test saved workbook protection mismatch: ';
case ACondition of
0: fail(msg + 'no protection');
1: fail(msg + 'bpLockStructure');
2: fail(msg + 'bpLockWindows');
3: fail(msg + 'bpLockStructure, bpLockWindows');
end;
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_WorksheetProtection(
AFormat: TsSpreadsheetFormat; ACondition: Integer);
const
ALL_SHEET_PROTECTIONS = [
spFormatCells, spFormatColumns, spFormatRows,
spDeleteColumns, spDeleteRows, spInsertColumns, spInsertRows,
spInsertHyperlinks, spSort, spObjects,
spSelectLockedCells, spSelectUnlockedCells
]; // NOTE: spCells is handled separately
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
TempFile: string; //write xls/xml to this file and read back from it
expected, actual: TsWorksheetProtections;
msg: String;
begin
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorksheet := MyWorkBook.AddWorksheet(ProtectionSheet);
expected := DEFAULT_SHEET_PROTECTION;
case ACondition of
0: ;
1: Exclude(expected, spFormatCells);
2: Exclude(expected, spFormatColumns);
3: Exclude(expected, spFormatRows);
4: Exclude(expected, spDeleteColumns);
5: Exclude(expected, spDeleteRows);
6: Exclude(expected, spInsertColumns);
7: Exclude(expected, spInsertHyperlinks);
8: Exclude(expected, spInsertRows);
9: Exclude(expected, spSort);
10: Exclude(expected, spSelectLockedCells);
11: Exclude(expected, spSelectUnlockedCells);
12: Include(expected, spObjects);
end;
{
case ACondition of
0: expected := [];
1: expected := [spFormatCells];
2: expected := [spFormatColumns];
3: expected := [spFormatRows];
4: expected := [spDeleteColumns];
5: expected := [spDeleteRows];
6: expected := [spInsertColumns];
7: expected := [spInsertHyperlinks];
8: expected := [spInsertRows];
9: expected := [spSort];
10: expected := [spSelectLockedCells];
11: expected := [spSelectUnlockedCells];
12: expected := [spObjects];
13: expected := ALL_SHEET_PROTECTIONS;
end;
}
MyWorksheet.Protection := expected;
MyWorksheet.Protect(true);
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
MyWorksheet := MyWorkbook.GetFirstWorksheet;
if (ACondition > 0) and not MyWorksheet.IsProtected then
fail(msg + 'Sheet protection not active');
actual := MyWorksheet.Protection;
// if actual <> [] then actual := actual - [spCells];
msg := 'Test saved worksheet protection mismatch: ';
if actual <> expected then
case ACondition of
0: fail(msg + 'default protection');
1: fail(msg + 'spFormatCells');
2: fail(msg + 'spFormatColumns');
3: fail(msg + 'spFormatRows');
4: fail(msg + 'spDeleteColumns');
5: fail(msg + 'spDeleteRows');
6: fail(msg + 'spInsertColumns');
7: fail(msg + 'spInsertHyperlinks');
8: fail(msg + 'spInsertRows');
9: fail(msg + 'spSort');
10: fail(msg + 'spSelectLockedCells');
11: fail(msg + 'spSelectUnlockedCells');
12: fail(msg + 'spObjects');
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_CellProtection(
AFormat: TsSpreadsheetFormat);
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
cell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
expected, actual: TsCellProtections;
msg: String;
begin
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorksheet := MyWorkBook.AddWorksheet(ProtectionSheet);
// A1 --> lock cell
cell := Myworksheet.WriteText(0, 0, 'Protected');
MyWorksheet.WriteCellProtection(cell, [cpLockCell]);
// A2 --> not protected at all
cell := MyWorksheet.WriteText(1, 0, 'Not protected');
MyWorksheet.WriteCellProtection(cell, []);
// B1 --> lock cell & hide formulas
cell := Myworksheet.WriteFormula(0, 1, '=A1');
MyWorksheet.WriteCellProtection(cell, [cpLockCell, cpHideFormulas]);
// B2 --> hide formula only
cell := MyWorksheet.WriteFormula(1, 1, '=A2');
Myworksheet.WriteCellProtection(Cell, [cpHideFormulas]);
MyWorksheet.Protect(true);
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
MyWorksheet := MyWorkbook.GetFirstWorksheet;
msg := 'Test saved worksheet protection mismatch: ';
if not MyWorksheet.IsProtected then begin
fail(msg + 'Sheet protection not active');
exit;
end;
cell := MyWorksheet.FindCell(0, 0);
if cell = nil then
fail(msg + 'Protected cell A1 not found.');
actual := MyWorksheet.ReadCellProtection(cell);
if actual <> [cpLockCell] then
fail(msg + 'cell A1 protection = [cpLockCells]');
cell := MyWorksheet.FindCell(1, 0);
if cell = nil then
fail(msg + 'Unprotected cell A2 not found.');
actual := MyWorksheet.ReadCellProtection(cell);
if actual <> [] then
fail(msg + 'cell A2 protection = []');
cell := Myworksheet.FindCell(0, 1);
if cell = nil then
fail(msg + 'Cell B1 not found.');
actual := MyWorksheet.ReadCellProtection(cell);
if actual <> [cpLockCell, cpHideFormulas] then
fail(msg + 'cell B1 protection = [cpLockCells, cpHideFormulas]');
cell := MyWorksheet.FindCell(1, 1);
if cell = nil then
fail(msg + 'Cell B2 protection = [cpHideFormulas]');
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_Passwords(
AFormat: TsSpreadsheetFormat);
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
cell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
bi, si, cinfo: TsCryptoInfo;
msg: String;
begin
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorksheet := MyWorkBook.AddWorksheet(ProtectionSheet);
MyWorkbook.Protection := [bpLockStructure];
InitCryptoInfo(bi);
bi.PasswordHash := 'ABCD';
bi.Algorithm := caExcel;
MyWorkbook.CryptoInfo := bi;
MyWorksheet.Protect(true);
if AFormat = sfExcel2 then
si := bi // in BIFF2: use the same crypto info for sheet and book
else begin
InitCryptoInfo(si);
si.PasswordHash := 'DCBA';
si.Algorithm := caExcel;
end;
MyWorksheet.CryptoInfo := si;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, AFormat);
MyWorksheet := MyWorkbook.GetFirstWorksheet;
cInfo := MyWorkbook.CryptoInfo;
CheckEquals(
bi.PasswordHash, cinfo.PasswordHash,
'Workbook protection password hash mismatch'
);
cInfo := MyWorksheet.CryptoInfo;
CheckEquals(
si.PasswordHash, cinfo.PasswordHash,
'Worksheet protection password hash mismatch'
);
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{------------------------------------------------------------------------------}
{ Tests for BIFF2 file format }
{------------------------------------------------------------------------------}
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_WorkbookProtection_None;
begin
TestWriteRead_WorkbookProtection(sfExcel2, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_WorkbookProtection_Struct;
begin
TestWriteRead_WorkbookProtection(sfExcel2, 1);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_WorkbookProtection_Win;
begin
TestWriteRead_WorkbookProtection(sfExcel2, 2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_WorkbookProtection_StructWin;
begin
TestWriteRead_WorkbookProtection(sfExcel2, 3);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_WorksheetProtection_Default;
begin
TestWriteRead_WorksheetProtection(sfExcel2, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_WorksheetProtection_Objects;
begin
TestWriteRead_WorksheetProtection(sfExcel2, 12);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_CellProtection;
begin
TestWriteRead_CellProtection(sfExcel2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_Passwords;
begin
TestWriteRead_Passwords(sfExcel2);
end;
{------------------------------------------------------------------------------}
{ Tests for BIFF5 file format }
{------------------------------------------------------------------------------}
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_WorkbookProtection_None;
begin
TestWriteRead_WorkbookProtection(sfExcel5, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_WorkbookProtection_Struct;
begin
TestWriteRead_WorkbookProtection(sfExcel5, 1);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_WorkbookProtection_Win;
begin
TestWriteRead_WorkbookProtection(sfExcel5, 2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_WorkbookProtection_StructWin;
begin
TestWriteRead_WorkbookProtection(sfExcel5, 3);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_WorksheetProtection_Default;
begin
TestWriteRead_WorksheetProtection(sfExcel5, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_WorksheetProtection_SelectLockedCells;
begin
TestWriteRead_WorksheetProtection(sfExcel5, 10);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_WorksheetProtection_SelectUnlockedCells;
begin
TestWriteRead_WorksheetProtection(sfExcel5, 11);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_WorksheetProtection_Objects;
begin
TestWriteRead_WorksheetProtection(sfExcel5, 12);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_CellProtection;
begin
TestWriteRead_CellProtection(sfExcel5);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_Passwords;
begin
TestWriteRead_Passwords(sfExcel5);
end;
{------------------------------------------------------------------------------}
{ Tests for BIFF8 file format }
{------------------------------------------------------------------------------}
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_WorkbookProtection_None;
begin
TestWriteRead_WorkbookProtection(sfExcel8, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_WorkbookProtection_Struct;
begin
TestWriteRead_WorkbookProtection(sfExcel8, 1);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_WorkbookProtection_Win;
begin
TestWriteRead_WorkbookProtection(sfExcel8, 2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_WorkbookProtection_StructWin;
begin
TestWriteRead_WorkbookProtection(sfExcel8, 3);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_WorksheetProtection_Default;
begin
TestWriteRead_WorksheetProtection(sfExcel8, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_WorksheetProtection_SelectLockedCells;
begin
TestWriteRead_WorksheetProtection(sfExcel8, 10);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_WorksheetProtection_SelectUnlockedCells;
begin
TestWriteRead_WorksheetProtection(sfExcel8, 11);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_WorksheetProtection_Objects;
begin
TestWriteRead_WorksheetProtection(sfExcel8, 12);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_CellProtection;
begin
TestWriteRead_CellProtection(sfExcel8);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_Passwords;
begin
TestWriteRead_Passwords(sfExcel8);
end;
{------------------------------------------------------------------------------}
{ Tests for OOXML file format }
{------------------------------------------------------------------------------}
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorkbookProtection_None;
begin
TestWriteRead_WorkbookProtection(sfOOXML, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorkbookProtection_Struct;
begin
TestWriteRead_WorkbookProtection(sfOOXML, 1);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorkbookProtection_Win;
begin
TestWriteRead_WorkbookProtection(sfOOXML, 2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorkbookProtection_StructWin;
begin
TestWriteRead_WorkbookProtection(sfOOXML, 3);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_Default;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_FormatCells;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 1);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_FormatColumns;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_FormatRows;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 3);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_DeleteColumns;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 4);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_DeleteRows;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 5);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_InsertColumns;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 6);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_InsertHyperlinks;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 7);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_InsertRows;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 8);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_Sort;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 9);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_SelectLockedCells;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 10);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_SelectUnlockedCells;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 11);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_WorksheetProtection_Objects;
begin
TestWriteRead_WorksheetProtection(sfOOXML, 12);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_CellProtection;
begin
TestWriteRead_CellProtection(sfOOXML);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_Passwords;
begin
TestWriteRead_Passwords(sfOOXML);
end;
{------------------------------------------------------------------------------}
{ Tests for OOXML file format }
{------------------------------------------------------------------------------}
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorkbookProtection_None;
begin
TestWriteRead_WorkbookProtection(sfExcelXML, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorkbookProtection_Struct;
begin
TestWriteRead_WorkbookProtection(sfExcelXML, 1);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorkbookProtection_Win;
begin
TestWriteRead_WorkbookProtection(sfExcelXML, 2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorkbookProtection_StructWin;
begin
TestWriteRead_WorkbookProtection(sfExcelXML, 3);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_Default;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_FormatCells;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 1);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_FormatColumns;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_FormatRows;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 3);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_DeleteColumns;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 4);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_DeleteRows;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 5);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_InsertColumns;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 6);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_InsertHyperlinks;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 7);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_InsertRows;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 8);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_Sort;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 9);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_SelectLockedCells;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 10);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_SelectUnlockedCells;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 11);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_WorksheetProtection_Objects;
begin
TestWriteRead_WorksheetProtection(sfExcelXML, 12);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_XML_CellProtection;
begin
TestWriteRead_CellProtection(sfExcelXML);
end;
{------------------------------------------------------------------------------}
{ Tests for OpenDocument file format }
{------------------------------------------------------------------------------}
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_WorkbookProtection_None;
begin
TestWriteRead_WorkbookProtection(sfOpenDocument, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_WorkbookProtection_Struct;
begin
TestWriteRead_WorkbookProtection(sfOpenDocument, 1);
end;
{
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_WorkbookProtection_Win;
begin
TestWriteRead_WorkbookProtection(sfOpenDocument, 2);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_WorkbookProtection_StructWin;
begin
TestWriteRead_WorkbookProtection(sfOpenDocument, 3);
end;}
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_WorksheetProtection_Default;
begin
TestWriteRead_WorksheetProtection(sfOpenDocument, 0);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_WorksheetProtection_SelectLockedCells;
begin
TestWriteRead_WorksheetProtection(sfOpenDocument, 10);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_WorksheetProtection_SelectUnlockedCells;
begin
TestWriteRead_WorksheetProtection(sfOpenDocument, 11);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_CellProtection;
begin
TestWriteRead_CellProtection(sfOpenDocument);
end;
procedure TSpreadWriteReadProtectionTests.TestWriteRead_ODS_Passwords;
begin
TestWriteRead_Passwords(sfOpenDocument);
end;
initialization
RegisterTest(TSpreadWriteReadProtectionTests);
end.

View File

@ -0,0 +1,46 @@
Tests for fpspreadsheet
spreadtestgui
=============
Lets you quickly run tests in a GUI.
If there are problems, you can open the spreadtestgui.lpr in Lazarus, compile it with debug mode, and trace through the offending test and the fpspreadsheet code it calls.
More details: FPCUnit documentation
spreadtestcli
=============
Command line version of the above, extended with database output. Useful for scripting use (use e.g. --all --format=plain.
For output to an embedded Firebird database, make sure the required dlls/packages are present and run the program, e.g:
spreadtestcli --comment="Hoped to have fixed that string issue" --revision="482"
(the revision is the SVN revision number, so you can keep track of regresssions)
More details: FPCUnit documentation and
https://bitbucket.org/reiniero/testdbwriter
The tests
=========
Basic tests read XLS files and check the retrieved values against a list. This tests whether reading dates, text etc works.
Another test is to take that list of normative values, write it to an xls file, then read back and compare with the original list. This basically tests whether write support is correct.
The files are written to the temp directory. They are deleted on succesful test completion; otherwise they are kept so you can open them up with a spreadsheet application/mso dumper tool/hex editor and check what exactly got written.
Finally, there is a manual test unit: these tests write out cells to a spreadsheet file (testmanual.xls) that the user should inspect himself. Examples are tests for colors, formatting etc.
Adding tests
============
For most tests:
- Add new cells to the A column in the relevant xls files; see comments in files.
- Add corresponding normative/expected value in the relevant test unit; increase array size
- Add your tests that read the data from xls and checks against the norm array.
Note that tests that check for known failures are quite valuable. You can indicate you expect an exception etc.
Ideas for more tests:
- add more tests to internaltests to explicitly tests fpspreadsheet functions/procedures/properties that don't read/write to xls/xml files
- writing RPN formulas in the manualtests unit
- more xls/xml file formats tested
- more corner cases
- writing all data available to various sheets and reading it back to test whether complex sheets work
- reading faulty files to test exception handling
For more details, please see the FPCUnit documentation.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,519 @@
unit sortingtests;
{$mode objfpc}{$H+}
interface
{ Tests for sorting cells
}
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8, fpsopendocument, {and a project requirement for lclbase for utf8 handling}
testsutility;
var
// Norm to test against - list of numbers and strings that will be sorted
SollSortNumbers: array[0..9] of Double;
SollSortStrings: array[0..9] of String;
CommentIsSortedToStringIndex: Integer;
CommentIsSortedToNumberIndex: Integer;
HyperlinkIsSortedToStringIndex: Integer;
HyperlinkIsSortedToNumberIndex: Integer;
procedure InitUnsortedData;
type
{ TSpreadSortingTests }
TSpreadSortingTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure Test_Sorting_1( // one column or row
ASortByCols: Boolean;
ADescending: Boolean; // true: desending order
AWhat: Integer // What = 0: number, 1: strings, 2: mixed
);
procedure Test_Sorting_2( // two columns/rows, primary keys equal
ASortByCols: Boolean;
ADescending: Boolean
);
published
procedure Test_SortingByCols1_Numbers_Asc;
procedure Test_SortingByCols1_Numbers_Desc;
procedure Test_SortingByCols1_Strings_Asc;
procedure Test_SortingByCols1_Strings_Desc;
procedure Test_SortingByCols1_NumbersStrings_Asc;
procedure Test_SortingByCols1_NumbersStrings_Desc;
procedure Test_SortingByRows1_Numbers_Asc;
procedure Test_SortingByRows1_Numbers_Desc;
procedure Test_SortingByRows1_Strings_Asc;
procedure Test_SortingByRows1_Strings_Desc;
procedure Test_SortingByRows1_NumbersStrings_Asc;
procedure Test_SortingByRows1_NumbersStrings_Desc;
procedure Test_SortingByCols2_Asc;
procedure Test_SortingByCols2_Desc;
procedure Test_SortingByRows2_Asc;
procedure Test_SortingByRows2_Desc;
end;
implementation
uses
fpsutils;
const
SortingTestSheet = 'Sorting';
procedure InitUnsortedData;
// The logics of the detection requires equal count of numbers and strings.
begin
// When sorted the value is equal to the index
SollSortNumbers[0] := 9; // --> A1 --> will contain comment and hyperlink
SollSortNumbers[1] := 8;
SollSortNumbers[2] := 5;
SollSortNumbers[3] := 2;
SollSortNumbers[4] := 6;
SollSortNumbers[5] := 7;
SollSortNumbers[6] := 1;
SollSortNumbers[7] := 3;
SollSortNumbers[8] := 4;
SollSortNumbers[9] := 0;
CommentIsSortedToNumberIndex := 9;
HyperlinkIsSortedToNumberIndex := 9;
// When sorted the value is equal to 'A' + index
SollSortStrings[0] := 'C'; // --> Ar --> will contain hyperlink and comment
SollSortStrings[1] := 'G';
SollSortStrings[2] := 'F';
SollSortStrings[3] := 'I';
SollSortStrings[4] := 'B';
SollSortStrings[5] := 'D';
SollSortStrings[6] := 'J';
SollSortStrings[7] := 'H';
SollSortStrings[8] := 'E';
SollSortStrings[9] := 'A';
CommentIsSortedToStringIndex := 2;
HyperlinkIsSortedToStringIndex := 2;
end;
{ TSpreadSortingTests }
procedure TSpreadSortingTests.SetUp;
begin
inherited SetUp;
InitUnsortedData;
end;
procedure TSpreadSortingTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadSortingTests.Test_Sorting_1(ASortByCols: Boolean;
ADescending: Boolean; AWhat: Integer);
const
AFormat = sfExcel8;
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
i, ilast, row, col: Integer;
TempFile: string; //write xls/xml to this file and read back from it
sortParams: TsSortParams;
actualNumber: Double;
actualString: String;
expectedNumber: Double;
expectedString: String;
cell: PCell;
begin
sortParams := InitSortParams(ASortByCols, 1);
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(SortingTestSheet);
col := 0;
row := 0;
if ASortByCols then begin
case AWhat of
0: for i :=0 to High(SollSortNumbers) do // Numbers only
MyWorksheet.WriteNumber(i, col, SollSortNumbers[i]);
1: for i := 0 to High(SollSortStrings) do // Strings only
Myworksheet.WriteText(i, col, SollSortStrings[i]);
2: begin // Numbers and strings
for i := 0 to High(SollSortNumbers) do
MyWorkSheet.WriteNumber(i*2, col, SollSortNumbers[i]);
for i := 0 to High(SollSortStrings) do
MyWorksheet.WriteText(i*2+1, col, SollSortStrings[i]);
end;
end
end
else begin
case AWhat of
0: for i := 0 to High(SollSortNumbers) do
MyWorksheet.WriteNumber(row, i, SollSortNumbers[i]);
1: for i := 0 to High(SollSortStrings) do
MyWorksheet.WriteText(row, i, SollSortStrings[i]);
2: begin
for i := 0 to High(SollSortNumbers) do
myWorkSheet.WriteNumber(row, i*2, SollSortNumbers[i]);
for i:=0 to High(SollSortStrings) do
MyWorksheet.WriteText(row, i*2+1, SollSortStrings[i]);
end;
end;
end;
// Add comment and hyperlink to cell A1. After sorting it is expected
// in cell defined by CommentIsSortedToXXXIndex (XXX = Number/String)
if AFormat <> sfExcel8 then // Comments not implemented for writing Excel8
MyWorksheet.WriteComment(0, 0, 'Test comment');
MyWorksheet.WriteHyperlink(0, 0, 'http://www.google.com');
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
MyWorkbook := TsWorkbook.Create;
try
// Read spreadsheet file...
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, SortingTestSheet);
if MyWorksheet = nil then
fail('Error in test code. Failed to get named worksheet');
// ... set up sorting direction
case ADescending of
false: sortParams.Keys[0].Options := []; // Ascending sort
true : sortParams.Keys[0].Options := [ssoDescending]; // Descending sort
end;
// ... and sort it.
case AWhat of
0: iLast:= High(SollSortNumbers);
1: iLast := High(SollSortStrings);
2: iLast := Length(SollSortNumbers) + Length(SollSortStrings) - 1;
end;
if ASortByCols then
MyWorksheet.Sort(sortParams, 0, 0, iLast, 0)
else
MyWorksheet.Sort(sortParams, 0, 0, 0, iLast);
// for debugging, to see the sorted data
//MyWorkbook.WriteToFile('sorted.xls', AFormat, true);
row := 0;
col := 0;
for i:=0 to iLast do
begin
if ASortByCols then
case ADescending of
false: row := i; // ascending
true : row := iLast - i; // descending
end
else
case ADescending of
false: col := i; // ascending
true : col := iLast - i; // descending
end;
case AWhat of
0: begin
cell := MyWorksheet.FindCell(row, col);
actualNumber := MyWorksheet.ReadAsNumber(cell);
expectedNumber := i;
CheckEquals(expectednumber, actualnumber,
'Sorted cell number mismatch, cell '+CellNotation(MyWorksheet, row, col));
if AFormat <> sfExcel8 then // Comments are not written for sfExcel8 --> ignore
CheckEquals(
i=CommentIsSortedToNumberIndex,
MyWorksheet.HasComment(cell),
'Sorted comment position mismatch, cell '+CellNotation(MyWorksheet, row, col));
CheckEquals(
i = HyperlinkisSortedToNumberIndex,
MyWorksheet.HasHyperlink(cell),
'Sorted hyperlink position mismatch, cell '+CellNotation(MyWorksheet, row, col));
end;
1: begin
cell := MyWorksheet.FindCell(row, col);
actualString := MyWorksheet.ReadAsText(cell);
expectedString := char(ord('A') + i);
CheckEquals(expectedstring, actualstring,
'Sorted cell string mismatch, cell '+CellNotation(MyWorksheet, row, col));
if AFormat <> sfExcel8 then // Comments are not written for sfExcel8 --> ignore
CheckEquals(
i=CommentIsSortedToStringIndex,
MyWorksheet.HasComment(cell),
'Sorted comment position mismatch, cell '+CellNotation(MyWorksheet, row, col));
CheckEquals(
i = HyperlinkisSortedToStringIndex,
MyWorksheet.HasHyperlink(cell),
'Sorted hyperlink position mismatch, cell '+CellNotation(MyWorksheet, row, col));
end;
2: begin // with increasing i, we see first the numbers, then the strings
if i <= High(SollSortNumbers) then begin
cell := MyWorksheet.FindCell(row, col);
actualnumber := MyWorksheet.ReadAsNumber(cell);
expectedNumber := i;
CheckEquals(expectednumber, actualnumber,
'Sorted cell number mismatch, cell '+CellNotation(MyWorksheet, row, col));
end else begin
actualstring := MyWorksheet.ReadAsText(row, col);
expectedstring := char(ord('A') + i - Length(SollSortNumbers));
CheckEquals(expectedstring, actualstring,
'Sorted cell string mismatch, cell '+CellNotation(MyWorksheet, row, col));
end;
end;
end;
end;
finally
MyWorkbook.Free;
end;
DeleteFile(TempFile);
end;
procedure TSpreadSortingTests.Test_Sorting_2(ASortByCols: Boolean;
ADescending: Boolean);
const
AFormat = sfExcel8;
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
i, ilast, row, col: Integer;
TempFile: string; //write xls/xml to this file and read back from it
sortParams: TsSortParams;
actualNumber: Double;
actualString: String;
expectedNumber: Double;
expectedString: String;
begin
sortParams := InitSortParams(ASortByCols, 2);
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;
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(SortingTestSheet);
col := 0;
row := 0;
if ASortByCols then
begin
// 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.WriteText(i, col, char(ord('A')+round(SollSortNumbers[i]) div 2));
end else
begin
// The same with the rows...
for i:=0 to iLast do
MyWorksheet.WriteNumber(row+1, i, SollSortNumbers[i]);
for i:=0 to iLast do
MyWorksheet.WriteText(row, i, char(ord('A')+round(SollSortNumbers[i]) div 2));
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
MyWorkbook := TsWorkbook.Create;
try
// Read spreadsheet file...
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, SortingTestSheet);
if MyWorksheet = nil then
fail('Error in test code. Failed to get named worksheet');
// ... set up sort direction
if ADescending then
begin
sortParams.Keys[0].Options := [ssoDescending];
sortParams.Keys[1].Options := [ssoDescending];
end else
begin
sortParams.Keys[0].Options := [];
sortParams.Keys[1].Options := [];
end;
// ... and sort it.
if ASortByCols then
MyWorksheet.Sort(sortParams, 0, 0, iLast, 1)
else
MyWorksheet.Sort(sortParams, 0, 0, 1, iLast);
// for debugging, to see the sorted data
// MyWorkbook.WriteToFile('sorted.xls', AFormat, true);
for i:=0 to iLast do
begin
if ASortByCols then
begin
// Read the number first, they must be in order 0...9 (if ascending).
col := 1;
case ADescending of
false : row := i;
true : row := iLast - i;
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.ReadAsText(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 ADescending of
false : col := i;
true : col := iLast - i;
end;
actualNumber := MyWorksheet.ReadAsNumber(row, col);
expectedNumber := i;
CheckEquals(expectednumber, actualnumber,
'Sorted cell number mismatch, cell '+CellNotation(MyWorksheet, row, col));
row := 0;
actualstring := MyWorksheet.ReadAsText(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;
end;
DeleteFile(TempFile);
end;
{ Sort 1 column }
procedure TSpreadSortingTests.Test_SortingByCols1_Numbers_ASC;
begin
Test_Sorting_1(true, false, 0);
end;
procedure TSpreadSortingTests.Test_SortingByCols1_Numbers_DESC;
begin
Test_Sorting_1(true, true, 0);
end;
procedure TSpreadSortingTests.Test_SortingByCols1_Strings_ASC;
begin
Test_Sorting_1(true, false, 1);
end;
procedure TSpreadSortingTests.Test_SortingByCols1_Strings_DESC;
begin
Test_Sorting_1(true, true, 1);
end;
procedure TSpreadSortingTests.Test_SortingByCols1_NumbersStrings_ASC;
begin
Test_Sorting_1(true, false, 2);
end;
procedure TSpreadSortingTests.Test_SortingByCols1_NumbersStrings_DESC;
begin
Test_Sorting_1(true, true, 2);
end;
{ Sort 1 row }
procedure TSpreadSortingTests.Test_SortingByRows1_Numbers_asc;
begin
Test_Sorting_1(false, false, 0);
end;
procedure TSpreadSortingTests.Test_SortingByRows1_Numbers_Desc;
begin
Test_Sorting_1(false, true, 0);
end;
procedure TSpreadSortingTests.Test_SortingByRows1_Strings_Asc;
begin
Test_Sorting_1(false, false, 1);
end;
procedure TSpreadSortingTests.Test_SortingByRows1_Strings_Desc;
begin
Test_Sorting_1(false, true, 1);
end;
procedure TSpreadSortingTests.Test_SortingByRows1_NumbersStrings_Asc;
begin
Test_Sorting_1(false, false, 2);
end;
procedure TSpreadSortingTests.Test_SortingByRows1_NumbersStrings_Desc;
begin
Test_Sorting_1(false, true, 2);
end;
{ two columns }
procedure TSpreadSortingTests.Test_SortingByCols2_Asc;
begin
Test_Sorting_2(true, false);
end;
procedure TSpreadSortingTests.Test_SortingByCols2_Desc;
begin
Test_Sorting_2(true, true);
end;
procedure TSpreadSortingTests.Test_SortingByRows2_Asc;
begin
Test_Sorting_2(false, false);
end;
procedure TSpreadSortingTests.Test_SortingByRows2_Desc;
begin
Test_Sorting_2(false, true);
end;
initialization
RegisterTest(TSpreadSortingTests);
InitUnsortedData;
end.

View File

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<PathDelim Value="\"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<CompatibilityMode Value="True"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="spreadtestcli"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<BuildModes Count="2">
<Item1 Name="Default" Default="True"/>
<Item2 Name="Debug">
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="spreadtestcli"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value=".."/>
<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>
</CodeGeneration>
<Other>
<WriteFPCLogo Value="False"/>
<CustomOptions Value="-dDEBUG -dDEBUGCONSOLE -O-1"/>
</Other>
</CompilerOptions>
</Item2>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
<Modes Count="1">
<Mode0 Name="default"/>
</Modes>
</RunParams>
<RequiredPackages Count="1">
<Item1>
<PackageName Value="LCLBase"/>
</Item1>
</RequiredPackages>
<Units Count="24">
<Unit0>
<Filename Value="spreadtestcli.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="testdbwriter.pas"/>
<IsPartOfProject Value="True"/>
</Unit1>
<Unit2>
<Filename Value="datetests.pas"/>
<IsPartOfProject Value="True"/>
</Unit2>
<Unit3>
<Filename Value="testsutility.pas"/>
<IsPartOfProject Value="True"/>
</Unit3>
<Unit4>
<Filename Value="manualtests.pas"/>
<IsPartOfProject Value="True"/>
</Unit4>
<Unit5>
<Filename Value="stringtests.pas"/>
<IsPartOfProject Value="True"/>
</Unit5>
<Unit6>
<Filename Value="internaltests.pas"/>
<IsPartOfProject Value="True"/>
</Unit6>
<Unit7>
<Filename Value="emptycelltests.pas"/>
<IsPartOfProject Value="True"/>
</Unit7>
<Unit8>
<Filename Value="colortests.pas"/>
<IsPartOfProject Value="True"/>
</Unit8>
<Unit9>
<Filename Value="errortests.pas"/>
<IsPartOfProject Value="True"/>
</Unit9>
<Unit10>
<Filename Value="numberstests.pas"/>
<IsPartOfProject Value="True"/>
</Unit10>
<Unit11>
<Filename Value="fonttests.pas"/>
<IsPartOfProject Value="True"/>
</Unit11>
<Unit12>
<Filename Value="formulatests.pas"/>
<IsPartOfProject Value="True"/>
</Unit12>
<Unit13>
<Filename Value="numformatparsertests.pas"/>
<IsPartOfProject Value="True"/>
</Unit13>
<Unit14>
<Filename Value="optiontests.pas"/>
<IsPartOfProject Value="True"/>
</Unit14>
<Unit15>
<Filename Value="virtualmodetests.pas"/>
<IsPartOfProject Value="True"/>
</Unit15>
<Unit16>
<Filename Value="dbexporttests.pas"/>
<IsPartOfProject Value="True"/>
</Unit16>
<Unit17>
<Filename Value="sortingtests.pas"/>
<IsPartOfProject Value="True"/>
</Unit17>
<Unit18>
<Filename Value="copytests.pas"/>
<IsPartOfProject Value="True"/>
</Unit18>
<Unit19>
<Filename Value="celltypetests.pas"/>
<IsPartOfProject Value="True"/>
</Unit19>
<Unit20>
<Filename Value="commenttests.pas"/>
<IsPartOfProject Value="True"/>
</Unit20>
<Unit21>
<Filename Value="enumeratortests.pas"/>
<IsPartOfProject Value="True"/>
</Unit21>
<Unit22>
<Filename Value="hyperlinktests.pas"/>
<IsPartOfProject Value="True"/>
</Unit22>
<Unit23>
<Filename Value="pagelayouttests.pas"/>
<IsPartOfProject Value="True"/>
</Unit23>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="spreadtestcli"/>
</Target>
<SearchPaths>
<IncludeFiles Value="..\source;$(ProjOutDir)"/>
<OtherUnitFiles Value="..\source\common;..\source\visual;..\source\export"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<UseExternalDbgSyms Value="True"/>
</Debugging>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="6">
<Item1>
<Name Value="ECodetoolError"/>
<Enabled Value="False"/>
</Item1>
<Item2>
<Name Value="EFOpenError"/>
<Enabled Value="False"/>
</Item2>
<Item3>
<Name Value="EAssertionFailedError"/>
</Item3>
<Item4>
<Name Value="Exception"/>
<Enabled Value="False"/>
</Item4>
<Item5>
<Name Value="EIBDatabaseError"/>
<Enabled Value="False"/>
</Item5>
<Item6>
<Name Value="EIgnoredTest"/>
</Item6>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,270 @@
program spreadtestcli;
{$mode objfpc}
{$h+}
uses
custapp, Classes, SysUtils, fpcunit,
plaintestreport {results output to plain text},
xmltestreport {used to get results into XML format},
testregistry,
testdbwriter {used to get results into db},
{the actual tests}
datetests, manualtests, stringtests, internaltests, testsutility, testutils,
formattests, colortests, emptycelltests, errortests,
numberstests, fonttests, formulatests, numformatparsertests, optiontests,
virtualmodetests, dbexporttests, sortingtests, copytests, celltypetests,
commenttests, enumeratortests, hyperlinktests, pagelayouttests;
const
ShortOpts = 'ac:dhlpr:x';
Longopts: Array[1..11] of String = (
'all','comment:','db', 'database', 'help','list','revision:','revisionid:','suite:','plain','xml');
Version = 'Version 1';
type
{ TTestRunner }
TTestOutputFormat = (tDB, tXMLAdvanced, tPlainText);
TTestRunner = Class(TCustomApplication)
private
FFormat: TTestOutputFormat;
FDBResultsWriter: TDBResultsWriter;
FPlainResultsWriter: TPlainResultsWriter;
FXMLResultsWriter: TXMLResultsWriter;
procedure WriteHelp;
protected
procedure DoRun ; Override;
procedure doTestRun(aTest: TTest); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
constructor TTestRunner.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FFormat:=tPlainText;
//FDBResultsWriter := TDBResultsWriter.Create; //done in procedures
FPlainResultsWriter:=TPlainResultsWriter.Create(nil);
//Don't write out timing info, makes it more difficult to run a diff.
//If you want to use timing, use the XML or db output:
{$if FPC_FULLVERSION>=20701}
FPlainResultsWriter.SkipTiming:=true;
{$endif}
FXMLResultsWriter:=TXMLResultsWriter.Create(nil);
end;
destructor TTestRunner.Destroy;
begin
//FDBResultsWriter.Free; //done in procedures
FPlainResultsWriter.Free;
FXMLResultsWriter.Free;
end;
procedure TTestRunner.doTestRun(aTest: TTest);
var
RevisionID: string;
testResult: TTestResult;
begin
testResult := TTestResult.Create;
try
case FFormat of
tDB:
begin
testResult.AddListener(FDBResultsWriter);
RevisionID:=GetOptionValue('r','revisionid');
if RevisionID='' then
RevisionID:=GetOptionValue('revision');
if RevisionID<>'' then
FDBResultsWriter.RevisionID:=RevisionID;
FDBResultsWriter.Comment:=GetOptionValue('c','comment');
{
// Depending on the application, you may want to add some fake test suite hierarchy
// at the top of the test project.
// Why? This makes it easier to avoid comparing apples to oranges when you have
// various platforms, editions, configurations, database connectors etc of your program/test set.
// Here, we demonstrate this with a Latin language edition of the code in its Enterprise edition:
FDBResultsWriter.TestSuiteRoot.Add('Enterprise');
FDBResultsWriter.TestSuiteRoot.Add('Latin');
}
{
// Normally, we would edit the testdbwriter.ini file and select our db
// where the tests are stored that way.... or omit any ini file and let it
// fallback to a Firebird embedded database.
// However, if needed, that can be overridden here:
FDBResultsWriter.DatabaseType:=TDBW_POSTGRESQLCONN_NAME;
FDBResultsWriter.DatabaseHostname:='dbserver';
FDBResultsWriter.DatabaseName:='dbtests';
FDBResultsWriter.DatabaseUser:='postgres';
FDBResultsWriter.DatabasePassword:='password';
FDBResultsWriter.DatabaseCharset:='UTF8';
}
end;
tPlainText:
begin
testResult.AddListener(FPlainResultsWriter);
end;
tXMLAdvanced:
begin
testResult.AddListener(FXMLResultsWriter);
// if filename='null', no console output is generated...
//FXMLResultsWriter.FileName:='';
end;
end;
aTest.Run(testResult);
case FFormat of
tDB: testResult.RemoveListener(FDBResultsWriter);
tPlainText:
begin
// This actually generates the plain text output:
FPlainResultsWriter.WriteResult(TestResult);
testResult.RemoveListener(FPlainResultsWriter);
end;
tXMLAdvanced:
begin
// This actually generates the XML output:
FXMLResultsWriter.WriteResult(TestResult);
// You can use fcl-xml's xmlwrite.WriteXMLFile to write the results
// to a stream or file...
testResult.RemoveListener(FXMLResultsWriter);
end;
end;
finally
testResult.Free;
end;
end;
procedure TTestRunner.WriteHelp;
begin
writeln(Title);
writeln(Version);
writeln(ExeName+': console test runner for fpspreadsheet tests');
writeln('Runs test set for fpspreadsheet and');
writeln('- stores the results in a database, or');
writeln('- outputs to screen');
writeln('');
writeln('Usage: ');
writeln('-c <comment>, --comment=<comment>');
writeln(' add comment to test run info.');
writeln(' (if database output is used)');
writeln('-d or --db or --database: run all tests, output to database');
writeln('-l or --list to show a list of registered tests');
writeln('-p or --plain: run all tests, output in plain text (default)');
writeln('-r <id> --revision=<id>, --revisionid=<id>');
writeln(' add revision id/application version ID to test run info.');
writeln(' (if database output is used)');
writeln('-x or --xml to run all tests and show the output in XML (new '
+'DUnit style)');
writeln('');
writeln('--suite=MyTestSuiteName to run only the tests in a single test '
+'suite class');
writeln('Example: --suite=TSpreadWriteReadStringTests');
end;
procedure TTestRunner.DoRun;
var
FoundTest: boolean;
I : Integer;
S : String;
begin
S:=CheckOptions(ShortOpts,LongOpts);
If (S<>'') then
begin
Writeln(StdErr,S);
WriteHelp;
halt(1);
end;
// Default to plain text output:
FFormat:=tPlainText;
if HasOption('d', 'database') or HasOption('db') then
FFormat:=tDB;
if HasOption('h', 'help') then
begin
WriteHelp;
halt(0);
end;
if HasOption('l', 'list') then
begin
writeln(GetSuiteAsPlain(GetTestRegistry));
halt(0);
end;
if HasOption('p', 'plain') then
FFormat:=tPlainText;
if HasOption('x', 'xml') then
FFormat:=tXMLAdvanced;
if HasOption('suite') then
begin
S := '';
S:=GetOptionValue('suite');
// For the db writer: recreate test objects so we get new runs each time
FoundTest:=false;
FDBResultsWriter:=TDBResultsWriter.Create;
try
if S = '' then
begin
writeln('Error');
writeln('You have to specify a test(suite). Valid test suite names:');
for I := 0 to GetTestRegistry.Tests.count - 1 do
writeln(GetTestRegistry[i].TestName)
end
else
begin
for I := 0 to GetTestRegistry.Tests.count - 1 do
begin
if GetTestRegistry[i].TestName = S then
begin
doTestRun(GetTestRegistry[i]);
FoundTest:=true;
end;
end;
if not(FoundTest) then
begin
writeln('Error: the testsuite "',S,'" you specified does not exist.');
end;
end;
finally
FDBResultsWriter.Free;
end;
end
else
begin
// No suite
// For the db writer: recreate test objects so we get new runs each time
FDBResultsWriter:=TDBResultsWriter.Create;
try
doTestRun(GetTestRegistry);
finally
FDBResultsWriter.Free;
end;
end;
Terminate;
end;
var
App: TTestRunner;
begin
App := TTestRunner.Create(nil);
App.Initialize;
App.Title := 'spreadtestcli';
App.Run;
App.Free;
end.

View File

@ -0,0 +1,260 @@
<?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="spreadtestgui"/>
<ResourceType Value="res"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<BuildModes Count="2">
<Item1 Name="Default" Default="True"/>
<Item2 Name="Debug">
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="spreadtestgui"/>
</Target>
<SearchPaths>
<IncludeFiles Value="..\source;$(ProjOutDir)"/>
<OtherUnitFiles Value="..\source\common"/>
<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"/>
<TrashVariables Value="True"/>
</Debugging>
</Linking>
</CompilerOptions>
</Item2>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
<Modes Count="1">
<Mode0 Name="default"/>
</Modes>
</RunParams>
<RequiredPackages Count="4">
<Item1>
<PackageName Value="LCLBase"/>
</Item1>
<Item2>
<PackageName Value="FPCUnitTestRunner"/>
</Item2>
<Item3>
<PackageName Value="LCL"/>
</Item3>
<Item4>
<PackageName Value="FCL"/>
</Item4>
</RequiredPackages>
<Units Count="33">
<Unit0>
<Filename Value="spreadtestgui.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="datetests.pas"/>
<IsPartOfProject Value="True"/>
</Unit1>
<Unit2>
<Filename Value="stringtests.pas"/>
<IsPartOfProject Value="True"/>
</Unit2>
<Unit3>
<Filename Value="numberstests.pas"/>
<IsPartOfProject Value="True"/>
</Unit3>
<Unit4>
<Filename Value="manualtests.pas"/>
<IsPartOfProject Value="True"/>
</Unit4>
<Unit5>
<Filename Value="testsutility.pas"/>
<IsPartOfProject Value="True"/>
</Unit5>
<Unit6>
<Filename Value="internaltests.pas"/>
<IsPartOfProject Value="True"/>
</Unit6>
<Unit7>
<Filename Value="formattests.pas"/>
<IsPartOfProject Value="True"/>
</Unit7>
<Unit8>
<Filename Value="colortests.pas"/>
<IsPartOfProject Value="True"/>
</Unit8>
<Unit9>
<Filename Value="fonttests.pas"/>
<IsPartOfProject Value="True"/>
</Unit9>
<Unit10>
<Filename Value="optiontests.pas"/>
<IsPartOfProject Value="True"/>
</Unit10>
<Unit11>
<Filename Value="numformatparsertests.pas"/>
<IsPartOfProject Value="True"/>
</Unit11>
<Unit12>
<Filename Value="rpnformulaunit.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="rpnFormulaUnit"/>
</Unit12>
<Unit13>
<Filename Value="formulatests.pas"/>
<IsPartOfProject Value="True"/>
</Unit13>
<Unit14>
<Filename Value="emptycelltests.pas"/>
<IsPartOfProject Value="True"/>
</Unit14>
<Unit15>
<Filename Value="errortests.pas"/>
<IsPartOfProject Value="True"/>
</Unit15>
<Unit16>
<Filename Value="virtualmodetests.pas"/>
<IsPartOfProject Value="True"/>
</Unit16>
<Unit17>
<Filename Value="colrowtests.pas"/>
<IsPartOfProject Value="True"/>
</Unit17>
<Unit18>
<Filename Value="celltypetests.pas"/>
<IsPartOfProject Value="True"/>
</Unit18>
<Unit19>
<Filename Value="sortingtests.pas"/>
<IsPartOfProject Value="True"/>
</Unit19>
<Unit20>
<Filename Value="copytests.pas"/>
<IsPartOfProject Value="True"/>
</Unit20>
<Unit21>
<Filename Value="commenttests.pas"/>
<IsPartOfProject Value="True"/>
</Unit21>
<Unit22>
<Filename Value="enumeratortests.pas"/>
<IsPartOfProject Value="True"/>
</Unit22>
<Unit23>
<Filename Value="hyperlinktests.pas"/>
<IsPartOfProject Value="True"/>
</Unit23>
<Unit24>
<Filename Value="pagelayouttests.pas"/>
<IsPartOfProject Value="True"/>
</Unit24>
<Unit25>
<Filename Value="exceltests.pas"/>
<IsPartOfProject Value="True"/>
</Unit25>
<Unit26>
<Filename Value="protectiontests.pas"/>
<IsPartOfProject Value="True"/>
</Unit26>
<Unit27>
<Filename Value="ssttests.pas"/>
<IsPartOfProject Value="True"/>
</Unit27>
<Unit28>
<Filename Value="testcases_calc3dformula.inc"/>
<IsPartOfProject Value="True"/>
</Unit28>
<Unit29>
<Filename Value="singleformulatests.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="SingleFormulaTests"/>
</Unit29>
<Unit30>
<Filename Value="fileformattests.pas"/>
<IsPartOfProject Value="True"/>
</Unit30>
<Unit31>
<Filename Value="mathtests.pas"/>
<IsPartOfProject Value="True"/>
</Unit31>
<Unit32>
<Filename Value="conditionalformattests.pas"/>
<IsPartOfProject Value="True"/>
</Unit32>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="spreadtestgui"/>
</Target>
<SearchPaths>
<IncludeFiles Value="..\source;$(ProjOutDir)"/>
<OtherUnitFiles Value="..\source\common"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf2"/>
</Debugging>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="7">
<Item1>
<Name Value="EAbort"/>
<Enabled Value="False"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
<Enabled Value="False"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
<Enabled Value="False"/>
</Item3>
<Item4>
<Name Value="EAssertionFailedError"/>
</Item4>
<Item5>
<Name Value="EIgnoredTest"/>
</Item5>
<Item6>
<Name Value="EConvertError"/>
<Enabled Value="False"/>
</Item6>
<Item7>
<Name Value="EFPSpreadsheetReader"/>
</Item7>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,34 @@
program spreadtestgui;
{$mode objfpc}{$H+}
{.$DEFINE HEAPTRC} // Instead of using -gh activate this to write the heap trace to file
uses
{$IFDEF HEAPTRC}
SysUtils,
{$ENDIF}
Interfaces, Forms, GuiTestRunner, testsutility,
datetests, stringtests, numberstests, manualtests, internaltests, mathtests,
fileformattests, formattests, colortests, fonttests, optiontests,
conditionalformattests,
numformatparsertests, formulatests, rpnFormulaUnit, singleformulatests,
exceltests, emptycelltests, errortests, virtualmodetests,
colrowtests, ssttests, celltypetests, sortingtests, copytests,
enumeratortests, commenttests, hyperlinktests, pagelayouttests, protectiontests;
begin
{$IFDEF HEAPTRC}
// Assuming your build mode sets -dDEBUG in Project Options/Other when defining -gh
// This avoids interference when running a production/default build without -gh
if FileExists('heap.trc') then
DeleteFile('heap.trc');
SetHeapTraceOutput('heap.trc');
{$ENDIF HEAPTRC}
Application.Initialize;
Application.CreateForm(TGuiTestRunner, TestRunner);
Application.Run;
end.

View File

@ -0,0 +1,547 @@
{
Test related to BIFF8 shared string table
This unit tests are writing out to and reading back from files.
}
unit ssttests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testregistry,
fpstypes, fpspreadsheet, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
type
{ TSpreadWriteReadColorTests }
//Write to xls/xml file and read back
TSpreadWriteReadSSTTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
// General test procedure
procedure TestWriteRead_SST_General(ATestCase: Integer);
published
{ 1 ASCII string in SST, entirely in SST record }
procedure TestWriteRead_SST_1ASCII;
{ 1 ASCII wide in SST, entirely in SST record }
procedure TestWriteRead_SST_1Wide;
{ 3 string in SST, all entirely in SST record }
procedure TestWriteRead_SST_3ASCII;
{ 3 string in SST, widestring case, all entirely in SST record }
procedure TestWriteRead_SST_3Wide;
{ 1 long ASCII string in SST, fills SST record completely, no CONTINUE record needed }
procedure TestWriteRead_SST_1LongASCII;
{ 1 long wide string in SST, fills SST record completely, no CONTINUE record needed }
procedure TestWriteRead_SST_1LongWide;
{ ASCII string 2 character longer than SST record max --> CONTINUE record needed }
procedure TestWriteRead_SST_1CONTINUE_1ASCII;
{ wide string 2 character longer than SST record max --> CONTINUE record needed }
procedure TestWriteRead_SST_1CONTINUE_1Wide;
{ short ASCII string, then long ASCII string, 1 CONTINUE record needed }
procedure TestWriteRead_SST_1CONTINUE_ShortASCII_LongASCII;
{ short widestring, then long widestring, 1 CONTINUE record needed }
procedure TestWriteRead_SST_1CONTINUE_ShortWide_LongWide;
{ long ASCII string, then short ASCII string, 1 CONTINUE record needed }
procedure TestWriteRead_SST_1CONTINUE_LongASCII_ShortASCII;
{ long widestring, then short wide string into CONTINUE record }
procedure TestWriteRead_SST_1CONTINUE_LongWide_ShortWide;
{ very long ASCII string needing two CONTINUE records }
procedure TestWriteRead_SST_2CONTINUE_VeryLongASCII;
{ very long widestring needing two CONTINUE records }
procedure TestWriteRead_SST_2CONTINUE_VeryLongWide;
{ three long ASCII strings needing two CONTINUE records }
procedure TestWriteRead_SST_2CONTINUE_3LongASCII;
{ three long widestrings needing two CONTINUE records }
procedure TestWriteRead_SST_2CONTINUE_3LongWide;
{ 1 ASCII string in SST, entirely in SST record, font alternating from char to char }
procedure TestWriteRead_SST_1ASCII_RichText;
{ 1 widestring in SST, entirely in SST record, font alternating from char to char }
procedure TestWriteRead_SST_1Wide_RichText;
{ long ASCII string which reaches beyond SST into CONTINUE. Short Rich-Text
staying within the same CONTINUE record}
procedure TestWriteRead_SST_CONTINUE_LongASCII_ShortRichText;
{ long widestring which reaches beyond SST into CONTINUE. Short Rich-Text
staying within the same CONTINUE record}
procedure TestWriteRead_SST_CONTINUE_LongWide_ShortRichText;
{ long ASCII string with rich-text formatting. The string stays within SST
but rich-text parameters reach into CONTINUE record. }
procedure TestWriteRead_SST_CONTINUE_ShortASCII_LongRichText;
{ long widestring with rich-text formatting. The string stays within SST
but rich-text parameters reach into CONTINUE record. }
procedure TestWriteRead_SST_CONTINUE_ShortWide_LongRichText;
{ long ASCII string with rich-text formatting. The string stays within SST
but long rich-text parameters flow into 2 CONTINUE records. }
procedure TestWriteRead_SST_2CONTINUE_ASCII_LongRichText;
{ long widestring with rich-text formatting. The string stays within SST
but long rich-text parameters flow into 2 CONTINUE records. }
procedure TestWriteRead_SST_2CONTINUE_Wide_LongRichText;
end;
implementation
uses
Math, LazUTF8;
const
SST_Sheet = 'SST';
MAX_BYTES_PER_RECORD = 8224;
{ TSpreadWriteReadSSTTests }
procedure TSpreadWriteReadSSTTests.SetUp;
begin
inherited SetUp;
end;
procedure TSpreadWriteReadSSTTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_General(ATestCase: Integer);
const
// Every record can contain 8224 data bytes (without BIFF header).
// The SST record needs 2x4 bytes for the string counts.
// The rest (8224-8) is for the string wbich has a header of 3 bytes (2 bytes
// string length + 1 byte flags). fpspreadsheet writes string as widestring,
// i.2. 2 bytes per character.
maxLenSST = MAX_BYTES_PER_RECORD - 3 - 8;
maxLenCONTINUE = MAX_BYTES_PER_RECORD - 1;
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
MyCell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
currentText: string;
currentRtParams: TsRichTextParams;
currentFont: TsFont;
expectedText: array of string;
expectedRtParams: array of TsRichTextParams;
expectedFont: Array[0..1] of TsFont;
expectedFontIndex: Array[0..1] of Integer;
i, j: Integer;
col, row: Cardinal;
fnt: TsFont;
function CreateString(ALen: Integer): String;
var
i: Integer;
begin
SetLength(Result, ALen);
for i:=1 to ALen do
Result[i] := char((i-1) mod 26 + ord('A'));
end;
function AlternatingFont(AStrLen: Integer): TsRichTextParams;
var
i: Integer;
begin
SetLength(Result, AStrLen div 2);
for i := 0 to High(Result) do begin
Result[i].FirstIndex := i*2 + 1;
// character index is 1-based in fps
Result[i].FontIndex := expectedFontIndex[i mod 2];
// Avoid using the default font here, it makes counting too complex.
end;
end;
begin
TempFile := GetTempFileName;
MyWorkbook := TsWorkbook.Create;
try
fnt := MyWorkbook.GetDefaultFont;
expectedFontIndex[0] := 1;
expectedFontIndex[1] := 2;
for j:=0 to 1 do
expectedFont[j] := MyWorkbook.GetFont(expectedFontIndex[j]);
case ATestCase of
0: begin
// 1 short ASCII string, easily fits within SST record
SetLength(expectedtext, 1);
expectedText[0] := 'ABC';
end;
1: begin
// 1 short wide string, easily fits within SST record
SetLength(expectedtext, 1);
expectedText[0] := 'äöü';
end;
2: begin
// 3 short ASCII strings, easily fit within SST record
SetLength(expectedtext, 3);
expectedText[0] := 'ABC';
expectedText[1] := 'DEF';
expectedText[2] := 'GHI';
end;
3: begin
// 3 short strings, widestring case, easily fit within SST record
SetLength(expectedtext, 3);
expectedText[0] := 'äöü';
expectedText[1] := 'DEF';
expectedText[2] := 'GHI';
end;
4: begin
// 1 long ASCII string, max length for SST record
SetLength(expectedtext, 1);
expectedText[0] := CreateString(maxLenSST);
end;
5: begin
// 1 long widestring, max length for SST record
SetLength(expectedtext, 1);
expectedText[0] := 'ä' + CreateString(maxLenSST div 2 - 1);
end;
6: begin
// 1 long ASCII string, 2 characters more than max SST length --> CONTINUE needed
SetLength(expectedtext, 1);
expectedText[0] := CreateString(maxLenSST + 2);
end;
7: begin
// 1 long widestring, 2 characters more than max SST length --> CONTINUE needed
SetLength(expectedtext, 1);
expectedText[0] := 'ä' + CreateString(maxLenSST div 2 + 1);
end;
8: begin
// a short ASCII string, plus 1 long ASCII string reaching into CONTINUE record
SetLength(expectedtext, 2);
expectedText[0] := 'ABC';
expectedText[1] := CreateString(maxLenSST);
end;
9: begin
// a short widestring, plus 1 long widestring reaching into CONTINUE record
SetLength(expectedtext, 2);
expectedText[0] := 'äöü';
expectedText[1] := 'äöü' + CreateString(maxLenSST div 2);
end;
10: begin
// 1 long ASCII string staying inside SST, 1 short ASCII string into CONTINUE
// The header of the short string does no longer fit in the SST record.
// The short string must bo into CONTINUE completely.
SetLength(expectedtext, 2);
expectedText[0] := CreateString(maxLenSST-2);
expectedText[1] := 'ABCDEF';
end;
11: begin
// 1 long widestring staying inside SST, 1 short widestring into CONTINUE
SetLength(expectedtext, 2);
expectedText[0] := 'ä' + CreateString(maxLenSST div 2 - 2);
expectedText[1] := 'ÄÖÜabc';
end;
12: begin
// a very long ASCII string needing two CONTINUE records
SetLength(expectedtext, 1);
expectedText[0] := CreateString(maxLenSST + maxLenCONTINUE + 3);
end;
13: begin
// a very long wide string needing two CONTINUE records
SetLength(expectedtext, 1);
expectedText[0] := 'äöü' + CreateString(maxLenSST div 2 + maxLenCONTINUE div 2);
end;
14: begin
// three long ASCII strings needing two CONTINUE records
SetLength(expectedtext, 3);
expectedText[0] := CreateString(maxLenSST - 3);
expectedText[1] := CreateString(maxLenSST - 3 + maxLenCONTINUE - 3);
expectedText[2] := CreateString(maxLenSST - 3 + maxLenCONTINUE - 3);
end;
15: begin
// three long wide strings needing two CONTINUE records
SetLength(expectedtext, 3);
expectedText[0] := CreateString(maxLenSST div 2 - 3);
expectedText[1] := CreateString(maxLenSST div 2 - 3 + maxLenCONTINUE div 2 - 3);
expectedText[2] := CreateString(maxLenSST div 2 - 3 + maxLenCONTINUE div 2 - 3);
end;
16: begin
// 1 short ASCII string, easily fits within SST record, with Rich-Text
SetLength(expectedtext, 1);
expectedText[0] := 'ABCD';
SetLength(expectedRtParams, 1);
expectedRtParams[0] := AlternatingFont(Length(expectedText[0]));
end;
17: begin
// 1 short widestring, easily fits within SST record, with Rich-Text
SetLength(expectedtext, 1);
expectedText[0] := 'äöüa';
SetLength(expectedRtParams, 1);
expectedRtParams[0] := AlternatingFont(4);
end;
18: begin
// 1 long ASCII string, reaches into CONTINUE record, short Rich-Text
SetLength(expectedtext, 1);
expectedText[0] := CreateString(maxLenSST+5);
SetLength(expectedRtParams, 1);
expectedRtParams[0] := AlternatingFont(10);
end;
19: begin
// 1 long wide string, reaches into CONTINUE record, short Rich-Text
SetLength(expectedtext, 1);
expectedText[0] := 'äöü' + CreateString(maxLenSST div 2 + 5);
SetLength(expectedRtParams, 1);
expectedRtParams[0] := AlternatingFont(10);
end;
20: begin
// ASCII string staying within SST. But has Rich-Text parameters
// overflowing into the CONTINUE record
SetLength(expectedtext, 1);
expectedText[0] := CreateString(maxLenSST - 10);
SetLength(expectedRtParams, 1);
expectedRtParams[0] := AlternatingFont(100);
end;
21: begin
// wide string staying within SST. But has Rich-Text parameters
// overflowing into the CONTINUE record
SetLength(expectedtext, 1);
expectedText[0] := 'äöü' + CreateString(maxLenSST div 2 - 13);
SetLength(expectedRtParams, 1);
expectedRtParams[0] := AlternatingFont(100);
end;
22: begin
// Long ASCII string staying within SST. But has long Rich-Text
// parameters overflowing into two CONTINUE records
SetLength(expectedtext, 1);
expectedText[0] := CreateString(maxLenSST - 10);
SetLength(expectedRtParams, 1);
expectedRtParams[0] := AlternatingFont(Length(expectedText[0]));
end;
23: begin
// Long widestring staying within SST. But has long Rich-Text
// parameters overflowing into two CONTINUE records
SetLength(expectedtext, 1);
expectedText[0] := 'äöü' + CreateString(maxLenSST div 2 - 13);
SetLength(expectedRtParams, 1);
expectedRtParams[0] := AlternatingFont(UTF8Length(expectedText[0]) div 2);
end;
end;
{ Create spreadsheet and write to file }
MyWorkSheet:= MyWorkBook.AddWorksheet(SST_Sheet);
col := 0;
for row := 0 to High(expectedText) do
if row < Length(expectedRtParams) then
MyCell := MyWorksheet.WriteText(row, col, expectedText[row], expectedRtParams[row])
else
MyCell := MyWorksheet.WriteText(row, col, expectedText[row]);
MyWorkBook.WriteToFile(TempFile, sfExcel8, true);
finally
MyWorkbook.Free;
end;
{ Read the spreadsheet }
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, sfExcel8);
MyWorksheet := MyWorkbook.GetWorksheetByIndex(0);
col := 0;
for row := 0 to High(expectedText) do begin
myCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
fail('Error in test code. Failed to get cell.');
currentText := MyWorksheet.ReadAsText(MyCell);
CheckEquals(expectedText[row], currentText,
'Saved cell text mismatch, cell '+CellNotation(MyWorksheet, row, col));
if row < Length(expectedRtParams) then
begin
currentRtParams := MyCell^.RichTextParams;
CheckEquals(Length(expectedRtParams[row]), Length(currentRtParams),
'Number of rich-text parameters mismatch, cell '+CellNotation(MyWorksheet, row, col));
for i:=0 to High(currentRtParams) do
begin
CheckEquals(expectedRtParams[row][i].FirstIndex, currentRtParams[i].FirstIndex,
'Character index mismatch in rich-text parameter #' + IntToStr(i) +
', cell ' + CellNotation(MyWorksheet, row, col));
currentFont := MyWorkbook.GetFont(currentRtParams[i].FontIndex);
CheckEquals(currentFont.Fontname, expectedFont[i mod 2].FontName,
'Font name mismatch in rich-text parameter #' + IntToStr(i) +
', cell ' + CellNotation(MyWorksheet, row, col));
CheckEquals(currentFont.Size, expectedFont[i mod 2].Size,
'Font size mismatch in rich-text parameter #' + IntToStr(i) +
', cell ' + CellNotation(MyWorksheet, row, col));
CheckEquals(integer(currentFont.Style), integer(expectedFont[i mod 2].Style),
'Font style mismatch in rich-text parameter #' + IntToStr(i) +
', cell ' + CellNotation(MyWorksheet, row, col));
CheckEquals(currentFont.Color, expectedFont[i mod 2].Color,
'Font color mismatch in rich-text parameter #' + IntToStr(i) +
', cell ' + CellNotation(MyWorksheet, row, col));
end;
end;
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ Writes/reads one string ASCII only. The string fits in the SST record }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1ASCII;
begin
TestWriteRead_SST_General(0);
end;
{ Writes/reads one wide string only. The string fits in the SST record }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1Wide;
begin
TestWriteRead_SST_General(1);
end;
{ Writes/reads 3 strings, all entirely in SST record }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_3ASCII;
begin
TestWriteRead_SST_General(2);
end;
{ Writes/reads 3 strings, widestring case, all entirely in SST record }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_3Wide;
begin
TestWriteRead_SST_General(3);
end;
{ 1 long ASCII string in SST, fills SST record exactly, no CONTINUE record needed }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1LongASCII;
begin
TestWriteRead_SST_General(4);
end;
{ 1 long widestring in SST, fills SST record exactly, no CONTINUE record needed }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1LongWide;
begin
TestWriteRead_SST_General(5);
end;
{ 1 ASCII string, 2 characters longer than in SST record max
--> CONTINUE record needed }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1CONTINUE_1ASCII;
begin
TestWriteRead_SST_General(6);
end;
{ 1 widestring, 2 characters longer than in SST record max
--> CONTINUE record needed }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1CONTINUE_1Wide;
begin
TestWriteRead_SST_General(7);
end;
{ short ASCII string, then long ASCII string, 1 CONTINUE record needed }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1CONTINUE_ShortASCII_LongASCII;
begin
TestWriteRead_SST_General(8);
end;
{ short widestring, then long widestring, 1 CONTINUE record needed }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1CONTINUE_ShortWide_LongWide;
begin
TestWriteRead_SST_General(9);
end;
{ long ASCII string, then short ACII string into CONTINUE record }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1CONTINUE_LongASCII_ShortASCII;
begin
TestWriteRead_SST_General(10);
end;
{ long widestring, then short widestring into CONTINUE record }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1CONTINUE_LongWide_ShortWide;
begin
TestWriteRead_SST_General(11);
end;
{ very long ASCII string, needing two CONTINUE records }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_2CONTINUE_VeryLongASCII;
begin
TestWriteRead_SST_General(12);
end;
{ very long widestring, needing two CONTINUE records }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_2CONTINUE_VeryLongWide;
begin
TestWriteRead_SST_General(13);
end;
{ three long ASCII strings, needing two CONTINUE records }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_2CONTINUE_3LongASCII;
begin
TestWriteRead_SST_General(14);
end;
{ three long widestrings, needing two CONTINUE records }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_2CONTINUE_3LongWide;
begin
TestWriteRead_SST_General(15);
end;
{ Writes/reads one ASCII string only. The string fits in the SST record.
Uses rich-text formatting toggling font every second character. }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1ASCII_RichText;
begin
TestWriteRead_SST_General(16);
end;
{ Writes/reads one wide string only. The string fits in the SST record.
Uses rich-text formatting toggling font every second character. }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_1Wide_RichText;
begin
TestWriteRead_SST_General(17);
end;
{ Writes/reads one long ASCII string which reaches beyond SST into CONTINUE.
Uses short rich-text formatting staying within this CONTINUE record. }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_CONTINUE_LongASCII_ShortRichText;
begin
TestWriteRead_SST_General(18);
end;
{ Writes/reads one long wide string which reaches beyond SST into CONTINUE.
Uses short rich-text formatting staying within this CONTINUE record. }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_CONTINUE_LongWide_ShortRichText;
begin
TestWriteRead_SST_General(19);
end;
{ Writes/reads one short ASCII string with rich-text formatting. The string
stay within SST, but rich-text parameters reach into CONTINUE record. }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_CONTINUE_ShortASCII_LongRichText;
begin
TestWriteRead_SST_General(20);
end;
{ Writes/reads one long widestring with rich-text formatting. The string
stay within SST, but rich-text parameters reach into CONTINUE record. }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_CONTINUE_ShortWide_LongRichText;
begin
TestWriteRead_SST_General(21);
end;
{ long ASCII string with rich-text formatting. The string stays within SST
but long rich-text parameters flow into 2 CONTINUE records. }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_2CONTINUE_ASCII_LongRichText;
begin
TestWriteRead_SST_General(22);
end;
{ long widestring with rich-text formatting. The string stays within SST
but long rich-text parameters flow into 2 CONTINUE records. }
procedure TSpreadWriteReadSSTTests.TestWriteRead_SST_2CONTINUE_Wide_LongRichText;
begin
TestWriteRead_SST_General(23);
end;
initialization
RegisterTest(TSpreadWriteReadSSTTests);
end.

View File

@ -0,0 +1,682 @@
{$ifdef fpc}
{$if FPC_FULLVERSION>20701}
//Explicitly specify this is an UTF8 encoded file.
//Alternative would be UTF8 with BOM but writing UTF8 BOM is bad practice.
//See http://wiki.lazarus.freepascal.org/FPC_Unicode_support#String_constants
{$codepage UTF8} //Win 65001
{$endif} //fpc_fullversion
{$endif fpc}
unit stringtests;
{$mode objfpc}{$H+}
{
Adding tests/test data:
1. Add a new value to column A in the relevant worksheet, and save the spreadsheet read-only
(for dates, there are 2 files, with different datemodes. Use them both...)
2. Increase SollStrings array size
3. Add value from 1) to InitNormVariables so you can test against it
4. Add your read test(s), read and check read value against SollStrings[<added number>]
}
interface
uses
// Not using lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testutils, testregistry,
fpstypes, fpsallformats, fpsutils, fpspreadsheet, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
testsutility;
var
// Norm to test against - list of strings that should occur in spreadsheet
SollStrings: array[0..13] of string; //"Soll" is a German word in Dutch accountancy jargon meaning "normative value to check against". There ;)
// Initializes Soll*/normative variables.
// Useful in test setup procedures to make sure the norm is correct.
procedure InitSollStrings;
type
{ TSpreadReadStringTests }
// Read from xls/xml file with known values
TSpreadReadStringTests= class(TTestCase)
private
// Tries to read string in column A, specified (0-based) row
procedure TestReadString(FileName: string; Row: integer);
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
published
// Reads string values from spreadsheet and checks against list
// One cell per test so some tests can fail and those further below may still work
procedure TestReadString0; //biff8 empty string
procedure TestReadString1;
procedure TestReadString2;
procedure TestReadString3;
procedure TestReadString4;
procedure TestReadString5;
procedure TestReadString6;
procedure TestReadString7;
procedure TestReadString8;
procedure TestReadString9;
procedure TestReadString10;
procedure TestReadString11;
procedure TestReadString12;
procedure TestReadString13;
procedure TestReadODFString0; //OpenDocument/LibreOffice format empty string
procedure TestReadODFString1;
procedure TestReadODFString2;
procedure TestReadODFString3;
procedure TestReadODFString4;
procedure TestReadODFString5;
procedure TestReadODFString6;
procedure TestReadODFString7;
procedure TestReadODFString8;
procedure TestReadODFString9;
procedure TestReadODFString10;
procedure TestReadODFString11;
procedure TestReadODFString12;
procedure TestReadODFString13;
procedure TestReadOOXMLString0; //Excel xlsx format empty string
procedure TestReadOOXMLString1;
procedure TestReadOOXMLString2;
procedure TestReadOOXMLString3;
procedure TestReadOOXMLString4;
procedure TestReadOOXMLString5;
procedure TestReadOOXMLString6;
procedure TestReadOOXMLString7;
procedure TestReadOOXMLString8;
procedure TestReadOOXMLString9;
procedure TestReadOOXMLString10;
procedure TestReadOOXMLString11;
procedure TestReadOOXMLString12;
procedure TestReadOOXMLString13;
procedure TestReadXMLString0; //Excel2003/XML format empty string
procedure TestReadXMLString1;
procedure TestReadXMLString2;
procedure TestReadXMLString3;
procedure TestReadXMLString4;
procedure TestReadXMLString5;
procedure TestReadXMLString6;
procedure TestReadXMLString7;
procedure TestReadXMLString8;
procedure TestReadXMLString9;
procedure TestReadXMLString10;
procedure TestReadXMLString11;
procedure TestReadXMLString12;
procedure TestReadXMLString13;
end;
{ TSpreadWriteReadStringTests }
//Write to xls/xml file and read back
TSpreadWriteReadStringTests= class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
published
// Writes out norm strings & reads back.
// If previous read tests are ok, this effectively tests writing.
procedure TestWriteReadStrings;
// Testing some limits & exception handling
procedure TestWriteReadStringsLimits;
end;
implementation
var
TestWorksheet: TsWorksheet = nil;
TestWorkbook: TsWorkbook = nil;
TestFileName: String = '';
// Initialize array with variables that represent the values
// we expect to be in the test spreadsheet files.
//
// When adding tests, add values to this array
// and increase array size in variable declaration
procedure InitSollStrings;
begin
// Set up norm - MUST match spreadsheet cells exactly
SollStrings[0]:='';
SollStrings[1]:='a';
SollStrings[2]:='1';
SollStrings[3]:='The quick brown fox jumps over the lazy dog';
SollStrings[4]:='café au lait'; //accent aigue on the e
SollStrings[5]:='водка'; //cyrillic
SollStrings[6]:='wódka'; //Polish o accent aigue
SollStrings[7]:='35%'; // 0.3536 formatted as percentage, no decimals
SollStrings[8]:=FormatFloat('0.00', 35.36)+'%'; // 0.3536 formatted as percentage, 2 decimals
SollStrings[9]:=FormatFloat('#,##0', 59000000.1234); // 59 million + 0.1234 formatted with thousand separator, no decimals
SollStrings[10]:=FormatFloat('#,##0.00', 59000000.1234); // 59 million + 0.1234 formatted with thousand separator, 2 decimals
SollStrings[11]:=FormatFloat('0.00E+00', -59000000.1234); // minus 59 million + 0.1234, formatted as "exp" with 2 decimals
SollStrings[12]:=FormatFloat('#,##0.00 "EUR";(#,##0.00 "EUR")', 59000000.1234); // 59 million + 0.1234, formatted as "currencyRed" with 2 decimals, brackets and EUR
SollStrings[13]:=FormatFloat('#,##0.00 "EUR";(#,##0.00 "EUR")', -59000000.1234); // minus 59 million + 0.1234, formatted as "currencyRed" with 2 decimals, brackets and EUR
end;
{ TSpreadWriteReadStringTests }
procedure TSpreadWriteReadStringTests.SetUp;
begin
inherited SetUp;
InitSollStrings; //just for security: make sure the variables are reset to default
end;
procedure TSpreadWriteReadStringTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadWriteReadStringTests.TestWriteReadStrings;
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
ActualString: String;
Row: Cardinal;
TempFile: string; //write xls/xml to this file and read back from it
begin
//todo: add support for ODF/LibreOffice format
{// Not needed: use workbook.writetofile with overwrite=true
if fileexists(TempFile) then
DeleteFile(TempFile);
}
// Write out all test values
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:=MyWorkBook.AddWorksheet(StringsSheet);
for Row := Low(SollStrings) to High(SollStrings) do
begin
MyWorkSheet.WriteUTF8Text(Row,0,SollStrings[Row]);
// Some checks inside worksheet itself
ActualString:=MyWorkSheet.ReadAsUTF8Text(Row,0);
CheckEquals(SollStrings[Row],ActualString,'Test value mismatch cell '+CellNotation(MyWorkSheet,Row));
end;
TempFile:=NewTempFile;
MyWorkBook.WriteToFile(TempFile, sfExcel8, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet, as biff8
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, sfExcel8);
MyWorksheet:=GetWorksheetByName(MyWorkBook,StringsSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
// Read test data from A column & compare if written=original
for Row := Low(SollStrings) to High(SollStrings) do
begin
ActualString:=MyWorkSheet.ReadAsUTF8Text(Row,0);
CheckEquals(SollStrings[Row],ActualString,'Test value mismatch, cell '+CellNotation(MyWorkSheet,Row));
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
procedure TSpreadWriteReadStringTests.TestWriteReadStringsLimits;
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
ActualString: String;
ExceptionMessage: string;
LocalNormStrings: array[0..3] of string;
Row: Cardinal;
TempFile: string; //write xls/xml to this file and read back from it
TestResult: boolean;
MaxBytesBIFF8: Integer;
limitations: TsSpreadsheetFormatLimitations;
begin
InitBIFF8Limitations(limitations);
MaxBytesBIFF8 := limitations.MaxCharsInTextCell;
LocalNormStrings[0]:=StringOfChar('a',MaxBytesBIFF8-1);
LocalNormStrings[1]:=StringOfChar('b',MaxBytesBIFF8);
LocalNormStrings[2]:=StringOfChar('z',MaxBytesBiff8+1); //problems should occur here
LocalNormStrings[3]:='this text should be readable'; //whatever happens, this text should be ok
{// Not needed: use workbook.writetofile with overwrite=true
if fileexists(TempFile) then
DeleteFile(TempFile);
}
// Write out all test values
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:=MyWorkBook.AddWorksheet(StringsSheet);
for Row := Low(LocalNormStrings) to High(LocalNormStrings) do
begin
// We could use CheckException but then you can't pass parameters
TestResult:=true;
try
MyWorkSheet.WriteUTF8Text(Row,0,LocalNormStrings[Row]);
// Some checks inside worksheet itself
ActualString:=MyWorkSheet.ReadAsUTF8Text(Row,0);
CheckEquals(length(LocalNormStrings[Row]),length(ActualString),
'Test value mismatch cell '+CellNotation(MyWorkSheet,Row)+
' for string length.');
except
{ When over size limit we expect to hit this:
if TextTooLong then
Raise Exception.CreateFmt('Text value exceeds %d character limit in cell [%d,%d]. Text has been truncated.',[MaxBytes,ARow,ACol]);
}
//todo: rewrite when/if the fpspreadsheet exception class changes
on E: Exception do
begin
if Row=2 then
TestResult:=true
else
begin
TestResult:=false;
ExceptionMessage:=E.Message;
end;
end;
end;
// Notify user of exception if it happened where we didn't expect it:
CheckTrue(TestResult,'Exception: '+ExceptionMessage);
end;
TestResult:=true;
TempFile:=NewTempFile;
try
MyWorkBook.WriteToFile(TempFile,sfExcel8,true);
except
//todo: rewrite when/if the fpspreadsheet exception class changes
on E: Exception do
begin
if Row=2 then
TestResult:=true
else
begin
TestResult:=false;
ExceptionMessage:=E.Message;
end;
end;
end;
// Notify user of exception if it happened where we didn't expect it:
CheckTrue(TestResult,'Exception: '+ExceptionMessage);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet, as biff8
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.ReadFromFile(TempFile, sfExcel8);
MyWorksheet:=GetWorksheetByName(MyWorkBook,StringsSheet);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
// Read test data from A column & compare if written=original
for Row := Low(LocalNormStrings) to High(LocalNormStrings) do
begin
ActualString:=MyWorkSheet.ReadAsUTF8Text(Row,0);
// Allow for truncation of excessive strings by fpspreadsheet
if length(LocalNormStrings[Row])>MaxBytesBIFF8 then
CheckEquals(MaxBytesBIFF8,length(ActualString),
'Test value mismatch cell '+CellNotation(MyWorkSheet,Row)+
' for string length.')
else
CheckEquals(length(LocalNormStrings[Row]),length(ActualString),
'Test value mismatch cell '+CellNotation(MyWorkSheet,Row)+
' for string length.');
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
{ TSpreadReadStringTests }
procedure TSpreadReadStringTests.TestReadString(FileName: string; Row: integer);
var
ActualString: string;
AFormat: TsSpreadsheetFormat;
begin
if Row>High(SollStrings) then
fail('Error in test code: array bounds overflow. Check array size is correct.');
// Load the file only if is the file name changes.
if (FileName <> TestFileName) then begin
if TestWorkbook <> nil then
TestWorkbook.Free;
// Open the spreadsheet
TestWorkbook := TsWorkbook.Create;
case Uppercase(ExtractFileExt(FileName)) of
'.XLSX': AFormat := sfOOXML;
'.ODS' : AFormat := sfOpenDocument;
'.XML' : AFormat := sfExcelXML;
else AFormat := sfExcel8;
end;
TestWorkbook.ReadFromFile(FileName, AFormat);
TestWorksheet := GetWorksheetByName(TestWorkBook, StringsSheet);
if TestWorksheet=nil then
fail('Error in test code: could not retrieve worksheet.');
end;
ActualString := TestWorkSheet.ReadAsUTF8Text(Row,0);
if (Row = 11) and (AFormat = sfOpenDocument) then
// SciFloat is not supported by Biff2 and ODS --> we just compare the value
CheckEquals(StrToFloat(SollStrings[Row]), StrToFloat(ActualString),
'Test value mismatch, cell ' + CellNotation(TestWorksheet, Row))
else
CheckEquals(SollStrings[Row], ActualString, 'Test value mismatch, '
+'cell '+CellNotation(TestWorkSheet, Row));
// Don't free the workbook here - it will be reused. It is destroyed at finalization.
end;
procedure TSpreadReadStringTests.SetUp;
begin
InitSollStrings;
end;
procedure TSpreadReadStringTests.TearDown;
begin
end;
procedure TSpreadReadStringTests.TestReadString0;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,0);
end;
procedure TSpreadReadStringTests.TestReadString1;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,1);
end;
procedure TSpreadReadStringTests.TestReadString2;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,2);
end;
procedure TSpreadReadStringTests.TestReadString3;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,3);
end;
procedure TSpreadReadStringTests.TestReadString4;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,4);
end;
procedure TSpreadReadStringTests.TestReadString5;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,5);
end;
procedure TSpreadReadStringTests.TestReadString6;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,6);
end;
procedure TSpreadReadStringTests.TestReadString7;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,7);
end;
procedure TSpreadReadStringTests.TestReadString8;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,8);
end;
procedure TSpreadReadStringTests.TestReadString9;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,9);
end;
procedure TSpreadReadStringTests.TestReadString10;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,10);
end;
procedure TSpreadReadStringTests.TestReadString11;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,11);
end;
procedure TSpreadReadStringTests.TestReadString12;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,12);
end;
procedure TSpreadReadStringTests.TestReadString13;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileBIFF8,13);
end;
{ ODF Tests }
procedure TSpreadReadStringTests.TestReadODFString0;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,0);
end;
procedure TSpreadReadStringTests.TestReadODFString1;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,1);
end;
procedure TSpreadReadStringTests.TestReadODFString2;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,2);
end;
procedure TSpreadReadStringTests.TestReadODFString3;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,3);
end;
procedure TSpreadReadStringTests.TestReadODFString4;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,4);
end;
procedure TSpreadReadStringTests.TestReadODFString5;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,5);
end;
procedure TSpreadReadStringTests.TestReadODFString6;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,6);
end;
procedure TSpreadReadStringTests.TestReadODFString7;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,7);
end;
procedure TSpreadReadStringTests.TestReadODFString8;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,8);
end;
procedure TSpreadReadStringTests.TestReadODFString9;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,9);
end;
procedure TSpreadReadStringTests.TestReadODFString10;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,10);
end;
procedure TSpreadReadStringTests.TestReadODFString11;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,11);
end;
procedure TSpreadReadStringTests.TestReadODFString12;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,12);
end;
procedure TSpreadReadStringTests.TestReadODFString13;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileODF,13);
end;
{ Excel XLSX Tests }
procedure TSpreadReadStringTests.TestReadOOXMLString0;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,0);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString1;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,1);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString2;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,2);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString3;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,3);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString4;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,4);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString5;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,5);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString6;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,6);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString7;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,7);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString8;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,8);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString9;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,9);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString10;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,10);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString11;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,11);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString12;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,12);
end;
procedure TSpreadReadStringTests.TestReadOOXMLString13;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileOOXML,13);
end;
{ Excel2003/XML Tests }
procedure TSpreadReadStringTests.TestReadXMLString0;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,0);
end;
procedure TSpreadReadStringTests.TestReadXMLString1;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,1);
end;
procedure TSpreadReadStringTests.TestReadXMLString2;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,2);
end;
procedure TSpreadReadStringTests.TestReadXMLString3;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,3);
end;
procedure TSpreadReadStringTests.TestReadXMLString4;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,4);
end;
procedure TSpreadReadStringTests.TestReadXMLString5;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,5);
end;
procedure TSpreadReadStringTests.TestReadXMLString6;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,6);
end;
procedure TSpreadReadStringTests.TestReadXMLString7;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,7);
end;
procedure TSpreadReadStringTests.TestReadXMLString8;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,8);
end;
procedure TSpreadReadStringTests.TestReadXMLString9;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,9);
end;
procedure TSpreadReadStringTests.TestReadXMLString10;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,10);
end;
procedure TSpreadReadStringTests.TestReadXMLString11;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,11);
end;
procedure TSpreadReadStringTests.TestReadXMLString12;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,12);
end;
procedure TSpreadReadStringTests.TestReadXMLString13;
begin
TestReadString(ExtractFilePath(ParamStr(0)) + TestFileXML,13);
end;
initialization
// Register so these tests are included in a full run
RegisterTest(TSpreadReadStringTests);
RegisterTest(TSpreadWriteReadStringTests);
// Initialize the norm variables in case other units want to use it:
InitSollStrings;
finalization
FreeAndNil(TestWorkbook);
end.

View File

@ -0,0 +1,97 @@
{ include file for "formulatests.pas", containing the test cases for the
calc3dformula test. }
// Setting up some test numbers
sheet1.WriteText(0, 4, 'abc'); // E1 = 'abc'
sheet1.WriteNumber(1, 5, 12.0); // F2 = 12.0
sheet2.WriteText(2, 1, 'A'); // B3 = 'A'
sheet2.WriteNumber(1, 4, 1.0); // E2 = 1.0
sheet2.WriteNumber(2, 4, -1.0); // E3 = -1.0
sheet2.WriteNumber(3, 4, 10.0); // E4 = 10.0
sheet3.WriteText(1, 2, 'B'); // C2 = 'B'
sheet3.WriteNumber(1, 1, 2.0); // B2 = 2.0
sheet3.WriteNumber(3, 4, 100); // E4 = 100.0
//------------------------------------------------------------------------------
Row := 0;
formula := 'Sheet2!B3'; { A1 }
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := StringResult('A');
inc(Row);
formula := 'Sheet2!B3&Sheet3!C2'; { A2 }
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := StringResult('AB');
inc(Row);
formula := 'Sheet2!E2'; { A3 }
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := FloatResult(1.0);
inc(Row);
formula := 'Sheet2!E2+Sheet3!B2'; { A4 }
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := FloatResult(3.0);
inc(Row);
formula := 'E1&Sheet2!B3'; { A5 }
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, 'E1&Sheet2!B3');
SetLength(SollValues, Row+1);
SollValues[Row] := StringResult('abcA');
inc(Row); { A6 }
formula := 'F2-Sheet2!E2-11';
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := FloatResult(0.0);
inc(Row);
formula := 'Sheet2!$B$3'; { A7 }
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := StringResult('A');
inc(Row);
formula := 'Sheet2!B$3&Sheet3!$C2'; { A8 }
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := StringResult('AB');
inc(Row);
formula := 'SUM(Sheet2!E2:E4)'; { A9 }
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := FloatResult(10.0);
inc(Row); { A10 }
formula := 'SUM(Sheet2:Sheet3!E4)';
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, formula);
SetLength(SollValues, Row+1);
SollValues[Row] := FloatResult(110.0);
{
inc(Row);
formula := 'D1&Sheet2!B3%"BC"';
sheet1.WriteText(Row, 0, formula);
sheet1.WriteFormula(Row, 1, 'D1&Sheet2!B3%"BC"');
SetLength(SollValues, Row+1);
SollValues[Row] := StringResult('abcABC');
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,136 @@
; testdbwriter.ini
; Database output selection for the testdbwriter fpcunit listener
; customized for fpspreadsheet tests (db names
;
; Specify the details for the connection to the database server or embedded database
; that has the database where your fpcunit test results need to be stored.
; This file contains several sections, one for each database type.
[Database]
; Select which profile you want to use:
profile=firebirdembedded
; The following sections contain the profiles you can use
; Please feel free to add/modify these:
[firebird]
; Interbase or Firebird database:
; Specify which TSQLConnection descendant you want to use - i.e. what database
; type you are using (use the spelling that the tsqlconnection uses)
type=firebird
; The name of the database:
name=/opt/firebird/data/fpspreadsheettest.fdb
; Default username/password for Interbase/Firebird
; is sysdba/masterkey. Change to your situation.
user=sysdba
password=masterkey
; hostname of the database server (or empty for embedded):
hostname=localhost
charset=UTF8
[firebirdembedded]
; Firebird embedded
; Same as Firebird, except we leave the host name blank
; and specify a db without path.
; Make sure your Firebird embedded library files (.dll/.so/.dylib)
; are installed; e.g. on Windows, you can put them in this
; directory.
type=firebird
name=fpspreadsheettest.fdb
user=sysdba
password=masterkey
hostname=
charset=UTF8
[mssql]
; MS SQL Server database:
type=mssql
name=fpspreadsheettest
user=sa
password=
hostname=127.0.0.1
[mysql40]
; MySQL 4.0 database:
type=mysql40
name=fpspreadsheettest
user=root
password=
hostname=127.0.0.1
[mysql41]
; MySQL 4.1 database:
type=mysql41
name=fpspreadsheettest
user=root
password=
hostname=127.0.0.1
[mysql50]
; MySQL 5.0 database:
type=mysql50
name=fpspreadsheettest
user=root
password=
hostname=127.0.0.1
[mysql51]
; MySQL 5.1 database:
type=mysql51
name=fpspreadsheettest
user=root
password=
hostname=127.0.0.1
[mysql55]
; MySQL 5.5 database (available since FPC 2.6.1):
type=mysql55
name=fpspreadsheettest
user=root
password=
hostname=127.0.0.1
[oracle]
; Oracle database:
; set up for a default Oracle express install
type=oracle
name=xe
user=system
password=
hostname=127.0.0.1
[odbc]
; ODBC database:
type=odbc
name=fpspreadsheettest
user=root
password=
hostname=127.0.0.1
[postgresql]
; PostgreSQL database:
type=postgresql
name=fpspreadsheettest
user=
password=
hostname=127.0.0.1
[sqlite]
; SQLite database:
type=sqlite3
name=fpspreadsheettest.db
[sybase]
; Sybase database:
type=sybase
name=fpspreadsheettest
user=sa
password=
hostname=127.0.0.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
SQLSCRIPT RCDATA "testdbwriter_firebird.sql"

View File

@ -0,0 +1,631 @@
/********************* ROLES **********************/
/********************* UDFS ***********************/
/****************** GENERATORS ********************/
CREATE GENERATOR GEN_APPLICATIONS_ID;
CREATE GENERATOR GEN_CPU_ID;
CREATE GENERATOR GEN_EXCEPTIONCLASSES_ID;
CREATE GENERATOR GEN_EXCEPTIONMESSAGES_ID;
CREATE GENERATOR GEN_METHODNAMES_ID;
CREATE GENERATOR GEN_OS_ID;
CREATE GENERATOR GEN_RESULTVALUES_ID;
CREATE GENERATOR GEN_SOURCELOCATIONS_ID;
CREATE GENERATOR GEN_SOURCEUNITS_ID;
CREATE GENERATOR GEN_TESTRESULTS_ID;
CREATE GENERATOR GEN_TESTRUNS_ID;
CREATE GENERATOR GEN_TESTSUITES_ID;
CREATE GENERATOR GEN_TESTS_ID;
/******************** DOMAINS *********************/
/******************* PROCEDURES ******************/
SET TERM ^ ;
CREATE PROCEDURE RECALCINDEXES
AS
BEGIN SUSPEND; END^
SET TERM ; ^
/******************** TABLES **********************/
CREATE TABLE APPLICATIONS
(
ID INTEGER NOT NULL,
NAME VARCHAR(800) NOT NULL,
CONSTRAINT APPPK PRIMARY KEY (ID),
CONSTRAINT APPNAMEUNIQ UNIQUE (NAME)
);
CREATE TABLE CPU
(
ID INTEGER NOT NULL,
CPUNAME VARCHAR(128) NOT NULL,
CONSTRAINT CPUPK PRIMARY KEY (ID),
CONSTRAINT CPUUNIQUE UNIQUE (CPUNAME)
);
CREATE TABLE EXCEPTIONCLASSES
(
ID INTEGER NOT NULL,
EXCEPTIONCLASS VARCHAR(128) NOT NULL,
CONSTRAINT EXCEPTIONSPK PRIMARY KEY (ID),
CONSTRAINT UNQ_EXCEPTIONCLASSES_CLASS UNIQUE (EXCEPTIONCLASS)
);
CREATE TABLE EXCEPTIONMESSAGES
(
ID INTEGER NOT NULL,
EXCEPTIONCLASS INTEGER NOT NULL,
EXCEPTIONMESSAGE VARCHAR(800) NOT NULL,
CONSTRAINT EXCEPTIONMESSAGESPK PRIMARY KEY (ID),
CONSTRAINT EXCEPTIONMESSAGEUNIQUE UNIQUE (EXCEPTIONMESSAGE)
);
CREATE TABLE METHODNAMES
(
ID INTEGER NOT NULL,
NAME VARCHAR(128) NOT NULL,
CONSTRAINT METHODNAMESPK PRIMARY KEY (ID),
CONSTRAINT METHODNAMESUNIQUENAME UNIQUE (NAME)
);
CREATE TABLE OPTIONS
(
OPTIONNAME VARCHAR(255) NOT NULL,
OPTIONVALUE VARCHAR(255),
REMARKS VARCHAR(255),
CONSTRAINT OPTIONSPK PRIMARY KEY (OPTIONNAME)
);
CREATE TABLE OS
(
ID INTEGER NOT NULL,
OSNAME VARCHAR(128) NOT NULL,
CONSTRAINT OSPK PRIMARY KEY (ID),
CONSTRAINT OSUNIQUE UNIQUE (OSNAME)
);
CREATE TABLE RESULTVALUES
(
ID INTEGER NOT NULL,
NAME VARCHAR(64) NOT NULL,
CONSTRAINT RESULTVALUESPK PRIMARY KEY (ID),
CONSTRAINT UNQ_RESULTVALUES_NAME UNIQUE (NAME)
);
CREATE TABLE SOURCELOCATIONS
(
ID INTEGER NOT NULL,
SOURCEUNIT INTEGER NOT NULL,
LINE INTEGER,
CONSTRAINT SOURCELOCATIONSPK PRIMARY KEY (ID),
CONSTRAINT SOURCELOCATIONSUNIQUE UNIQUE (SOURCEUNIT,LINE)
);
CREATE TABLE SOURCEUNITS
(
ID INTEGER NOT NULL,
NAME VARCHAR(128) NOT NULL,
CONSTRAINT SOURCEUNITS_PK PRIMARY KEY (ID),
CONSTRAINT SOURCEUNITS_NAME_UNIQUE UNIQUE (NAME)
);
CREATE TABLE TESTRESULTS
(
ID INTEGER NOT NULL,
TESTRUN INTEGER NOT NULL,
TEST INTEGER NOT NULL,
RESULTVALUE INTEGER,
EXCEPTIONMESSAGE INTEGER,
METHODNAME INTEGER,
SOURCELOCATION INTEGER,
RESULTCOMMENT VARCHAR(800),
ELAPSEDTIME TIME,
CONSTRAINT TESTRESULTSPK PRIMARY KEY (ID)
);
CREATE TABLE TESTRUNS
(
ID INTEGER NOT NULL,
DATETIMERAN TIMESTAMP,
APPLICATIONID INTEGER,
CPU INTEGER,
OS INTEGER,
REVISIONID VARCHAR(64),
RUNCOMMENT VARCHAR(800),
TOTALELAPSEDTIME TIME,
CONSTRAINT TESTRUNSPK PRIMARY KEY (ID)
);
CREATE TABLE TESTS
(
ID INTEGER NOT NULL,
TESTSUITE INTEGER NOT NULL,
NAME VARCHAR(128) NOT NULL,
CONSTRAINT TESTSPK PRIMARY KEY (ID),
CONSTRAINT UNQ_TESTS UNIQUE (TESTSUITE,NAME)
);
CREATE TABLE TESTSUITES
(
ID INTEGER NOT NULL,
PARENTSUITE INTEGER,
NAME VARCHAR(128) NOT NULL,
DEPTH INTEGER,
CONSTRAINT TESTSUITESPK PRIMARY KEY (ID),
CONSTRAINT UNQ_TESTSUITES_NAMEPAR UNIQUE (PARENTSUITE,NAME)
);
/********************* VIEWS **********************/
CREATE VIEW TESTSUITESFLAT (TESTSUITEID, TESTSUITENAME, DEPTH)
AS
with recursive suite_tree as (
select id as testsuiteid, name as testsuitename, depth from TESTSUITES
where parentsuite is null
union all
select chi.id as testsuiteid, par.testsuitename||'/'||chi.name as testsuitename, chi.depth from testsuites chi
join suite_tree par on chi.parentsuite=par.testsuiteid
)
select testsuiteid,testsuitename,depth from suite_tree;
CREATE VIEW FLAT (TESTRUNID, TESTRESULTID, TESTID, APPLICATION, REVISIONID, RUNCOMMENT, TESTRUNDATE, OS, CPU, TESTSUITE, TESTSUITEDEPTH, TESTNAME, TESTRESULT, EXCEPTIONCLASS, EXCEPTIONMESSAGE, METHOD, SOURCELINE, SOURCEUNIT, ELAPSEDTIME)
AS
SELECT
R.ID as TESTRUNID,
TR.ID as TESTRESULTID,
T.ID as TESTID,
AP.NAME as APPLICATION,
R.REVISIONID,
R.RUNCOMMENT,
R.DATETIMERAN as TESTRUNDATE,
OS.OSNAME,
CP.CPUNAME,
S.TESTSUITENAME as TESTSUITE,
S.DEPTH as TESTSUITEDEPTH,
T.NAME as TESTNAME,
RV.NAME as RESULT,
E.EXCEPTIONCLASS,
EM.EXCEPTIONMESSAGE as EXCEPTIONMESSAGE,
M.NAME as METHOD,
SL.LINE as SOURCELINE,
SU.NAME as SOURCEUNIT,
TR.ELAPSEDTIME as ELAPSEDTIME
FROM TESTRUNS R inner join TESTRESULTS TR on R.ID=TR.TESTRUN
inner join TESTS T on TR.TEST=T.ID
inner join TESTSUITESFLAT S on T.TESTSUITE=S.TESTSUITEID
inner join RESULTVALUES RV on TR.RESULTVALUE=RV.ID
left join APPLICATIONS AP on R.APPLICATIONID=AP.ID
left join
EXCEPTIONMESSAGES EM on TR.EXCEPTIONMESSAGE=EM.ID
left join EXCEPTIONCLASSES E on EM.EXCEPTIONCLASS=E.ID
left join METHODNAMES M on TR.METHODNAME=M.ID
left join SOURCELOCATIONS SL on TR.SOURCELOCATION=SL.ID
left join SOURCEUNITS SU on SL.SOURCEUNIT=SU.ID
left join OS on R.OS=OS.ID
left join CPU CP on R.CPU=CP.ID;
CREATE VIEW FLATSORTED (TESTRUNID, TESTRESULTID, TESTID, APPLICATION, REVISIONID, RUNCOMMENT, TESTRUNDATE, OS, CPU, TESTSUITE, TESTSUITEDEPTH, TESTNAME, TESTRESULT, EXCEPTIONCLASS, EXCEPTIONMESSAGE, METHOD, SOURCELINE, SOURCEUNIT)
AS
select
f.TESTRUNID, f.TESTRESULTID, f.TESTID,
f.APPLICATION, f.REVISIONID,
f.RUNCOMMENT, f.TESTRUNDATE, f.OS, f.CPU,
f.TESTSUITE, f.TESTSUITEDEPTH, f.TESTNAME, f.TESTRESULT,
f.EXCEPTIONCLASS, f.EXCEPTIONMESSAGE,
f.METHOD, f.SOURCELINE, f.SOURCEUNIT from
flat f
order by f.TESTRUNDATE desc, f.application, f.revisionid, f.TESTSUITEDEPTH, f.TESTSUITE, f.TESTNAME;
CREATE VIEW LASTFAILURE (APPLICATIONID, OSID, CPUID, TESTID, LASTFAILURE)
AS
SELECT tr.applicationid, tr.os, tr.cpu, r.test,
max(cast(tr.revisionid as integer)) lastsuccess
FROM testresults r inner join resultvalues rv
on r.RESULTVALUE=rv.id
inner join testruns tr
on r.testrun=tr.ID
where (rv.name='Failed') or (rv.name='Error')
group by tr.applicationid, tr.os, tr.cpu, r.test;
CREATE VIEW LASTSUCCESS (APPLICATIONID, OSID, CPUID, TESTID, LASTSUCCESS)
AS
SELECT tr.applicationid, tr.os, tr.cpu, r.test,
max(cast(tr.revisionid as integer)) lastsuccess
FROM testresults r inner join resultvalues rv
on r.RESULTVALUE=rv.id
inner join testruns tr
on r.testrun=tr.ID
where rv.name='OK' or rv.name='Ignored'
group by tr.applicationid, tr.os, tr.cpu, r.test;
CREATE VIEW TESTRESOK (TESTRESULTID)
AS
SELECT tr.id
from
testresults tr inner join
resultvalues rv on
tr.resultvalue=rv.id
where (rv.name='OK' or rv.name='Ignored');
CREATE VIEW OKRESULTS (RUNID, APPLICATION, OS, CPU, OKCOUNT, OKPERCENTAGE)
AS
SELECT run.id, a.name, o.osname, c.cpuname, count(rv.name),
((count(ok.testresultid))*100)/(SELECT COUNT(resultvalue) FROM testresults where testresults.testrun=run.id)
from
testresults tr inner join
testruns run on tr.TESTRUN=run.id inner join
testresok ok on tr.id=ok.testresultid inner join
resultvalues rv on tr.resultvalue=rv.id
inner join applications a on run.applicationid=a.ID
inner join cpu c on run.cpu=c.ID
inner join os o on run.os=o.id
group by run.id, a.name, o.osname, c.cpuname;
CREATE VIEW REGRESSIONS (APPLICATIONID, CPUID, OSID, TESTID, LASTSUCCESFULREVISION)
AS
select
s.applicationid, s.cpuid, s.osid, s.testid, s.lastsuccess as lastsuccessfulrevision
from
lastfailure f inner join lastsuccess s on
(f.osid=s.osid) and
(f.cpuid=s.cpuid) and
(f.applicationid=s.applicationid) and (f.testid=s.testid)
where f.lastfailure>s.lastsuccess;
CREATE VIEW REGRESSIONSFLAT (TESTRUNID, APPLICATION, LASTSUCCESFULREVISION, TESTRUNDATE, OS, CPU, TESTSUITE, TESTNAME)
AS
select
run.id,
a.NAME,
r.LASTSUCCESFULREVISION,
run.DATETIMERAN,
o.OSNAME,
c.CPUNAME,
ts.TESTSUITENAME,
t.NAME
from
regressions r inner join testresults tr on
(r.testid=tr.test)
inner join testruns run on
(r.applicationid=run.APPLICATIONID) AND
(r.osid=run.os) AND
(r.cpuid=run.cpu) AND
(tr.testrun=run.id) AND
(r.lastsuccesfulrevision=run.revisionid)
inner join applications a on run.applicationid=a.ID
inner join cpu c on run.cpu=c.ID
inner join os o on run.os=o.id
inner join tests t on tr.test=t.ID
inner join TESTSUITESFLAT ts on t.TESTSUITE=ts.TESTSUITEID;
/******************* EXCEPTIONS *******************/
/******************** TRIGGERS ********************/
SET TERM ^ ;
CREATE TRIGGER APPLICATIONS_BI FOR APPLICATIONS ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_APPLICATIONS_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_APPLICATIONS_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_APPLICATIONS_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER CPU_BI FOR CPU ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_CPU_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_CPU_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_CPU_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER EXCEPTIONCLASSES_BI FOR EXCEPTIONCLASSES ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_EXCEPTIONCLASSES_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_EXCEPTIONCLASSES_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_EXCEPTIONCLASSES_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER EXCEPTIONMESSAGES_BI FOR EXCEPTIONMESSAGES ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_EXCEPTIONMESSAGES_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_EXCEPTIONMESSAGES_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_EXCEPTIONMESSAGES_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER METHODNAMES_BI FOR METHODNAMES ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_METHODNAMES_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_METHODNAMES_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_METHODNAMES_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER OS_BI FOR OS ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_OS_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_OS_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_OS_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER RESULTVALUES_BI FOR RESULTVALUES ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_RESULTVALUES_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_RESULTVALUES_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_RESULTVALUES_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER SOURCELOCATIONS_BI FOR SOURCELOCATIONS ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_SOURCELOCATIONS_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_SOURCELOCATIONS_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_SOURCELOCATIONS_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER SOURCEUNITS_BI FOR SOURCEUNITS ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_SOURCEUNITS_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_SOURCEUNITS_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_SOURCEUNITS_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER TESTRESULTS_BI FOR TESTRESULTS ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_TESTRESULTS_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_TESTRESULTS_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_TESTRESULTS_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER TESTRUNS_BI FOR TESTRUNS ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_TESTRUNS_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_TESTRUNS_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_TESTRUNS_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER TESTSUITES_BI FOR TESTSUITES ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_TESTSUITES_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_TESTSUITES_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_TESTSUITES_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
CREATE TRIGGER TESTS_BI FOR TESTS ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_TESTS_ID, 1);
ELSE
BEGIN
tmp = GEN_ID(GEN_TESTS_ID, 0);
if (tmp < new.ID) then
tmp = GEN_ID(GEN_TESTS_ID, new.ID-tmp);
END
END^
SET TERM ; ^
SET TERM ^ ;
ALTER PROCEDURE RECALCINDEXES
AS
declare variable index_name VARCHAR(31);
BEGIN
for select RDB$INDEX_NAME from RDB$INDICES into :index_name do
execute statement 'SET statistics INDEX ' || :index_name || ';';
END^
SET TERM ; ^
UPDATE RDB$PROCEDURES set
RDB$DESCRIPTION = 'Recalculates index selectivity for all tables. This is normally only done during backup/restore etc, and can be useful after adding or removing a lot of data.'
where RDB$PROCEDURE_NAME = 'RECALCINDEXES';
ALTER TABLE EXCEPTIONMESSAGES ADD CONSTRAINT FK_EXCEPTIONCLASSES_CLASS
FOREIGN KEY (EXCEPTIONCLASS) REFERENCES EXCEPTIONCLASSES (ID) ON UPDATE CASCADE ON DELETE CASCADE;
UPDATE RDB$RELATIONS set
RDB$DESCRIPTION = 'Stores schema version and any application-specific options.'
where RDB$RELATION_NAME = 'OPTIONS';
ALTER TABLE SOURCELOCATIONS ADD CONSTRAINT SOURCELOCATIONSFK_UNIT
FOREIGN KEY (SOURCEUNIT) REFERENCES SOURCEUNITS (ID) ON UPDATE CASCADE ON DELETE CASCADE;
UPDATE RDB$RELATION_FIELDS set RDB$DESCRIPTION = 'Name of the pascal unit' where RDB$FIELD_NAME = 'NAME' and RDB$RELATION_NAME = 'SOURCEUNITS';
UPDATE RDB$RELATIONS set
RDB$DESCRIPTION = 'Pascal units where errrors occurred'
where RDB$RELATION_NAME = 'SOURCEUNITS';
UPDATE RDB$RELATION_FIELDS set RDB$DESCRIPTION = 'Note: let''s not use COMMENT as it is reserved in Firebird' where RDB$FIELD_NAME = 'RESULTCOMMENT' and RDB$RELATION_NAME = 'TESTRESULTS';
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_EXCEPTION
FOREIGN KEY (EXCEPTIONMESSAGE) REFERENCES EXCEPTIONMESSAGES (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_RESULT
FOREIGN KEY (RESULTVALUE) REFERENCES RESULTVALUES (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_SOURCELOCATION
FOREIGN KEY (SOURCELOCATION) REFERENCES SOURCELOCATIONS (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_TEST
FOREIGN KEY (TEST) REFERENCES TESTS (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_TESTRUN
FOREIGN KEY (TESTRUN) REFERENCES TESTRUNS (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTSRES_METHODNAME
FOREIGN KEY (METHODNAME) REFERENCES METHODNAMES (ID) ON UPDATE CASCADE ON DELETE CASCADE;
UPDATE RDB$RELATION_FIELDS set RDB$DESCRIPTION = 'Identifies operating system the test application runs on' where RDB$FIELD_NAME = 'OS' and RDB$RELATION_NAME = 'TESTRUNS';
UPDATE RDB$RELATION_FIELDS set RDB$DESCRIPTION = 'String that uniquely identifies the revision/version of the code that is tested. Useful when running regression tests, identifying when an error occurred first etc.' where RDB$FIELD_NAME = 'REVISIONID' and RDB$RELATION_NAME = 'TESTRUNS';
UPDATE RDB$RELATION_FIELDS set RDB$DESCRIPTION = 'Comment provided by user/test run suite on this test run (e.g. used compiler flags)' where RDB$FIELD_NAME = 'RUNCOMMENT' and RDB$RELATION_NAME = 'TESTRUNS';
ALTER TABLE TESTRUNS ADD CONSTRAINT FK_TESTRUNSCPU
FOREIGN KEY (CPU) REFERENCES CPU (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRUNS ADD CONSTRAINT FK_TESTRUNSOS
FOREIGN KEY (OS) REFERENCES OS (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRUNS ADD CONSTRAINT FK_TESTRUNS_APPLICATIONS
FOREIGN KEY (APPLICATIONID) REFERENCES APPLICATIONS (ID) ON UPDATE CASCADE ON DELETE CASCADE;
CREATE INDEX IDX_TESTRUNSCOMM ON TESTRUNS (RUNCOMMENT);
CREATE DESCENDING INDEX IDX_TESTRUNSDTREV ON TESTRUNS (DATETIMERAN);
CREATE INDEX IDX_TESTRUNSREV ON TESTRUNS (REVISIONID);
UPDATE RDB$RELATIONS set
RDB$DESCRIPTION = 'Represents a run by a single program of one or more testsuites'
where RDB$RELATION_NAME = 'TESTRUNS';
ALTER TABLE TESTS ADD CONSTRAINT TESTSTESTSUITESFK
FOREIGN KEY (TESTSUITE) REFERENCES TESTSUITES (ID) ON UPDATE CASCADE ON DELETE CASCADE;
UPDATE RDB$RELATIONS set
RDB$DESCRIPTION = 'Name and testsuite (hierarchy) for a specific test.
This table uniquely identifies tests, no need to add joins to testsuite.'
where RDB$RELATION_NAME = 'TESTS';
UPDATE RDB$RELATION_FIELDS set RDB$DESCRIPTION = 'Level in the hierarchy this testsuite has.' where RDB$FIELD_NAME = 'DEPTH' and RDB$RELATION_NAME = 'TESTSUITES';
ALTER TABLE TESTSUITES ADD CONSTRAINT FK_TESTSUITES_PARENT
FOREIGN KEY (PARENTSUITE) REFERENCES TESTSUITES (ID) ON UPDATE CASCADE ON DELETE CASCADE;
UPDATE RDB$RELATIONS set
RDB$DESCRIPTION = 'Flattens the hierarchical tree of the testsuites and displays the name much like a path, including it depth in the hierarchy, for display and selection purposes.'
where RDB$RELATION_NAME = 'TESTSUITESFLAT';
GRANT EXECUTE
ON PROCEDURE RECALCINDEXES TO SYSDBA;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON APPLICATIONS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON CPU TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON EXCEPTIONCLASSES TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON EXCEPTIONMESSAGES TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON METHODNAMES TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON OPTIONS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON OS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON RESULTVALUES TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON SOURCELOCATIONS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON SOURCEUNITS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON TESTRESULTS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON TESTRUNS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON TESTS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON TESTSUITES TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON FLAT TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON FLATSORTED TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON LASTFAILURE TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON LASTSUCCESS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON TESTRESOK TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON OKRESULTS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON REGRESSIONS TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON REGRESSIONSFLAT TO SYSDBA WITH GRANT OPTION;
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
ON TESTSUITESFLAT TO SYSDBA WITH GRANT OPTION;

View File

@ -0,0 +1,222 @@
CREATE TABLE APPLICATIONS
(
ID serial NOT NULL,
NAME VARCHAR(800),
CONSTRAINT APPPK PRIMARY KEY (ID),
CONSTRAINT APPNAMEUNIQ UNIQUE (NAME)
);
CREATE TABLE CPU
(
ID serial NOT NULL,
CPUNAME VARCHAR(255),
CONSTRAINT CPUPK PRIMARY KEY (ID),
CONSTRAINT CPUUNIQUE UNIQUE (CPUNAME)
);
CREATE TABLE EXCEPTIONCLASSES
(
ID serial NOT NULL,
EXCEPTIONCLASS VARCHAR(800),
CONSTRAINT EXCEPTIONSPK PRIMARY KEY (ID),
CONSTRAINT UNQ_EXCEPTIONCLASSES_CLASS UNIQUE (EXCEPTIONCLASS)
);
CREATE TABLE EXCEPTIONMESSAGES
(
ID serial NOT NULL,
EXCEPTIONCLASS INTEGER,
EXCEPTIONMESSAGE VARCHAR(800),
CONSTRAINT EXCEPTIONMESSAGESPK PRIMARY KEY (ID),
CONSTRAINT EXCEPTIONMESSAGEUNIQUE UNIQUE (EXCEPTIONMESSAGE)
);
CREATE TABLE METHODNAMES
(
ID serial NOT NULL,
NAME VARCHAR(800),
CONSTRAINT METHODNAMESPK PRIMARY KEY (ID),
CONSTRAINT METHODNAMESUNIQUENAME UNIQUE (NAME)
);
CREATE TABLE OPTIONS
(
OPTIONNAME VARCHAR(255) NOT NULL,
OPTIONVALUE VARCHAR(255),
REMARKS VARCHAR(255),
CONSTRAINT OPTIONSPK PRIMARY KEY (OPTIONNAME)
);
CREATE TABLE OS
(
ID serial NOT NULL,
OSNAME VARCHAR(255),
CONSTRAINT OSPK PRIMARY KEY (ID),
CONSTRAINT OSUNIQUE UNIQUE (OSNAME)
);
CREATE TABLE RESULTVALUES
(
ID serial NOT NULL,
NAME VARCHAR(800),
CONSTRAINT RESULTVALUESPK PRIMARY KEY (ID),
CONSTRAINT UNQ_RESULTVALUES_NAME UNIQUE (NAME)
);
CREATE TABLE SOURCELOCATIONS
(
ID serial NOT NULL,
SOURCEUNIT INTEGER,
LINE INTEGER,
CONSTRAINT SOURCELOCATIONSPK PRIMARY KEY (ID),
CONSTRAINT SOURCELOCATIONSUNIQUE UNIQUE (SOURCEUNIT,LINE)
);
CREATE TABLE SOURCEUNITS
(
ID serial NOT NULL,
NAME VARCHAR(800),
CONSTRAINT SOURCEUNITS_PK PRIMARY KEY (ID),
CONSTRAINT SOURCEUNITS_NAME_UNIQUE UNIQUE (NAME)
);
CREATE TABLE TESTS
(
ID serial NOT NULL,
TESTSUITE INTEGER,
NAME VARCHAR(800),
CONSTRAINT TESTSPK PRIMARY KEY (ID),
CONSTRAINT UNQ_TESTS_SUITENAME UNIQUE (TESTSUITE,NAME)
);
CREATE TABLE TESTRUNS
(
ID serial NOT NULL,
DATETIMERAN TIMESTAMP,
APPLICATIONID INTEGER,
CPU INTEGER,
OS INTEGER,
REVISIONID VARCHAR(800),
RUNCOMMENT VARCHAR(800),
TOTALELAPSEDTIME TIME,
CONSTRAINT TESTRUNSPK PRIMARY KEY (ID)
);
CREATE TABLE TESTRESULTS
(
ID serial NOT NULL,
TESTRUN INTEGER,
TEST INTEGER,
RESULTVALUE INTEGER,
EXCEPTIONMESSAGE INTEGER,
METHODNAME INTEGER,
SOURCELOCATION INTEGER,
RESULTCOMMENT VARCHAR(800),
ELAPSEDTIME TIME,
CONSTRAINT TESTRESULTSPK PRIMARY KEY (ID)
);
CREATE TABLE TESTSUITES
(
ID serial NOT NULL,
PARENTSUITE INTEGER,
NAME VARCHAR(800),
DEPTH INTEGER,
CONSTRAINT TESTSUITESPK PRIMARY KEY (ID),
CONSTRAINT UNQ_TESTSUITES_NAMEPAR UNIQUE (PARENTSUITE,NAME)
);
CREATE VIEW TESTSUITESFLAT (TESTSUITEID, TESTSUITENAME, DEPTH)
AS
with recursive suite_tree as (
select id as testsuiteid, ''||name as testsuitename, depth from TESTSUITES
where parentsuite is null
-- to do: find a better way to cast testsuitename from varchar(800) to character varying without limits
union all
select chi.id as testsuiteid, par.testsuitename||'/'||chi.name as testsuitename, chi.depth from testsuites chi
join suite_tree par on chi.parentsuite=par.testsuiteid
)
select testsuiteid,testsuitename,depth from suite_tree;
CREATE VIEW FLAT (TESTRUNID, TESTRESULTID, TESTID, APPLICATION, REVISIONID, RUNCOMMENT, TESTRUNDATE, OS, CPU, TESTSUITE, TESTSUITEDEPTH, TESTNAME, TESTRESULT, EXCEPTIONCLASS, EXCEPTIONMESSAGE, METHOD, SOURCELINE, SOURCEUNIT, ELAPSEDTIME)
AS
SELECT
R.ID as TESTRUNID,
TR.ID as TESTRESULTID,
T.ID as TESTID,
AP.NAME as APPLICATION,
R.REVISIONID,
R.RUNCOMMENT,
R.DATETIMERAN as TESTRUNDATE,
OS.OSNAME,
CP.CPUNAME,
S.TESTSUITENAME as TESTSUITE,
S.DEPTH as TESTSUITEDEPTH,
T.NAME as TESTNAME,
RV.NAME as RESULT,
E.EXCEPTIONCLASS,
EM.EXCEPTIONMESSAGE as EXCEPTIONMESSAGE,
M.NAME as METHOD,
SL.LINE as SOURCELINE,
SU.NAME as SOURCEUNIT,
TR.ELAPSEDTIME as ELAPSEDTIME
FROM TESTRUNS R inner join TESTRESULTS TR on R.ID=TR.TESTRUN
inner join TESTS T on TR.TEST=T.ID
inner join TESTSUITESFLAT S on T.TESTSUITE=S.TESTSUITEID
inner join RESULTVALUES RV on TR.RESULTVALUE=RV.ID
left join APPLICATIONS AP on R.APPLICATIONID=AP.ID
left join
EXCEPTIONMESSAGES EM on TR.EXCEPTIONMESSAGE=EM.ID
left join EXCEPTIONCLASSES E on EM.EXCEPTIONCLASS=E.ID
left join METHODNAMES M on TR.METHODNAME=M.ID
left join SOURCELOCATIONS SL on TR.SOURCELOCATION=SL.ID
left join SOURCEUNITS SU on SL.SOURCEUNIT=SU.ID
left join OS on R.OS=OS.ID
left join CPU CP on R.CPU=CP.ID;
CREATE VIEW FLATSORTED (TESTRUNID, TESTRESULTID, TESTID, APPLICATION, REVISIONID, RUNCOMMENT, TESTRUNDATE, OS, CPU, TESTSUITE, TESTSUITEDEPTH, TESTNAME, TESTRESULT, EXCEPTIONCLASS, EXCEPTIONMESSAGE, METHOD, SOURCELINE, SOURCEUNIT)
AS
select
f.TESTRUNID, f.TESTRESULTID, f.TESTID,
f.APPLICATION, f.REVISIONID,
f.RUNCOMMENT, f.TESTRUNDATE, f.OS, f.CPU,
f.TESTSUITE, f.TESTSUITEDEPTH, f.TESTNAME, f.TESTRESULT,
f.EXCEPTIONCLASS, f.EXCEPTIONMESSAGE,
f.METHOD, f.SOURCELINE, f.SOURCEUNIT from
flat f
order by f.TESTRUNDATE desc, f.application, f.revisionid, f.TESTSUITEDEPTH, f.TESTSUITE, f.TESTNAME;
ALTER TABLE EXCEPTIONMESSAGES ADD CONSTRAINT FK_EXCEPTIONCLASSES_CLASS
FOREIGN KEY (EXCEPTIONCLASS) REFERENCES EXCEPTIONCLASSES (ID) ON UPDATE
CASCADE ON DELETE CASCADE;
ALTER TABLE SOURCELOCATIONS ADD CONSTRAINT SOURCELOCATIONSFK_UNIT
FOREIGN KEY (SOURCEUNIT) REFERENCES SOURCEUNITS (ID) ON UPDATE CASCADE ON
DELETE CASCADE;
ALTER TABLE TESTS ADD CONSTRAINT TESTSTESTSUITESFK
FOREIGN KEY (TESTSUITE) REFERENCES TESTSUITES (ID) ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE TESTRUNS ADD CONSTRAINT FK_TESTRUNSCPU
FOREIGN KEY (CPU) REFERENCES CPU (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRUNS ADD CONSTRAINT FK_TESTRUNSOS
FOREIGN KEY (OS) REFERENCES OS (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRUNS ADD CONSTRAINT FK_TESTRUNS_APPLICATIONS
FOREIGN KEY (APPLICATIONID) REFERENCES APPLICATIONS (ID) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_EXCEPTION
FOREIGN KEY (EXCEPTIONMESSAGE) REFERENCES EXCEPTIONMESSAGES (ID) ON UPDATE
CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_METHODNAME
FOREIGN KEY (METHODNAME) REFERENCES METHODNAMES (ID) ON UPDATE CASCADE ON
DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_RESULT
FOREIGN KEY (RESULTVALUE) REFERENCES RESULTVALUES (ID) ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_SOURCELOC
FOREIGN KEY (SOURCELOCATION) REFERENCES SOURCELOCATIONS (ID) ON UPDATE
CASCADE ON DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_TEST
FOREIGN KEY (TEST) REFERENCES TESTS (ID) ON UPDATE CASCADE ON
DELETE CASCADE;
ALTER TABLE TESTRESULTS ADD CONSTRAINT FK_TESTRES_TESTRUN
FOREIGN KEY (TESTRUN) REFERENCES TESTRUNS (ID) ON UPDATE CASCADE ON DELETE
CASCADE;
ALTER TABLE TESTSUITES ADD CONSTRAINT FK_TESTSUITES_PARENT
FOREIGN KEY (PARENTSUITE) REFERENCES TESTSUITES (ID) ON UPDATE CASCADE ON DELETE CASCADE;
COMMENT ON TABLE options
IS 'Stores schema version and any application-specific options.';
COMMENT ON TABLE sourceunits
IS 'Pascal units where errrors occurred';
COMMENT ON COLUMN testruns.revisionid IS 'String that uniquely identifies
the revision/version of the code that is tested. Useful when running
regression tests, identifying when an error occurred first etc.';
COMMENT ON COLUMN testruns.runcomment IS 'Comment provided by user/test run
suite on this test run (e.g. used compiler flags)';
COMMENT ON COLUMN tests.name IS 'Identifies both the name (and following
the FK), the test suite. This means that multiple test suites with the same
test name text are allowed.';

View File

@ -0,0 +1,150 @@
unit testsutility;
{ Utility unit with general functions for the real fpspreadsheet test units,
e.g. getting temporary files }
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fpspreadsheet;
const
TestFileBIFF8_1904='testbiff8_1904.xls'; //with 1904 datemode date system
TestFileBIFF8_1899='testbiff8_1899.xls'; //with 1899/1900 datemode date system
TestFileBIFF8 = TestFileBIFF8_1899;
TestFileODF_1904='testodf_1904.ods'; //OpenDocument/LibreOffice with 1904 datemode date system
TestFileODF_1899='testodf_1899.ods'; //OpenDocument/LibreOffice with 1899/1900 datemode date system
TestFileODF = TestFileODF_1899;
TestFileOOXML_1904='testooxml_1904.xlsx'; //Excel xlsx with 1904 datemode date system
TestFileOOXML_1899='testooxml_1899.xlsx'; //Excel xlsx with 1899/1900 datemode date system
TestFileOOXML = TestFileOOXML_1899;
TestFileXML_1904='testxml_1904.xml'; //Excel 2003/XML file with 1904 datemode date system
TestFileXML_1899='testxml_1899.xml'; //Excel 2003/XML file with 1899/1900 datemode date system
TestFileXML = TestFileXML_1899;
TestFileManual = 'testmanual.xls'; //file name for manual checking using external spreadsheet program (Excel/LibreOffice..)
DatesSheet = 'Dates'; //worksheet name
FormulasSheet = 'Formulas'; //worksheet name
ManualSheet = 'ManualTests'; //worksheet names
NumbersSheet = 'Numbers'; //worksheet name
StringsSheet = 'Texts'; //worksheet name
// Returns an A.. notation based on sheet, row, optional column (e.g. A1).
function CellNotation(WorkSheet: TsWorksheet; Row: integer; Column: integer=0): string;
// Returns an A notation of column based on sheet and column
function ColNotation(WorkSheet: TsWorksheet; Column:Integer): String;
// Returns a notation for row bassed on sheet and row
function RowNotation(Worksheet: TsWorksheet; Row: Integer): String;
// Note: using this function instead of GetWorkSheetByName for compatibility with
// older fpspreadsheet versions that don't have that function
function GetWorksheetByName(AWorkBook: TsWorkBook; AName: String): TsWorksheet;
// Gets new empty temp file and returns the file name
// Removes any existing file by that name
// Should be called just before writing to the file as
// GetTempFileName is used which does not guarantee
// file uniqueness
function NewTempFile: String;
implementation
function NewTempFile: String;
begin
Result := GetTempFileName;
if FileExists(Result) then
begin
DeleteFile(Result);
sleep(50); //e.g. on Windows, give file system chance to perform changes
end;
end;
function GetWorksheetByName(AWorkBook: TsWorkBook; AName: String): TsWorksheet;
var
i:integer;
Worksheets: cardinal;
begin
Result := nil;
if AWorkBook=nil then
exit;
Worksheets:=AWorkBook.GetWorksheetCount;
try
for i:=0 to Worksheets-1 do
begin
if AWorkBook.GetWorksheetByIndex(i).Name=AName then
begin
Result := AWorkBook.GetWorksheetByIndex(i);
exit;
end;
end;
except
Result := nil; //e.g. Getworksheetbyindex unexpectedly gave nil
exit;
end;
end;
// Converts column number to A.. notation
function ColumnToLetter(Column: integer): string;
begin
begin
if Column < 26 then
Result := char(Column+65)
else
if Column < 26*26 then
Result := char(Column div 26 + 65) +
char(Column mod 26 + 65)
else
if Column < 26*26*26 then
Result := char(Column div (26*26) + 65) +
char(Column mod (26*26) div 26 + 65) +
char(Column mod (26*26*26) + 65)
else
Result := 'ColNotation: At most three digits supported.';
end;
end;
function CellNotation(WorkSheet: TsWorksheet; Row: integer; Column: integer=0): string;
begin
// From 0-based to Excel A1 notation
if not(assigned(Worksheet)) then
result:='CellNotation: error getting worksheet.'
else
if Worksheet.Name <> '' then
result := WorkSheet.Name + '!' + ColumnToLetter(Column) + inttostr(Row+1)
else
Result := ColumnToLetter(Column) + IntToStr(Row + 1);
end;
function ColNotation(WorkSheet: TsWorksheet; Column:Integer): String;
begin
if not Assigned(Worksheet) then
Result := 'ColNotation: error getting worksheet.'
else
if Worksheet.Name <> '' then
Result := WorkSheet.Name + '!' + ColumnToLetter(Column)
else
Result := ColumnToLetter(Column);
end;
function RowNotation(Worksheet: TsWorksheet; Row: Integer): String;
begin
if not Assigned(Worksheet) then
Result := 'RowNotation: error getting worksheet.'
else
if Worksheet.Name <> '' then
Result := Worksheet.Name + '!' + IntToStr(Row+1)
else
Result := IntToStr(Row+1);
end;
end.

View File

@ -0,0 +1,591 @@
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>Pamler</Author>
<LastAuthor>Werner</LastAuthor>
<Created>2014-08-05T08:05:53Z</Created>
<LastSaved>2015-04-30T11:25:25Z</LastSaved>
<Version>16.00</Version>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>8190</WindowHeight>
<WindowWidth>16380</WindowWidth>
<WindowTopX>32767</WindowTopX>
<WindowTopY>32767</WindowTopY>
<TabRatio>500</TabRatio>
<ActiveSheet>2</ActiveSheet>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font ss:FontName="Verdana" x:Family="Swiss"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
<Style ss:ID="s16">
<Font ss:FontName="Verdana" x:Family="Swiss" ss:Bold="1"/>
</Style>
<Style ss:ID="s17">
<NumberFormat ss:Format="Short Date"/>
</Style>
<Style ss:ID="s18">
<NumberFormat ss:Format="hh:mm:ss"/>
</Style>
<Style ss:ID="s19">
<NumberFormat ss:Format="0%"/>
</Style>
<Style ss:ID="s20">
<NumberFormat ss:Format="Percent"/>
</Style>
<Style ss:ID="s21">
<NumberFormat ss:Format="#,##0"/>
</Style>
<Style ss:ID="s22">
<NumberFormat ss:Format="Standard"/>
</Style>
<Style ss:ID="s23">
<NumberFormat ss:Format="Scientific"/>
</Style>
<Style ss:ID="s24">
<NumberFormat ss:Format="h:mm;@"/>
</Style>
<Style ss:ID="s25">
<NumberFormat ss:Format="[$-F400]h:mm:ss\ AM/PM"/>
</Style>
<Style ss:ID="s26">
<NumberFormat ss:Format="[$-409]h:mm\ AM/PM;@"/>
</Style>
<Style ss:ID="s27">
<NumberFormat ss:Format="[$-409]h:mm:ss\ AM/PM;@"/>
</Style>
<Style ss:ID="s28">
<NumberFormat ss:Format="dd/\ mmm"/>
</Style>
<Style ss:ID="s29">
<NumberFormat ss:Format="mmm\ yy"/>
</Style>
<Style ss:ID="s30">
<NumberFormat ss:Format="mm:ss"/>
</Style>
<Style ss:ID="s31">
<NumberFormat ss:Format="[h]:mm:ss"/>
</Style>
<Style ss:ID="s32">
<NumberFormat/>
</Style>
<Style ss:ID="s33">
<NumberFormat ss:Format="General Date"/>
</Style>
<Style ss:ID="s35">
<NumberFormat ss:Format="#,##0.00\ &quot;€&quot;"/>
</Style>
<Style ss:ID="s36">
<NumberFormat ss:Format="#,##0.00\ [$$-409]"/>
</Style>
<Style ss:ID="s37">
<NumberFormat ss:Format="[$$-409]#,##0.00;[Red]\-#,###.00\ [$$-409]"/>
</Style>
<Style ss:ID="s38">
<NumberFormat ss:Format="#,##0.00\ [$EUR];[Red]\(#,##0.00\ [$EUR]\)"/>
</Style>
<Style ss:ID="s39">
<NumberFormat ss:Format="yyyy\-mm\-dd\Thh:mm:ss"/>
</Style>
</Styles>
<Worksheet ss:Name="Numbers">
<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="23" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="54">
<Column ss:AutoFitWidth="0" ss:Width="95.25"/>
<Row>
<Cell><Data ss:Type="Number">-59000000</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s16"><Data ss:Type="String">Please use the A column for cells that will be read by fpspreadsheet</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-988</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s16"><Data ss:Type="String">Do not modify or delete cells; it will mess up the tests</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-124.23432</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s16"><Data ss:Type="String">You can use other cells for comments, intermediate calculations, etc</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-81.902850873027404</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-15</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-2.934E-3</Data></Cell>
<Cell><Data ss:Type="String">minus small fraction</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">0</Data></Cell>
<Cell><Data ss:Type="String">minus zero</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">0</Data></Cell>
<Cell><Data ss:Type="String">zero</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">5.0000000000000001E-9</Data></Cell>
<Cell><Data ss:Type="String">small fraction</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">0.98239399999999999</Data></Cell>
<Cell><Data ss:Type="String">almost 1</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">3.14159265358979</Data></Cell>
<Cell><Data ss:Type="String">some parts of pi</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">59000000</Data></Cell>
<Cell><Data ss:Type="String">59 million</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">59000000.100000001</Data></Cell>
<Cell><Data ss:Type="String">same + a tenth</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s19"><Data ss:Type="Number">0.35360000000000003</Data></Cell>
<Cell><Data ss:Type="String" x:Ticked="1">0.3536 formatted as percent with no decimal</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s20"><Data ss:Type="Number">0.35360000000000003</Data></Cell>
<Cell><Data ss:Type="String" x:Ticked="1">0.3536 formatted as percent with two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s21"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted with thousand separator, no decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s22"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted with thousand separator, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s23"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as &quot;exp&quot; with 2 decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s35"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted as EUROs, € at end, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s36"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted as DOLLARs, $ at end, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s35"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as EUROs, € at end, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s36"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as DOLLARs, $ at end, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s37"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as DOLLARs, $ at end, negative red, two decimals</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.51180555555555551"/>
<Footer x:Margin="0.51180555555555551"/>
<PageMargins x:Bottom="0.98402777777777772" x:Left="0.74791666666666667"
x:Right="0.74791666666666667" x:Top="0.98402777777777772"/>
</PageSetup>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>9</PaperSizeIndex>
<HorizontalResolution>300</HorizontalResolution>
<VerticalResolution>300</VerticalResolution>
</Print>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
<EnableSelection>NoSelection</EnableSelection>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Texts">
<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="14" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="54">
<Column ss:AutoFitWidth="0" ss:Width="119.25"/>
<Row>
<Cell ss:Index="2"><Data ss:Type="String">nothing, empty text</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s16"><Data ss:Type="String">Please use the A column for cells that will be read by fpspreadsheet</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">a</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s16"><Data ss:Type="String">Do not modify or delete cells; it will mess up the tests</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">1</Data></Cell>
<Cell><Data ss:Type="String">a number</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s16"><Data ss:Type="String">You can use other cells for comments, intermediate calculations, etc</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">The quick brown fox jumps over the lazy dog</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">café au lait</Data></Cell>
<Cell><Data ss:Type="String">accent aigue on the e</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">водка</Data></Cell>
<Cell><Data ss:Type="String">Cyrillic</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">wódka</Data></Cell>
<Cell><Data ss:Type="String">Polish o accent aigue</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s19"><Data ss:Type="Number">0.35360000000000003</Data></Cell>
<Cell><Data ss:Type="String" x:Ticked="1">0.3536 formatted as percent with no decimal</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s20"><Data ss:Type="Number">0.35360000000000003</Data></Cell>
<Cell><Data ss:Type="String" x:Ticked="1">0.3536 formatted as percent with two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s21"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted with thousand separator, no decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s22"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted with thousand separator, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s23"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as &quot;exp&quot; with 2 decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s38"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted as &quot;currencyRed&quot; with 2 decimals, brackets and EUR</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s38"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as &quot;currencyRed&quot; with 2 decimals, brackets and EUR</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.51180555555555551"/>
<Footer x:Margin="0.51180555555555551"/>
<PageMargins x:Bottom="0.98402777777777772" x:Left="0.74791666666666667"
x:Right="0.74791666666666667" x:Top="0.98402777777777772"/>
</PageSetup>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>9</PaperSizeIndex>
<HorizontalResolution>300</HorizontalResolution>
<VerticalResolution>300</VerticalResolution>
</Print>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>11</ActiveRow>
<RangeSelection>R12C1:R12C256</RangeSelection>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
<EnableSelection>NoSelection</EnableSelection>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Dates">
<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="38" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="66">
<Column ss:StyleID="s17" ss:AutoFitWidth="0" ss:Width="108.75"/>
<Column ss:StyleID="s17" ss:AutoFitWidth="0" ss:Width="63.75"/>
<Column ss:AutoFitWidth="0" ss:Width="134.25"/>
<Column ss:AutoFitWidth="0" ss:Width="104.25"/>
<Row>
<Cell><Data ss:Type="DateTime">1905-09-12T00:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1905-09-12T00:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">midnight</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">Please use the A column for cells that will be read by fpspreadsheet</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">Do not modify or delete cells; it will mess up the tests</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">2013-11-24T00:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">2013-11-24T00:00:00.000</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s16"><Data ss:Type="String">You can use other cells for comments, intermediate calculations, etc</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">2030-12-31T00:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">2030-12-31T00:00:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1899-12-31T00:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">time only...</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1899-12-31T01:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T01:00:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1899-12-31T03:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T03:00:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1899-12-31T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1899-12-31T18:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T18:00:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1899-12-31T23:59:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortDateTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s24"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s25"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s26"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s27"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s28"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfDayMonth</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s29"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfMonthYear</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s33"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfFmtDateTime, ms</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortDateTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s24"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s25"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s26"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s27"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s28"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfDayMonth</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s29"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfMonthYear</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s30"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfFmtDateTime, ms</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortDateTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s24"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s25"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s26"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s27"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s28"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfDayMonth</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s29"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfMonthYear</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s30"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1899-12-31T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfFmtDateTime, ms</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s31"><Data ss:Type="DateTime">1899-12-31T03:45:12.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell><Data ss:Type="String">3 hours 45 mins 12 secs</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">formatted as nfTimeDuration</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s31"><Data ss:Type="DateTime">1900-01-01T03:45:12.000</Data></Cell>
<Cell ss:StyleID="s32"/>
<Cell><Data ss:Type="String">the same plus 1 day</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">formatted as nfTimeDuration</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.51180555555555551"/>
<Footer x:Margin="0.51180555555555551"/>
<PageMargins x:Bottom="0.98402777777777772" x:Left="0.74791666666666667"
x:Right="0.74791666666666667" x:Top="0.98402777777777772"/>
</PageSetup>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>9</PaperSizeIndex>
<HorizontalResolution>300</HorizontalResolution>
<VerticalResolution>300</VerticalResolution>
</Print>
<Selected/>
<TopRowVisible>9</TopRowVisible>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>35</ActiveRow>
<ActiveCol>4</ActiveCol>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
<EnableSelection>NoSelection</EnableSelection>
</WorksheetOptions>
</Worksheet>
</Workbook>

View File

@ -0,0 +1,580 @@
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>Pamler</Author>
<LastAuthor>Werner</LastAuthor>
<Created>2013-11-25T11:24:52Z</Created>
<LastSaved>2015-04-30T11:27:08Z</LastSaved>
<Version>16.00</Version>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>8190</WindowHeight>
<WindowWidth>16380</WindowWidth>
<WindowTopX>32767</WindowTopX>
<WindowTopY>32767</WindowTopY>
<TabRatio>500</TabRatio>
<Date1904/>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font ss:FontName="Verdana" x:Family="Swiss"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
<Style ss:ID="s16">
<NumberFormat ss:Format="Short Date"/>
</Style>
<Style ss:ID="s17">
<Font ss:FontName="Verdana" x:Family="Swiss" ss:Bold="1"/>
</Style>
<Style ss:ID="s18">
<NumberFormat ss:Format="hh:mm:ss"/>
</Style>
<Style ss:ID="s20">
<Font ss:FontName="Verdana" x:Family="Swiss" ss:Bold="1"/>
<NumberFormat ss:Format="Short Date"/>
</Style>
<Style ss:ID="s21">
<NumberFormat ss:Format="Percent"/>
</Style>
<Style ss:ID="s22">
<NumberFormat ss:Format="0%"/>
</Style>
<Style ss:ID="s23">
<NumberFormat ss:Format="#,##0"/>
</Style>
<Style ss:ID="s24">
<NumberFormat ss:Format="Standard"/>
</Style>
<Style ss:ID="s25">
<NumberFormat ss:Format="Scientific"/>
</Style>
<Style ss:ID="s26">
<NumberFormat ss:Format="h:mm;@"/>
</Style>
<Style ss:ID="s27">
<NumberFormat ss:Format="[$-F400]h:mm:ss\ AM/PM"/>
</Style>
<Style ss:ID="s28">
<NumberFormat ss:Format="[$-409]h:mm\ AM/PM;@"/>
</Style>
<Style ss:ID="s29">
<NumberFormat ss:Format="[$-409]h:mm:ss\ AM/PM;@"/>
</Style>
<Style ss:ID="s30">
<NumberFormat ss:Format="dd/\ mmm"/>
</Style>
<Style ss:ID="s31">
<NumberFormat ss:Format="mmm\ yy"/>
</Style>
<Style ss:ID="s32">
<NumberFormat ss:Format="mm:ss"/>
</Style>
<Style ss:ID="s33">
<NumberFormat ss:Format="[h]:mm:ss"/>
</Style>
<Style ss:ID="s34">
<NumberFormat ss:Format="d/m/yy\ h:mm;@"/>
</Style>
<Style ss:ID="s35">
<NumberFormat ss:Format="#,##0.00\ &quot;€&quot;"/>
</Style>
<Style ss:ID="s36">
<NumberFormat ss:Format="#,##0.00\ [$$-409]"/>
</Style>
<Style ss:ID="s37">
<NumberFormat ss:Format="[$$-409]#,##0.00;[Red]\-#,###.00\ [$$-409]"/>
</Style>
<Style ss:ID="s38">
<NumberFormat ss:Format="#,##0.00\ [$EUR];[Red]\(#,##0.00\ [$EUR]\)"/>
</Style>
<Style ss:ID="s39">
<NumberFormat ss:Format="yyyy\-mm\-dd\Thh:mm:ss"/>
</Style>
</Styles>
<Worksheet ss:Name="Numbers">
<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="23" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="54">
<Column ss:AutoFitWidth="0" ss:Width="105.75"/>
<Row>
<Cell><Data ss:Type="Number">-59000000</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s17"><Data ss:Type="String">Please use the A column for cells that will be read by fpspreadsheet</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-988</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s17"><Data ss:Type="String">Do not modify or delete cells; it will mess up the tests</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-124.23432</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s17"><Data ss:Type="String">You can use other cells for comments, intermediate calculations, etc</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-81.902850873027404</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-15</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">-2.934E-3</Data></Cell>
<Cell><Data ss:Type="String">minus small fraction</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">0</Data></Cell>
<Cell><Data ss:Type="String">minus zero</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">0</Data></Cell>
<Cell><Data ss:Type="String">zero</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">5.0000000000000001E-9</Data></Cell>
<Cell><Data ss:Type="String">small fraction</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">0.98239399999999999</Data></Cell>
<Cell><Data ss:Type="String">almost 1</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">3.14159265358979</Data></Cell>
<Cell><Data ss:Type="String">some parts of pi</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">59000000</Data></Cell>
<Cell><Data ss:Type="String">59 million</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="Number">59000000.100000001</Data></Cell>
<Cell><Data ss:Type="String">same + a tenth</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s22"><Data ss:Type="Number">0.35360000000000003</Data></Cell>
<Cell><Data ss:Type="String" x:Ticked="1">0.3536 formatted as percent with no decimal</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s21"><Data ss:Type="Number">0.35360000000000003</Data></Cell>
<Cell><Data ss:Type="String" x:Ticked="1">0.3536 formatted as percent with two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s23"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted with thousand separator, no decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s24"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted with thousand separator, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s25"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as &quot;exp&quot; with 2 decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s35"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted as EUROs, € at end, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s36"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted as DOLLARs, $ at end, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s35"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as EUROs, € at end, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s36"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as DOLLARs, $ at end, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s37"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as DOLLARs, $ at end, negative red, two decimals</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<PageMargins x:Bottom="0.984251969" x:Left="0.78740157499999996"
x:Right="0.78740157499999996" x:Top="0.984251969"/>
</PageSetup>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>9</PaperSizeIndex>
<HorizontalResolution>600</HorizontalResolution>
<VerticalResolution>600</VerticalResolution>
</Print>
<Selected/>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Texts">
<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="14" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="54">
<Column ss:AutoFitWidth="0" ss:Width="122.25"/>
<Row>
<Cell ss:Index="2"><Data ss:Type="String">nothing, empty text</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s17"><Data ss:Type="String">Please use the A column for cells that will be read by fpspreadsheet</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">a</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s17"><Data ss:Type="String">Do not modify or delete cells; it will mess up the tests</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String" x:Ticked="1">1</Data></Cell>
<Cell><Data ss:Type="String">a number</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s17"><Data ss:Type="String">You can use other cells for comments, intermediate calculations, etc</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">The quick brown fox jumps over the lazy dog</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">café au lait</Data></Cell>
<Cell><Data ss:Type="String">accent aigue on the e</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">водка</Data></Cell>
<Cell><Data ss:Type="String">Cyrillic</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">wódka</Data></Cell>
<Cell><Data ss:Type="String">Polish o accent aigue</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s22"><Data ss:Type="Number">0.35360000000000003</Data></Cell>
<Cell><Data ss:Type="String" x:Ticked="1">0.3536 formatted as percent with no decimal</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s21"><Data ss:Type="Number">0.35360000000000003</Data></Cell>
<Cell><Data ss:Type="String" x:Ticked="1">0.3536 formatted as percent with two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s23"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted with thousand separator, no decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s24"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted with thousand separator, two decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s25"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as &quot;exp&quot; with 2 decimals</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s38"><Data ss:Type="Number">59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">59 million + 0.1234, formatted as &quot;currencyRed&quot; with 2 decimals, brackets and EUR</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s38"><Data ss:Type="Number">-59000000.123400003</Data></Cell>
<Cell><Data ss:Type="String">minus 59 million + 0.1234, formatted as &quot;currencyRed&quot; with 2 decimals, brackets and EUR</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<PageMargins x:Bottom="0.984251969" x:Left="0.78740157499999996"
x:Right="0.78740157499999996" x:Top="0.984251969"/>
</PageSetup>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>9</PaperSizeIndex>
<HorizontalResolution>600</HorizontalResolution>
<VerticalResolution>600</VerticalResolution>
</Print>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Dates">
<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="40" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="66">
<Column ss:StyleID="s16" ss:AutoFitWidth="0" ss:Width="100.5"/>
<Column ss:StyleID="s16" ss:AutoFitWidth="0"/>
<Column ss:AutoFitWidth="0" ss:Width="127.5"/>
<Column ss:AutoFitWidth="0" ss:Width="104.25"/>
<Row>
<Cell><Data ss:Type="DateTime">1905-09-12T00:00:00.000</Data></Cell>
<Cell ss:StyleID="Default"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1905-09-12T00:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">midnight</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">Please use the A column for cells that will be read by fpspreadsheet</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:StyleID="s20"/>
<Cell ss:StyleID="s39" ss:Formula="=RC[-2]"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">Do not modify or delete cells; it will mess up the tests</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">2013-11-24T00:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">2013-11-24T00:00:00.000</Data></Cell>
<Cell ss:Index="5" ss:StyleID="s17"><Data ss:Type="String">You can use other cells for comments, intermediate calculations, etc</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="DateTime">2030-12-31T00:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">2030-12-31T00:00:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1904-01-01T00:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">time only...</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1904-01-01T01:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T01:00:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1904-01-01T03:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T03:00:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1904-01-01T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1904-01-01T18:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T18:00:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1904-01-01T23:59:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:00.000</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s18"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s34"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortDateTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s26"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s27"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s28"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s29"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s30"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfDayMonth</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s31"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfMonthYear</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s32"><Data ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1908-09-12T12:00:00.000</Data></Cell>
<Cell><Data ss:Type="String">noon</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfFmtDateTime, ms</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s34"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortDateTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s26"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s27"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s28"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s29"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s30"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfDayMonth</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s31"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfMonthYear</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s32"><Data ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T00:00:01.000</Data></Cell>
<Cell><Data ss:Type="String">just after midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfFmtDateTime, ms</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s34"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortDateTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s26"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s27"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTime</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s28"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfShortTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s29"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfLongTimeAM</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s30"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfDayMonth</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s31"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfMonthYear</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s32"><Data ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell ss:Index="3" ss:StyleID="s39" ss:Formula="=RC[-2]"><Data
ss:Type="DateTime">1904-01-01T23:59:59.000</Data></Cell>
<Cell><Data ss:Type="String">almost midnight</Data></Cell>
<Cell><Data ss:Type="String">formatted as nfFmtDateTime, ms</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s33"><Data ss:Type="DateTime">1904-01-01T03:45:12.000</Data></Cell>
<Cell ss:Index="3"><Data ss:Type="String">3 hours 45 mins 12 secs</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">formatted as nfTimeDuration</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s33"><Data ss:Type="DateTime">1904-01-02T03:45:12.000</Data></Cell>
<Cell ss:Index="3"><Data ss:Type="String">the same plus 1 day</Data></Cell>
<Cell ss:Index="5"><Data ss:Type="String">formatted as nfTimeDuration</Data></Cell>
</Row>
<Row ss:Index="40">
<Cell ss:StyleID="s33"/>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.51180555555555551"/>
<Footer x:Margin="0.51180555555555551"/>
<PageMargins x:Bottom="0.98402777777777772" x:Left="0.74791666666666667"
x:Right="0.74791666666666667" x:Top="0.98402777777777772"/>
</PageSetup>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>9</PaperSizeIndex>
<HorizontalResolution>300</HorizontalResolution>
<VerticalResolution>300</VerticalResolution>
</Print>
<TopRowVisible>6</TopRowVisible>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>19</ActiveRow>
<ActiveCol>4</ActiveCol>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
<EnableSelection>NoSelection</EnableSelection>
</WorksheetOptions>
</Worksheet>
</Workbook>

View File

@ -0,0 +1,195 @@
unit virtualmodetests;
{ Tests for VirtualMode }
{$mode objfpc}{$H+}
interface
uses
// Not using lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testutils, testregistry,
fpstypes, fpsallformats, fpspreadsheet, xlsbiff8 {and a project requirement for lclbase for utf8 handling},
fpsutils, testsutility;
type
{ TSpreadVirtualModeTests }
TSpreadVirtualModeTests= class(TTestCase)
private
procedure WriteVirtualCellDataHandler(Sender: TsWorksheet; ARow, ACol: Cardinal;
var AValue:Variant; var AStyleCell: PCell);
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
procedure TestWriteVirtualMode(AFormat: TsSpreadsheetFormat; ABufStreamMode: Boolean);
published
// Virtual mode tests for all file formats
procedure TestWriteVirtualMode_BIFF2;
procedure TestWriteVirtualMode_BIFF5;
procedure TestWriteVirtualMode_BIFF8;
procedure TestWriteVirtualMode_ODS;
procedure TestWriteVirtualMode_OOXML;
procedure TestWriteVirtualMode_XML;
procedure TestWriteVirtualMode_BIFF2_BufStream;
procedure TestWriteVirtualMode_BIFF5_BufStream;
procedure TestWriteVirtualMode_BIFF8_BufStream;
procedure TestWriteVirtualMode_ODS_BufStream;
procedure TestWriteVirtualMode_OOXML_BufStream;
procedure TestWriteVirtualMode_XML_BufStream;
end;
implementation
uses
numberstests, stringtests;
const
VIRTUALMODE_SHEET = 'VirtualMode'; //worksheet name
procedure TSpreadVirtualModeTests.SetUp;
begin
end;
procedure TSpreadVirtualModeTests.TearDown;
begin
end;
procedure TSpreadVirtualModeTests.WriteVirtualCellDataHandler(Sender: TsWorksheet;
ARow, ACol: Cardinal; var AValue:Variant; var AStyleCell: PCell);
begin
Unused(ACol);
Unused(AStyleCell);
// First read the SollNumbers, then the first 4 SollStrings
// See comment in TestVirtualMode().
if ARow < Length(SollNumbers) then
AValue := SollNumbers[ARow]
else
AValue := SollStrings[ARow - Length(SollNumbers)];
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode(AFormat: TsSpreadsheetFormat;
ABufStreamMode: Boolean);
var
tempFile: String;
workbook: TsWorkbook;
worksheet: TsWorksheet;
row, col: Integer;
value: Double;
s: String;
begin
try
workbook := TsWorkbook.Create;
try
worksheet := workbook.AddWorksheet(VIRTUALMODE_SHEET);
workbook.Options := workbook.Options + [boVirtualMode];
if ABufStreamMode then
workbook.Options := workbook.Options + [boBufStream];
worksheet.VirtualColCount := 1;
worksheet.VirtualRowCount := Length(SollNumbers) + 4;
// We'll use only the first 4 SollStrings, the others cause trouble due to utf8 and formatting.
worksheet.OnWriteCellData := @WriteVirtualCellDataHandler;
tempFile:=NewTempFile;
workbook.WriteToFile(tempfile, AFormat, true);
finally
workbook.Free;
end;
workbook := TsWorkbook.Create;
try
workbook.ReadFromFile(tempFile, AFormat);
worksheet := workbook.GetWorksheetByIndex(0);
col := 0;
CheckEquals(Length(SollNumbers) + 4, worksheet.GetLastRowIndex+1,
'Row count mismatch');
for row := 0 to Length(SollNumbers)-1 do
begin
value := worksheet.ReadAsNumber(row, col);
CheckEquals(SollNumbers[row], value,
'Test number value mismatch, cell '+CellNotation(workSheet, row, col))
end;
for row := Length(SollNumbers) to worksheet.GetLastRowIndex do
begin
s := worksheet.ReadAsText(row, col);
CheckEquals(SollStrings[row - Length(SollNumbers)], s,
'Test string value mismatch, cell '+CellNotation(workSheet, row, col));
end;
finally
workbook.Free;
end;
finally
DeleteFile(tempFile);
end;
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_BIFF2;
begin
TestWriteVirtualMode(sfExcel2, false);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_BIFF5;
begin
TestWriteVirtualMode(sfExcel5, false);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_BIFF8;
begin
TestWriteVirtualMode(sfExcel8, false);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_ODS;
begin
TestWriteVirtualMode(sfOpenDocument, false);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_OOXML;
begin
TestWriteVirtualMode(sfOOXML, false);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_XML;
begin
TestWriteVirtualMode(sfExcelXML, false);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_BIFF2_BufStream;
begin
TestWriteVirtualMode(sfExcel2, True);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_BIFF5_BufStream;
begin
TestWriteVirtualMode(sfExcel5, true);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_BIFF8_BufStream;
begin
TestWriteVirtualMode(sfExcel8, true);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_ODS_BufStream;
begin
TestWriteVirtualMode(sfOpenDocument, true);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_OOXML_BufStream;
begin
TestWriteVirtualMode(sfOOXML, true);
end;
procedure TSpreadVirtualModeTests.TestWriteVirtualMode_XML_BufStream;
begin
TestWriteVirtualMode(sfExcelXML, true);
end;
initialization
// Register so these tests are included in a full run
RegisterTest(TSpreadVirtualModeTests);
end.