VBA для анализа имени пользовательской формы в методе

Я пытаюсь писать меньше кода, изучая, как использовать метод ООП. Для меня это было немного тяжело, и я застрял. Я хотел бы знать, как я смогу проанализировать имя строки моей пользовательской формы. В моем модуле 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  `

Я продолжаю получать сообщение об ошибке «Требуется объект» всякий раз, когда пытаюсь проанализировать имя моей пользовательской формы в методе, который я создал выше. Я буду признателен, если вы, ребята, поможете мне разобрать мою пользовательскую форму в этом методе.

Пожалуйста, простите меня, если мои коды кажутся вам странными. Я пытаюсь научиться использовать класс, и у меня это полный рот. Я все еще понимаю концепцию

Ваш formname — это не просто имя формы, это также имя элемента управления в форме, поэтому вы не можете использовать его с userforms.add

Rory 02.09.2024 09:01
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
1
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я не уверен, полностью ли я понимаю конечную цель вашего кода.

Судя по тому, что я читаю в вашей подпрограмме 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»? Я немного запутался в этой части. Но я ценю ваше решение. Спасибо

Kobby Adom 02.09.2024 17:18

Я не знаком с ошибкой «Недостаточно места в стеке». Я тоже не уверен, почему он сломался из-за этой ошибки. Функция разделения принимает строку и разделитель и возвращает массив строк, отсчитываемый от нуля, где каждый элемент представляет собой текст между разделителями. (1) используется для возврата второго элемента этого массива, начинающегося с нуля. Вы должны иметь возможность запускать <? Split("frmAddDonor.cmbAddDonr_Country", ".")(1)> в ближайшем окне и возвращаемый результат должен быть "cmbAddDonr_Country". Если вы измените его на <? Split("frmAddDonor.cmbAddDonr_Country", ".")(0)>, он должен вернуть "frmAddDonor".

AttackOnTyler 02.09.2024 19:33

Да, запуск строки кода в ближайшем окне отображается правильно. Моя основная причина, по которой я хочу проанализировать имя пользовательской формы в методе sql, заключается в том, что я буду вызывать этот метод во многих других формах. Я не хочу напрямую указывать имя формы и ее элементы управления в методе. Тогда это будет то же самое, что я повторяю те же коды методов для любой другой формы, которая будет запускать эту процедуру. Потому что, если я заменю <form.Controls(control_name)> в методе на <frmAddDonor.cmbAddDonr_Country>, все будет работать нормально.

Kobby Adom 03.09.2024 04:28

Ваш код работает правильно, если я пройдусь по ним с помощью F8. Но если я решу вызвать подпрограмму модуля «Select_AddDonor_Country» в моей форме «frmAddDonor» на этапе инициализации во время выполнения, я получу ошибку «Недостаточно места в стеке». Возможно, я неправильно вызываю процедуру модуля.

Kobby Adom 03.09.2024 04:54

Мне удалось заставить это работать. Строка кода «Set .form = New frmAddDonor» открывает пользовательскую форму. Поэтому, если я вызываю процедуру «Select_AddDonor_Country» в своей пользовательской форме во время инициализации, она вызывает рекурсию, которая, согласно моим исследованиям, является одной из причин получения ошибки «Недостаточно места в стеке». Поэтому я удалил «Новый» и просто использовал «Set .form = frmAddDonor», и все сработало нормально. Спасибо, братан

Kobby Adom 03.09.2024 06:12

Гораздо проще использовать существующую (пустую) пользовательскую форму для чего-то подобного. Убедитесь, что форма содержит элементы управления (и их код), которые являются общими для задач, которые должна выполнять форма (например, заголовок, кнопки «ОК/Отмена», кнопки выбора записи и т. д.). Добавьте все остальное во время выполнения. Это означает, что любой код событий, необходимый для добавленных элементов управления во время выполнения, должен помещаться в отдельные классы, экземпляры которых создаются при добавлении этих элементов управления.

Если разница между тем, что должно быть в форме в разных обстоятельствах, не очень велика, рассмотрите возможность размещения в форме всего и скрытия ненужного. Упрощает написание кода событий, и у вас появляется больше событий для работы. Не ООП, но иногда ограничения языка вынуждают делать менее элегантные вещи.

Другие вопросы по теме