Извлечение данных


Два следующих фрагмента TDBStatistics очень тесно связаны, поэтому мы постараемся работать над ними одновременно. Первый — процедура проверки ошибок GetRange. Во время извлечения данных компонентом она должна убедиться в том, что все делается «законно». Обычно это сводится к тому, чтобы компонент не пытался читать за последней записью, и т. д.

Однако в случае TDBStatistics все оказывается несколько сложнее. Так как пользователь может захотеть проанализировать набор записей, превышающий границы нашего массива, мы должны позволить ему выбрать подмножество данных. Для этого используются два свойства: UpperBound и LowerBound. Они предоставляют компоненту информацию о начальной и конечной записях набора. Следовательно, процедура проверки должна следить за этими двумя величинами. Самый простой выход заключается в использовании функции, которая:

  1. Проверяет правильность свойств;
  2. Вносит необходимые поправки;
  3. Возвращает разность (с учетом поправок) между UpperBound и LowerBound.

Прежде всего мы проверяем, что значение LowerBound положительно, а UpperBound не меньше, чем

LowerBound + 1: if (LowerBound < 1) then LowerBound := 1; if (UpperBound < 1) then UpperBound := LowerBound + 1;

ALIGN="JUSTIFY">Следующая проверка убеждает в том, что UpperBound больше, чем LowBound. Если выясняется обратное, значения LowBound и UpperBound меняются местами:

if (LowerBound > UpperBound) then begin TempInt := UpperBound; UpperBound := LowerBound; LowerBound := TempInt; end;

Затем мы проверяем, не превышают ли UpperBound и LowerBound количество записей в источнике (то есть значение DataSource.DataSet.RecordCount, извлечен ное ранее и сохраненное в переменной Records), и при необходимости исправляем их:

if (LowerBound > Records) then LowerBound := 1; if (UpperBound > Records) then UpperBound := Records;

При последней проверке мы убеждаемся в том, что разность между UpperBound и LowerBound не превышает количества элементов в массиве Data. Другими словами, количество сохраняемых элементов не должно превышать размер массива:

if (UpperBound - LowerBound > MaxValues) then UpperBound := LowerBound + MaxValues;

Наконец, функция GetRange возвращает разность между проверенными и исправленными значениями



UpperBound и LowerBound: Result := UpperBound - LowerBound;

Так в нашем случае выполняется проверка ошибок.

После завершения проверки можно переходить к извлечению данных из источника и их сохранению в массиве Data. Это происходит в процедуре FillArray.

Настоящая работа FillArray начинается с вызова GetRange. Затем, после проверки границ (см. выше), можно извлечь данные и сохранить их в локальном массиве. Сначала мы открываем источник данных и переходим к записи, номер которой задается свойством

LowerBound: fDataSource.DataSet.Open; fDataSource.DataSet.MoveBy(LowerBound);

Затем мы проверяем тип fDataField. Если поле содержит числовые значения, мы читаем данные, запись за записью, и помещаем их в массив Data:

if ((fDataSource.DataSet.FieldByName(fDataField) is TCurrencyField) or (fDataSource.DataSet.FieldByName(fDataField) is TFloatField) or (fDataSource.DataSet.FieldByName(fDataField) is TIntegerField) or (fDataSource.DataSet.FieldByName(fDataField) is TSmallIntField))then begin for i := LowerBound to UpperBound do begin if not (fDataSource.DataSet.FieldByName (fDataField).IsNull) then Data[Index] := fDataSource.DataSet.FieldByName (fDataField).Value else Data[Index] := 0; Inc(Index); fDataSource.DataSet.Next; end; end

Из символьных полей данные извлекаются несколько иначе. Единственный вид символьных данных, с которыми умеет работать наш компонен т, — это ZIP-коды1. Существует два типа ZIP-кодов: старые, состоящие из пяти цифр, и новые, «пять плюс четыре».

С точки зрения TDBStatistics ZIP-коды из пяти цифр можно преобразовать в числовой тип без дальнейшей обработки. Если значение состоит из девяти цифр и включает дефис, то дефис необходимо предварительно заменить символом «точка» (.), чтобы поле можно было привести к числовому типу:

else if (fDataSource.DataSet.FieldByName (fDataField) is TStringField) then begin for i := LowerBound to UpperBound do begin TempString := fDataSource.DataSet.FieldByName (fDataField).Value; if (Pos('-', TempString) > 0) then TempString[Pos('-', TempString)] := '.'; Data[Index] := StrToFloat(TempString); Inc(Index); fDataSource.DataSet.Next; end; end;

Наконец, мы закрываем источник данных и сбрасываем два флага:

fDataSource.DataSet.Close;

IsArrayFilled := True;

DidGetAll := False;

Переменная IsArrayFilled позволяет другим методам компонента узнать, были ли извлечены данные из источника. Если она равна False, другие процедуры могут вызвать FillArray перед тем, как начинать свою работу. Переменная DidGetAll — другой флаг, используемый методами доступа (его смысл разъясняется ниже).



Содержание раздела