Вопрос или проблема
В окне запроса Access SQL-код выполняется корректно и дает точные результаты, однако, когда я переношу код в модуль VBA, я получаю ошибку “Внешнее имя не определено” на [tblAssociate].[AssocID] в функции DMax.
Имя определено, так что не уверен, в чем проблема?
SELECT
tblAssociate.AssocID,
tblAssociate.PersNo,
tblAssociate.Inactive,
" & DLookup("[Position]", "tblAssocHistory", "[AssocHistoryID] = " & DMax("[AssocHistoryID]", "tblAssocHistory", "[AssocID] = " & [tblAssociate].[AssocID])) & " AS CurrPos,
tblAssignments.Inactive,
tblAssignments.AssignmentID
FROM tblAssociate
INNER JOIN tblAssignments ON tblAssociate.AssocID = tblAssignments.AssocID WHERE
(
((tblAssociate.Inactive)=True) AND (tblAssignments.Inactive = False)
)
OR
(
(tblAssociate.Inactive = False)
AND
(
" & DLookup("[Position]", "tblAssocHistory", "[AssocHistoryID] = " & DMax("[AssocHistoryID]", "tblAssocHistory", "[AssocID] = "
& [tblAssociate].[AssocID])
) & " Not In
(SELECT ref_Config.ConfigLongDesc FROM ref_Config WHERE ref_Config.ConfigShortDesc In ('Agent Positions')
)
)
AND tblAssignments.Inactive = False
)"
Ошибка возникает в обоих случаях в условии DMax.
Эта строка кода должна предоставить список заданий, которые подлежат отмене, поскольку агент больше не является активным сотрудником.
[tblAssociate].[AssocID] не определяется до тех пор, пока не будет выполнен DLookup и объединен в SQL-запрос. Вы не можете использовать значения из запроса внутри DLookup, которые объединяются в SQL. Я предлагаю вам рассмотреть использование соединений SQL.
Ответ или решение
Ошибку "External Name Not Defined" в вашем SQL-запросе в VBA можно объяснить тем, что вы пытаетесь сослаться на tblAssociate.AssocID
в функции DMax
, находясь в контексте строки SQL, где эта таблица еще не определена. В промежуточных вычислениях, таких как DLookups
или DMax
, вы не можете использовать значения из других таблиц, если они не были явно предоставлены в рамках запроса.
Вот несколько шагов, которые помогут вам решить проблему:
Решение 1: Используйте SQL-запросы с объединениями
Вместо использования DMax
и DLookup
в строке SQL, вы можете написать SQL-запрос с использованием объединений (JOIN
), который позволит вам извлекать необходимые данные без необходимости использования подзапросов или функции DLookup
.
Пример вашего запроса может выглядеть так:
SELECT
tblAssociate.AssocID,
tblAssociate.PersNo,
tblAssociate.Inactive,
(SELECT TOP 1 Position FROM tblAssocHistory
WHERE AssocID = tblAssociate.AssocID
ORDER BY AssocHistoryID DESC) AS CurrPos,
tblAssignments.Inactive,
tblAssignments.AssignmentID
FROM
tblAssociate
INNER JOIN
tblAssignments ON tblAssociate.AssocID = tblAssignments.AssocID
WHERE
(
(tblAssociate.Inactive = True AND tblAssignments.Inactive = False)
OR
(tblAssociate.Inactive = False AND
(SELECT Position FROM tblAssocHistory
WHERE AssocHistoryID =
(SELECT MAX(AssocHistoryID) FROM tblAssocHistory
WHERE AssocID = tblAssociate.AssocID)
NOT IN
(SELECT ref_Config.ConfigLongDesc
FROM ref_Config
WHERE ref_Config.ConfigShortDesc IN ('Agent Positions')))
AND tblAssignments.Inactive = False)
)
Этот запрос будет возвращать необходимые данные без необходимости в DMax
и DLookup
, что устранит ошибки, связанные с неопределенностью внешнего имени.
Решение 2: Использование переменных и циклов в VBA
Если вам нужны такие вычисления в VBA, возможно, стоит рассмотреть вариант выполнения отдельного запроса для извлечения идентификаторов перед основным запросом. Вы можете делать это с помощью Recordset
, извлекая данные, которые потом сможете использовать в дальнейших расчетах.
Пример:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Dim sql As String
sql = "SELECT AssocID, PersNo, Inactive FROM tblAssociate"
Set rs = db.OpenRecordset(sql)
Do While Not rs.EOF
Dim currentAssocID As Long
currentAssocID = rs!AssocID
' Здесь вы можете использовать currentAssocID для выполнения DMax и DLookup
' и последующей логики.
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
Заключение
Использование SQL-запросов с объединениями вместо DLookup
и DMax
, а также применение подхода с использование Recordset
может помочь вам избежать проблемы с ошибкой "External Name Not Defined". Если у вас есть дополнительные вопросы или требуется помощь по другим аспектам вашей задачи, не стесняйтесь обращаться.