Ошибка в поле поиска доступа, возвращается неправильное поле

#excel #vba #ms-access #ms-access-2010 #dao

#excel #vba #ms-access #ms-access-2010 #dao

Вопрос:

Я нахожусь в Excel 2010 VBA, используя ADO 2.8 для запроса базы данных Access 2010. Я не владею базой данных и не имею никаких полномочий вносить в нее какие-либо изменения. Я много лет работаю с Excel VBA, но мои знания Access отрывочны.

Используя тот же SQL, что и один из запросов в базе данных (скопированный из запроса Access и вставленный в Excel VBA), я получаю в некоторых полях результаты, отличные от результатов, полученных этим запросом в базе данных.

Для затронутых полей я вижу, что в Access эти поля определены как поисковые запросы. Вот пример поиска из свойства источника строки одного из затронутых полей:

 SELECT [Signers].[SignerID], [Signers].[SignerName] FROM Signers ORDER BY [SignerID], [SignerName];
  

В базе данных Access, где инструкция SQL ссылается на это поле, запрос возвращает SignerName.

Но в моем коде ADO, где тот же самый оператор SQL ссылается на это поле, запрос возвращает SignerID, а не SignerName.

Могу ли я что-нибудь сделать из своего кода ADO, чтобы получить SignerName вместо SignerID из того же оператора SQL? Или мне нужно изменить инструкцию SQL?

Спасибо,

Грег

Обновить:

На стороне доступа, я думаю, теперь я понимаю, почему отображается только имя входа. На вкладке поиска поля свойство Ширины столбца:

0″;1.2605″

Итак, я предполагаю, что SignerID присутствует в результате запроса Access, но с шириной столбца 0.

К сожалению, это не помогает мне на стороне ADO. Есть предложения по получению имени пользователя вместо SignerID в результате запроса ADO?

Обновление2:

Вот пример инструкции SQL, которая возвращает разные поля в зависимости от того, находится ли она в Access или в ADO:

 SELECT MasterAccount.[SignerKey1] 
FROM MasterAccount ;
  

По запросу Preet вот код ADO в Excel VBA:

 strDatabasePath = rgDatabasePathCell.Value 'rgDatabasePathCell is a worksheet cell object.
strPWD = DATABASE_PASSWORD

Set cnn = New ADODB.Connection
cnn.Provider = "Microsoft.ACE.OLEDB.12.0"
cnn.ConnectionString = "Data Source='" amp; strDatabasePath amp; "';Jet OLEDB:Database Password='" amp; strPWD amp; "';"
cnn.Open

Set cmd = New ADODB.Command
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdText
cmd.CommandText = strSQL
Set rst = New ADODB.Recordset

rst.Open cmd.Execute

shMA.Cells(2, 1).CopyFromRecordset rst 'shMA is a worksheet object.
  

Обновление 3:

Мне пришло в голову, что из того, что я сказал до сих пор, может показаться, что я мог бы просто изменить это:

 SELECT MasterAccount.[SignerKey1] 
FROM MasterAccount ;
  

to this:

 SELECT [Signers].[SignerName] 
FROM MasterAccount ;
  

Но есть 13 затронутых полей поиска, все с точно таким же текстом свойства «Источник строки», как показано выше, и все возвращают разные элементы SignerName для каждой строки. Я не знаю, почему все они возвращают разные элементы в строке; Я не смог найти никакой разницы в том, как они определены. Мне было поручено получить тот же результат в Excel, что и в запросе Access.

Обновление 4:

VBlades — Спасибо, я нашел форму, в которой есть вкладка с выпадающими списками для каждого из 13 полей SignerKey-n. Если я щелкну правой кнопкой мыши по этой форме и выберу Свойства формы, свойство RecordSource будет:

 SELECT MasterAccount.*, Bank.BankRating FROM Bank INNER JOIN MasterAccount ON Bank.BankID = MasterAccount.Bank;
  

Однако я не понимаю, как это будет означать выбор другого элемента SignerName для каждого из 13 полей SignerKey-n или что делать с этой информацией, чтобы получить те же результаты в ADO, что и в запросе Access. Есть предложения?

Обновление 5:

Возможно, я близок к обходному пути. Если я сделаю это, я получу поле имени входа для SignerKey1:

 SELECT Signers.SignerName
FROM Signers RIGHT JOIN MasterAccount ON Signers.SignerID = MasterAccount.SignerKey1.Value;
  

И если я это сделаю, я получу разные элементы имени входа для каждого поля в каждой строке:

 SELECT Signers.SignerName, Signers_1.SignerName, Signers_2.SignerName
FROM Signers AS Signers_2 INNER JOIN (Signers AS Signers_1 INNER JOIN (Signers RIGHT JOIN MasterAccount ON Signers.SignerID = MasterAccount.SignerKey1.Value) ON Signers_1.SignerID = MasterAccount.SignerKey2.Value) ON Signers_2.SignerID = MasterAccount.SignerKey3;
  

Это работает как в запросе Access, так и в ADO. Следующим шагом я попытаюсь добавить эти объединения в основной оператор SQL.

Обновление 6:

Ну, когда я пытаюсь добавить хотя бы одно из этих 13 соединений к основному оператору SQL, оно отлично работает в запросе Access, но в ADO я получаю ошибку:

Все дескрипторы строк должны быть освобождены, прежде чем можно будет получить новые.

Итак, я застрял. Есть предложения?

Я поднял проблему с владельцем базы данных, но они не знают, почему свойство источника строк затронутых полей включает SignerID, поэтому я не уверен, поможет ли это.

Комментарии:

1. Есть ли шанс, что вы можете поместить оба набора кода здесь, пожалуйста?

2. Привет, Прит — вы имеете в виду инструкцию SQL? Я добавил пример выше.

3. Привет, Прит. Я добавил код ADO из Excel VBA. Кода DAO нет. На стороне Access нет кода; это просто запрос в Access.

4. Спасибо. Интересно… возможно, если бы вы попробовали следующее: напишите некоторый код DAO в vba и убедитесь, что вы получаете те же данные в каждой строке / столбце, что и Ado? Тогда, возможно, повторите тест из другого приложения Vba — скажем, другого экземпляра Access? Я думаю, что это не проблема DAO / ADO, а скорее что-то в том, как Access внутренне выдает запрос. Также я вижу, что вы добавили еще один запрос. Можете ли вы повторить ошибку со свежей базой данных Access и указать примерные данные?

5. Привет, Прит — Спасибо, но я не понимаю, какое это имеет отношение к DAO. Кода DAO нет. В Excel VBA есть код ADO и есть запрос Access (никакого кода, кроме инструкции SQL; просто запрос в Access). Вместо того, чтобы тратить время на переписывание кода ADO как устаревшего кода DAO, я собираюсь попробовать переписать инструкцию SQL, чтобы избежать столбцов поиска.

Ответ №1:

Вы можете сделать следующее (самый простой способ)

Исключить [Signers].[SignerID] из запроса

 SELECT [Signers].[SignerName] FROM Signers ORDER BY [SignerID], [SignerName];
  

Или создайте составное поле, содержащее оба [SignerID] , [Имя пользователя] и извлеките любую часть с помощью VBA, с которой вы знакомы:

  SELECT ([SignerID] amp; "_" amp; [SignerName]) As Composite FROM Signers ORDER BY [SignerID], [SignerName]
  

С уважением,

Комментарии:

1. Алекс — спасибо, но у меня нет контроля над базой данных Access, поэтому я не могу исключить [подписантов]. [SignerID], который находится в свойстве «Источник строки» затронутых полей поиска в базе данных Access. Я могу управлять оператором SQL, который я использую в своем коде ADO, из Excel VBA, но [Подписчики]. [Идентификатор подписи] там не отображается.

Ответ №2:

Хорошо, я решил проблему, получив отдельный набор записей полей SignerID и SignerName из таблицы подписантов.

Затем я перебрал все строки каждого затронутого поля, нашел идентификатор подписи во 2-й таблице и заменил имя подписи на идентификатор подписи в исходной таблице.

Я попытался сделать это в ADO, но получил сообщение об ошибке «Запрос НА ОБНОВЛЕНИЕ или УДАЛЕНИЕ не может содержать многозначное поле». Поэтому вместо этого я произвел замены после копирования набора записей на лист Excel.

Я хотел бы знать, как справиться со всем этим в ADO, но это работает. Теперь все хорошо.