Delphi 10.4 не может отображать десятичные (5,2) поля BCD в DBGrids, если также есть поле datetime

Когда у меня есть ClientDataset с полями datetime и decimal (5,2), Delphi 10.4 не может отображать их в TDBGrid, возникает исключение convert.

Я подготовил небольшой тестовый проект, чтобы показать эту ошибку (мои настоящие данные поступают из 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;, то ошибки не возникнет.

Кроме того, если нет поля datetime, то ошибка также не возникает. Это нормально работает:

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;

Как вы думаете, можно ли это исправить, не заменяя все мои десятичные (5,2) поля на десятичные (18,2)?

ОБНОВЛЕНИЕ. Это проблема, специфичная для ClientDataset. Если я открою те же данные в TADOQuery или TFDMemTable (с точно такими же полями datetime и decimal (5,2) BCD), Delphi 10.4 покажет DBGrid без каких-либо проблем.

Проблема также специфична для DBGrid. Нет проблем с отображением этих полей в DBEdits.


person Marc Guillot    schedule 04.08.2020    source источник
comment
Странный баг. Вы пробовали с TFDMemTable?   -  person Olivier    schedule 04.08.2020
comment
Не отмечен ли бета-код Unicode UTF-8 в разделе "Регион" в окнах?   -  person Ravaut123    schedule 04.08.2020
comment
@Olivier, я только что попробовал TFDMemTable, и он отлично работает. Действительно странная ошибка. :-(   -  person Marc Guillot    schedule 04.08.2020
comment
@ Ravaut123 Я никогда не слышал об этой настройке, где мне ее найти ?. Это чистая установка Delphi 10.4, только с обновлениями Delphi и построителем отчетов, больше ничего не было сделано.   -  person Marc Guillot    schedule 04.08.2020
comment
@ Ravaut123 Как вы думаете, почему проблема связана с этой настройкой?   -  person Olivier    schedule 04.08.2020
comment
@Olivier Несколько недель назад у меня возникла проблема с датой и временем в базе данных. Это было с компонентом Devart. После 2-х дневных поисков я обнаружил пробу в настройках региона системы Windows. Бета-версия UTF была проверена, я снял флажок с бета-версии UTF, и все работает нормально.   -  person Ravaut123    schedule 05.08.2020
comment
@ Ravaut123 В моей системе этот параметр уже не отмечен.   -  person Marc Guillot    schedule 05.08.2020
comment
@MarcGuillot Хорошо, снятие флажка с бета-версии utf не было решением   -  person Ravaut123    schedule 05.08.2020


Ответы (2)


В версии 10.4 в модуль Data.FmtBcd внесены изменения, касающиеся функций BCDToCurr и BCDToCurrency.

Delphi 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;

Delphi 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;

Итак, с точностью: = 5 в функции BCDToCurr:

иначе, если BcdPrecision (B) ‹= (MaxFMTBcdFractionSize - 4), то Inc (B.Precision, 4)

и B.Precision приращение до 9. Тогда переменная Curr принимает неправильное значение.

person Barba    schedule 26.08.2020

Я сообщил об ошибке, и теперь она исправлена ​​в недавнем обновлении 1 для Delphi 10.4.

person Marc Guillot    schedule 08.09.2020