Reputation: 65
I have a problem with Fast Report displaying incorrect data from an ADOquery. I use the following sql.text
SELECT * FROM JOB_DATA
INNER JOIN CUSTOMER ON JOB_DATA.CUST_CODE = CUSTOMER.CUST_CODE
WHERE JOB_DATA.SHIP_DATE Between [Date1] And [Date2]
ORDER by SHIP_DATE
Fast Report only shows the data where SHIP_DATE = null.
If I throw up a TDBgrid and attach it to a data source attached to the same ADOquery, then the dbgrid shows exactly the correct information.
I'm out of ideas, any suggestions?
To answer questions about where the dates come from:
var
date1:string;
date2:string;
sql_str:string;
begin
date1:=inputbox('Date Range','Enter Beginning Date','');
Try
StrToDate(date1);
Except
On EConvertError Do
Begin
MessageDlg('Please enter a valid date. Format xx/xx/xx',
mtError, [mbOK], 0);
//ShowMessage('Please enter a valid date. Format `enter code here`xx/xx/xx');
Exit;
End;
End;
date2:=inputbox('Date Range','Enter Ending Date','');
Try
StrToDate(date2);
Except
On EConvertError Do
Begin
MessageDlg('Please enter a valid date. Format xx/xx/xx',
mtError, [mbOK], 0);
//ShowMessage('Please enter a valid date. Format `enter code here`xx/xx/xx');
Exit;
End;
End;
sql_str:= 'SELECT * FROM JOB_DATA INNER JOIN CUSTOMER ON ' +
'JOB_DATA.CUST_CODE = CUSTOMER.CUST_CODE ' +
'WHERE JOB_DATA.SHIP_DATE Between ';
sql_str:= sql_str+ ''' ';
sql_st:=sql_str + date1;
sql_str:= sql_str+ '''';
sql_str:= sql_str+ ' AND ';
sql_str:= sql_str+ ''' ';
sql_str:= sql_str+ date2;
sql_str:= sql_str+ ' ''';
with ADOQuery5 do
begin
Close;
SQL.Clear;
SQL.text:= sql_str;
Open;
end;
frxreport2.ShowReport();
end;
The ADOquery is attached to frxDBDataset2 which is attached to frxReport2. I am doing nothing to alter the results in the query.
No, I have no code in the report, it was all generated from the wizard.
Upvotes: 3
Views: 5326
Reputation: 386
When I start having problems with ADO, I log the information.
You'll need to create your own logger...but here's the jest of it...Note it will log the parameter values that are being passed to the query, including the SQL.
procedure TLogger.SetUpConnectionLogging(aParent: TComponent);
var
a_Index: integer;
begin
for a_Index := 0 to aParent.ComponentCount - 1 do
if aParent.Components[a_Index] is TAdoConnection then
begin
TAdoConnection(aParent.Components[a_Index]).OnWillExecute := WillExecute;
TAdoConnection(aParent.Components[a_Index]).OnExecuteComplete := ExecuteComplete;
end;
end;
procedure TLogger.ExecuteComplete(Connection: TADOConnection;
RecordsAffected: Integer; const Error: Error; var EventStatus: TEventStatus;
const Command: _Command; const Recordset: _Recordset);
var
a_Index: integer;
begin
AddLog('AdoConnection ExecuteComplete', True);
AddLog('Execution In MilliSeconds', IntToStr(MilliSecondsBetween(Time, FDif)));
AddLog('Execution In Seconds', IntToStr(SecondsBetween (Time, FDif)));
AddLog('Execution In Minutes', IntToStr(MinutesBetween (Time, FDif)));
AddLog('CommandText', Command.CommandText);
if Assigned(Command) then
begin
AddLog('Param Count', IntToStr(Command.Parameters.Count));
for a_Index := 0 to Command.Parameters.Count - 1 do
begin
AddLog(Command.Parameters.Item[a_Index].Name, VarToWideStr(Command.Parameters.Item[a_Index].Value));
end;
AddLog('CommandType', GetEnumName(TypeInfo(TCommandType),Integer(Command.CommandType)));
end;
AddLog('EventStatus', GetEnumName(TypeInfo(TEventStatus),Integer(EventStatus)));
if Assigned(RecordSet) then
begin
AddLog('CursorType', GetEnumName(TypeInfo(TCursorType),Integer(Recordset.CursorType)));
AddLog('LockType', GetEnumName(TypeInfo(TADOLockType),Integer(Recordset.LockType)));
end;
AddLog('RecordsAffected', IntToStr(RecordsAffected));
AddLog('AdoConnection ExecuteComplete', False);
end;
procedure TLogger.WillExecute(Connection: TADOConnection;
var CommandText: WideString; var CursorType: TCursorType;
var LockType: TADOLockType; var CommandType: TCommandType;
var ExecuteOptions: TExecuteOptions; var EventStatus: TEventStatus;
const Command: _Command; const Recordset: _Recordset);
begin
AddLog('Connection WillExecute', True);
AddLog('Connection Name', Connection.Name);
AddLog('CommandText', CommandText);
AddLog('CommandType', GetEnumName(TypeInfo(TCommandType),Integer(CommandType)));
AddLog('EventStatus', GetEnumName(TypeInfo(TEventStatus),Integer(EventStatus)));
AddLog('CursorType', GetEnumName(TypeInfo(TCursorType),Integer(CursorType)));
AddLog('Connection WillExecute', False);
FDif := Time;
end;
Upvotes: 0
Reputation: 125757
FastReport cannot display records only where SHIP_DATE
is NULL
, because your query shouldn't be returning them based on your WHERE
clause if Date1
and Date2
are properly assigned. This means that either your dataset and the FastReport aren't connected properly or that something in your code assigning the date values for the BETWEEN
clause is wrong, and the dates aren't being provided to the query correctly.
The first place to start looking is to make sure that all of the report columns are correctly assigned the proper TfrxDataSet
and the proper database column. (Click on the report item (text object or whatever it might be), and check its DataSet
and DataField
properties to ensure they are correct.)
If that's not the problem, it may be the way you're building your query, which probably isn't correctly formatting the dates for ADO. (You're just using whatever format happens to pass the StrToDate
calls without raising an exception.)
The way you're setting up your SQL is really unadviseable. It's unreadable and unmaintainable when you try to manage quoting yourself in code.
You should use parameters, which first and foremost protects you against SQL injection, but also allows the database driver to properly format quoted values and dates for you and keeps things readable. (You can also use readable names for the parameters, so that when you see them six months from now you'll know what they mean.)
var
// Your other variable declarations here
StartDate, EndDate: TDateTime;
begin
Date1 := InputBox(Whatever);
try
StartDate := StrToDate(Date1);
except
// Handle EConvertError
end;
Date2 := InputBox(Whatever);
try
EndDate := StrToDate(Date2);
except
// Handle EConvertError
end;
sql_str := 'SELECT * FROM JOB_DATA J'#13 +
'INNER JOIN CUSTOMER C'#13 +
'ON J.CUST_CODE = C.CUST_CODE'#13 +
'WHERE J.SHIP_DATE BETWEEN :StartDate AND :EndDate';
with ADOQuery5 do
begin
Close;
// No need to clear. If you're using the same query more than once,
// move the SQL assignment and the Parameter.DataType somewhere
// else, and don't set them here.
// The query can be reused just by closing, changing parameter values,
// and reopening.
SQL.Text := sql_str;
with Parameters.ParamByName('StartDate') do
begin
DataType := ftDate;
Value := StartDate;
end;
with Parameters.ParamByName('EndDate') do
begin
DataType := ftDate;
Value := EndDate;
end;
Open;
end;
frxReport2.ShowReport;
end;
Upvotes: 2