Есть ли способ записи / редактирования иначе доступного только для чтения набора записей для контекста формы и работы с данными? - PullRequest
1 голос
/ 13 июня 2019

В моей базе данных есть форма, которая отображает записи, отфильтрованные по аббревиатуре, которую вы можете выбрать в поле со списком.Теперь в некоторых случаях я захочу открыть другую форму с теми же записями, которые были показаны ранее, но на этот раз должно быть два дополнительных столбца, и записи (в частности, два новых столбца) должны быть доступны для редактирования.Пока что мой подход выглядит так: я извлекаю данные из предыдущей формы, помещаю их в новый набор записей и добавляю два столбца.Выглядит следующим образом:

Dim cpRS As New ADODB.Recordset, RS As DAO.Recordset, cb As checkBox, addr As String
'Creating copy of previously displayed result table
Set cpRS = New ADODB.Recordset
With cpRS
'all the fields needed. I shortened this because it's too long and has no important information
     .Fields.Append "some_value", adInteger
     .Fields.Append "some_value", adInteger
     .Fields.Append "some_value", adSmallInt, , adFldIsNullable

     'new Fields for temporary purposes
     .Fields.Append "first_new_field_checkbox", adBoolean
     .Fields.Append "second_new_field_textbox", adVarChar, 50

     .CursorLocation = adUseClient
     .Open , , adOpenKeyset, adLockPessimistic, 8
End With

'get result set of previous window by applying filter to the same query used before
Dim argv() As String
Dim argRest As String
Dim qdef As DAO.QueryDef
Dim restrictedQuery As String

'When opening this form I hand over OpenArgs which i restore here
'took the code out but "argv" and "argRest" will be used later    

'this is the query that is used in the previous form. i need an extra where clause though so i had to rewrite it.
restrictedQuery = "some very long SQL statement I feel I don't need to put here because it doesn't contribute to the problem." & _
    "If I'm incorrect, please let me know and I will rewrite it to protect the data in it"

Set qdef = CurrentDb.CreateQueryDef("")
qdef.SQL = restrictedQuery
Set RS = qdef.OpenRecordset
Set RS = CurrentDb.OpenRecordset(restrictedQuery, dbOpenSnapshot)
RS.MoveLast
RS.MoveFirst
If RS.RecordCount = 0 Then
    MsgBox "some error text", vbOKOnly, "error title"
    DoCmd.Close acForm, Me.Name
    Exit Sub
End If

'populate new recordset with data from table in previous form
Do Until RS.EOF
'putting the data from the "old" recordset into the new one, shortened again, you get the idea
    cpRS.AddNew
    cpRS.Fields("some_value") = RS("some_value")
    cpRS.Fields("some_value2") = RS("some_value2")
    cpRS.Fields("first_new_field_checkbox") = False
    cpRS.Fields("second_new_field_textbox") = ""
    cpRS.Update
    RS.MoveNext
Loop

Set Me.Recordset = cpRS

RS.Close
Set RS = Nothing
'cpRS.Close  - I removed this
Set cpRS = Nothing

'error here:
Me.RecordSource = cpRS

Проблема в том, что записи в форме будут пустыми.(не совсем пустой. Если быть точным, в каждой ячейке в одной строке написано #Name?). Я не совсем уверен, что я делаю неправильно.При отладке все работает, я вижу, как набор записей заполняется данными из моей предыдущей формы.Поэтому я предполагаю, что я просто не могу правильно назначить новый набор записей в качестве источника для формы.Вероятно, в строке Set Me.Recordset = cpRS происходит неправильное назначение, но я не знаю, как это исправить, если это (единственная) проблема, то есть.

Вторая часть этого вопроса былаперемещен в другой поток для более ясной структуры.

1 Ответ

1 голос
/ 14 июня 2019

Вы смешиваете значения и ссылки (хранящиеся в переменных), что вызывает случайное закрытие набора форм.

Set cpRS = New ADODB.Recordset создает экземпляр объекта набора записей и сохраняет ссылку на экземпляр в переменной cpRS.

Set Me.RecordSet = cpRS копирует Ссылку из cpRS в Forms-RecordSet, что делает оба указателя на один и тот же Экземпляр объекта Recordset-Object.Он не создает копию объекта (как ByRef в аргументах-функциях напротив ByVal)!

Теперь cpRS.Close закрывает Recordset, но это то же самое, что Forms-Recordset, что приводит к пустой форме, потому что Forms-Recordset закрыт!

Просто пропустите cpRS.close(Вы можете уничтожить переменную с помощью cpRS = Nothing, потому что это просто уничтожает ссылку на экземпляр, сохраненный в cpRS, но экземпляр уничтожается только в том случае, если не осталось ссылки, указывающей на него, но Me.Recordset по-прежнему содержит ссылку!) чтобы заполнить форму (если остальная часть кода верна, что я не проверял!).

Пример:

Private Sub CloseCopyOfRecordsetReference()

Dim rs1 As DAO.Recordset, rs2 As DAO.Recordset, rs3 As DAO.Recordset

With CurrentDb
    Set rs1 = .OpenRecordset("SELECT * FROM MSysObjects")
    Set rs2 = rs1 'copy Reference
    Set rs3 = rs1 '2. copy Reference

    Set rs1 = Nothing 'this does not affect rs2,rs3
    Debug.Print "rs3.RecordCount: " & rs3.RecordCount

    rs2.Close ' this closes rs3 too!
    Debug.Print "rs3.RecordCount: " & rs3.RecordCount 'Error 3420 here as Recordset is closed
End With

End Sub
...