質問

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.

役に立ちましたか?

解決

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;

他のヒント

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;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top