Базы данных и ADO Перемещение по Recordset в ADO/VBA

          Назад



9.5.3 Перемещение по Recordset


Перемещение по Recordset в ADO/VBA, свойства BOF, EOF, Bookmark, методы Move(), MoveNext(), MovePrevious(), MoveFirst(), MoveLast(), Find(), Seek()

После того, как объект Recordset создан, нам необходимо выполнять с ним различные операции. Самое простое действие, с которого мы начнем — перемещение по объекту Recordset.

В Recordset всегда имеется ограниченное количество записей (столько, сколько мы получили с источника). Изначально курсор устанавливается на первую запись в Recordset (убедиться в этом можно при помощи свойства AbsolutePosition). Однако, если мы дадим команду MovePrevious() (один раз), ошибки не произойдет (если мы попробуем выполнить команду MovePrevious() второй раз, то возникнет ошибка). AbsolutePosition вернет загадочное значение (-2). Связано это с тем, в Recordset перед первой записью, полученной с источника помещается специальная запись BOF (от Begin Of File, хотя никаких файлов, конечно же, нет). Проверить, находимся ли мы на этой специальной записи, можно при помощи свойства BOF. Например, такой код:

Debug.Print rs.BOF

rs.MovePrevious

Debug.Print rs.BOF

вернет нам вначале False, а затем True.

Точно так же после последней записи в Recordset находится специальная запись EOF (End Of File). Проверить, не находится ли курсор на ней, можно при помощи аналогичного одноименного свойства EOF.

Иногда бывает так, что сразу после открытия Recordset и BOF, и EOF одновременно возвращают True. Объяснение такой ситуации очень простое — в Recordset с источника по каким-то причинам не вернулось ни одной записи. Рекомендуется во избежание неожиданностей предусматривать сразу после открытия Recordset проверку на наличие в нем записей.

После того, как мы определились с нашей текущей позицией в Recordset, необходимо разобраться с тем, как можно по нему перемещаться. Проще всего это делать при помощи методов Move…(). Вот их краткое описание:

  • Move() — этот метод принимает два параметра: NumRecords — на сколько записей необходимо переместиться (это число может быть и отрицательным, что значит — переместиться назад) и второй параметр — необязательный — имя закладки, с которой нужно начать перемещение. Можно использовать три встроенные закладки: для текущей, первой и последней записи. Если имя закладки не указано, то перемещение начинается с текущей позиции.
  • MoveFirst(), MoveLast(), MoveNext() и MovePrevious() — назначение этих методов понятно из названия: перемещение на первую, последнюю, следующую и предыдущую запись соответственно.

Необходимо отметить, что перемещение назад (при помощи MovePrevious() или Move() с отрицательным значением) для курсора, открытого как Forward-only, может привести к совершенно непредсказуемому результату (в зависимости от источника данных) — от ошибки до перехода на случайную запись.

Чаще всего для прохода по всем записям используется такой нехитрый алгоритм:

rs.MoveFirst

Do Until rs.EOF

'что-то делаем с каждой записью, например,

'получаем значение нужного поля

rs.MoveNext

Loop

Если нужно напрямую перепрыгнуть на нужную запись, можно использовать методы Find() и Seek().

Метод Find() предназначен для поиска по значению одного столбца. Он принимает в качестве параметра критерий поиска, насколько нужно отступить от исходной позиции, направление поиска и откуда нужно начать поиск. Очень удобно, что при определения критерия поиска можно использовать оператор Like с подстановочными символами. При обнаружении нужной записи метод Find() переставляет курсор на найденную запись, если же запись не обнаружена, то курсор устанавливается на EOF (или BOF, если поиск был назад). Например, чтобы найти все немецкие фирмы в нашем Recordset для таблицы Customers, можно использовать код вида

rs.Find "country = 'Germany'"

Do While Not rs.EOF

Debug.Print "Название фирмы: "; rs.Fields("CompanyName")

mark = rs.Bookmark

rs.Find "country = 'Germany'", 1, adSearchForward, mark

Loop

В этом примере используются еще незнакомые нам объекты Fields и Bookmark, но их назначение понятно: объект Field нужен нам, чтобы вывести название фирмы, а объект Bookmark — чтобы продолжить поиск позиции +1 от последней найденной записи.

Метод Seek() отличается от метода Find() тем, что они ищет значение по индексу (объект Index для Recordset создается либо программным способом, либо автоматически — если на таблицу, на основе который был создан Recordset, было наложено ограничение Primary Key). Этот метод работает только для серверных курсоров с типом команды TableDirect, и поэтому к использованию не рекомендуется.

Теперь — о еще одном свойстве, которое может сильно помочь в перемещении по Recordset (и которое уже встречалось в наших примерах) — свойстве Bookmark. Это свойство очень простое — достаточно присвоить его значение переменной типа Variable, когда указатель стоит в нужном месте Recordset, а затем присвоить этому свойству значение этой переменной, чтобы опять на него вернуться — как в нашем примере с поиском.

Вообще говоря, значение, которое возвращает это свойство, изначально совпадает с номером записи в Recordset, однако Microsoft честно предупреждает, что таким способом пользоваться закладкой очень не рекомендуется — если курсор стоит в одном и том же месте, свойство Bookmark может возвращать разные значения.




Далее