Delphi 3. Библиотека программиста

       

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


Два следующих фрагмента 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 — другой флаг, используемый методами доступа (его смысл разъясняется ниже).



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