Перемещение по 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…(). Вот их краткое описание:
Необходимо отметить, что перемещение назад (при помощи 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 может возвращать разные значения.