Wątek przeniesiony 2021-09-16 10:21 z Inne języki programowania przez cerrato.

VBA - Automatyczne wypełnianie pola textbox po dokonaniu wyboru w dwóch kontrolkach combobox

0

Witam.
Szukałem czegoś na forum, ale nie mogę znaleźć nic co pomogłoby mi rozwiązać mój problem. Jeśli w ogóle jest to możliwe.
Zaznaczam że z VBA miałem niewiele do czynienia.
Poproszono mnie, abym napisał w dokumencie worda makro, które wskazywało by użytkownikowi adres oddziału po wybraniu przez niego
Nazwy firmy, i miasta w którym oddział jest zlokalizowany.
Konkretnie ma to być realizowane przez UserForm, w formatce są dwa pola comboBox i jedno pole TextBox.
Chodzi o to, aby po wybraniu w polu ComboBox1 nazwy firmy, uzupełniane było pole ComboBox2 o nazwy miast w których znajdują się jej oddziały, a po wybraniu konkretnego miasta w polu textbox ma się pojawić adres firmy, następnie te trzy dane za pomocą przycisku mają się wpisać do dokumentu.
Nie ma problemu ze stworzeniem formatki, pól itp. Nie widzę problemu, aby wstawiać dane do dokumentu, ale jak zrobić te pola, aby nie musieć korzystać z zagnieżdżonych if-ów.
Mogę napisać:
if nazwa firmy = "jakaś nazwa" then
else
if nazwa firmy = "jakaś nazwa" then

i tak do końca, ale kod będzie wtedy rozwleczony na kilometry. Czy da się to zrobić prościej.
Najchętniej użyłbym do tego jakiejś relacyjnej bazy danych, ale kierownictwo upiera się na Worda i już.

1
  1. Możesz skorzystać z pliku xml, w VBA załadować go w DOMDocument i lecąc pętelką po node'ach tego xmla wypełniać ComboBoxa.
  2. Jeśli koniecznie musisz mieć to w kodzie, to nie wiem czy bym nie załadowała i tak xmla wprost ze stringa ;)
  3. Możesz też to skonfigurować jako tablicę tablic (albo kolekcję kolekcji) https://stackoverflow.com/questions/9435608/how-do-i-set-up-a-jagged-array-in-vba
0

Niestety nie mogę użyć xml'a, gdybym mógł skorzystać z czegokolwiek innego poza kodem, to było by fajnie.
Co do tabel dla tabel i kolekcji dla kolekcji to nie łapię tego.

Ja to piszę tak:

Private Sub UserForm_Initialize()
ComboBoxFirmy.List = Array("Firma1", "Firma2", "Firma3")

End Sub

Private Sub ComboBoxFirmy_Change()
If ComboBoxFirmy = "Firma1" Then
ComboBoxOddzialy.List = Array("Miasto1", "Miasto2", "Miasto3")

       If ComboBoxFirmy = "Firma2" Then
       ComboBoxOddzialy.List = Array("Miasto2", "Miasto3")
       End If
End If

End Sub

Private Sub ComboBoxOddzialy_Change()
If ComboBoxFirma = "Firma1" Then
If ComboBoxOddzialy = "Miasto1" Then
TextBoxAdresOddzialu.Value = "adres1"
If ComboBox Oddzialy = "Miasto2" Then
TextBoxAdresOddzialu.Value = "adres2"

A w przypadku kolekcji napisałbym tak:

Dim Firmy As New Collection

Firmy.Add "Firma1"
Firmy.Add "Firma2"
Firmy.Add "Firma3"

Dalej nadal musiałbym jednak korzystać z if-ów, więc czym to się różni poza tym, że mam więcej roboty przy deklarowaniu kolekcji?

0

Miałam na myśli trochę bardziej wyrafinowane użycie tablic / kolekcji.
Możesz zadeklarować tablicę dwuwymiarową, która ma taką strukturę:

[ "Firma1", ["Miasto1", "Miasto2", "Miasto3"]]
[ "Firma2", ["Miasto4"]]
[ "Firma3", ["Miasto5"]]
[ "Firma4", ["Miasto1", "Miasto7", "Miasto6"]]

Czyli jej pierwszy element to string z nazwą firmy, a drugi element to tablica stringów z nazwami miast przypisanymi do tej firmy. Żeby robić takie tablice w VBA trzeba wykorzystać typ Variant, który przyjmie wszystko. Uwaga na ewentualne rzutowania przy sprawdzeniach itp. Warto wyguglać "multidimensional arrays in vba", "dynamic multidimensional arrays in vba"

Następnie możemy skorzystać z tej struktury mniej więcej tak:

Private Sub ComboBoxFirmy_Change()
    ForEach item in myArray
        If ComboBoxFirmy == item[0] Then
            ComboBoxMiasta.List = item[1]
        End If
    Next item
End Sub

Dodanie oddziałów to po prostu ekstrapolacja powyższego do trzeciego wymiaru.
IMHO jednak prawdopodobnie prościej będzie wczytać po prostu xmla na żywca ze stringa i działać na node'ach.

0
Dim dane As String
dane = "<xml><dane><firma nazwa='firma1'><oddzial nazwa='o1'/><oddzial nazwa='O2'/></firma><firma nazwa='firma2'><oddzial nazwa='odd1' /><oddzial nazwa='ODD2'/><oddzial nazwa='ODDzial3'/></firma><firma nazwa='pusta'></firma></dane></xml>"

Dim xml As Object

Set xml = CreateObject("MSXML2.DOMDocument")
xml.LoadXML dane

Dim firmy As Object, firma As Object

Set firmy = xml.SelectNodes("//firma[oddzial]/@nazwa")
For Each firma In firmy
    Debug.Print firma.Text
Next


Dim oddzialy As Object, oddzial As Object
Set oddzialy = xml.SelectNodes("//firma[@nazwa='" & firmy(1).Text & "']/oddzial")

For Each oddzial In oddzialy
    Debug.Print oddzial.Attributes.getnamedItem("nazwa").Text
Next


1 użytkowników online, w tym zalogowanych: 0, gości: 1