Добавление новой записи с VBA
У меня есть форма, в которой один из ComboBoxes перечисляет все документы данного проекта. Пользователь должен выбрать один и после нажатия кнопки, и если присутствует в таблице Dessins
он открывает вторую форму, показывающую эту запись. Если его нет в этой таблице, я хочу добавить его в.
Один из моих коллег сказал мне, что все, что мне нужно было сделать, это выполнить SQL-запрос с помощью VBA. То, что я до сих пор, это:
Dim rsDessin As DAO.Recordset
Dim strContrat As String
Dim strProjet As String
Dim strDessin As String
Dim sqlquery As String
'I think these next 3 lines are unimportant. I set a first query to get information I need from another table
strDessin = Me.Combo_Dessin
strProjet = Me.Combo_Projet
sqlquery = "SELECT [Projet HNA] FROM [Projets] WHERE [Projet AHNS] = '" & strProjet & "'"
Set rsDessin = CurrentDb.OpenRecordset(sqlquery)
If Not rsDessin.RecordCount > 0 Then 'If not present I want to add it
strContrat = rsDessin![Projet HNA]
sqlquery = "INSERT INTO Feuilles ([AHNS], [Contrat], [No Projet]) VALUES (strDessin, strContrat, strDessin)"
'Not sure what to do with this query or how to make sure it worked.
End If
'Checking my variables
Debug.Print strProjet
Debug.Print strContrat
Debug.Print strDessin
'By here I'd like to have inserted my new record.
rsDessin.Close
Set rsDessin = Nothing
Я также читал в Интернете, что я мог бы достичь аналогичного результата с чем-то вроде этого:
Set R = CurrentDb.OpenRecordset("SELECT * FROM [Dessins]")
R.AddNew
R![Contrat] = strContrat
R![Projet] = strProjet
R![AHNS] = strDessin
R.Update
R.Close
Set R = Nothing
DoCmd.Close
Один путь лучше другого? В случае, когда мой запрос INSERT INTO лучше, что я должен сделать, чтобы выполнить его?
2 ответа
Вы спрашиваете, что предпочтительнее при вставке записи: использовать оператор SQL, выданный объекту Database, или использовать методы объекта Recordset.
Для одной записи это не имеет значения. Тем не менее, вы могли бы выдать INSERT
утверждение как это:
CurrentDb.Execute "INSERT INTO Feuilles ([AHNS], [Contrat], [No Projet]) VALUES (" & strDessin & ", " & strContrat & ", " & strDessin & ")", dbFailOnError
(Вы должны использовать dbFailOnError
возможность ловить определенные ошибки, как указывает HansUp в этом ответе.)
Для вставки нескольких записей из другой таблицы или запроса, как правило, быстрее и эффективнее выдать оператор SQL, подобный следующему:
Dim sql = _
"INSERT INTO DestinationTable (Field1, Field2, Field3) " & _
"SELECT Field1, Field2, Field3 " & _
"FROM SourceTable"
CurrentDb.Execute sql
чем эквивалент с использованием объекта Recordset:
Dim rsSource As DAO.Recordset, rsDestination As DAO.Recordset
Set rsSource = CurrentDb.OpenRecordset("SourceTable")
Set rsDestination = CurrentDb.OpenRecordset("DestinationTable")
Do Until rs.EOF
rsDestination.AddNew
rsDestination!Field1 = rsSource!Field1
rsDestination!Field2 = rsSource!Field2
rsDestination!Field3 = rsSource!Field3
rsDestination.Update
rs.MoveNext
Loop
Тем не менее, использование оператора SQL имеет свои ограничения:
Вы ограничены синтаксисом SQL и функциями.
Это частично смягчено в Access, потому что операторы SQL могут использовать многие встроенные функции VBA или функции, которые вы определяете.
Операторы SQL предназначены для работы с блоками строк. Локальную логику сложнее выразить, используя только функции Iif, Choose или Switch; а логика, которая зависит от текущего состояния (например, вставка каждой другой записи), сложнее или невозможнее при использовании чистого SQL. Это может быть легко сделано с использованием метода Recordset.
Это также можно включить с помощью комбинации VBA и SQL, если у вас есть функции, которые сохраняют состояние в переменных уровня модуля. Одно предостережение: вам нужно будет сбрасывать состояние каждый раз перед выполнением оператора SQL. Смотрите здесь для примера.
Одна часть* вашего вопроса о INSERT
против Recordset.AddNew
добавить одну строку. Я предлагаю этот подход набора записей:
Dim db As DAO.Database
Dim R As DAO.Recordset
Set db = CurrentDb
Set R = db.OpenRecordset("Dessins", dbOpenTable, dbAppendOnly)
With R
.AddNew
!Contrat = rsDessin![Projet HNA].Value
!Projet = Me.Combo_Projet.Value
!AHNS = Me.Combo_Dessin.Value
.Update
.Close
End With
* Вы также спросили, как выполнить INSERT
, Использовать DAO.Database.Execute
метод, который рекомендовал Зев и включающий опцию dbFailOnError. Это добавит ясности в отношении определенных ошибок вставки. Например, ошибка нарушения ключа может привести к INSERT
молча провалиться Но включение dbFailOnError гарантирует, что вы получите уведомление о проблеме немедленно. Поэтому всегда включайте эту опцию... за исключением случаев, когда вы действительно хотите разрешить INSERT
молча провалиться. (Для меня это никогда.)