Error using datetime parameter on firedac stored procedure component - delphi

I have a FDStored procedure that has a datetime parameter:
create procedure [dbo].[p_gl_for_ap]
(#inMode char(1), --I=Invoice, C=Check
#inId_Invoice integer, --reqd for invoice or credit memo maintenance, I
#inReg char(3), --reqd for check update or void, C
#inCheckNo integer, --reqd for check update or void, C
#inIs_Reversal char, --Y only if Invoice Delete or Check Void
#inDt_Rev datetime, --reqd only for reversal
#inDt datetime, --optl G/L tran date; normally null
#inId_glsrcjrn varchar(10),
#inId_create integer,
#ret integer output)
AS
declare....
and I have a FDStoredProc component using the stored procedure:
(following is from component to code)
var
spGLForAP: TFDStoredProc;
spGLForAP := TFDStoredProc.Create(Self);
spGLForAP.Name := 'spGLForAP';
spGLForAP.Connection := dmConnect.cnxData;
with spGLForAP.FormatOptions.MapRules.Add do begin
SourceDataType := dtDateTime;
TargetDataType := dtDateTimeStamp;
end;
spGLForAP.StoredProcName := 'p_gl_for_ap';
with spGLForAP.ParamData.Add do begin
Position := 1;
Name := 'RESULT';
DataType := ftInteger;
ParamType := ptResult;
end;
with spGLForAP.ParamData.Add do begin
Position := 2;
Name := 'inMode';
DataType := ftFixedChar;
ParamType := ptInput;
Size := 1;
end;
with spGLForAP.ParamData.Add do begin
Position := 3;
Name := 'inId_Invoice';
DataType := ftInteger;
ParamType := ptInput;
end;
with spGLForAP.ParamData.Add do begin
Position := 4;
Name := 'inReg';
DataType := ftFixedChar;
ParamType := ptInput;
Size := 3;
end;
with spGLForAP.ParamData.Add do begin
Position := 5;
Name := 'inCheckNo';
DataType := ftInteger;
ParamType := ptInput;
end;
with spGLForAP.ParamData.Add do begin
Position := 6;
Name := 'inIs_Reversal';
DataType := ftFixedChar;
ParamType := ptInput;
Size := 1;
end;
with spGLForAP.ParamData.Add do begin
Position := 7;
Name := 'inDt_Rev';
DataType := ftDateTime;
FDDataType := dtDateTimeStamp;
NumericScale := 3;
ParamType := ptInput;
end;
with spGLForAP.ParamData.Add do begin
Position := 8;
Name := 'inDt';
DataType := ftDateTime;
FDDataType := dtDateTimeStamp;
NumericScale := 3;
ParamType := ptInput;
end;
with spGLForAP.ParamData.Add do begin
Position := 9;
Name := 'inId_glsrcjrn';
DataType := ftString;
ParamType := ptInput;
Size := 10;
end;
with spGLForAP.ParamData.Add do begin
Position := 10;
Name := 'inId_create';
DataType := ftInteger;
ParamType := ptInput;
end;
with spGLForAP.ParamData.Add do begin
Position := 11;
Name := 'ret';
DataType := ftInteger;
ParamType := ptInputOutput;
end;
I am initializing with this code:
function tdmAP.DoGLForAP(whichInvoice: integer; hasDelete: Boolean):
integer;
begin
spGLForAP.Params.ClearValues;
spGLForAP.ParamByName('inMode').AsString := 'I';
spGLForAP.ParamByName('inId_Invoice').AsInteger := whichInvoice;
spGLForAP.ParamByName('inReg').AsString := '';
spGLForAP.ParamByName('inCheckNo').AsInteger := 0;
if hasDelete then
begin
spGLForAP.ParamByName('inIs_Reversal').AsString := 'Y';
spGLForAP.ParamByName('indt_Rev').value := Date;
end
else
begin
spGLForAP.ParamByName('inIs_Reversal').AsString := 'N';
spGLForAP.ParamByName('indt_Rev').AsDateTime := Date;
end;
spGLForAP.ParamByName('indt').AsDateTime := Date;
spGLForAP.ParamByName('inId_glsrcjrn').AsString := '';
spGLForAP.ParamByName('inId_create').AsInteger := LoginRec.LoginUserId;;
try
spGLForAP.Prepare;
spGLForAP.Execute;
Result := spGLForAP.ParamByName('ret').AsInteger;
except
on E:Exception do
begin
ShowMessage('Error executing stored procedure p_gl_for_ap: ' + e.Message);
result := -1;
end;
end;
end;
but I keep getting error back from firedac complaining about the parameter type changing:
error on execute
I have tried using the datatype mapping.
I have tried using this code:
spGLForAP.ParamByName('indt_Rev').value = 0;
and
spGLForAP.ParamByName('indt_Rev').AsDateTime := Date;
and
spGLForAP.ParamByName('indt_Rev').AsDateTime := now;
I have also tried changing the datatypes on the two date parameters from ftTimeStamp to ftDateTime, repreparing the query after setting the parameters types, and just about anything else I can think of. obviously, I'm missing something...
using Delphi 10.2.2 Tokyo, against mssql server 2008R2.
note: in this particular case, I'm trying to set the inDt_rev and inDt to 0. but can't seem to successfully set them to any value.

Try to change this part of your code:
with spGLForAP.ParamData.Add do begin
Position := 7;
Name := 'inDt_Rev';
DataType := ftDateTime;
FDDataType := dtDateTimeStamp;
NumericScale := 3;
ParamType := ptInput;
end;
with spGLForAP.ParamData.Add do begin
Position := 8;
Name := 'inDt';
DataType := ftDateTime;
FDDataType := dtDateTimeStamp;
NumericScale := 3;
ParamType := ptInput;
end;
to this one:
with spGLForAP.Params.Add do begin
Name := '#inDt_Rev';
DataType := ftTimeStamp;
ParamType := ptInput;
end;
with spGLForAP.Params.Add do begin
Name := '#inDt';
DataType := ftTimeStamp;
ParamType := ptInput;
end;
and use Value property instead of .AsDateTime accessor like:
spGLForAP.Params.ParamByName('#inDt').Value := Now;
or use AsSQLTimeStamp accessor:
// uses Data.SqlTimSt;
spGLForAP.Params.ParamByName('#inDt').AsSQLTimeStamp := DateTimeToSQLTimeStamp(Now);
because FireDAC maps such parameter as dtDateTimeStamp type (for which is the AsSQLTimeStamp accessor for).

You can create a custom data type mapping rule:
http://docwiki.embarcadero.com/RADStudio/XE5/en/Data_Type_Mapping_(FireDAC)
And map dtTimeStamp into dtDateTime.
// --------------------------- MAP RULES ------------------------- \\
with dm6.fdDB.FormatOptions do begin
OwnMapRules := True;
with MapRules.Add do begin
SourceDataType := dtDateTimeStamp;
TargetDataType := dtDateTime;
end;
end;

Related

Delphi IBX to Firedac Migration For Firebird

I migrated an IBX application which have 500+ forms to Firedac. I mapped the datatypes with Delphi Help. Here is my data mapping:
with ADB.FormatOptions do
begin
OwnMapRules := True;
DefaultParamDataType := ftVariant;
MapRules.Clear;
with MapRules.Add do
begin
PrecMax := 4;
PrecMin := 0;
ScaleMax := 0;
ScaleMin := 0;
SourceDataType := dtFmtBCD;
TargetDataType := dtInt16;
end;
with MapRules.Add do
begin
PrecMax := 10;
PrecMin := 5;
ScaleMax := 0;
ScaleMin := 0;
SourceDataType := dtFmtBCD;
TargetDataType := dtInt32;
end;
with MapRules.Add do
begin
PrecMax := 18;
PrecMin := 11;
ScaleMax := 0;
ScaleMin := 0;
SourceDataType := dtFmtBCD;
TargetDataType := dtInt64;
end;
with MapRules.Add do
begin
SourceDataType := dtFmtBCD;
TargetDataType := dtDouble;
end;
with MapRules.Add do
begin
SourceDataType := dtDateTimeStamp;
TargetDataType := dtDateTime;
end;
end;
Is this mapping is true? If it's false, how do I it's true?
When a FDQuery has parameters and a parameter has no value on execute the query,an exception occured :
[FireDAC][Phys][FB]-338. Param [XXX] type changed from [ftVariant] to [ftInteger]. Query must be reprepared. Possible reason: an assignment to a TFDParam.AsXXX property implicitly changed the parameter data type. Hint: use the TFDParam.Value or appropriate TFDParam.AsXXX property
How do I solve this problem? Thanks for everything.
I solved my problem by using the mapping below:
with ADB.FormatOptions do
begin
OwnMapRules := True;
with MapRules.Add do
begin
SourceDataType := dtDateTimeStamp;
TargetDataType := dtDateTime;
end;
with MapRules.Add do
begin
SourceDataType := dtDateTime;
TargetDataType := dtDateTimeStamp;
end;
end;
After than I build my application and test it. The Result is OK for me.

qrDBRichview whitout paragraph format and font format

I save my DBrichView( formatted justified) in a database and I need print in the quickreport.
I using "TRichView wrapper (RVQRControls) v3.0 for QuickReport", tQrDBRichview, but it isn't show the text formatted and also show with different font.
var
sds1: TSQLDataSet;
dsp1: TDataSetProvider;
cds1: TClientDataSet;
qrp1: TQuickRep;
qrbDetailBand1: TQRBand;
qrDBRvw1: TQRDBRichView;
...
with sds1 do
begin
CommandText :=
'select a.id_anot, a.text, a.cod_user from anot a where a.id_ANOT = 1977';
end;
with dsp1 do
begin
Name := 'dsp1';
DataSet := sds1;
end;
with cds1 do
begin
Name := 'cds1';
ProviderName := 'dsp1';
end;
with qrp1 do
begin
Name := 'qrp1';
DataSet := cds1;
end;
with qrbDetailBand1 do
begin
Name := 'qrbDetailBand1';
Parent := qrp1;
BandType := rbDetail;
end;
with qrDBRvw1 do
begin
Name := 'qrDBRvw1';
Parent := qrbDetailBand1;
NoMargins := True;
DataField := 'TEXTO';
DataSet := cds1;
end;
...
How I resolve this?

Draw TPanel and TSplitter at runtime results in wrong component order

If I create multiple TPanel and TSplitter components at runtime into a TScrollBox, the order of the components is wrong. If I call drawInput() 3 times, the scrollbox contains 3 panels followed by 3 splitters instead of 1 panel followed by 1 splitter (repeated).
How can I force the correct order?
Here is a screenshot
function drawInput(owner: TWinControl): TWinControl;
var
panel: TPanel;
edit: TEdit;
splitter: TSplitter;
begin
panel := TPanel.Create(owner);
panel.Parent := owner;
panel.Align := alTop;
panel.AlignWithMargins := True;
panel.BorderWidth := 0;
panel.Color := clRed;
panel.BorderStyle := bsNone;
panel.ParentBackground := False;
panel.Ctl3D := False;
edit := TEdit.Create(panel);
edit.Parent := panel;
edit.Align := alTop;
edit.AlignWithMargins := True;
edit.Text := 'foo';
edit.Margins.Left := 5;
edit.Margins.top := 5;
edit.Margins.Bottom := 5;
edit.Margins.Right := 5;
splitter := TSplitter.Create(owner);
splitter.Parent := owner;
splitter.Align := alTop;
splitter.Beveled := True;
splitter.Height := 3;
end;
EDIT:
Here is how I call this function:
procedure TForm2.Button1Click(Sender: TObject);
var
form: TForm;
sb: TScrollBox;
begin
form := TForm.Create(Application);
sb := TScrollBox.Create(form);
sb.Parent := form;
sb.Align := alClient;
sb.Color := clBlack;
drawInput(sb);
drawInput(sb);
drawInput(sb);
drawInput(sb);
form.Width := 300;
form.Height := 700;
form.ShowModal;
end;
Position your panel + splitter then set the alignment
You can position you panel below all other components by aligning it to the client
function drawInput(owner: TWinControl): TWinControl;
var
panel: TPanel;
edit: TEdit;
splitter: TSplitter;
begin
panel := TPanel.Create(owner);
panel.Parent := owner;
///
panel.Align := alclient;
///
panel.Align := alTop;
panel.AlignWithMargins := True;
panel.BorderWidth := 0;
panel.Color := clRed;
panel.BorderStyle := bsNone;
panel.ParentBackground := False;
panel.Ctl3D := False;
splitter := TSplitter.Create(owner);
splitter.Parent := owner;
//
splitter.top := panel.top+panel.height;
//
splitter.Align := alTop;
splitter.Beveled := True;
splitter.Height := 3;
end;
Delphi's alignment logic can be hard at times. But the following works. Note the line splitter.Top := -1;
function drawInput(owner: TWinControl): TWinControl;
var
panel: TPanel;
edit: TEdit;
splitter: TSplitter;
begin
splitter := TSplitter.Create(owner);
splitter.Parent := owner;
splitter.Align := alTop;
splitter.Beveled := True;
splitter.Height := 3;
splitter.Top := -1;
panel := TPanel.Create(owner);
panel.Parent := owner;
panel.Align := alTop;
panel.AlignWithMargins := True;
panel.BorderWidth := 0;
panel.Color := clRed;
panel.BorderStyle := bsNone;
panel.ParentBackground := False;
panel.Ctl3D := False;
edit := TEdit.Create(panel);
edit.Parent := panel;
edit.Align := alTop;
edit.AlignWithMargins := True;
edit.Text := 'foo';
edit.Margins.Left := 5;
edit.Margins.top := 5;
edit.Margins.Bottom := 5;
edit.Margins.Right := 5;
end;
Here's the code that works for me on XE5. I still have to solve my problem but at least I fixed yours :)
procedure drawInput(owner: TWinControl; var t: integer);
var
panel: TPanel;
edit: TEdit;
splitter: TSplitter;
begin
panel := TPanel.Create(owner);
panel.Parent := owner;
panel.Align := alTop;
panel.AlignWithMargins := True;
panel.BorderWidth := 0;
panel.Color := clRed;
panel.BorderStyle := bsNone;
panel.ParentBackground := False;
panel.Ctl3D := False;
panel.Top := t;
t := panel.Top + panel.Height + 1;
edit := TEdit.Create(panel);
edit.Parent := panel;
edit.Align := alTop;
edit.AlignWithMargins := True;
edit.Text := 'foo';
edit.Margins.Left := 5;
edit.Margins.top := 5;
edit.Margins.Bottom := 5;
edit.Margins.Right := 5;
splitter := TSplitter.Create(owner);
splitter.Parent := owner;
splitter.Align := alTop;
splitter.Beveled := True;
splitter.Height := 3;
splitter.Top := t;
t := splitter.Top + splitter.Height + 1;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
form: TForm;
sb: TScrollBox;
t: integer;
begin
form := TForm.Create(Application);
sb := TScrollBox.Create(form);
sb.Parent := form;
sb.Align := alClient;
sb.Color := clBlack;
t := 0;
drawInput(sb, t);
drawInput(sb, t);
drawInput(sb, t);
drawInput(sb, t);
form.Width := 300;
form.Height := 700;
form.ShowModal;
end;
In one of my applications, I have a function that creates a TImage and follows it with a TSplitter with the parent and containing control being a TScrollbox (sbScroller). The function is either called by the end user (tied to a TButton OnClick event) when they select an image or when the program starts it loads a previously loaded set of images each divided by a TSplitter.
It works when run alone by itself (creating one TImage + TSplitter pairing) or when run in a continuous loop to create multiple pairings. The key element in getting it to work seems to the positioning of the TSplitter.Top property as the previous answer says:
procedure AddImage(AFilename: string);
var
Image: TImage;
begin
Image := TImage.Create(sbScroller);
with Image do
begin
Image.Parent := sbScroller;
Left := 0;
Top := 0;
Width := 150;
Height := 150;
Constraints.MinHeight := 128;
Align := alTop;
Anchors := [akLeft, akTop, akRight];
Proportional := True;
Stretch := True;
Visible := True;
end;
if sbScroller.ControlCount > 0 then
with TSplitter.Create(sbScroller) do
begin
Parent := sbScroller;
Top := Image.Top;
Align := alTop;
Color := clGray;
end;
end;

Get component text based on component name

So I creat some TEdit components like this
var
lb : TLabel;
topLabel, i: Integer;
dbedit : TEdit;
begin
inherited;
topLabel := 40;
i := 0;
lb := TLabel.Create(nil);
lb.Parent := GroupBox2;
lb.Left := 245;
lb.Top := 20;
lb.Caption := 'ASD';
with DataModule.myStoredProc do begin
Close;
ParamByName('#Param1').AsInteger := 1;
ExecProc;
Open;
SetLength(nrPozitiiDinctionar,RecordCount);
First;
while not Eof do begin
lb := TLabel.Create(nil);
lb.Parent := GroupBox2;
lb.Left := 7;
lb.Top := topLabel ;
lb.Caption := FieldByName('X').AsString;
dbedit := TEdit.Create(nil);
dbedit.Name := 'Edit'+IntToStr(FieldByName('Poz').AsInteger);
dbedit.Text := '';
dbedit.Parent := GroupBox2;
dbedit.Height := 21;
dbedit.Width := 40;
dbedit.Left := 240;
dbedit.Top := lb.Top-3 ;
topLabel := topLabel + 30;
nrPozitiiDinctionar[i] := FieldByName('Poz').AsInteger;
i := i + 1;
Next;
end;
end;
end;
Then after the user add his input I run a function with this code
var
IDPoz, I : Integer;
dbedit : TEdit;
pctj,nume : string;
begin
for I := Low(nrPozitiiDinctionar) to High(nrPozitiiDinctionar) do
begin
nume := 'Edit'+IntToStr(nrPozitiiDinctionar[i]);
pctj := TEdit(FindComponent('Edit'+IntToStr(nrPozitiiDinctionar[i]))).Text;
with DateCOFurnizori.spCOFCmzFurnizoriEvaluarePozitii_Edit do begin
ParamByName('#IDEvaluare').AsInteger := StrToInt(Edit1.Text);
ParamByName('#IDPozitie').AsInteger := IDPoz;
ParamByName('#DictionarID').AsInteger := 9103;
ParamByName('#DictionarPozitiiID').AsInteger := nrPozitiiDinctionar[i];
ParamByName('#Punctaj').AsFloat := 1 ;//StrToFloat(pctj) ;
ParamByName('#DataEvaluare').AsDateTime := Now;
ExecProc;
IDPoz := IDPoz + 1;
end;
end;
This is only a portion of the code but this should relate to my problem.
When I use the debugger there is no value in pctj, what am I doing wrong? I try to get the value of the TEdits based on their names. What am I doing wrong with the FindComponent function?
You are not assigning an Owner to the TEdit controls, so that is why FindComponent() cannot find them. Either assign Self as the Owner (since you are calling Self.FindComponent()), or else store the TEdit pointers in a TList or TObjectList that you can loop through when needed.

Access violation at sql query in deserialization in Delphi

I wrote the following code by serialization and a deserialization of forms and their contents to Delphi
unit SerAndDeser;
interface
uses Classes,MainForm,ListOfTables,DataOfTable,SerialForms,sysutils,ActiveX, DatabaseClasses, UnloadProcs;
procedure Ser();
procedure Deser();
function GetGUID(): string;
function DeleteSymbols(inputstr : string) : string;
implementation
function GetGUID(): string;
var
GUID : TGUID;
begin
Result := '';
if CoCreateGuid(GUID) = 0 then
Result := GUIDToString(GUID);
Result := StringReplace(Result, '{', '', []);
Result := StringReplace(Result, '}', '', []);
Result := StringReplace(Result, '-', '', [rfReplaceAll]);
end;
function DeleteSymbols(inputstr : string): string;
begin
Result := '';
Result := StringReplace(inputstr, '-', '', [rfReplaceAll]);
Result := StringReplace(Result, ' ', '', [rfReplaceAll]);
Result := StringReplace(Result, '\', '', [rfReplaceAll]);
Result := StringReplace(Result, '/', '', [rfReplaceAll]);
end;
procedure Ser();
var mForm : MainFormInfo;
tForm : TableFormInfo;
lForm : ListFormInfo;
tempFmtable : TfmTableData;
i,j : integer;
MyFileStream : TFileStream;
MyMemoryStream : TMemoryStream;
field : TableFieldInfo;
begin
try
mForm := nil;
mForm := MainFormInfo.Create(
nil,
MainWindow.Left,
MainWindow.Top,
MainWindow.Height,
MainWindow.Width,
MainWindow.partofconnectstring,
MainWindow.dbname,
MainWindow.dbfilename);
mForm.Name := 'MainWindow';
//table forms
try
tForm := nil;
field := nil;
for i := 0 to MainWindow.ComponentCount - 1 do
if (MainWindow.Components[i] is TfmTableData) then
begin
tempFmtable := MainWindow.Components[i] as TfmTableData;
tForm := TableFormInfo.Create(
mForm,
tempFmtable.Left,
tempFmtable.Top,
tempFmtable.Height,
tempFmtable.Width,
tempFmtable.tname);
tForm.Name := tempFmtable.Name;
//fields
for j := 0 to tempFmtable.DBGrid1.Columns.Count - 1 do
begin
field := nil;
field := TableFieldInfo.Create(
tForm,
tempFmtable.DBGrid1.Columns[j].FieldName,
tempFmtable.DBGrid1.Columns[j].Title.Caption,
tempFmtable.DBGrid1.Columns[j].Index,
tempFmtable.DBGrid1.Columns[j].Visible);
field.Name := DeleteSymbols(tempFmtable.DBGrid1.Columns[j].FieldName);{tempFmtable.DBGrid1.Columns[j].FieldName} {+ GetGUID;}
end;
//
end;
except
field.Free;
tForm.Free;
end;
//
//List form
try
lForm := nil;
lForm := ListFormInfo.Create(
mForm,
fmListOfTables.Left,
fmListOfTables.Top,
fmListOfTables.Height,
fmListOfTables.Width);
lForm.Name := 'fmListOfTables';
except
lForm.Free;
end;
//
//save
MyFileStream := nil;
MyMemoryStream := nil;
MyFileStream := TFileStream.Create('test.txt', fmCreate);
MyMemoryStream := TMemoryStream.Create;
MyMemoryStream.WriteComponent(mForm);
MyMemoryStream.Position := 0;
ObjectBinaryToText(MyMemoryStream,MyFileStream);
MainWindow.Panel1.DockManager.SaveToStream(MyFileStream);
//
finally
mForm.Free;
MyFileStream.Free;
MyMemoryStream.Free;
end;
end;
procedure Deser();
var mForm : MainFormInfo;
tForm : TableFormInfo;
lForm : ListFormInfo;
tempFmtable : TfmTableData;
i,j : integer;
MyFileStream : TFileStream;
MyMemoryStream : TMemoryStream;
table : TTableSpec;
descr : string;
field : TableFieldInfo;
begin
try
//destroy environment
i := 0;
while (i <= MainWindow.ComponentCount - 1) do
begin
if MainWindow.Components[i] is TfmTableData then
try
tempFmTable := nil;
tempFmTable := MainWindow.Components[i] as TfmTableData;
tempFmTable.IBQuery1.Close;
tempFmtable.Free;
except
tempFmTable.Free;
end
else
inc(i);
end;
fmListOfTables.Free;
DBSchema.Free;
//
//read
mForm := nil;
MyFileStream := nil;
MyMemoryStream := nil;
mForm := MainFormInfo.Create(nil, -1, -1, -1, -1, MainWindow.partofconnectstring, MainWindow.dbname, MainWindow.dbfilename);
MyFileStream := TFileStream.Create('test.txt', fmOpenRead);
MyMemoryStream := TMemoryStream.Create;
ObjectTextToBinary(MyFileStream,MyMemoryStream);
MyMemoryStream.Position := 0;
MyMemoryStream.ReadComponent(mForm);
//
//go
UnloadProcs.ConnectToDatabase(MainWindow.partofconnectstring, MainWindow.SQLConnection1);
//UnloadProcs.CreateObjs(MainWindow.SQLConnection1, MainForm.DBSchema);
//fmListOfTables.Show;
MainWindow.Left := mForm.LeftValue;
MainWindow.Top := mForm.TopValue;
MainWindow.Height := mForm.HeightValue;
MainWindow.Width := mForm.WidthValue;
//list
i := 0;
while i <= mForm.ComponentCount - 1 do
begin
if mForm.Components[i] is ListFormInfo then
try
lForm := nil;
lForm := mForm.Components[i] as ListFormInfo;
fmListOfTables.Left := lForm.LeftValue;
fmListOfTables.Top := lForm.TopValue;
fmListOfTables.Height := lForm.HeightValue;
fmListOfTables.Width := lForm.WidthValue;
fmListOfTables.Show;
inc(i);
finally
lForm.Free;
end
else
inc(i);
end;
//
//fmListOfTables.Show;
//tables
for j := 0 to mForm.ComponentCount - 1 do
if mForm.Components[j] is TableFormInfo then
try
table := nil;
tempFmtable := nil;
tForm := nil;
tForm := mForm.Components[j] as TableFormInfo;
table := TTableSpec(DBSchema.Tables.FindComponent(tForm.Table));
tempFmtable := TfmTableData.Create(MainWindow);
tempFmtable.Name := tForm.Name;
tempFmtable.tname := tForm.Table;
//tempFmtable.Caption := Utf8ToAnsi(table.Description);
tempFmtable.Left := tForm.LeftValue;
tempFmtable.Top := tForm.TopValue;
tempFmtable.Height := tForm.HeightValue;
tempFmtable.Width := tForm.WidthValue;
tempFmTable.IBQuery1.SQL.Clear;
tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);
tempFmtable.IBQuery1.Open;
i := 0;
while i <= tForm.ComponentCount - 1 do
if tForm.Components[i] is TableFieldInfo then
begin
field := nil;
field := tForm.Components[i] as TableFieldInfo;
tempFmtable.DBGrid1.Columns[i].FieldName := field.FieldNameValue;
tempFmtable.DBGrid1.Columns[i].Title.Caption := field.DescriptionValue;
tempFmtable.DBGrid1.Columns[i].Index := field.IndexValue;
tempFmtable.DBGrid1.Columns[i].Visible := field.VisibleValue;
//tempFmtable.CheckListBox1.Items.Add(field.Description);
//tempFmtable.CheckListBox1.Checked[i] := field.Visible;
inc(i);
end
else
inc(i);
{for i := 0 to table.Fields.ComponentCount - 1 do
begin
descr := Utf8ToAnsi(((table.Fields.Components[i]) as TFieldSpec).Description);
tempFmtable.CheckListBox1.Items.Add(descr);
tempFmtable.DBGrid1.Columns[i].Title.Caption := descr;
tempFmtable.CheckListBox1.Checked[i] := true;
end; }
tempFmtable.Show;
except
tempFmtable.Free;
tForm.Free;
table.Free;
end;
//
//dock
MainWindow.Panel1.DockManager.BeginUpdate;
MainWindow.Panel1.DockManager.LoadFromStream(MyFileStream);
MainWindow.Panel1.DockManager.ResetBounds(TRUE);
MainWindow.Panel1.DockManager.EndUpdate;
//
finally
MyFileStream.Free;
MyMemoryStream.Free;
end;
end;
end.
When debugging I found out that gives out
'Project GUI.exe raised exception class $C0000005 with message 'access violation at 0x00821dae: read of address 0x00000044'.
exception at line
tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);
in the following block of a code from a code is higher
//tables
for j := 0 to mForm.ComponentCount - 1 do
if mForm.Components[j] is TableFormInfo then
try
table := nil;
tempFmtable := nil;
tForm := nil;
tForm := mForm.Components[j] as TableFormInfo;
table := TTableSpec(DBSchema.Tables.FindComponent(tForm.Table));
tempFmtable := TfmTableData.Create(MainWindow);
tempFmtable.Name := tForm.Name;
tempFmtable.tname := tForm.Table;
//tempFmtable.Caption := Utf8ToAnsi(table.Description);
tempFmtable.Left := tForm.LeftValue;
tempFmtable.Top := tForm.TopValue;
tempFmtable.Height := tForm.HeightValue;
tempFmtable.Width := tForm.WidthValue;
tempFmTable.IBQuery1.SQL.Clear;
tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);
tempFmtable.IBQuery1.Open;
i := 0;
while i <= tForm.ComponentCount - 1 do
if tForm.Components[i] is TableFieldInfo then
begin
field := nil;
//tempFmtable.Show;
field := tForm.Components[i] as TableFieldInfo;
tempFmtable.DBGrid1.Columns[i].FieldName := field.FieldNameValue;
tempFmtable.DBGrid1.Columns[i].Title.Caption := field.DescriptionValue;
tempFmtable.DBGrid1.Columns[i].Index := field.IndexValue;
tempFmtable.DBGrid1.Columns[i].Visible := field.VisibleValue;
//tempFmtable.CheckListBox1.Items.Add(field.Description);
//tempFmtable.CheckListBox1.Checked[i] := field.Visible;
//tempFmtable.Show;
inc(i);
end
else
inc(i);
{for i := 0 to table.Fields.ComponentCount - 1 do
begin
descr := Utf8ToAnsi(((table.Fields.Components[i]) as TFieldSpec).Description);
tempFmtable.CheckListBox1.Items.Add(descr);
tempFmtable.DBGrid1.Columns[i].Title.Caption := descr;
tempFmtable.CheckListBox1.Checked[i] := true;
end; }
tempFmtable.Show;
except
tempFmtable.Free;
tForm.Free;
table.Free;
end;
The line that fails is:
tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);
Before this line runs you assigned table like this:
table := TTableSpec(DBSchema.Tables.FindComponent(tForm.Table));
It would seem that FindComponent returned nil.
As I'm sure you know, you have to have a valid object instance in order to call methods, access fields and properties etc. Your code should check for this condition and respond accordingly.
You can see all this quite readily in the debugger. The debugger will break on that line and when you inspect the variables it will tell you that table is nil. Then you have to look at the code and work out why. I recommend that you spend some time improving your debugging skills and learning how to use the tools available.

Resources