У меня есть UserForm1, который содержит ComboBox с тремя элементами. Когда выбран элемент №3, появляется новая форма UserForm2. Эта UserForm2 содержит ListBox, заполненный множеством записей с листа. Я хочу иметь возможность выбрать одну из этих записей в ListBox, а затем передать выбранную запись из ListBox в ComboBox в UserForm1 (с помощью кнопки в UserForm2).

Мой упрощенный код выглядит так:

(UserForm1)

Sub UserForm1_Initialize()
   ComboBox1.AddItem "Item1"
   ComboBox1.AddItem "Item2"
   ComboBox1.AddItem "Item3"
End Sub

Sub ComboBox1_Click()
   If ComboBox1 = "Item3" Then
      Load UserForm2
      UserForm2.show
   End If
End Sub

(UserForm2)

Sub UserForm2_Initialize()
   ListBox.AddItem "Apple"
   ListBox.AddItem "Pear"
   ListBox.AddItem "Banana"
End Sub

Sub CommandButton1_Click()
   MyVal = ListBox                 'using .Value or .Text in this or the next line doesn't help
   UserForm1.ComboBox1 = MyVal
   Unload Me
End Sub

(Модуль1)

Public MyVal As String

Как только я нажимаю кнопку, чтобы передать значение из ListBox в ComboBox1, я получаю

«Время выполнения '380' - недопустимое значение свойства»

Ошибка. Любые идеи?

1
blowcake 10 Дек 2019 в 17:58
Вы пробовали регулировать яркость MyVal как Variant и использовать .List?
 – 
braX
10 Дек 2019 в 18:00
Добавление .List к какому объекту?
 – 
blowcake
10 Дек 2019 в 18:07
Между прочим: кажется, что перед передачей MyVal в ComboBox1 программа снова запускает «Sub UserForm1_Initialize ()». В конце (я думаю, когда он действительно пытается передать значение) он вылетает. Зачем ему снова инициализироваться? Я не выгружаю / не закрываю UserForm1.
 – 
blowcake
10 Дек 2019 в 18:10
Отправил ответ на проблему повторной инициализации вашей формы UserForm на основе фундаментальной статьи @MathieuGuindon "UserForm1.Show?" и его многочисленные сообщения на Stack Overflow; надеюсь внести свой вклад в дальнейшее понимание, по крайней мере, для этих читателей SO, столкнувшихся с той же проблемой :-)
 – 
T.M.
11 Дек 2019 в 21:15

2 ответа

Вы выбираете данные из списка с помощью свойства Column. Начиная с 0.

MyVal = ListBox.Column(0) 'This will store the data in the first column of the selected row
0
tomBob 10 Дек 2019 в 18:04
Я пробовал это раньше, и, боюсь, это не помогло ...
 – 
blowcake
10 Дек 2019 в 18:06
Вы получили ошибку в строке с UserForm1.ComboBox1 = MyVal
 – 
tomBob
10 Дек 2019 в 18:07
Подробнее см. Выше. Это именно строка ошибки.
 – 
blowcake
10 Дек 2019 в 18:11

Обновить поле со списком с помощью списка из второй пользовательской формы

«Похоже, что перед передачей MyVal в ComboBox1 программа снова запускает« Sub UserForm1_Initialize () ».»

Помимо некоторых опечаток (в отношении обоих синтаксисов UserForm_Initiate) ваша основная проблема заключается в том, что, вызывая экземпляр по умолчанию (n существующей) пользовательской формы, вы восстанавливаете ее. Особенно при попытке присвоить значение, ссылаясь на экземпляр по умолчанию другой пользовательской формы (см. Модуль кода UserForm2) через

    UserForm1.ComboBox1 = MyVal 

... повторно инициализирует экземпляр UserForm1 по умолчанию и удаляет все предыдущие изменения.

Измененный пример для понимания пути (см. код ниже)

Поэтому удалите строку кода выше во втором модуле кода Userform и вызовите экземпляр UserForm2 через функцию YourChoice() в первом, возвращая найденное значение MyVal в качестве результата функции, чтобы максимально приблизиться к ваше сообщение с использованием "глобальной" переменной MyVal. Это позволит вам использовать экземпляры UserForm и получить то, что вы хотите.

Дальнейшие возможные шаги - (Не) tl; tr

Однако это хорошее применение

  • не только для создания экземпляра ("нового") объекта UserForm вместо вызова экземпляра формы по умолчанию,

Но

  • для обработки своего события QueryClose, чтобы предотвратить необдуманное завершение,
  • определить время жизни UserForm вызывающим кодом (обычным или классовым модулем),
  • для разделения логики модели (то есть данных), просмотра (то есть формы) и представления, также известного как шаблон проектирования MVP, используя расширенные возможности классов.

Как правило, вы не должны выгружать внутри кода формы - я не изменил этого, чтобы пример был понятен, но рекомендую изучить выдающуюся статью ►Mathieu Guindon " UserForm1.Show? " для первого понимания, лучшего понимания и некоторых идей в пути.

Цитирование

Пользовательская форма - это не только класс , но и внутренняя особенность - или, если процитировать Матье :

"UserForm - это модуль класса: он определяет план объекта . Объекты обычно хотят создавать экземпляры, но потом кому-то пришла в голову гениальная идея предоставить все экземпляры MSForms.UserForm предопределенного идентификатора , что в терминах COM означает, что вы в основном получаете глобальный объект бесплатно ».

ср. Недостатки при помещении кода в UserForms вместо модулей

Измененный пример кода

  • UserForm1
Option Explicit

Sub UserForm_Initialize()             ' << typo: not UserForm1_Initialize !
   ComboBox1.AddItem "Item1"
   ComboBox1.AddItem "Item2"
   ComboBox1.AddItem "Item3"
End Sub

Sub ComboBox1_Click()
   If ComboBox1 = "Item3" Then
      '''      Load UserForm2          ' << don't reference the default instance 
      '''      UserForm2.Show          ' << but
      ComboBox1.List(2) = yourChoice   '    make it a function call returning your choice
   End If
End Sub
  • UserForm2
Option Explicit

Sub UserForm_Initialize()               ' typo: not UserForm2_Initialize !
   ListBox1.AddItem "Apple"
   ListBox1.AddItem "Pear"
   ListBox1.AddItem "Banana"
End Sub

Sub CommandButton1_Click()
    ' Purpose: assign listbox value to variable (here: global; better: via class property)
    MyVal = ListBox1                    ' equals ListBox1.List(ListBox1.ListIndex)
    '''   UserForm1.ComboBox1 = MyVal   ' << reinitializes the default instance of UF1 !!!
    Unload Me                           ' (better to make the calling function terminate the form instead)
End Sub
  • Пример звонка

Боковое примечание: - как можно ближе к OP и придерживаться метода глобальной переменной, как указано выше, чтобы обеспечить лучшее понимание (также учитывайте упомянутые предложения :-)

Option Explicit

Public MyVal As String                  ' here: global variable

Sub showMain()
With New UserForm1
    .Show vbModeless ' any mode allowed: 0-vbModeless  or 1-vbModal (default)
End With
End Sub

Function yourChoice$()
With New UserForm2
    .Show vbModal   ' or simply: .Show to allow a correct return of the function result
End With
yourChoice = MyVal  ' (a modeless form would execute any code before termination)
End Function

Дополнительная ссылка В этом посте не рассматриваются немодальные формы; для вызова второй пользовательской формы таким образом потребуется другая логика - см. Правильно уничтожить немодальный экземпляр UserForm

0
T.M. 11 Дек 2019 в 21:00