Access 2016 VBA не удалось установить нажатие кнопки на форме для записи многозначных полей во вторую таблицу

#vba #ms-access #recordset #multivalue

#vba #ms-access #набор записей #многозначный

Вопрос:

Я создаю приложение для отслеживания времени между проектом, сотрудниками и т.д. Компания, в которой я работаю, имеет серьезные проблемы с безопасностью, поэтому мне приходится использовать MS Access 2016, мне запрещено использовать YouTube для поиска решений, и я не могу загружать какие-либо файлы из Интернета. К счастью, я все еще могу получить доступ к StackOverflow.

У меня есть форма ввода («Task_List_Entry_Form»), в которой есть кнопка. При нажатии кнопка отправляет значения в таблицу («tbl_Task_List»). В форме VBA я включил, что таблица («tbl_Task_List») обновляется, и все значения переходят в другую таблицу, которая действует как журнал исправлений («tbl_Task_List_Corrections»). Но многозначные поля (я знаю, они худшие, если бы это не было чем-то, что казалось бы необходимым, я бы не включал их) не могут быть запущены. Итак, я включил 2-й запрос в VBA для получения значения многозначных полей и ввода в поля, но пока это не увенчалось успехом.

Первый вариант запроса выглядел следующим образом:
strSQL2 = "INSERT INTO tbl_Task_List_Corrections " amp; Tags.Value amp; " FROM tbl_Task_List " amp; "WHERE tbl_Task_List.ID IN (SELECT MAX(tbl_Task_List.ID) FROM tbl_Task_List);"
'DoCmd.RunSQL strSQL2

Результат: выдана ошибка «Ошибка времени выполнения ‘3134’: синтаксическая ошибка в инструкции INSERT INTO», с ошибкой в строке «DoCmd.RunSQL strSQL2», поля, не содержащие нескольких значений, переданы правильно, но значение не было извлечено, tbl_Task_List_Corrections.Поле тегов остается пустым.

Затем я попробовал что-то более похожее на это:
CurrentDb.Execute "INSERT INTO tbl_Task_List_Corrections (Tags) VALUES ('" amp; Me.[Tags].Value amp; "');"
Результат: Ошибка не была выдана, но значение не было извлечено, и в таблицу «tbl_Task_List_Corrections» была вставлена дополнительная строка

Потенциально я мог бы попробовать третье решение, которое я нашел в этом источнике, однако оно основано на примере базы данных access, которую из-за ограничений безопасности я не могу загрузить и просмотреть, и я не мог понять это только из кода. Вот этот источник: https://www.utteraccess.com/forum/index.php?s=66e048c0880b46f8bd25a0541c30df63amp;showtopic=2018212amp;st=0amp;p=2463687amp;#entry2463687

Это не весь код, а код, который имеет отношение к перемещению значений после сохранения формы.

 Me.Requery                'Refresh so the table is complete

Dim strSQL1 As String     'Declaring the Non-Multivalued fields
Dim strSQL2 As String     'attempting the multi-value fields again

strSQL1 = "INSERT INTO tbl_Task_List_Corrections (Task_ID, Task_Title,  
Task_Start_Time, Task_End_Time, Break_Length_Minutes, Priority,  
Blockage_Reason, Requirements, Notes, Task_Complete) SELECT 
tbl_Task_List.ID, tbl_Task_List.Task_Title, tbl_Task_List.Task_Start_Time, 
tbl_Task_List.Task_End_Time, tbl_Task_List.Break_Length_Minutes, 
tbl_Task_List.Priority, tbl_Task_List.Blockage_Reason, 
tbl_Task_List.Requirements, tbl_Task_List.Notes, 
tbl_Task_List.Task_Complete FROM tbl_Task_List WHERE tbl_Task_List.ID IN 
(SELECT MAX(tbl_Task_List.ID) FROM tbl_Task_List);"
DoCmd.RunSQL strSQL1

'strSQL2 = "INSERT INTO tbl_Task_List_Corrections " amp; Tags.Value amp; " FROM 
tbl_Task_List " amp; "WHERE tbl_Task_List.ID IN (SELECT MAX(tbl_Task_List.ID) 
FROM tbl_Task_List);"
'DoCmd.RunSQL strSQL2          'THIS IS ATTEMPT 1

'CurrentDb.Execute "INSERT INTO tbl_Task_List_Corrections (Tags) VALUES ('" 
amp; Me.[Tags].Value amp; "');"      'THIS IS ATTEMPT 2


    Dim db As Database                               'Attempt4
    Dim rs As Recordset                              'Attempt4
    Dim childRS As Recordset                         'Attempt4
                                                'Attempt4
    Set db = CurrentDb()                             'Attempt4
                                                'Attempt4
    ' Open a Recordset for the Tasks table.                    'Attempt4
    Set rs = db.OpenRecordset("tbl_Task_List")                 'Attempt4
    rs.MoveFirst                                               'Attempt4
                                                               'Attempt4
    Do Until rs.EOF                                            'Attempt4
       ' Print the name of the task to the Immediate window.   'Attempt4
       Debug.Print rs!Task_Title.Value                         'Attempt4
                                                               'Attempt4
       ' Open a Recordset for the multivalued field.           'Attempt4
       Set childRS = rs!Tags.Value                             'Attempt4
                                                               'Attempt4
          ' Exit the loop if the multivalued field contains no records 'Attempt4
         Do Until childRS.EOF                                      'Attempt4
              childRS.MoveFirst                                     'Attempt4
                                                               'Attempt4
             ' Loop through the records in the child recordset.    'Attempt4
              Do Until childRS.EOF                                  'Attempt4
                  ' Print the owner(s) of the task to the Immediate 'Attempt4
                  ' window.                                         'Attempt4
                  Debug.Print Chr(0), childRS!Value.Value           'Attempt4
                  childRS.MoveNext                                  'Attempt4
              Loop                                                  'Attempt4
          Loop                                                      'Attempt4
      rs.MoveNext                                                  'Attempt4
    Loop                                                            'Attempt4

MsgBox "You have successfully added this Task"

DoCmd.Close

End Sub
 Below is attempt 5

 Dim db As Database                               'Attempt5
    Dim rs As Recordset                              'Attempt5
    Dim rs2 As Recordset                             'Defining the tbl_Task_List_Corrections
    Dim childRS As Recordset                         'Attempt5
                                                'Attempt5
    Set db = CurrentDb()                             'Attempt5
                                                'Attempt5
    ' Open a Recordset for the Tasks table.                              'Attempt5
    Set rs = db.OpenRecordset("tbl_Task_List")                           'Attempt5
    Set rs2 = db.OpenRecordset("tbl_Task_List_Corrections")              'Setting the value of tbl_Task_List_Corrections
    rs.MoveLast                                                         'Attempt5
                                                                    'Attempt5
  

‘Делать до rs.EOF’Попытка 5

   ' Print the name of the task to the Immediate window.             'Attempt5
  Debug.Print rs!ID.Value                                           'Attempt5
  Debug.Print rs!Task_Title.Value                                   'Attempt5
  Debug.Print rs!Priority.Value                                     'Attempt5
  Debug.Print rs!Blockage_Reason.Value                              'Attempt5
  Debug.Print rs!Requirements.Value                                 'Attempt5
  Debug.Print rs!Notes.Value                                        'Attempt5

  ' Open a Recordset for the multivalued field.                     'Attempt5
  Set childRS1 = rs!Tags.Value                                      'Attempt5
  Set childRS2 = rs!Assigned_To.Value
                                                                    'Attempt5
     ' Exit the loop if the multivalued field contains no records.  'Attempt5
     Do Until childRS1.EOF                                          'Attempt5
         childRS1.MoveFirst                                         'Attempt5
                                                                    'Attempt5
         ' Loop through the records in the child recordset.         'Attempt5
         Do Until childRS1.EOF                                      'Attempt5
             ' Print the owner(s) of the task to the Immediate      'Attempt5
             ' window.                                              'Attempt5
             Debug.Print Chr(0), childRS1!Value.Value               'Attempt5

             childRS1.MoveNext                                       'Attempt5
         Loop                                                        'Attempt5
    Loop                                                            'End of loop that checks if Tags multi-value field is NULL

    ' Exit the loop if the multivalued field contains no records.  'Attempt5
     Do Until childRS2.EOF                                           'Attempt5
         childRS2.MoveFirst                                          'Attempt5

         ' Loop through the records in the child recordset.         'Attempt5
         Do Until childRS2.EOF                                       'Attempt5
             ' Print the owner(s) of the task to the Immediate      'Attempt5
             ' window.                                              'Attempt5
             Debug.Print Chr(0), childRS2!Value.Value                'Attempt5

             childRS2.MoveNext                                       'Attempt5
         Loop                                                       'Attempt5

     Loop                                                           'End of loop that checks if Assigned_To multi-value field is NULL

    rs2.AddNew                                                          'Attempt5
    rs2!Task_ID = rs!ID.Value                                           'Attempt5
    rs2!Task_Title = rs!Task_Title                                      'Attempt5
    rs2!Tags = childRS1!Value.Value                                     'Attempt5
    rs2!Priority = rs!Priority                                          'Attempt5
    rs2!Assigned_To = childRS2!Value.Value                              'Attempt5
    rs2!Blockage_Reason = rs!Blockage_Reason                            'Attempt5
    rs2!Requirements = rs!Requirements                                  'Attempt5
    rs2!Notes = rs!Notes                                                'Attempt5
    rs2.Update                                                          'Attempt5
  

Ниже приведена попытка 7, ссылающаяся на ответ на 4/13 (отредактированный снова 4/23)

 Me.Requery                                                          'Refresh the table before running the query

Dim strSQL1 As String                                               'Declaring the Non-Multivalued fields to move to Corrections Log

strSQL1 = "INSERT INTO tbl_Task_List_Corrections (Task_ID, Task_Title, " amp; _
        "Task_Start_Time, Task_End_Time, Break_Length_Minutes, Priority, " amp; _
        "Blockage_Reason, Requirements, Notes, Task_Complete) " amp; _
        "SELECT ID, Task_Title, Task_Start_Time, Task_End_Time, " amp; _
        "Break_Length_Minutes, Priority, Blockage_Reason, Requirements, " amp; _
        "Notes, Task_Complete FROM tbl_Task_List WHERE ID IN " amp; _
        "(SELECT MAX(ID) FROM tbl_Task_List);"
DoCmd.RunSQL strSQL1

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT ID FROM tbl_Task_List") 'error 3061
Set rs = CurrentDb.OpenRecordset("SELECT MAX(ID) FROM tbl_Task_List") '3265
    Do Until rs.EOF
    CurrentDb.Execute "INSERT INTO " amp; _ 
    " tbl_Task_List_Corrections(Tags.Value) SELECT Tags.Value FROM " amp; _  
    " (SELECT Tags.Value FROM tbl_Task_List WHERE ID = " amp; rs!ID amp; ") " amp; _ 
    " AS T1 WHERE tbl_Task_List_Corrections.Task_ID = " amp; rs!ID
    rs.MoveNext
Loop

MsgBox "You have successfully added this Task"

'DoCmd.SetWarnings False                                             'Turning the "You are about to Update 1 Row" warning back on

DoCmd.Close

End Sub
  

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

1. С CurrentDb.Execute не нужно беспокоиться о SetWarnings. Заставьте INSERT работать с объектом запроса, прежде чем пытаться с VBA. support.office.com/en-us/article / …

2. Часть «SetWarnings» относится к всплывающему «Вы собираетесь вставить …». С которым я не хочу иметь дело. На прошлой неделе я попробовал несколько разных подходов, но любой SELECT или INSERT с объектом запроса еще не извлек искомое значение — он возвращает «1», иногда «1» и «2» в зависимости от того, как я его структурирую (если в многозначном поле есть два значения; создает два столбца со значениями «1» и «2»). Есть ли способ получить доступ к строке, если я могу изолировать позицию этой строки в многозначном поле? Я отредактировал свой пост, добавив для этого новый код.

3. Многозначное поле не содержит строковых данных CSV. В нем есть ссылки на записи в скрытой зависимой таблице. Выполнение не вызовет предупреждений, поэтому SetWarnings не требуется. Поэтому используйте Execute вместо RunSQL.

4. Если я закомментирую все, кроме строки CurrentDb.Execute — это не выдает ошибок, но в ней нет значения, которое анализируется. Это значение равно НУЛЮ. Можете ли вы сказать мне, где я ошибаюсь в этой строке?

5. Я попробовал несколько разных попыток использования наборов записей. Который, кажется, работает нормально, за исключением того, что значение, которое я получаю в окне Locals, равно «1», когда я ожидаю, что это будет «TEST». Когда есть два значения «TEST» и «TEST2», аналогично это ‘1’ и ‘2’. Таким образом, кажется, что он находит значение позиции, но не строку. Код, который делает это, теперь помечен в коде как «Attempt4»

Ответ №1:

Оказалось намного проще, чем я думал. Похоже, первоначальная попытка была на правильном пути.

Как только будет создана новая запись с данными, отличными от MVF, запустите другое действие INSERT SELECT для заполнения MVF. В примере показано заполнение MVF второй таблицы в цикле скопированных записей. Протестировано и сработало. Должно быть просто выполнить действие SQL для одной записи, указанной идентификатором записи в форме, вместо зацикливания набора записей.

 Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT RateID FROM CopyOfRates")
Do Until rs.EOF
    CurrentDb.Execute "INSERT INTO CopyOfRates(MVTest.Value) SELECT MVTest.Value FROM " amp; _
        "(SELECT MVTest.Value FROM Rates WHERE RateID = " amp; rs!RateID amp; ") AS Q1 " amp; _
        "WHERE CopyOfRates.RateID = " amp; rs!RateID
    rs.MoveNext
Loop
  

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

1. Это кажется ДЕЙСТВИТЕЛЬНО близким. Я получаю «Ошибка компиляции: синтаксическая ошибка», которая, похоже, предполагает, что у меня что-то названо неправильно. Я перепробовал кучу разных решений, но все еще возвращаю ошибку. Для пояснения: таблица, которую я извлекаю из «tbl_Task_List», таблица, в которую я пытаюсь ее записать: «tbl_Task_List_Corrections». Поле MV (в обеих таблицах» называется «Теги». Поле идентификатора автоматического номера в «tbl_Task_List» называется «ID», а поле неавтоматического номера, которому оно соответствует, — «Task_ID». Приветствуется любой обновленный синтаксис, но я буду продолжать пытаться!

2. Предоставленный код отлично работает для меня. Вам нужно будет предоставить свою попытку для анализа. Редактировать вопрос.

3. Добавил свои правки, извините, я не смог правильно их отформатировать, чтобы вам не приходилось прокручивать…

4. Используйте символ продолжения строки и конкатенацию в своем коде, чтобы сделать его более читаемым без прокрутки.

5. Черт возьми, прошло 2,5 года, и я пытаюсь воспроизвести свой собственный код, но это не сработает.