Я пытаюсь писать меньше кода, изучая, как использовать метод ООП. Для меня это было немного тяжело, и я застрял. Я хотел бы знать, как я смогу проанализировать имя строки моей пользовательской формы. В моем модуле md_AddCountry есть следующие коды.
`Sub Select_AddDonor_Country()
Dim showsql As New cls_DBConPath
With showsql
.colname = "country_Name"
.sqlst = "Select country_Name From ccf_country;"
.formname = "frmAddDonor.cmbAddDonr_Country"
.DBConPath
Set showsql = Nothing
End With
End Sub`
у меня есть следующие коды в моем модуле класса под названием cls_DBConPath
`Option Explicit
Private psqlSt As String
Private pcolumnName As String
Private pform As Object
Private pformName As String
Public Property Get colname() As String
colname = pcolumnName
End Property
Public Property Let colname(Value As String)
pcolumnName = Value
End Property
Public Property Get sqlst() As String
sqlst = psqlSt
End Property
Public Property Let sqlst(Value As String)
psqlSt = Value
End Property
Public Property Get formname() As String
formname = pformName
End Property
Public Property Let formname(Value As String)
pformName = Value
End Property
Public Property Get form() As Object
form = pform
End Property
Public Property Let form(Value As Object)
pform = Value
End Property`
`Sub DBConPath()
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Dim dbPath As String
Dim fName As Object
Set con = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
'On Error GoTo ErrHandler
dbPath = frmCCFDashboard.DBAddress.Caption
Set con = New ADODB.Connection
con.Open dbPath
Set rs = con.Execute(sqlst)
While rs.EOF = False
UserForms.Add(formname).AddItem rs.Fields(colname).Value
UserForms.Add(formname).AddItem rs.Fields(colname).Value
rs.MoveNext
Wend
End Sub `
Я продолжаю получать сообщение об ошибке «Требуется объект» всякий раз, когда пытаюсь проанализировать имя моей пользовательской формы в методе, который я создал выше. Я буду признателен, если вы, ребята, поможете мне разобрать мою пользовательскую форму в этом методе.
Пожалуйста, простите меня, если мои коды кажутся вам странными. Я пытаюсь научиться использовать класс, и у меня это полный рот. Я все еще понимаю концепцию
Я не уверен, полностью ли я понимаю конечную цель вашего кода.
Судя по тому, что я читаю в вашей подпрограмме md_AddCountry Select_AddDonor_Country, цель состоит в том, чтобы передать строковые ссылки на класс с этими свойствами, а затем выполнить метод запроса sql с использованием этих свойств и отобразить результаты в элементах управления пользовательских форм с другими свойствами, определенными в строительство объектов.
Кажется, вы также хотите, чтобы объект был создан и очищен с помощью оператора with, и у вас есть некоторое свойство объекта формы, которое, как я предполагаю, предназначено для установки в качестве формы для отображения содержимого. Я также хочу предположить, что вы делаете этот модуль общедоступным, чтобы его можно было запускать с помощью кнопки макросов на ленте разработчика Excel.
Хорошая новость: вы не за горами! После освоения классы могут оказаться очень мощными, и попробовать ООП в VBA очень полезно. Это мой первый ответ SA! Мы все делаем что-то новое. Надеюсь, я правильно использую этот раздел ответов.
'md_AddCountry
Sub Select_AddDonor_Country()
With New cls_DBConPath 'you don't need to new the class if you are disposing it
.colname = "country_Name"
.sqlst = "Select country_Name From ccf_country;"
.formname = "frmAddDonor.cmbAddDonr_Country"
set .form = new frmAddDonor 'if you want to pass the userform to your class
.DBConPath
.form.show 'if you want to show your new prepopulated form
End With
End Sub
'cls_DBConPath
Option Explicit
Private psqlSt As String
Private pcolumnName As String
Private pform As Object
Private pformName As String
Public Property Get colname() As String
colname = pcolumnName
End Property
Public Property Let colname(Value As String)
pcolumnName = Value
End Property
Public Property Get sqlst() As String
sqlst = psqlSt
End Property
Public Property Let sqlst(Value As String)
psqlSt = Value
End Property
Public Property Get formname() As String
formname = pformName
End Property
Public Property Let formname(Value As String)
pformName = Value
End Property
Public Property Get form() As Object 'objects need to be set'
set form = pform
End Property
Public Property Set form(Value As Object) 'objects need to be set
set pform = Value
End Property
Sub DBConPath()
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Dim dbPath As String
Dim fName As Object
'Set con = CreateObject("ADODB.Connection") 'you don't need to set here
Set rs = CreateObject("ADODB.Recordset")
'On Error GoTo ErrHandler
dbPath = frmCCFDashboard.DBAddress.Caption
Set con = New ADODB.Connection 'if you set down here
con.Open dbPath
Set rs = con.Execute(sqlst)
Dim control_name as string
control_name = split(formname, ".")(1) 'split takes a delimiter and creates an
'array; (1) takes the 2nd item of the
'zero based array; (0) would get the
'formname
While rs.EOF = False
form.Controls(control_name).AddItem rs.Fields(colname).Value '*
'UserForms.Add(formname).AddItem rs.Fields(colname).Value 'not sure why the
rs.MoveNext 'second one
Wend
End Sub
* Я заменил Userforms.Add (который, я думаю, используется для динамического добавления пользовательской формы. Если это ваша цель, приведенный выше ответ не является правильным) на form.Controls. При этом используется недавно созданная пользовательская форма, ранее переданная в класс, которая еще не была показана, но существует в памяти. Затем передайте control_name в коллекцию Controls и добавьте значение этого поля!
Спасибо. Я ценю ваше решение. Это работает до такой степени, что код читает <control_name = Split(formname, ".")(1)>. Я получаю сообщение об ошибке «Недостаточно места в стеке». Можете ли вы объяснить, что делает (1)? Заменить его формой управления «.cmbUpdateDonor_Country»? Я немного запутался в этой части. Но я ценю ваше решение. Спасибо
Я не знаком с ошибкой «Недостаточно места в стеке». Я тоже не уверен, почему он сломался из-за этой ошибки. Функция разделения принимает строку и разделитель и возвращает массив строк, отсчитываемый от нуля, где каждый элемент представляет собой текст между разделителями. (1) используется для возврата второго элемента этого массива, начинающегося с нуля. Вы должны иметь возможность запускать <? Split("frmAddDonor.cmbAddDonr_Country", ".")(1)> в ближайшем окне и возвращаемый результат должен быть "cmbAddDonr_Country". Если вы измените его на <? Split("frmAddDonor.cmbAddDonr_Country", ".")(0)>, он должен вернуть "frmAddDonor".
Да, запуск строки кода в ближайшем окне отображается правильно. Моя основная причина, по которой я хочу проанализировать имя пользовательской формы в методе sql, заключается в том, что я буду вызывать этот метод во многих других формах. Я не хочу напрямую указывать имя формы и ее элементы управления в методе. Тогда это будет то же самое, что я повторяю те же коды методов для любой другой формы, которая будет запускать эту процедуру. Потому что, если я заменю <form.Controls(control_name)> в методе на <frmAddDonor.cmbAddDonr_Country>, все будет работать нормально.
Ваш код работает правильно, если я пройдусь по ним с помощью F8. Но если я решу вызвать подпрограмму модуля «Select_AddDonor_Country» в моей форме «frmAddDonor» на этапе инициализации во время выполнения, я получу ошибку «Недостаточно места в стеке». Возможно, я неправильно вызываю процедуру модуля.
Мне удалось заставить это работать. Строка кода «Set .form = New frmAddDonor» открывает пользовательскую форму. Поэтому, если я вызываю процедуру «Select_AddDonor_Country» в своей пользовательской форме во время инициализации, она вызывает рекурсию, которая, согласно моим исследованиям, является одной из причин получения ошибки «Недостаточно места в стеке». Поэтому я удалил «Новый» и просто использовал «Set .form = frmAddDonor», и все сработало нормально. Спасибо, братан
Гораздо проще использовать существующую (пустую) пользовательскую форму для чего-то подобного. Убедитесь, что форма содержит элементы управления (и их код), которые являются общими для задач, которые должна выполнять форма (например, заголовок, кнопки «ОК/Отмена», кнопки выбора записи и т. д.). Добавьте все остальное во время выполнения. Это означает, что любой код событий, необходимый для добавленных элементов управления во время выполнения, должен помещаться в отдельные классы, экземпляры которых создаются при добавлении этих элементов управления.
Если разница между тем, что должно быть в форме в разных обстоятельствах, не очень велика, рассмотрите возможность размещения в форме всего и скрытия ненужного. Упрощает написание кода событий, и у вас появляется больше событий для работы. Не ООП, но иногда ограничения языка вынуждают делать менее элегантные вещи.
Ваш
formname
— это не просто имя формы, это также имя элемента управления в форме, поэтому вы не можете использовать его сuserforms.add