Разделитель тысяч в DBGrid

Я использую MySQL и Delphi XE4 для создания приложения. В базе данных есть большие числа, и я использовал функцию FORMAT в своих запросах, чтобы применить разделитель тысяч!

SELECT Field1,FORMAT((Field2 * Coef), 0) AS blabla FROM MyTable WHERE .....

Все было хорошо, но когда я попытался добавить функцию SUM в FastReprot, произошла логическая ошибка!

Функция FORMAT возвращает результат в виде строки, а функция SUM объединяет строки!!!

SUM(frxDBDataset1."blabla",MasterData1)

Product1| 123,500,000
Product2| 1,455,999,100
________________________________
SUM = 123,500,000-1,455,999,100

Как лучше всего показать разделитель тысяч в DBGrid! Я думаю о применении разделителя тысяч в событии OnGetText. Вызывает ли этот метод задержку отображения данных в DBGrid, когда количество записей > 5000?

У Вас есть какие-то предложения?


person Jessica    schedule 04.02.2014    source источник
comment
Используйте свойство DisplayFormat.   -  person Stefan Glienke    schedule 04.02.2014


Ответы (2)


Это действительно плохая идея - форматировать результаты внутри запроса. Запрос следует использовать для получения информации... представление должно обрабатываться в другом месте. В этом случае я бы использовал (фактически использую) DisplayFormat, как это предлагается в комментариях.

Вы также можете написать код для автоматического форматирования, если вы не всегда хотите добавлять поля в TDataSet во время разработки:

DataSet.Open;
For I := 0 To DataSet.Fields.Count - 1 Do Begin
    If DataSet.Fields[I] Is TFloatField Then
        (DataSet.Fields[I] As TNumericField).DisplayFormat := '###,###,##0.00'
    Else If DataSet.Fields[I] Is TIntegerField Then
        (DataSet.Fields[I] As TNumericField).DisplayFormat := '###,###,##0';
End;

Это должно быть адаптировано к вашим фактическим потребностям ... вы можете прочитать метаданные с BD (это зависит от BD), чтобы принять решение о точности, например.

Внутри FastReport вы также можете использовать DisplayFormat, или вы также можете использовать функцию форматирования внутри вашей заметки: [Format('%.2n', [<DataSet."Field">])], где .2 указывает используемую точность.

РЕДАКТИРОВАТЬ: Чтобы решить проблему со знаком минус, появляющимся справа с BiDiMode = bdRightToLeft (см. ="nofollow">это), я считаю, что вам действительно нужно использовать событие OnGetText. Я думаю, что вы уже нашли этот обходной путь самостоятельно, но я тем не менее включаю его для полноты картины:

procedure TForm1.FieldGetText(Sender: TField; var Text: String; DisplayText: Boolean);
var
  FmtStr: string;
  F: Double;
begin
  F := Sender.AsFloat;
  FmtStr := TNumericField(Sender).DisplayFormat;
  if Sign(F) = -1 then
    Text := '-' + FormatFloat(FmtStr, Abs(F))
  else
    Text := FormatFloat(FmtStr, F)
end;
person GabrielF    schedule 04.02.2014
comment
Спасибо @GabrielF. Как я могу использовать DisplayFormat внутри FastReport? - person Jessica; 04.02.2014
comment
@Jessica Просто установите для свойства Memo.DisplayFormat.FormatStr некоторую строку формата, то же самое так же, как вы делаете с функцией Format (например, %.2n, чтобы включить разделители тысяч и 2 десятичных знака), и установите Memo.DisplayFormat.Kind на fkNumeric. Вы также должны установить DecimalSeparator на свой локальный. Кроме того, вы можете нажать кнопку ... на DisplayFormat, чтобы визуально построить собственность. - person GabrielF; 04.02.2014
comment
@GabrielF- Новая проблема: я использовал OnGetText для некоторых полей, и когда я использую для них DisplayFormat, это не работает! - person Jessica; 04.02.2014
comment
@Jessica Если вы используете OnGetText, DisplayFormat действительно будет игнорироваться. Вы можете увидеть это в функции TField.GetDisplayText. Итак, если вам действительно нужно использовать OnGetText, вы должны отформатировать значение самостоятельно. Вы можете сделать это, используя: Text := FormatFloat((Sender As TNumericField).DisplayFormat, Sender.AsFloat);. Это будет использовать ваше свойство DisplayFormat. Но вам, вероятно, следует проверить, действительно ли вам нужно использовать OnGetText. - person GabrielF; 04.02.2014
comment
Я должен использовать RightToLeft DBGrid, и знак минус появляется справа от отрицательных чисел (например, 100-), поэтому я должен использовать OnGetText для обработки этого! У вас есть идея получше?! @ГабриэльФ - person Jessica; 04.02.2014
comment
Извините, не могу вам помочь. Я никогда не использовал RightToLeft и не смог воспроизвести вашу проблему здесь (может быть, это зависит от локали?)... однако, согласно справке, это не должно влиять на числовые поля: For example, with data aware controls, the alignment does not change for the following field types: ftSmallint, ftInteger, ftWord, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime, ftAutoInc. Может быть, это ошибка? Работал ли обходной путь с OnGetText? - person GabrielF; 04.02.2014
comment
О Боже ! Посмотрите на это: s22.postimg.org/f7kwuzxw1/minus.png BidiMode вызывает это проблема и выравнивание ничего не меняют. в OnGetText я просто перемещаю знак минус в начало строки! - person Jessica; 04.02.2014
comment
Вы имеете в виду, что все в порядке (с отрицательными числами) в вашей DBGrid, когда BiDiMode - RightToLeft? DBGrid.ParentBidiMode=False?! О_о - person Jessica; 04.02.2014
comment
Для ParentBidiMode не было установлено значение false... но теперь оно установлено, и снова ничего не изменилось. На самом деле, вообще ничего не меняется... Пробовал TEdit, TMemo... Думаю, это связано с локалью. Но похоже, решения вашей проблемы нет: borland .newsgroups.archived.at/. Итак, вам действительно понадобится обходной путь. Я отредактирую свой ответ с предложенным обходным путем. - person GabrielF; 04.02.2014

С небольшими изменениями получилось очень хорошо. [Текст := FormatFloat(FmtStr, -F) + '-';]

Особая благодарность Габриэлю Ф.

procedure TForm1.FieldGetText(Sender: TField; var Text: String; DisplayText: Boolean);
var
  FmtStr: string;
  F: Double;
begin
  F := Sender.AsFloat;
  FmtStr := TNumericField(Sender).DisplayFormat;
  if F < 0 then
    Text := FormatFloat(FmtStr, -F) + '-';
  else
    Text := FormatFloat(FmtStr, F)
end;
person Jessica    schedule 06.02.2014