Шаг 121 - Методы FindFirst, FindLast, FindNext, FindPrevious

Описание
Находят в объектах Recordset типа динамических и статических наборов записей первую, последнюю, следующую или предыдущую запись, удовлетворяющую заданным условиям, и делают эту запись текущей записью (только в рабочей области ядра Microsoft Jet).

наборЗаписей.{FindFirst | FindLast | FindNext | FindPrevious} условия

Параметры
наборЗаписей
Объектная переменная, представляющая существующий объект Recordset типа динамического или статического набора записей.
условия
Выражение или переменная типа String, используемая для поиска записи. Этот аргумент аналогичен предложению WHERE в инструкции SQL (без зарезервированного слова WHERE).

Замечания
Если необходимо работать со всеми записями набора, а не только с записями, удовлетворяющими заданным условиям поиска, следует использовать методы группы Move, обеспечивающие переход с записи на запись. Для поиска записи в объекте Recordset табличного типа следует использовать метод Seek.
Если запись, удовлетворяющая заданным условиям, не обнаружена, то состояние указателя текущей записи становится неопределенным, и свойству NoMatch присваивается значение True. Если наборЗаписей содержит несколько записей, удовлетворяющих условиям отбора, то в методе FindFirst будет найдена первая из этих записей, в методе FindNext следующая и т.д.
Начальная позиция и направление поиска для каждого из методов группы Find представлены в следующей таблице.

FindFirst		Начало набора записей		Конец набора записей
FindLast		Конец набора записей		Начало набора записей
FindNext		Текущая запись			Конец набора записей
FindPrevious	Текущая запись			Начало набора записей

При вызове метода FindLast ядро базы данных Microsoft Jet сначала полностью заполняет объект Recordset, а уже потом выполняет поиск.
Результат применения методов группы Find отличается от результата применения методов группы Move, в которых просто делается текущей первая, последняя, следующая или предыдущая запись без применения условий поиска. После вызова метода группы Find можно применить метод группы Move.
Всегда необходимо следить с помощью свойства NoMatch за тем, была ли успешной операция Find. Если запись обнаружена, свойство NoMatch получает значение False. При неудачном поиске свойство NoMatch принимает значение True, а текущая запись становится неопределенной. В этом случае пользователь должен явно установить указатель текущей записи на допустимую запись.
Применение методов группы Find к наборам записей, доступ к которым через подключение ODBC ядра Microsoft Jet, может оказаться неэффективным. Обычно для поиска конкретной записи удобнее изменить аргумент условия, особенно при работе с большими наборами записей.
В рабочей области ODBCDirect нельзя использовать методы группы Find и метод Seek с объектами Recordset любых типов, поскольку вызов Find или Seek через сетевое подключение ODBC не является эффективным. Вместо этого следует создать запрос (используя аргумент источник в методе OpenRecordset) с соответствующим предложением WHERE, которое ограничивает возвращаемые записи теми, которые удовлетворяют условиям, указанным в методе Find или Seek.
При подключении ядра Microsoft Jet к базам данных ODBC и использовании больших динамических объектов Recordset, пользователь может обнаружить, что выполнение методов Find, а также использование свойств Sort или Filter является достаточно медленным. Для повышения быстродействия пользуйтесь запросами SQL со специализированными предложениями ORDER BY или WHERE, запросами с параметрами или объектами QueryDef, которые возвращают конкретные индексированные записи.
При поиске в полях, содержащих даты, следует использовать американский формат даты (месяц-день-год) даже в случае работы с локализованной версией ядра базы данных Microsoft Jet; в противном случае искомая запись может быть не найдена. Перевести дату в нужный формат позволяет функция Visual Basic Format. Например:

rstEmployees.FindFirst "ДатаНайма > #" 	& Format(mydate, 'm-d-yy' ) & "#"

Если значение аргумента условия образуется путем строкового слияния с нецелым числом, а в системной настройке задано использование национального символа десятичного разделителя, такого как запятая (например, strSQL = "ЦЕНА > " & lngPrice, где lngPrice = 125,50), то при попытке вызова метода возникает ошибка. Появление ошибки объясняется тем, что при слиянии число преобразуется в строковое значение с использованием стандартного символа десятичного разделителя, а язык SQL ядра Microsoft Jet поддерживает только американский символ десятичного разделителя (десятичную точку).
Для обеспечения максимального быстродействия аргумент условия должен быть задан либо в виде "поле = значение", где поле является индексированным полем в базовой таблице, либо в виде "поле LIKE префикс" где поле является индексированным полем в базовой таблице, а префикс представляет начальную часть искомой строки (например, "ART*").
В общем случае, при прочих равных условиях метод Seek выполняется быстрее, чем методы Find. Если табличные объекты Recordset достаточны для решения задач пользователя, следует применять этот метод.

Пример
Следующая программа использует методы FindFirst, FindLast, FindNext и FindPrevious для перевода указателя записи в объекте Recordset на базе указанной строки поиска и команды. Для выполнения этой процедуры требуется функция FindAny.

Sub FindFirstX()

	Dim dbsNorthwind As Database
	Dim rstCustomers As Recordset
	Dim strCountry As String
	Dim varBookmark As Variant
	Dim strMessage As String
	Dim intCommand As Integer

	Set dbsNorthwind = OpenDatabase("Борей.mdb")
	Set rstCustomers = dbsNorthwind.OpenRecordset( "SELECT Название, Город, Страна " & "FROM Клиенты ORDER BY Название", 	dbOpenSnapshot)
	Do While True
	' Принимает данные от пользователя и собирает строку поиска.
	strCountry = Trim(InputBox("Введите название страны."))
		If strCountry = "" Then Exit Do
		strCountry = "Страна = '" & strCountry & "'"
		With rstCustomers
			' Заполняет набор записей.
			.MoveLast
			' Находит первую запись, удовлетворяющую строке поиска. 
			' Выходит из цикла, если такой строки нет.
			.FindFirst strCountry
			If .NoMatch Then
				MsgBox "Не найдены записи для " & strCountry & "."
			Exit Do
			End If
			Do While True
				' Сохраняет закладку текущей записи.
				varBookmark = .Bookmark
				' Принимает способ поиска, выбранный пользователем.
				strMessage = "Компания: " & !Название & 	vbCr & "Место: " & !Город & ", " & _
					!Страна & vbCr & vbCr & _
					strCountry & vbCr & vbCr & _
					"[1 - FindFirst, 2 - FindLast, " & _
					vbCr & "3 - FindNext, " & "4 - FindPrevious]"
				intCommand = Val(Left(InputBox(strMessage), 1))
				If intCommand < 1 Or intCommand > 4 Then Exit Do
				' Применяет выбранный метод Find. При неудачном 
				' поиске возвращает последнюю текущую запись.
				If FindAny(intCommand, rstCustomers, strCountry) = False Then
					.Bookmark = varBookmark
					MsgBox "Запись не найдена Возврат " & 	"на текущую запись."
				End If
			Loop
		End With
	Exit Do
	Loop
	rstCustomers.Close
	dbsNorthwind.Close

End Sub

Function FindAny(intChoice As Integer, rstTemp As Recordset, strFind As String) As Boolean

	' Использует способ поиска, выбранный пользователем.
	Select Case intChoice
		Case 1
			rstTemp.FindFirst strFind
		Case 2
			rstTemp.FindLast strFind
		Case 3
			rstTemp.FindNext strFind
		Case 4
			rstTemp.FindPrevious strFind

	End Select
	' Задает возвращаемое значение по значению свойства NoMatch.
	FindAny = IIf(rstTemp.NoMatch, False, True)

End Function

Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 23.03.2002