Глава 9: Работа с наборами данных Recordset Интерфейс пользователя Access Microsoft обеспечивает много гибких возможностей для пользователей прикладной программы, чтобы отображать, управлять, и модифицировать данные. Иногда, однако, ваша прикладная программа должна брать прямой контроль над данными, чтобы выполнить определенную задачу. VBA вместе с объектами доступа к данным обеспечивает полный язык манипулирования данными, который используется для нахождения, отображения, модификации), удаления и добавления данных. Эта глава представляет основные правила манипулирования данными с объектами доступа к данным Recordset, QueryDef и TableDef. Использование объекта Recordset Вы используете объекты Recordset, чтобы управлять данными в базе данных. Три типа объектов Recordset - table, dynaset, и snapshot - значительно отличаются от друг друга. Х Объект Recordset тип table обращается к локальной таблице в текущей базе данных или к связанной таблице во внешней базе данных, созданной с Microsoft Access или Jet engine Microsoft. Вы можете выполнять некоторые операции типа сортировки, индексации и использования метод Seek( Установки) только на объектах Recordset типа table. Find методы не могут использоваться в этом типе. Х Объект Recordset типа dynaset обращается к локальным или связанным таблицам или к результатам запросов. С dynaset Вы можете извлекать данные для модификации из больше чем одной таблицы, включая связанные таблицы из других баз данных. Х Объект Recordset типа snapshot подобен dynaset, за исключением того, что содержит фиксированную копию данныхи не может модифицироваться. Snapshot содержит копию выбранных записей в таблице или результате запроса, в то время как dynaset содержит только набор косвенных ссылок к записям. Поэтому snapshot создает меньшее количество обработки чем другие типы, он может открываться быстрее, особенно при работе с ODBC - данными. Тип Recordset, который Вы используете, зависит от того, что Вы хотите делать и хотите ли Вы изменять или просто рассматривать данные. Например, если Вы должны сортировать данные или работать с индексами, используйте table. Поскольку данные индексированы, объекты Recordset типа table обеспечивают самый быстрый способ поиска. Если Вам необходимо модифицировать набор записей, выбранных запросом, используйте dynaset. Если тип table недоступен в некоторой ситуации, и Вы только должны просмотреть набор записей, использование snapshot значительно повысит эффективность. Создание Переменной Recordset OpenRecordset метод - основной метод создания объектной переменной Recordset. Для этого сначала объявляете переменную типа Recordset, и затем устанавливаете переменную к объекту, возвращенному из OpenRecordset метода. OpenRecordset метод доступен для объектов Database, TableDef, и QueryDef. Также доступно для объектов Recordset, чтобы новые объекты Recordset могли быть созданы на основе существующих. Синтаксис OpenRecordset метода для объектов Database: Set переменную = database.OpenRecordset (источник [, тип [, опции]]) Синтаксис OpenRecordset метода для всех других типов объектов: Set переменную = object.OpenRecordset (тип [, опции]) Переменная параметр - имя нового объекта Recordset. Объектный параметр - Database, TableDef, QueryDef, или существующий объект Recordset, из которого Вы создаете новый объект Recordset. Microsoft Jet Engine использует параметр источник только для объектов Recordset, созданных из объектов Database. Источник - существующий объект TableDef или QueryDef в базе данных или строка запроса SQL. Объекты TableDef, QueryDef и Recordset автоматически используются как источник. Параметр типа - внутренняя константа, которая определяет вид Recordset, который Вы хотите создать. Доступные константы типа: DbOpenTable DbOpenDynaset DbOpenSnapshot Если Вы не определяете константу типа, engine базы данных выбирает самый эффективный доступный тип, в зависимости от источника данных. Параметр опций состоит из одной или более внутренних констант, которые определяют многопользовательскую достижимость данных. Создание Recordset из Таблицы Метод, который Вы используете, чтобы создать объект Recordset из основной таблицы, зависит на том, ли таблица является локальной для текущей(актуальной) базы данных или - связанная таблица в другой базе данных. Следующее обсуждение объясняет различия и обеспечивает примеры для каждого типа основной таблицы. Из Local Таблицы Следующий пример использует OpenRecordset метод создать объект Recordset типа таблицы для таблицы в текущей базе данных. Dim dbsCurrent As Database, rstCustomer As Recordset Set dbsCurrent = CurrentDB() Set rstCustomer = dbsCurrent.OpenRecordset("Customer") Обратите внимание, что Вы не должны использовать dbOpenTable константу, чтобы создать Recordset типf table. Если Вы опускаете константу типа, engine базы данных выбирает, самый высоко эффективный доступный тип Recordset, в зависимости от объекта, внутри которого Recordset создан источник данных. Поскольку тип table доступен, когда Вы открываете Recordset из локальной таблицы, engine базы данных использует его. Из Связанной Таблицы отличного формата Следующий пример создает объект Recordset типа dynaset для связанной таблицы Paradox версии 3.x. Поскольку тип таблицы не доступен, когда Вы открываете Recordset из связанной таблицы в базе данных не- Access, engine базы данных выбирает следующий наиболее эффективный тип, открывая Recordset dynaset-тип. Dim dbsCurrent As Database Dim tdfNonJetLinked As TableDef, rstTableData As Recordset ' Get current database. Set dbsCurrent = CurrentDB() Set tdfNonJetLinked = dbsCurrent.CreateTableDef("PDXAuthor") ' Connect to Paradox table Author in database C:\PDX\Publish. tdfNonJetLinked.Connect = "Paradox 3.X;DATABASE=C:\PDX\Publish" tdfNonJetLinked.SourceTableName = "Author" ' Attach table. dbsCurrent.TableDefs.Append tdfNonJetLinked ' Create a dynaset-type Recordset for the table. Set rstTableData = tdfNonJetLinked.OpenRecordset() Использование Индекса в Recordset типа table Вы можете рассматривать записи в объекте Recordset типа таблицы, устанавливая Index свойство. Объект Index в семействе Index объекта Recordset основной таблицы может быть определен в Index свойстве. 2 Следующий пример иллюстрирует тип таблицы Recordset основанный на таблице Customers, используя существующий Index с именем City. Dim dbsCurrent As Database, rstTableData As Recordset Set dbsCurrent = CurrentDB() Set rstTableData = dbsCurrent.OpenRecordset("Customers", dbOpenTable) rstTableData.MoveFirst ' Move to first record. MsgBox rstTableData!CompanyName ' First record with no index set. rstTableData.Index = "City" ' Select City index. rstTableData.MoveFirst ' Move to first record. MsgBox rstTableData!CompanyName Вы должны установить Index свойство перед некоторыми операциями, типа метода Seek. Если Вы устанавливаете Index свойство, который не существует, происходит ошибка во время выполнения программы. Если Вы хотите сортировать записи согласно индекса, который не существуют, то создайте сначала индекс, или создайте dynaset- или тип snapshot Recordset, который возвращает записи в определенной последовательности сортировки. Создание Recordset на основе Запроса Вы можете также создавать объект Recordset, основанный на запросе выбора. В следующем примере, Customer List - существующий запрос выбора в текущей базе данных. Dim dbsCurrent As Database, rstCustomers As Recordset Set dbsCurrent = CurrentDB() Set rstCustomers = dbsCurrent.OpenRecordset("Customer List") Примечание Вы не может создавать Recordset тип table основанный на запросе выбора. Если подходящий запрос выбора еще не существует, OpenRecordset метод также принимает строку SQL вместо имени запроса. Предыдущий пример может быть переделан следующим образом: Dim dbsCurrent As Database, rstCustomers As Recordset Dim strQuerySQL As String Set dbsCurrent = CurrentDB() strQuerySQL = "SELECT * FROM Customers ORDER BY CustomerID;" Set rstCustomers = dbsCurrent.OpenRecordset(strQuerySQL) Обратите внимание, когда Вы создаете объект Recordset использование запроса выбора или строки SQL, ваш код не продолжается, пока запрос не возвращает первую строку в Recordset. Создание Recordset на основе формы Чтобы создавать объект Recordset, основанный на форме Microsoft Access, Вы не должны использовать OpenRecordset метод. но можете использовать RecordsetClone свойство формы. RecordsetClone свойство - dynaset-тип Recordset, который обращается к тому же самому основному запросу или данным как форма. Если форма основана на запросе, то RecordsetClone свойство эквивалент создания dynaset с тем же самым запросом. Вы можете использовать RecordsetClone свойство, когда Вы хотите применять метод, который не может использоваться с формами, типа FindFirst метода. RecordsetClone свойство обеспечивает доступ к всем методам и свойствам, которые Вы можете использовать с dynaset. Синтаксис для RecordsetClone свойство: Set recordsetname = form.RecordsetClone Параметр form - имя формы Access Microsoft. Следующий пример показывает, как назначить объект Recordset к записям в форме Orders. Dim rstOrders As Recordset Set rstOrders = Forms!Orders.RecordsetClone Поскольку Microsoft Jet engine базы данных выбирает заданный по умолчанию тип для источника данных, Вы не должны определить тип Recordset. Вы можете указывать различный тип, определяя параметр типа в OpenRecordset методе. 3 Следующий список описывает доступные типы и заданный по умолчанию тип, в зависимости от того, как Вы открываете объект Recordset: Х OpenRecordset метод из объекта Database: Set rstNew = dbsCurrent.OpenRecordset (" Источник Данных ") Все три типа доступны. Заданный по умолчанию тип - table только, если Источник Данных основная таблица, локальная для базы данных. Иначе, доступен только dynaset и snapshot, и dynaset - заданный по умолчанию тип. Х OpenRecordset метод из объекта TableDef: Set rstNew = tdfTableData.OpenRecordset Все три типа доступны. Заданный по умолчанию тип - table, если tdfTableData обращается к таблице в базе данных Jet Microsoft или к ISAM datatabse открытый непосредственно. Если tdfTableData находится в базе данных ODBC или - связанная таблица во внешней базе данных, заданный по умолчанию тип - dynaset; и dynaset и snapshot доступен. Х OpenRecordset метод из объекта QueryDef: Set rstNew = qdfQueryData.OpenRecordset Только dynaset и snapshot доступен, и dynaset - заданный по умолчанию тип. Х OpenRecordset метод из существующего объекта Recordset: Set rstNew = rstExisting.OpenRecordset Только dynaset и snapshot доступен. Заданный по умолчанию тип - тип существующего Recordset. Х RecordsetClone свойство формы Access Microsoft: Set rstNew = Forms! FrmAccessForm.RecordsetClone Будет всегда создаваться тип имитируемого Recordset; никакие другие типы не доступны. Сортировка и Фильтрация Записей Если Вы не определяете, что сортировка выполняется для объекта Recordset, Вы не можете быть уверены, что записи появятся в определенном порядке. Большую чась времени, однако, Вы необходимо отыскивать записи. Например, Вы можете рассматривать счета, размещаемые по увеличению номера счета или отыскивать записи служащих в алфавитном порядке. Самые быстрые и самые простые способы сортировки и фильтрации данных в Recordset при открытии Recordset из объекта QueryDef или сохраненного запроса выполняются при использовании утверждения SQL как источника Recordset при использовании SQL Where и предложения ORDER BY в запросе. Следующий пример открывает объект Recordset, который использует утверждение SQL, чтобы отыскивать и сортировать записи, используя Where и предложения ORDER BY. Dim dbsCurrent As Database, rstManagers As Recordset Set dbsCurrent = CurrentDB() Set rstManagers = dbsCurrent.OpenRecordset("SELECT FirstName, " & _ "LastName FROM Employees WHERE Title = 'Manager' " & _ "ORDER BY LastName") Один недостаток этого типа запроса состоит в том, что он должен быть перетранслирован, каждый раз выполнении. Если этот запрос должен использоваться часто, Вы можете улучшать эффективность, создавая сохраненный запрос, использующий то же самое утверждение SQL, и затем открывать объект Recordset вместо запроса, как показано в следующем примере. Dim dbsCurrent As Database, rstManagers As Recordset 4 Set dbsCurrent = CurrentDB() Set rstManagers = dbsCurrent.OpenRecordset("Managers") Сортировка Записей в Существующем Recordset В некоторых случаях необходимо сортировать записи в существующем Recordset, без вторичного использования первоначального источника данных. Например, Вы можете захотеть, чтобы конечные пользователи были способны сами сортировать записи, возвращенные из сохраненного запроса без изменения сохраненного запроса. Вы не можете изменять порядок сортировки существующего dynaset или snapshot. В место этого, Вы должны создать второй объект Recordset с записями в необходимом порядке. Чтобы создавать dynaset основанный на таблице Orders, которая отсортирована согласно полю ShipCountry, используют свойство Sort, как показано в следующем примере. Dim dbsCurrent As Database Dim rstOrders As Recordset, rstSorted As Recordset Dim strSortOrder As String Set dbsCurrent = CurrentDB() ' Create dynaset. Set rstOrders = dbsCurrent.OpenRecordset("", dbOpenDynaset) ' Prompt user for order by expression. strSortOrder = InputBox("Enter an SQL ORDER BY expression") rstOrders.Sort = strSortOrder ' Set sort order. Set rstSorted = rstOrders.OpenRecordset() ' Create new dynaset. Выражение, которое Вы назначаете к свойству Sort, должно быть имеющее силу выражение SQL ORDER BY, без SORT слова - обычно одиночное имя поля, типа PostalCode в следующем примере. Если Вы хотите сортировать по выражению, состоящему из более чем одно поле, вносите в список поля по через запятую. RstOrders.Sort = " Contry, PostalCode " Заданная по умолчанию последовательность сортировки для свойства Sort –по возрастанию, но Вы можете сортировать по убыванию, добавляя DESC. RstOrders.Sort = " OrderDate DESC " Хотя Вы не можете изменять порядок сортировки для существующего dynaset- или типа snapshot Recordset, Вы можете создавать новый Recordset и назначать его к первоначальной переменной. Set rstOrders = dbsCurrent.OpenRecordset("Employees", dbOpenDynaset) rstOrders.Sort = "LastName, FirstName" Set rstOrders = rstOrders.OpenRecordset() Если Вы сортируете Recordset, используя эту методику, единственый способ ввести эффект сортировки - освежить оригинал Recordset. Может быть более эффективно создать второй объект Recordset с условиями в одном шаге. Как правило, когда Вы знаете, кокие данные Вы хотите выбирать, обычно лучше создать второй Recordset использование строки SQL. Следующий пример показывает Вам, как создать только один объект Recordset. Dim dbsCurrent As Database, rstOrders As Recordset Set dbsCurrent = CurrentDB() Set rstOrders = dbsCurrent.OpenRecordset("SELECT * FROM Orders " & _ "ORDER BY ShipCountry") Фильтрация существующего Recordset Аналогично, для существущего Recordset может быть установлено свойство Filter для фильтрации сзаписей. Например, можно фильтровать записи, содержащий все записи, так что второй набор данных будет содержать записи из United Kingdom. Dim dbsCurrent As Database Dim rstOrders As Recordset, rstFiltered As Recordset 5 Dim strFilterCriteria As String Set dbsCurrent = CurrentDB() ' Create dynaset. Set rstOrders = dbsCurrent.OpenRecordset("Orders", dbOpenDynaset) ' Prompt user for ' filter criteria. strFilterCriteria = InputBox("Enter an SQL WHERE expression") rstOrders.Filter = strFilterCriteria ' Set filter ' condition. Set rstFiltered = rstOrders.OpenRecordset() ' Create filtered ' dynaset. Обратите внимание, чтобы изменить содержание rstOrders dynaset, Вы должны установить свойство Filter и затем открывать второй объект Recordset из rstOrders. Выражение, которое Вы используете, чтобы установить свойство Filter, может быть сложное выражение, содержащее сложные условия. rstOrders.Filter = "Region = 'WA' And Status = 'A'" Следующий пример иллюстрирует, как Вы можете фильтровать результаты запроса, именованного Sales в течение 1994 так, чтобы только продукты в категории 'Beverages' (Напитков) были включены. Dim dbsCurrent As Database, rst1994Sales As Recordset Set dbsCurrent = CurrentDB() Set rst1994Sales = dbsCurrent.OpenRecordset("Sales for 1994") rst1994Sales.Filter = "CategoryName = 'Beverages'" Set rst1994Sales = rst1994Sales.OpenRecordset() Предшествующий пример показывает методику использования существующего объекта Recordset, чтобы создать второй, отфильтронный dynaset. Чтобы освежать нефильтрованную версию dynaset, Вы должны освежить оригинал Recordset и повторно выполнять запрос. Вы можете объединять сортировку и просачивание одна операция, как показано в следующем примере. rstOrders.Sort = "OrderDate DESC" rstOrders.Filter = "CategoryName = 'Beverages'" Set rstOrders = rstOrders.OpenRecordset() Здесь, оригинал Recordset (основанный на запросе, возможно) сортируется в порядке по убыванию OrderDate и фильтруется так, чтобы только продажа напитка была включена. Вы не можете фильтровать Recordset тип таблицы. Если Вы хотите ограничивать записи, восстановленные(отысканные) из таблицы, создайте тип dynaset- или snapshot Recordset. Использование переменной QueryDef OpenRecordset метод, используя константы dbOpenDynaset или dbOpenSnapshot, может принимать строку SQL как параметр. Вы можете также создавать Recordset типа dynaset- или snapshot, создавая объект QueryDef на существующем запросе и с использованием этого объекта QueryDef метода OpenRecordset. Set qdfTexasCustomers = dbsCurrent.QueryDefs("Texas Customers") Set rstTexasCustomers = qdfTexasCustomers.OpenRecordset() Преимущество использования строки SQL - то, что Вы не должны создать запрос, чье имя появляется в окне Database. Если Вы используете много запросов, чтобы создать dynasets, Вы можете ограничивать число имен запроса в окне Database, используя утверждения SQL в коде. Хотя этот тип запроса выполняется более медленно, может оказаться важным, чтобы пользователи вашей прикладной программы способны рассмотривать окно Database. Dim dbsCurrent As Database, qdfCustomers As QueryDef Set dbsCurrent = CurrentDB() 6 ' Create QueryDef. Set qdfCustomers = dbsCurrent.CreateQueryDef ("UpdateCustomers") ' Set SQL property. qdfCustomers.SQL = "UPDATE DISTINCTROW Products " & _ "SET Products!SupplierID = 2 WHERE Products!SupplierID = 1;" qdfCustomers.Execute ' Invoke query. Обратите внимание, что утверждение UPDATE не возвращает строки, и Вы не используете OpenRecordset метод. Взамен, Вы используете Execute метод объекта QueryDef. Перемещение через Recordset Recordsets обычно имеют текущую позицию. Когда Вы обращаетесь к полям в Recordset, Вы получаете значения из текущей записи. Однако, текущая позиция может также быть непосредственно перед первой записью в Recordset или непосредственно после последней записи. В некоторых обстоятельствах, текущая позиция неопределена. Вы можете использовать методы Move для цикла через записи в Recordset: MoveFirst метод перемещается в первую запись. MoveLast метод перемещается в последнюю запись. MoveNext метод перемещается в следующую запись. MovePrevious метод перемещается в предыдущую запись. Move метод [0] перемещает вперед или назад определенное число записей. Следующий пример изменяет заголовок работы всех Sales Representative (коммерческих представителей) в таблице c именtv Employees. После открытия таблицы устанавливается индекс, после чего необходимо использовать MoveFirst метод для размещения на первой записи. Для каждой записи, удовлетворяющей условие заголовка, изменяется заголовок и сохраняет изменение методом Update. Здесь используется MoveNext метод для перемещения на следующую запись. Dim dbsCurrent As Database, rstEmployees As Recordset Set dbsCurrent = CurrentDB() Set rstEmployees = dbsCurrent.OpenRecordset("", dbOpenTable) rstEmployees.Index = "LastName" ' Set current index. rstEmployees.MoveFirst ' Locate first record. Do Until rstEmployees.EOF ' Begin loop. ' Check title. If rstEmployees!Title = "Sales Representative" Then rstEmployees.Edit ' Enable editing. rstEmployees!Title = "Account Executive" ' Change title. rstEmployees.Update ' Save changes. End If rstEmployees.MoveNext ' Locate next record. Loop ' End of loop. rstEmployees.Close ' Close table. Обнаружение границ Recordset 7 В Recordset, если Вы пытаетесь двигаться слишком далеко в одном направлении происходит ошибка во время выполнения программы,. Например, если Вы пробуете использовать MoveNext метод, когда вы - уже в конце Recordset, ошибка происходит. По этой причине, полезно знать границы объекта Recordset. BOF свойство указывает является ли текущая позиция в начале Recordset. Если BOF True, текущая позиция - перед первой записью в Recordset. BOF свойство - также True, если нет записей в Recordset, когда он открытвается. Аналогично, EOF свойство True, если текущая позиция - после последней записи в Recordset или если нет записей. Следующий пример показывает Вам, как использовать BOF и EOF свойства, чтобы обнаружить начало и конец Recordset. Этот фрагмент кода создает тип таблицы Recordset основанный на таблице Orders из текущей базы данных. Происходит перемещени через записи, с начала файла к концу, и затем от конца файла к началу. Dim dbsCurrent As Database, rstOrders As Recordset Set dbsCurrent = CurrentDB() ' Open Recordset from TableDef. Set rstOrders = dbsCurrent.OpenRecordset("", dbOpenTable) Do Until rstOrders.EOF . . . rstOrders.MoveNext Loop rstOrders.MoveLast Do Until rstOrders.BOF . . . rstOrders.MovePrevious Loop ' Until end of table. ' Move to next record. ' MoveLast since now past the ' last record. ' Move to last record. ' Until beginning of file. ' Move to previous record. rstOrders.Close ' Close Recordset. Обратите внимание, что не имеется текущей записи сразу после первого цикла. BOF и EOF свойства имеют следующие характеристики: если Recordset не содержит никакие записи, когда Вы открываете его BOF и EOF True. когда BOF и EOF True, они остаются True, пока Вы не двигаетесь в существующую запись, когда BOF и EOF станут. , когда BOF и EOF - и единственая запись в Recordset удалена, BOF и EOF остаются False, пока Вы не пытаетесь двигаться в другую запись, при которой BOF и EOF станет True. В настоящее время Вы создаете или открываете Recordset, который содержит по крайней мере одну запись, первая запись - текущая запись и BOFи EOF False. если первая запись – текущая и Вы используете MovePrevious, в то время как BOF True, происходит ошибка во время выполнения программы. Когда это случается, BOF остается True и не имеется текущей записи. Аналогично, при перемещении после последней записи в Recordset изменяет значение EOF свойствои к True. Если Вы используете MoveNext метод, в то время как EOF True, происходит 8 ошибка во время выполнения программы. Когда это случается, EOF остается True не имеется никакая текущая(актуальная) запись. Подсчет числа Записей в Recordset Вы можете узнать количество записей в объекте Recordset. Например, Вы можете создать форму, которая показывает информацию для каждой из таблиц в базе данных. Или Вы можете изменять вид формы или отчета, основанного на записях, которые они включает. RecordCount свойство содержит число записей, доступных в определенном Recordset. Recordset без записей имеет значение RecordCount 0. Замечание Значение RecordCount равняется числу записей фактически доступных. Например, когда Вы сначала создаете dynaset или snapshot, Вы "посетили" только одну запись. Если Вы считаете записи сразу после создания dynaset или snapshot (предполагается по крайней мере одна запись), значение RecordCount 1. Когда Вы создаете объект Recordset типа table, Вы действительно "посетили" все записи в основной таблице, и RecordCount отразит это количество. Чтобы определять общее количество записей в Recordset, используйте MoveLast метод двигаться на последнюю запись и затем проверять значение RecordCount. Следующий пример создает Recordset основанный на таблице Employees, и затем определяет число записей в Recordset. Dim dbsCurrent As Database, rstEmployees As Recordset, _ lngTotal As Long Set dbsCurrent = CurrentDB() Set rstEmployees = dbsCurrent.OpenRecordset("Employees") rstEmployees.MoveLast lngTotal = rstEmployees.RecordCount If lngTotal = -1 Then Debug.Print "Count not available." End If Когда записи в dynaset-типе Recordset удаляются программой, значение RecordCount свойств уменьшается. Однако, в многопользовательской среде, записи, удаленные другими пользователями не отражаются в значении RecordCount, пока текущая запись установлена в удаленную запись. В это время, установка RecordCount свойств уменьшается на один. Использование метода Requery на Recordset, сопровождаемом MoveLast методом, устанавливает RecordCount свойство к текущему общему количеству записей в Recordset. Recordset тип snapshot - статический и значение RecordCount, не изменяется, когда Вы добавляете или удаляете записи в основной таблице snapshot. Поиск текущей позиции в Recordset 9 В некоторых ситуациях необходимо определить, как далеко в Recordset Вы переместили текущую позицию. Вы можете указывать текущую позицию в программе. Два свойства доступны, чтобы указать текущую позицию: AbsolutePosition свойство и PercentPosition свойство. Значение свойства AbsolutePosition - позиция текущей записи относительно 0. Однако это не номер записи; если текущая запись неопределена, то AbsolutePosition возвращает -1. Кроме того, не имеется никакой гарантии, что записи появятся в том же самом порядке, каждый раз когда обращаются к Recordset. PercentPosition свойство показывает текущую позицию, выраженную как процент от общего количества записей, обозначенных в RecordCount свойстве. Поскольку RecordCount свойство не отражает общее количество записей в Recordset, пока Recordset не полностью заполнился, PercentPosition свойство только отражает текущую позицию записи как процент от числа записей, к которым обратились, с тех пор как Recordset был открыт. Чтобы удостовериться, что PercentPosition свойство отражает текущую позицию записи относительно всего Recordset, использует MoveLast и MoveFirst методы немедленно после открытия Recordset. Это полностью заполнит Recordset прежде, чем Вы пытаетесь использовать PercentPosition свойство. Следующий пример открывает Recordset на таблице с именем Employees и полностью заполняет его. Программа затем вносит в список содержание каждого поля каждой записи в таблице, нумеруя записи, как они введены. Когда половина записей введена, появляется сообщение, указывая, что Вы на полпути в таблице. Dim dbsCurrent As Database, rstEmployees As Recordset Set dbsCurrent = CurrentDB() Set rstEmployees = dbsCurrent.OpenRecordset("Employees", _ dbOpenDynaset) rstEmployees.MoveLast rstEmployees.MoveFirst ' The Recordset is now fully populated. While rstEmployees.EOF = False Debug.Print "Record No. " & rstEmployees.AbsolutePosition Debug.Print rstEmployees!LastName Debug.Print rstEmployees!FirstName If rstEmployees.PercentPosition > 50.0 Then Debug.Print "Over half way!" End If rstEmployees.MoveNext Wend rstEmployees.Close dbsCurrent.Close Поиск определенной записи Предыдущий раздел, " Перемещение через Recordset, " исследует пути, которыми Вы можете использовать методы Move - MoveFirst, MoveLast, MovePrevious, и MoveNext - для цикла по записям Recordset. В большинстве случаев, однако, более эффективно искать определенного запись. Например, Вы можете находить служащего по номеру служащего, или Вы можете найти все записи, которые принадлежат определенному заказу. В этих случаях, цикл через всех служащих или записей заказа требуют много времени. Взамен, чтобы найти записи Вы можете использовать метод Seek с объектами Recordset типа table и Find методами с dynaset- и объектами Recordset типа snapshot. Использование Метода Seek 10 Метод Seek используется для указания записи в Recordset типа table. Чтобы найти запись в dynaset или snapshot, используйте один из Find методов, описанных в следующем разделе. Когда Вы используете метод Seek для указания записи, engine базы данных использует текущий индекс таблицы, который определен в Index свойстве. Table.Seek сравнение, key1, key2 ... Параметр Table - объект Recordset типа table ,в которой Вы ищете. Метод Seek принимает ряд параметров, первых из которого является сравнение, которое является строкой, которая определяет вид сравнения, которое выполняется. Следующая таблица представляет список строк сравнения, которые Вы можете использовать с методом Seek. Comparison string Description "=" Equal to the specified key values ">=" Greater than or equal to the specified key values ">" Greater than the specified key values "<=" Less than or equal to the specified key values "<" Less than the specified key values Параметры keyn - ряд значений, которые соответствуют полю или полям, которые делают текущий индекс Recordset. Engine базы данных сравнивает эти значения со значениями в соответствующих полях записей объекта Recordset. Следующий пример открывает Recordset тип table с именем Products, и использует метод Seek найти первую запись, содержащую значение 1 в SupplierID поле (который является неуникальным индексным полем). Он изменяется с 1 на 2 и сохраняет изменение методом Update. Последующие переходы в цикле устанавливаются на следующую запись, которые удовлетворяющую условию. Dim dbsCurrent As Database, rstProducts As Recordset Set dbsCurrent = CurrentDB() Set rstProducts = dbsCurrent.OpenRecordset("Products", dbOpenTable) rstProducts.Index = "SupplierID" ' Define current index. rstProducts.Seek "=", 1 ' Seek record. Do Until rstProducts.NoMatch rstProducts.Edit rstProducts("SupplierID") = 2 rstProducts.Update rstProducts.Seek "=", 1 Loop ' ' ' ' ' ' Until no record is found. Enable editing. Change SupplierID. Save changes. Seek next record. End of loop. rstProducts.Close ' Close Recordset. Если Вы используете метод Seek с объектом Recordset типа таблицы без первой установки текущего индекса, происходит ошибка во время выполнения программы. Следующий пример иллюстрирует, как Вы можете создать функцию, которая использует метод Seek для установки на запись, использующую сложный индекс. Function GetFirstPrice(ByVal lngOrderID As Long, _ ByVal lngProductID As Long) As Variant Dim dbsCurrent As Database, rstOrderDetail As Recordset Set dbsCurrent = CurrentDB() Set rstOrderDetail = dbsCurrent.OpenRecordset("Order Details", _ dbOpenTable) rstOrderDetail.Index = "PrimaryKey" rstOrderDetail.Seek "=", lngOrderID, lngProductID If rstOrderDetail.NoMatch Then 11 GetFirstPrice = Null MsgBox "Couldn't find order detail record." Else GetFirstPrice = rstOrderDetail!UnitPrice End If rstOrderDetail.Close dbsCurrent.Close End Function В этом примере, первичный ключ таблицы состоит из двух полей: OrderID и ProductID. Когда Вы вызываете функцию GetFirstPrice с допустиой комбинацией OrderID и ProductID значений полей, функция возвращает цену из найденной записи. Если комбинация поля не может быть найдена в таблице, функция возвращает Null. Если текущий индекс – множественное поле, хвост может быть опущен и обрабатывается как Null. То есть Вы можете отбрасывать от любого числа значений ключа с конца параметра ключа метода Seek, но не из начала или середины. Однако, если Вы не определяете все значения в индексе, Вы можете использовать только " > "или" < " оператор сравнения с методом Seek. Использование Find методов Вы можете использовать следующие методы для поиска записи в Recordset типа dynaset- или snapshot. (Чтобы найти запись в Recordset типе таблицы, используйте метод Seek, который описан в предыдущем разделе.) Microsoft Jet базы данных engine поддерживает четыре Find метода: Х FindFirst метод находит первую запись, удовлетворяющую определенному критерию. Х FindLast метод находит последнюю запись, удовлетворяющую определенному критерию. Х FindNext метод находит следующую запись, удовлетворяющую определенному критерию. Х FindPrevious метод находит предыдущую запись, удовлетворяющую определенному критерию. Когда Вы используете Find методы, Вы определяете критерии поиска, обычно выражение, сравнивающее имя поля со определенным значением. Следующий пример иллюстрирует, как изменить Title работы всех коммерческих представителей в таблице с именем Employees. Создается объект Recordset и затем использует FindFirst и FindNext методы для поиска всех записей, удовлетворяющих условию: "Title = 'Sales Representative'" Подготовка каждой записи для редактирования, изменения Title и сохранение изменения методом Update. Dim strCriterion As String Dim dbsCurrent As Database, rstEmployees As Recordset ' Define search criterion. strCriterion = "Title = 'Sales Representative'" Set dbsCurrent = CurrentDB() ' Create dynaset. Set rstEmployees = dbsCurrent.OpenRecordset("Employees", dbOpenDynaset) ' Locate first occurrence. rstEmployees.FindFirst strCriterion ' Loop until no matching records. Do Until rstEmployees.NoMatch rstEmployees.Edit 12 ' Enable editing. rstEmployees!Title = "Account Executive" ' Change title. rstEmployees.Update ' Save changes. rstEmployees.FindNext strCriterion ' Locate next record. Loop ' End of loop. Вы можете искать соответствующие записи в обратном порядке, находя последнюю с FindLast методом и затем используя FindPrevious метод вместо FindNext метода. Совет, Используюя запрос модификации для замены Title более эффективно. Engine базы данных устанавливает NoMatch свойство к True всякий раз, когда Find метода дает сбой и текущая позиция записи неопределена. Может иметься текущая запись, но Вы не имеете никакого способа сообщить, которая запись это может быть. Если Вы хотите быть способными возвратиться предыдущей текущей записи после неудачного использования Find метода, используйте (BookMark) закладку. NoMatch False всякий раз, когда операция успешна. В этом случае текущая позиция записи, найдена одним из Find методов. Следующий пример иллюстрирует, как Вы можете использовать FindNext метод найти все записи, которые содержат Null в поле Phone в таблице, именованной Customers. Затем запрашивает пользователя вводить номер телефона для заказчика. Dim dbsCurrent As Database, rstCustomers As Recordset Dim strCriterion As String, strNumber As String Set dbsCurrent = CurrentDB() Set rstCustomers = dbsCurrent.OpenRecordset("Customers", _ dbOpenDynaset) strCriterion = "Phone Is Null" rstCustomers.FindFirst strCriterion Do Until rstCustomers.NoMatch strNumber = InputBox(rstCustomers!CompanyName & _ " is missing a phone number.") rstCustomers.Edit rstCustomers!Phone = strNumber rstCustomers.Update rstCustomers.FindNext strCriterion Loop Совет Может быть более эффективно использовать утверждение SQL SELECT, чтобы отыскать все необходимые записи, затем модифицировать их как набор. Использование Bookmarks вместо номера записи Если Вы использовали другую базу данных или среду программирования, Вы можете быть привыкли к использованию номера записи. Например, Вы можете написать код, который открывает текстовый файл и затем обращаеться к определенным записям по относительной позициии в файле. Первая запись в файле была бы запись 1, вторая будет запись 2, и так далее. В Microsoft Access, ваше представление записей - Recordset - является обычно подмножеством записей во всей таблице. Поскольку фактическое число записей в Recordset может изменяться в любое время, особенно в многопользовательской среде, нет никакого абсолютного номера записи, который Вы можете всегда использовать, чтобы обратиться к определенной записи. AbsolutePosition свойство изменится, если предыдущая запись удалена. Взамен, Вы можете использовать bookmarks, чтобы идентифицировать, и затем возвратиться на специфическую запись. Записи, возвращенные в объект Recordset не находятся ни в каком определенном порядке, если Recordset не был создан с запросом, который включает предложение ORDER BY, или - тип таблицы Recordset с Index. Номера записей были бы обычно бессмысленны в объекте Recordset. Bookmark - сгенерированный системой массив Byte, который однозначно идентифицирует каждую запись. Свойство Bookmark объекта Recordset изменяется каждый раз при перемещении на новую запись. Чтобы идентифицировать запись, перемещайтесь на нее, и затем назначьте значение 13 свойства Bookmark переменной типа Variant. Чтобы возвратиться к записи, установите свойство Bookmark значению переменной. Следующий пример иллюстрирует, как можно использовать закладку, чтобы сохранить текущую позицию записи и затем быстро возвращаться к той позиции записи, если Find или Seek методы терпят неудачу. Если методы неудачны, текущая позиция записи неопределены. Dim dbsCurrent As Database, rstCustomers As Recordset Dim varOrigin As Variant Set dbsCurrent = CurrentDB() Set rstCustomers = dbsCurrent.OpenRecordset("Customers", _ dbOpenTable) rstCustomers.Index = "CompanyName" . . . varOrigin = rstCustomers.Bookmark rstCustomers.Seek ">=", "Z" If rstCustomers.NoMatch Then MsgBox "Can't find a company name starting with 'Z'." rstCustomers.Bookmark = varOrigin End If rstCustomers.Close dbsCurrent.Close В этом примере, сохраняя свойство Bookmark, и затем сбрасывая свойство Bookmark к предыдущему значению, когда сбой метода Seek, заставляют предварительно текущую запись быть текущей записью вновь. Вы можете также использовать свойство Bookmark в Recordset лежащий в основе формы. С этим свойством, ваш код может отмечать, которая запись в настоящее время отображается в форме, и затем изменять отображаемую запись. Например, в форме, содержащей информацию служащего, Вы можете иметь кнопку, которую пользователь может нажимать, чтобы показать запись для руководителя служащего. Следующий пример иллюстрирует процедуру обработки события, которую Вы использовали бы для Click события кнопки. Sub ShowSuper_Click () Dim frmEmployees As Form, rstEmployees As Recordset Dim varOrigin As String, strEmployee As String, strSuper As String Set frmEmployees = Screen.ActiveForm ' Create Recordset from form. Set rstEmployees = frmEmployees.RecordsetClone ' Save current record information. varOrigin = frmEmployees.Bookmark strEmployee = frmEmployees!FirstName & " " &frmEmployees!LastName rstEmployees.FindFirst "EmployeeID = " & frmEmployees!ReportsTo If rstEmployees.NoMatch Then MsgBox "Couldn't find " & strEmployee & "'s supervisor." Else frmEmployees.Bookmark = rstEmployees.Bookmark Super = frmEmployees!FirstName & " " & _ frmEmployees!LastName MsgBox strEmployee & "'s supervisor is " & strSuper frmEmployees.Bookmark = varOrigin End If 14 rstEmployees.Close End Sub Некоторые связанные таблицы, типа таблиц Paradox, которые не имеют никакого первичного ключа, не могут поддерживать закладки. Следовательно, Вы не можете также использовать закладки ни на таких таблицах, ни на объектах Recordset или запросах, основанных на этих таблицах. Однако, все snapshot поддерживают закладки, независимо от их основных таблиц. Вы можете определять, поддерживает ли таблица Bookmark, проверяя значение Bookmarkable свойство, как в следующем примере. If rstLinkedTable.Bookmarkable Then MsgBox "The underlying table supports bookmarks." Else MsgBox "The underlying table doesn't support bookmarks." End If Если Вы пробуете использовать закладки в Recordset, который не поддерживает закладки, происходит ошибка во время выполнения программы. Когда Вы закрываете Recordset, любые закладки, которые Вы сохранили, станут недопустимым. Вы не можете использовать закладку, полученную из одного Recordset в другом Recordset, даже если оба объекта Recordset основаны на той же самой основной таблице или запросе. Однако, Вы можете использовать закладку на двойнике (аналоге) Recordset, как показано в следующем примере. Dim dbsCurrent As Database Dim rstOriginal As Recordset, rstDuplicate As Recordset Dim varPlaceholder As String Set dbsCurrent = CurrentDB() ' Create first Recordset. Set rstOriginal = dbsCurrent.OpenRecordset("Orders", dbOpenDynaset) varPlaceholder = rstOriginal.Bookmark ' Save current record position. Set rstDuplicate = rstOriginal.Clone() ' Create duplicate Recordset. rstDuplicate.Bookmark = varPlaceholder ' Go to same record. Изменение данных Как только вы создали объект Recordset типа table или dynaset, Вы можете изменять, удалять или добавлять новые записи. Вы не можете изменять, удалять или добавлять записи в объекте snapshottype Recordset. Этот раздел представляет методы и процедуры для измения данных в объектах Recordset таблице - и dynaset-типа. Использование Queries Parameter В многих ситуациях необходимо для пользователя или другой программы обеспечить параметры для ваших сохраненных запросов и объектов Recordset. Microsoft Jet Engine базы данных обеспечивает средства, чтобы сделать это. Вы сначала создаете сохраненный запрос, определяя, какие параметры должны обеспечиваться конечным пользователем. Когда Вы открываете Recordset одного из этих запросов, прикладная программа открывает диалоговое окно, которое запрашивает пользователя вводить значение такие как критерий для предложения WHERE или поля для сортировки выбранных записей. Следующий пример использует код Visual Basic, чтобы создать новый параметический запрос, именованный Seniority, который возвращает фамилию каждого служащего, нанятого после некоторой даты. Перед выполнением запроса, программа вызывает функцию InputBox$, чтобы запросить пользователя относительно пороговой даты. Имена затем показываются в окне Отладки, начиная с самого недавнего найма. Sub Param_Query () Dim dbsCurrent As Database, rstEmployees As Recordset 15 Dim qdfEmployees As QueryDef Dim strSQLQuery As String, strHireDate As String Set dbsCurrent = CurrentDB() strSQLQuery = "PARAMETERS BeginningDate DateTime; " & _ "SELECT LastName FROM Employees " & _ "WHERE HireDate >= BeginningDate " & _ "ORDER BY HireDate DESC;" Set qdfEmployees = dbsCurrent.CreateQueryDef("Seniority",strSQLQuery) strHireDate = InputBox$("Enter the earliest hire date") qdfEmployees.Parameters("BeginningDate") = strHireDate Set rstEmployees = qdfEmployees.OpenRecordset() rstEmployees.MoveFirst While rstEmployees.EOF = False Debug.Print rstEmployees!LastName rstEmployees.MoveNext Wend End Sub Большинство задач сопровождения базы данных, описанных в остальной части этой главы может быть выполнено, используя сохраненные запросы параметра. Выполнение массовых изменений Многие из изменений, которые Вы могли бы выполнять в цикле, могут быть выполнены более эффективно запросом модификациии или удаления. Например, задача изменения всех заголовков работы для коммерческих представителей, иллюстрируемая в нескольких предыдущих примерах в цикле по записям каждого служащего и проверку существующего заголовка работы, может быть выполнена быстро запросом модификации. Dim dbsCurrent As Database, qdfChangeTitles As QueryDef Set dbsCurrent = CurrentDB() Set qdfChangeTitles = dbsCurrent.CreateQueryDef() qdfChangeTitles.Name = "Change Job Titles" ' Create query. qdfChangeTitles.SQL = "UPDATE DISTINCTROW Employees " & _ "SET Employees!Title = 'Account Executive' " & _ "WHERE Employees!Title = 'Sales Representative';" dbsCurrent.QueryDefs.Append qdfChangeTitles ' Append query. qdfChangeTitles.Execute ' Invoke query. dbsCurrent.QueryDefs.Delete "Change Job Titles" ' Delete query. Конечно, вся строка SQL может быть заменена в сохраненном запрос параметра, в котором программа запросила бы пользователя относительно значений параметра. Следующий пример показывает, как предыдущий пример может быть изменен на сохраненный запрос параметра. Dim dbsCurrent As Database, qdfChangeTitles As QueryDef Dim strSQLUpdate As String, strOld As String, strNew As String Set dbsCurrent = CurrentDB() ' Define the parameters and ' the SQL update query. strSQLUpdate = "PARAMETERS [Old Title] Text, [New Title] Text; " & _ "UPDATE DISTINCTROW Employees " & _ "SET Employees!Title = [New Title] " & _ "WHERE Employees!Title = [Old Title]; " Set qdfChangeTitles = dbsCurrent.CreateQueryDef("Change Job Titles", _ 16 strSQLUpdate) strOld = InputBox$("Enter old job title") strNew = InputBox$("Enter new job title") qdfChangeTitles.Parameters("Old Title") = strOld qdfChangeTitles.Parameters("New Title") = strNew ' ' ' ' ' ' ' Create the QueryDef object. Prompt for old title. Prompt for new title. Set parameters. qdfChangeTitles.Execute ' Invoke query. dbsCurrent.QueryDefs.Delete "Change Job Titles" ' Delete query. В зависимости от вашей задачи, Вы можете также находить, что удаляющийся запрос более эффективен чем код цикла по записям для их удаления. Изменение существующей Записи Изменение существующей записи в объекте Recordset - процесс из четырех шагов: 1. Переход к записи, которую Вы хотите изменять. 2. Использовать метод Edit для подготовки текущую записи для редактирования. 3. Сделать необходимые изменения в записи. 4. Использовать метод Update для сохранения изменений для текущей записи. Следующий пример иллюстрирует, как изменить заголовки работы для всех коммерческих представителей в таблице, именованной Employees. Set dbsCurrent = CurrentDB() Set rstEmployees = dbsCurrent.OpenRecordset("Employees") rstEmployees.MoveFirst Do Until rstEmployees.EOF If rstEmployees!Title = "Sales Representative" Then rstEmployees.Edit rstEmployees!Title = "Account Executive" rstEmployees.Update End If rstEmployees.MoveNext Loop rstEmployees.Close dbsCurrent.Close Если Вы не используете метод Edit до изменения значения в текущей записи, происходит ошибка во время выполнения программы. Важно . Если Вы изменяете текущую запись, и затем двигаетесь в другую запись или закрываете Recordset без предварительного использования метод Update, ваши изменения потеряются без предупреждения. Например, опущение метода Update из предшествующего примера не имеет результата ни в каких изменениях, сделанных к таблице Employees. Объекты Recordset типа dynaset- могут быть основаны на запросе многих таблиц с запросом, часто выполняющим one-to-many связь. Например, предположим, что Вы хотите создать запрос к многим таблицам, который объединяет поля из таблиц Orders и Order Details. Обычно, Вы не можете изменять значения в таблице Orders, потому что она находится на "один" стороне связи. В зависимости от вашей прикладной программы, однако, Вы можете быть способны делать изменения для таблицы Orders. Чтобы делать возможным свободно изменить значения на "одной" стороне oneto-many связи, используйте dbInconsistent константу OpenRecordset метода для создания противоречивого dynaset. 17 Set rstTotalSales = dbsCurrent.OpenRecordset("Sales Totals",, _ dbInconsistent) Важно, Когда Вы модифицируете противоречивый dynaset, Вы можете легко уничтожить реляционную целостность данных в dynaset. Вы должны быть осторожны, чтобы понять, как данные связаны one-to-many связью и модифицировать значения с обеих сторон для сохранения целостности данных. DbInconsistent константа доступна только для объектов dynaset-type Recordset. Она игнорируется для таблицы - и Snapshot - типов, но не возвращается ошибка компиляции или выполнения программы , если dbInconsistent используется с указанными типами объектов Recordset. Даже с непротиворечивым Recordset, некоторые поля не могут быть замещаемы. Например, Вы не можете изменять значение поля AutoNumber, и Recordset основанный на некоторых связанных таблицах не может быть замещаемым. Удаление существующей записи Вы можете удалять существующую запись в table - или dynaset-типе Recordset используя Delete метод. Вы не можете удалять записи из Recordset типа snapshot. Следующий пример удаляет все записи для стажеров в таблице, именованной Employees. Dim dbsCurrent As Database, rstEmployees As Recordset Set dbsCurrent = CurrentDB() Set rstEmployees = dbsCurrent.OpenRecordset("Employees") rstEmployees.MoveFirst Do Until rstEmployees.EOF If rstEmployees!Title = "Trainee" Then rstEmployees.Delete End If rstEmployees.MoveNext Loop rstEmployees.Close dbsCurrent.Close Когда Вы используете Delete метод, engine базы данных немедленно удаляет текущую запись, без предупреждения или подсказки. Удаление записи автоматически не заставляет следующую запись стать текущей записью; чтобы перейти на следующую запись, Вы должны использовать MoveNext метод. Добавление новой записи Добавление новой записи на dynaset- или тип таблицы Recordset - процесс из трех шагов: 1. Использовать AddNew метод для подготовки новой записи для редактирования. 2. Присвоить значения каждому из полей записи. 3. Использовать метод Update для сохранения новой записи. Следующий пример добавляет новую запись на таблицу, именованную Shippers. Dim dbsCurrent As Database, rstShippers As Recordset Set dbsCurrent = CurrentDB() Set rstShippers = dbsCurrent.OpenRecordset("Shippers") rstShippers.AddNew rstShippers!CompanyName = "Global Parcel Service" . . ' Set remaining fields. 18 . rstShippers.Update rstShippers.Close dbsCurrent.Close Когда Вы используете AddNew метод, engine базы данных готовит новую, пустую запись и делает это текущей записью. Когда Вы используете метод Update для сохранения новой записи, запись, которая была текущая прежде, чем Вы использовали AddNew метод, становится текущей записью снова. Позиция новой записи в Recordset зависит от того, добавили Вы запись на dynaset- или тип table Recordset. Если Вы добавляете запись в Recordset dynaset-тип, новая запись появляется в конце Recordset, независимо от того как Recordset сортируется. Чтобы заставить новую запись появляться в правильно сортируемой позиции, Вы можете использовать метод Requery для воссоздания объекта Recordset, или создать новый Recordset основанный на оригинале. Если Вы добавляете запись в Recordset типа таблицы, запись появляется установленной согласно текущему индексу, или в конце таблицы, если нет первичного ключа и текущего индекса. Важно Если Вы используете AddNew метод для добавления новой записи, затем двигаетесь в другую запись, или закрываете Recordset без использования метод Update, ваши изменения потеряются без предупреждения. Например, опущение метода Update из предшествующего примера не кончается изменениями, сделанными к таблице Shippers. Извлечение данных из записи После того, как вы разместили специфическую запись или записи, Вы можете извлекать данные, чтобы использовать в вашей прикладной программе вместо того, чтобы изменить основную таблицу источника. Копирование одиночного поля Одиночное поле записи может быть скопировано переменной соответствующего типа данных. Следующий пример извлекает три поля из каждой записи в объекте Recordset. Dim dbsCurrent As Database, rstEmployees As Recordset Dim strFirstName As String, strLastName As String, strTitle As String Set dbsCurrent = CurrentDB() Set rstEmployees = dbsCurrent.OpenRecordset("Employees") rstEmployees.MoveFirst strFirstName = rstEmployees!FirstName strLastName = rstEmployees!LastName strTitle = rstEmployees!Title Копирование всех записей в массив Чтобы копировать одну или все записи, Вы можете создать двумерный массив и копировать записи по одной. Увеличивайте первый индекс для каждого поля и второй индекс для каждой записи. Быстрый способ делать то же самое - с GetRows методом. GetRows метод возвращает массив с двумя размерностями. Первый индекс идентифицирует поле, а второй идентифицирует номер строки, следующим образом: VarRecords (intField, intRecord) Следующий пример использует утверждение SQL, чтобы восстановить(отыскать) три поля из таблицы называемой Employees в объект Recordset. Затем используется GetRows метод для запроса первых трех записей Recordset, и сохраняет выбранные записи в массиве с размерностью два. Каждая запись затем печатается по одному полю с использованием двух индексов для выбора специфического поля и записи. 19 Чтобы ясно иллюстрировать, как индексы массива используются, пример использует отдельное утверждение, чтобы идентифицировать и выводить каждое поле каждой записи. Практически более реально использовать два вложенных цикла. Sub GetRows_Test() Dim dbsCurrent As Database, rstEmployees As Recordset Dim varRecords As Variant Set dbsCurrent = CurrentDB() Set rstEmployees = dbsCurrent.OpenRecordset("SELECT FirstName, " & _ "LastName, Title FROM Employees", dbOpenSnapshot) varRecords = rstEmployees.GetRows(3) Debug.Print "First Name", "Last Name", "Title" Debug.Print varRecords(0, 0), Debug.Print varRecords(1, 0), Debug.Print varRecords(2, 0) Debug.Print varRecords(0, 1), Debug.Print varRecords(1, 1), Debug.Print varRecords(2, 1) Debug.Print varRecords(0, 2), Debug.Print varRecords(1, 2), Debug.Print varRecords(2, 2) End Sub Вы можете использовать последующие обращения для GetRows метода, если большое количество записей доступно. Поскольку массив заполняется, как только Вы вызываете GetRows метод, Вы можете видеть, почему этот подход - намного быстрее чем использование утверждений назначения, для копирования по одному полю как в первом примере. Обратите внимание также, что Вы не должны описывать Variant как массив, потому что это выполняется автоматически, когда GetRows метод возвращает записи. Это позволяет Вам использовать массив фиксированной длины без того, чтобы знать, сколько записей или полей будут возвращены, вместо переменной длины, которые требуют большего количества памяти. 20