You've already forked lazarus-ccr
LazStats: Extract and add some general purpose grid-related routines to the new unit GridProcs.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7738 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -122,7 +122,7 @@
|
||||
<PackageName Value="LCL"/>
|
||||
</Item7>
|
||||
</RequiredPackages>
|
||||
<Units Count="180">
|
||||
<Units Count="181">
|
||||
<Unit0>
|
||||
<Filename Value="LazStats.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
@ -1534,6 +1534,11 @@
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="BasicStatsReportAndChartFormUnit"/>
|
||||
</Unit179>
|
||||
<Unit180>
|
||||
<Filename Value="units\gridprocs.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="GridProcs"/>
|
||||
</Unit180>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@ -8,7 +8,7 @@ uses
|
||||
{$ENDIF}{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms, tachartlazaruspkg, tachartprint, lhelpcontrolpkg, Globals, LicenseUnit,
|
||||
OptionsUnit, MainDM, MainUnit;
|
||||
OptionsUnit, MainDM, MainUnit, GridProcs;
|
||||
|
||||
{$R LazStats.res}
|
||||
|
||||
|
@ -65,7 +65,7 @@ implementation
|
||||
|
||||
uses
|
||||
Math, Grids,
|
||||
Utils, DictionaryUnit;
|
||||
Utils, DictionaryUnit, GridProcs;
|
||||
|
||||
|
||||
{ TCrossTabCalculator }
|
||||
@ -232,13 +232,13 @@ begin
|
||||
for i := 1 to no_in_list do
|
||||
begin
|
||||
j := FVarList[i-1];
|
||||
if not GoodRecord(FDataGrid, 1, NoSelected, FColNoSelected) then continue;
|
||||
if not GoodRecord(FDataGrid, 1, FColNoSelected) then continue;
|
||||
value := StrToFloat(FDataGrid.Cells[j, 1]);
|
||||
min_value[i-1] := round(value);
|
||||
max_value[i-1] := round(value);
|
||||
for k := 2 to NoCases do
|
||||
begin
|
||||
if not GoodRecord(FDataGrid, k, NoSelected, FColNoSelected) then continue;
|
||||
if not GoodRecord(FDataGrid, k, FColNoSelected) then continue;
|
||||
value := StrToFloat(FDataGrid.Cells[j, k]);
|
||||
if value < min_value[i-1] then
|
||||
min_value[i-1] := round(value);
|
||||
@ -292,11 +292,11 @@ begin
|
||||
freq[i] := 0;
|
||||
for i := 1 to NoCases do
|
||||
begin
|
||||
if IsFiltered(i) then
|
||||
if IsFiltered(FDataGrid, i) then
|
||||
continue;
|
||||
for j := 1 to no_in_list do
|
||||
begin
|
||||
if not GoodRecord(i, NoSelected, FColNoSelected) then continue;
|
||||
if not GoodRecord(FDataGrid, i, FColNoSelected) then continue;
|
||||
k := FVarList[j-1];
|
||||
value := StrToFloat(FDataGrid.Cells[k,i]);
|
||||
x := round(value);
|
||||
@ -453,6 +453,9 @@ var
|
||||
noSelected: Integer;
|
||||
cellValue: String;
|
||||
begin
|
||||
AVarList := nil; // Silence the compiler
|
||||
AColNoSelected := nil;
|
||||
|
||||
SetLength(AVarList, SelList.Count);
|
||||
SetLength(AColNoSelected, SelList.Count);
|
||||
|
||||
|
@ -7,10 +7,11 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
|
||||
StdCtrls, ExtCtrls, Clipbrd, Grids,
|
||||
Globals, OptionsUnit, DictionaryUnit;
|
||||
Globals, OptionsUnit, DictionaryUnit, GridProcs;
|
||||
|
||||
Function GoodRecord(Row, NoVars: integer; const GridPos: IntDyneVec): boolean; overload;
|
||||
Function GoodRecord(AGrid: TStringGrid; Row, NoVars: integer; const GridPos: IntDyneVec): boolean; overload;
|
||||
function GoodRecord(Row, NoVars: integer; const GridPos: IntDyneVec): boolean;
|
||||
function IsFiltered(GridRow: integer): boolean; overload;
|
||||
function ValidValue(row, col: integer): boolean;
|
||||
|
||||
procedure FormatCell(Col, Row : integer);
|
||||
procedure FormatGrid;
|
||||
@ -29,10 +30,6 @@ procedure CopyRow;
|
||||
procedure PasteRow;
|
||||
procedure PrintDict(AReport: TStrings);
|
||||
procedure PrintData(AReport: TStrings);
|
||||
function ValidValue(row, col: integer): boolean; overload;
|
||||
function ValidValue(AGrid: TStringGrid; row, col: integer): boolean; overload;
|
||||
function IsFiltered(GridRow: integer): boolean; overload;
|
||||
function IsFiltered(AGrid: TStringGrid; GridRow: integer): boolean; overload;
|
||||
|
||||
procedure MatRead(const a: DblDyneMat; out NoRows, NoCols: integer;
|
||||
const Means, StdDevs: DblDyneVec; out NCases: integer;
|
||||
@ -66,25 +63,21 @@ implementation
|
||||
uses
|
||||
Utils, MainUnit;
|
||||
|
||||
function GoodRecord(Row, NoVars: Integer; const GridPos: IntDyneVec): boolean;
|
||||
begin
|
||||
Result := GoodRecord(OS3MainFrm.DataGrid, Row, NoVars, GridPos);
|
||||
end;
|
||||
|
||||
function GoodRecord(AGrid: TStringGrid; Row, NoVars: integer;
|
||||
const GridPos: IntDyneVec): boolean;
|
||||
// NOTE: Do not call GridProcs.GoodRecord here because this old function may
|
||||
// use an over-dimensioned GridPos array.
|
||||
function GoodRecord(Row, NoVars: Integer; const GridPos: IntDyneVec): boolean;
|
||||
var
|
||||
i, j: integer;
|
||||
begin
|
||||
Result := true;
|
||||
for i := 0 to NoVars-1 do
|
||||
for i := 0 to NoVars - 1 do
|
||||
begin
|
||||
j := GridPos[i];
|
||||
if not ValidValue(AGrid, Row, j) then
|
||||
if not ValidValue(Row, j) then
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
procedure FormatCell(Col, Row: integer);
|
||||
var
|
||||
@ -802,33 +795,7 @@ end;
|
||||
|
||||
function ValidValue(row, col: Integer): Boolean;
|
||||
begin
|
||||
Result := ValidValue(OS3MainFrm.DataGrid, row, col);
|
||||
end;
|
||||
|
||||
function ValidValue(AGrid: TStringGrid; row, col: integer): boolean;
|
||||
var
|
||||
valid: boolean;
|
||||
xvalue: string;
|
||||
cellstring: string;
|
||||
begin
|
||||
valid := true;
|
||||
if FilterOn then
|
||||
begin
|
||||
cellstring := Trim(AGrid.Cells[FilterCol, row]);
|
||||
if cellstring = 'NO' then valid := false;
|
||||
Result := valid;
|
||||
exit;
|
||||
end;
|
||||
|
||||
xvalue := Trim(AGrid.Cells[col,row]);
|
||||
if (xvalue = '') and (DictionaryFrm.DictGrid.Cells[4, col] <> 'S') then
|
||||
valid := false;
|
||||
if valid then // check for user-defined missing value
|
||||
begin
|
||||
if Trim(DictionaryFrm.DictGrid.Cells[6, col]) = xvalue then
|
||||
valid := false;
|
||||
end;
|
||||
Result := valid;
|
||||
Result := GridProcs.ValidValue(OS3MainFrm.DataGrid, row, col);
|
||||
end;
|
||||
|
||||
function IsFiltered(GridRow: Integer): Boolean;
|
||||
@ -836,12 +803,6 @@ begin
|
||||
Result := IsFiltered(OS3MainFrm.DataGrid, GridRow);
|
||||
end;
|
||||
|
||||
function IsFiltered(AGrid: TStringGrid; GridRow: integer): boolean;
|
||||
begin
|
||||
Result := FilterOn and (Trim(AGrid.Cells[FilterCol,GridRow]) = 'NO');
|
||||
end;
|
||||
|
||||
|
||||
procedure MatRead(const a: DblDyneMat; out NoRows, NoCols: integer;
|
||||
const means, stddevs: DblDyneVec; out NCases: integer;
|
||||
const RowLabels, ColLabels: StrDyneVec; const AFileName: string);
|
||||
|
157
applications/lazstats/source/units/gridprocs.pas
Normal file
157
applications/lazstats/source/units/gridprocs.pas
Normal file
@ -0,0 +1,157 @@
|
||||
unit GridProcs;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Grids,
|
||||
Globals, DictionaryUnit;
|
||||
|
||||
function CollectValues(AGrid: TStringGrid; AColIndex: Integer;
|
||||
AColCheck: IntDyneVec): DblDyneVec;
|
||||
|
||||
procedure GetMinMax(AGrid: TStringGrid; AColIndex: Integer;
|
||||
const AColCheck: IntDyneVec; out AMin, AMax: Double);
|
||||
|
||||
function GoodRecord(AGrid: TStringGrid; ARow: integer;
|
||||
const AColCheck: IntDyneVec): boolean;
|
||||
|
||||
function IsEmptyNumericValue(AGrid: TStringGrid; ARow, ACol: Integer): Boolean;
|
||||
|
||||
function IsFiltered(AGrid: TStringGrid; ARow: integer): boolean;
|
||||
|
||||
function IsMissingValueCode(AGrid: TStringGrid; ARow, ACol: Integer): Boolean;
|
||||
|
||||
function ValidValue(AGrid: TStringGrid; ARow, ACol: integer): boolean;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Math;
|
||||
|
||||
{ Extracts the values in the given column from the grid and returns them as an
|
||||
array.
|
||||
Cells which are filtered or empty are not considered. This check is extended
|
||||
over all columns specified by the column indices in AColCheck; AColCheck
|
||||
should be empty to consider only the current column.
|
||||
Non-numeric values in the considered cell will raise an exception.
|
||||
|
||||
NOTE: AColCheck must not be overdimensioned! }
|
||||
function CollectValues(AGrid: TStringGrid; AColIndex: Integer; AColCheck: IntDyneVec): DblDyneVec;
|
||||
var
|
||||
row, n: Integer;
|
||||
begin
|
||||
SetLength(Result, AGrid.RowCount);
|
||||
n := 0;
|
||||
for row := 1 to AGrid.RowCount-1 do
|
||||
begin
|
||||
if Length(AColCheck) = 0 then
|
||||
begin
|
||||
if not ValidValue(AGrid, row, AColIndex) then continue;
|
||||
end else
|
||||
begin
|
||||
if not GoodRecord(AGrid, row, AColCheck) then continue;
|
||||
end;
|
||||
Result[n] := StrToFloat(trim(AGrid.Cells[AColIndex, row]));
|
||||
inc(n);
|
||||
end;
|
||||
SetLength(Result, n);
|
||||
end;
|
||||
|
||||
|
||||
{ Determines the minimum and maximum of the values in the specified column of
|
||||
the grid. Rows with "invalid" data are ignored. If AColCheck contains other
|
||||
column indices these cells must be "valid", too. }
|
||||
procedure GetMinMax(AGrid: TStringGrid; AColIndex: Integer;
|
||||
const AColCheck: IntDyneVec; out AMin, AMax: Double);
|
||||
var
|
||||
row: Integer;
|
||||
value: Double;
|
||||
begin
|
||||
AMin := Infinity;
|
||||
AMax := -Infinity;
|
||||
for row := 1 to AGrid.RowCount-1 do
|
||||
begin
|
||||
if Length(AColCheck) = 0 then
|
||||
begin
|
||||
if not ValidValue(AGrid, row, AColIndex) then continue;
|
||||
end else
|
||||
begin
|
||||
if not GoodRecord(AGrid, row, AColCheck) then continue;
|
||||
end;
|
||||
value := StrToFloat(trim(AGrid.Cells[AColIndex, row]));
|
||||
if value < AMin then AMin := value;
|
||||
if value > AMax then AMax := value;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Checks whether all cells specified for the given row in the columns listed in
|
||||
the GridPos array are "valid": not filtered and not empty }
|
||||
function GoodRecord(AGrid: TStringGrid; ARow: integer;
|
||||
const AColCheck: IntDyneVec): boolean;
|
||||
var
|
||||
i, j: integer;
|
||||
begin
|
||||
Result := true;
|
||||
for i := 0 to High(AColCheck) do
|
||||
begin
|
||||
j := AColCheck[i];
|
||||
if not ValidValue(AGrid, ARow, j) then
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Checks whether the cell in the given row in the given numeric column is empty. }
|
||||
function IsEmptyNumericValue(AGrid: TStringGrid; ARow, ACol: Integer): Boolean;
|
||||
var
|
||||
value: String;
|
||||
isStringField: Boolean;
|
||||
begin
|
||||
value := Trim(AGrid.Cells[ACol, ARow]);
|
||||
isStringField := DictionaryFrm.DictGrid.Cells[4, ACol] = 'S';
|
||||
Result := not IsStringField and (value = '');
|
||||
end;
|
||||
|
||||
|
||||
{ Checks whether the specified row is "filtered". Two criteria are needed for
|
||||
a row to be filtered:
|
||||
- The cell in column FilterCol (global value) must contain the text 'NO'.
|
||||
- The global variable "FilterOn" must be TRUE. }
|
||||
function IsFiltered(AGrid: TStringGrid; ARow: integer): boolean;
|
||||
begin
|
||||
Result := FilterOn and (Trim(AGrid.Cells[FilterCol, ARow]) = 'NO');
|
||||
end;
|
||||
|
||||
|
||||
{ Checks whether specified cell contains the "missing value code" defined by
|
||||
the Dictionary }
|
||||
function IsMissingValueCode(AGrid: TStringGrid; ARow, ACol: Integer): Boolean;
|
||||
var
|
||||
missingCode: String;
|
||||
value: String;
|
||||
begin
|
||||
missingCode := Trim(DictionaryFrm.DictGrid.Cells[6, ACol]);
|
||||
value := Trim(AGrid.Cells[ACol, ARow]);
|
||||
Result := (value = missingCode);
|
||||
end;
|
||||
|
||||
|
||||
{ Checks wheter the value in cell at the given column and row is a not-filtered,
|
||||
non-empty number.
|
||||
NOTE: non-numeric characters in a numeric field are not taken into account! }
|
||||
function ValidValue(AGrid: TStringGrid; ARow, ACol: integer): boolean;
|
||||
begin
|
||||
Result := not (
|
||||
IsFiltered(AGrid, ARow) or // filtering is active and row is marked to be excluded
|
||||
IsEmptyNumericValue(AGrid, ARow, aCol) or // column is numeric, but cell is empty
|
||||
IsMissingValueCode(AGrid, ARow, ACol) // cell contains the "missing value code"
|
||||
);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
Reference in New Issue
Block a user