0

当我有一个带有 datetime 字段和 decimal(5,2) 字段的 ClientDataset 时,Delphi 10.4 无法在 TDBGrid 上显示它们,它会引发转换异常。

我准备了一个小测试项目来显示这个错误(我的真实数据来自 SQL Server,虽然我可以手动填充 Clientdataset 得到相同的错误)。

procedure TForm1.FormCreate(Sender: TObject);
var ClientDataset: TClientDataset;
    Datasource: TDatasource;
    DBGrid: TDBGrid;
begin
  ClientDataset := TClientDataset.Create(Self);
  ClientDataset.FieldDefs.Add('Id', ftInteger);
  ClientDataset.FieldDefs.Add('Date', ftDateTime);
  ClientDataset.FieldDefs.Add('Decimal', ftBCD, 2);
  ClientDataset.FieldDefs.Find('Decimal').Precision := 5;
  ClientDataset.CreateDataSet;
  Datasource := TDatasource.Create(Self);
  Datasource.Dataset := ClientDataset;

  ClientDataset.Insert;
  ClientDataset.FieldValues['id'] := 1;
  ClientDataset.FieldValues['Date'] := Now;
  ClientDataset.FieldValues['Decimal'] := 7.55;
  ClientDataset.Post;
  ClientDataset.Insert;
  ClientDataset.FieldValues['id'] := 2;
  ClientDataset.FieldValues['Date'] := Now;
  ClientDataset.FieldValues['Decimal'] := 8.2;
  ClientDataset.Post;

  DBGrid := TDBGrid.Create(Self);
  DBGrid.Parent := Self;
  DBGrid.Align := alClient;
  DBGrid.Datasource := Datasource;
end;

它引发了这个异常:'8200@' is not a valid integer value

小数(18,2)没有这个问题,如果我评论该行,ClientDataset.FieldDefs.Find('Decimal').Precision := 5;则不会引发错误。

此外,如果没有日期时间字段,则也不会引发错误。这运行良好:

procedure TForm1.FormCreate(Sender: TObject);
var ClientDataset: TClientDataset;
    Datasource: TDatasource;
    DBGrid: TDBGrid;
begin
  ClientDataset := TClientDataset.Create(Self);
  ClientDataset.FieldDefs.Add('Id', ftInteger);
  ClientDataset.FieldDefs.Add('Decimal', ftBCD, 2);
  ClientDataset.FieldDefs.Find('Decimal').Precision := 5;
  ClientDataset.CreateDataSet;
  Datasource := TDatasource.Create(Self);
  Datasource.Dataset := ClientDataset;

  ClientDataset.Insert;
  ClientDataset.FieldValues['id'] := 1;
  ClientDataset.FieldValues['Decimal'] := 7.55;
  ClientDataset.Post;
  ClientDataset.Insert;
  ClientDataset.FieldValues['id'] := 2;
  ClientDataset.FieldValues['Decimal'] := 8.2;
  ClientDataset.Post;

  DBGrid := TDBGrid.Create(Self);
  DBGrid.Parent := Self;
  DBGrid.Align := alClient;
  DBGrid.Datasource := Datasource;
end;

你认为这可以解决,而不必用十进制(18,2)字段替换我所有的十进制(5,2)字段?

更新:这是特定于 ClientDataset 的问题。如果我在 TADOQuery 或 TFDMemTable 上打开相同的数据(具有完全相同的 datetime 和 decimal(5,2) BCD 字段),Delphi 10.4 会毫无问题地显示 DBGrid。

该问题也特定于 DBGrid。在 DBEdits 上显示这些字段没有问题。

4

2 回答 2

1

版本 10.4 中已对单元 Data.FmtBcd 关于函数 BCDToCurr e BCDToCurrency 进行了更改。

德尔福 10.3

function BCDToCurr(const BCD: TBcd; var Curr: Currency): Boolean;
  Curr := StrToCurr(string(Bcd));
  Result := True;
end;

function BCDToCurrency(const BCD: TBcd): Currency;
begin
  Result := StrToCurr(string(Bcd)); 
end;

德尔福 10.4

function BCDToCurr(const BCD: TBcd; var Curr: Currency): Boolean;
var
  B: TBcd;
  S: string;
const
  DecimalSeparator = '.';
begin
  // B := BCD * 10000;
  B := BCD;
  if BcdScale(B) >= 4 then
    Dec(B.SignSpecialPlaces, 4)
  else if BcdPrecision(B) <= (MaxFMTBcdFractionSize - 4) then
    Inc(B.Precision, 4)
  else
    OverflowError(SBcdOverflow);

  S := BcdToStr(B, DecimalSeparator);
  Round(S, DecimalSeparator, 0);
  // The real format of Currency type is Int64.
  PInt64(@Curr)^ := StrToInt64(S);
  Result := True;
end;

function BCDToCurrency(const BCD: TBcd): Currency;
begin
  BCDToCurr(BCD, Result);
end;

因此,在 BCDToCurr 函数中具有精度:=5:

否则,如果 BcdPrecision(B) <= (MaxFMTBcdFractionSize - 4) 那么 Inc(B.Precision, 4)

B.Precision 增量为 9。然后变量 Curr 采用不正确的值。

于 2020-08-26T09:37:21.100 回答
0

我报告了这个错误,现在已在最近的 Delphi 10.4 Update 1 中修复。

于 2020-09-08T15:07:07.000 回答