Microsoft Excel

Herbers Excel/VBA-Archiv

Informationen und Beispiele zum Thema InputBox
BildScreenshot zu InputBox InputBox-Seite mit Beispielarbeitsmappe aufrufen
Informationen und Beispiele zum Thema MsgBox
BildScreenshot zu MsgBox MsgBox-Seite mit Beispielarbeitsmappe aufrufen
Informationen und Beispiele zum Thema CommandButton
BildScreenshot zu CommandButton CommandButton-Seite mit Beispielarbeitsmappe aufrufen
Informationen und Beispiele zum Thema Userform
BildScreenshot zu Userform Userform-Seite mit Beispielarbeitsmappe aufrufen
Informationen und Beispiele zum Thema Frame
BildScreenshot zu Frame Frame-Seite mit Beispielarbeitsmappe aufrufen
Informationen und Beispiele zum Thema Label
BildScreenshot zu Label Label-Seite mit Beispielarbeitsmappe aufrufen
Informationen und Beispiele zum Thema ListBox
BildScreenshot zu ListBox ListBox-Seite mit Beispielarbeitsmappe aufrufen
Informationen und Beispiele zum Thema TextBox
BildScreenshot zu TextBox TextBox-Seite mit Beispielarbeitsmappe aufrufen

change-ereignis bei dynamischen Controls / Teil 2

Betrifft: change-ereignis bei dynamischen Controls / Teil 2 von: Thomas
Geschrieben am: 20.03.2008 15:50:18

Hallo,

nachdem ich vor ein paar Tagen die bittere Erfahrung machen mußte, daß es bei meinem Problem ohne Klassenmodul nicht gelöst werden kann, habe ich mich damit beschäftigt und komme zu folgender Frage.

Sehe ich das richtig, daß zunächst meine Controls wie gehabt dynamisch erstellt und dann als Klassen-Objekte definiert werden müssen?

UserForm: Positionen

Option Explicit
Dim new_ctl As MSForms.Control
Dim ctl_Art(88) As Variant


Private Sub UserForm_Initialize()
    For n = 0 To Anz_ctl
            
    Set new_ctl = Positionen.Controls.Add("Forms.TextBox.1", ctl_Art( n), True)
    new_ctl.Move Left:=Links_Box(n),Top:=Oben_Box(n),Width:=Breite_Box(n),Height:=Höhe_Box(n)

    Call Klassen_Objekte_definieren
Next n


Sub Klassen_Objekte_definieren()
    Dim ctl_txt As Object
    Dim m As Integer
    
    m = -1
    For Each ctl_txt In Positionen.Controls
        If TypeOf ctl_txt Is MSForms.TextBox Then
            m = m + 1
            ReDim Preserve Ftxt(m)
            Set Ftxt(m) = New cls_txt
            Ftxt(m).Create ctl_txt
        End If
    Next ctl_txt
End Sub



Meine Eingaben im Klassenmodul sind nun folgende:

Klassenmodul: cls_txt

Option Explicit
Dim WithEvents txt As MSForms.TextBox


Public Function Create(TextBox As MSForms.TextBox) As Boolean
    Set txt = TextBox
    If Not txt Is Nothing Then
        Create = True
    End If
End Function




Private Sub txt_Change()
    On Error Resume Next
    ' MsgBox txt.Name
End Sub



Obwohl das ganze funktioniert, meine Frage an die Fachleute, ob ich so weiter wursteln kann, oder ob ihr irgendwelche Bedenken dabei habt.

Viele Grüße
Thomas

  

Betrifft: AW: change-ereignis bei dynamischen Controls / Tei von: Rudi Maintaire
Geschrieben am: 20.03.2008 16:28:28

Hallo,
so:
in der UF (Positionen)

Option Explicit

Private Sub UserForm_Initialize()
   Dim i As Integer
   For i = 1 To 88
   Set oClsPositionen(i).myTxt = Me.Controls.Add("forms.textbox.1")
   With oClsPositionen(i).myTxt
      .Left = 20
      .Top = (i - 1) * 24 + 10
   End With
   Next
   Me.Height = oClsPositionen(88).myTxt.Top + 30
End Sub



In einem Modul:

Option Explicit
Public oClsPositionen(1 To 88) As New clsPositionen


Klassenmodul (clsPositionen)

Option Explicit

Public WithEvents myTxt As MSForms.TextBox

Private Sub myTxt_Change()
   myTxt = UCase(myTxt)
End Sub



Gruß
Rudi

Eine Kuh macht Muh, viele Kühe machen Mühe


  

Betrifft: AW: change-ereignis bei dynamischen Controls / Tei von: Thomas
Geschrieben am: 21.03.2008 11:12:13

Hallo Rudi,

vielen Dank für Deine Antwort.

Natürlich funktioniert alles genau so wie Du es angegeben hast.
Nun wollte ich es für mich ein bisschen abändern und bin dabei kläglich gescheitert.

Dehalb meine Fragen:

1. Wie kann ich die Controls in Gruppen bestehend aus jeweils:
TextBox
TextBox
TextBox
TextBox
ComboBox
TextBox
ComboBox
TextBox
TextBox
zusammenfassen?

2. Wie kann ich dann diese Gruppen so durchnummerieren
Gruppe1 Controls 110 - 118
Gruppe2 Controls 120 - 128 usw.

3. Wie kann ich durch einen Button eine Gruppe hinzufügen?

4. Wie kann ich durch einen Button eine Gruppe löschen und dann neu durchnummerieren?

Du hast recht mit Muh und Mühe, aber ich befürchte auch alleine Mühe zu machen.

Viele Grüße
Thomas


  

Betrifft: AW: change-ereignis bei dynamischen Controls / Tei von: Thomas
Geschrieben am: 21.03.2008 14:11:40

Hallo Rudi,

momentan überhole ich mich selbst.
Zu meiner Nachfrage habe ich für 1. und 2. folgende Lösung gefunden:

For m = 0 To 88
        Links = 6
        For n = 0 To 8
            Set ctl_txt(m, n).txt = Me.Controls.Add("forms.textbox.1", _
                "TextBox" & ((100 + (m + 1) * 10) + n), True)
            With ctl_txt(m, n).txt
                .Left = Links
                .Top = Oben
                .Width = 60
            End With
            Links = Links + 80
        Next n
        Oben = Oben + 20
    Next m


Nun mal nur am Beispiel der TextBoxen. Für die ComboBoxen will ich eine If-Abfrage machen für n=4 oder n=6.
Natürlich muß ich die ComboBoxen noch im Modul definieren und ein Klassenmodul für sie anlegen.

Was bleibt ist 3. und 4.

Viele Grüße
Thomas (Muh)


  

Betrifft: AW: change-ereignis bei dynamischen Controls / Tei von: fcs
Geschrieben am: 21.03.2008 22:01:29

Hallo Thomas,

wie bist du nur auf die Idee verfallen hier bis zu 88 Steuerfeld-Gruppen anzulegen (Horror). Das muss doch auch anders in übersichtlicherer Form darstellbar sein.

Grundsätzlich kann man die Elemente über den Namen wieder löschen und dabei systematisch nach der Gruppennummer suchen. Zum Einfügen weiterer Gruppen muss die kleinste und die max. Gruppennummer in einer Modulweiten-Variablen gespeichert und jeweils bei Löschungen/Hinzufügen angepasst werden.

In der mit Excel97 erstellten Beispieldatei findest du auch den nachfolgenden Code im Userform.
https://www.herber.de/bbs/user/50911.xls

Gruß
Franz

Option Explicit
Private Gruppe1 As Integer ' niedrigste Gruppen-Zählnummer
Private GruppeMax As Integer 'höchste Gruppen-Zählnummer
Private Oben As Double, Links As Double
Private element As Control 'Steuerelement
Const Links1 As Double = 10 'Startposition für Steuerelemente
Const Oben1 As Double = 35 'Startposition für Steuerelemente
Const AbstandVertikal As Double = 20 'Abstand der Gruppen

Private Sub CB_GruppeHinzu_Click()
  GruppeMax = GruppeMax + 1
  Oben = Oben1 + (GruppeMax - Gruppe1) * AbstandVertikal
  Call GruppeHinzu(GruppeMax, Oben)
End Sub

Private Sub CB_GruppeLoeschen_Click()
  Dim iGruppe As Integer
  iGruppe = Val(InputBox("Bitte die ersten beiden Ziffern der Gruppe eingeben", _
      "Steuerelement-Gruppe löschen", Format(Gruppe1, "00")))
  If iGruppe = 0 Then GoTo ende
  'Gruppenelement löschen
  For Each element In Me.Controls
    If Left(Right(element.Name, 3), 2) = Format(iGruppe, "00") Then
      Oben = element.Top
      Me.Controls.Remove (element.Name)
    End If
  Next element
  'Gruppen neu nummeriern und positionieren
  If iGruppe < GruppeMax Then
    For iGruppe = iGruppe + 1 To GruppeMax
      For Each element In Me.Controls
        If Left(Right(element.Name, 3), 2) = Format(iGruppe, "00") Then
          element.Name = Left(element.Name, Len(element.Name) - 3) _
                & Format(iGruppe - 1, "00") & Right(element.Name, 1)
          element.Top = Oben
          If element.Name = "LabelGr" & Format(iGruppe - 1, "00") & "1" Then
            element.Object.Caption = Format(iGruppe - 1, "00")
          End If
        End If
      Next element
    Oben = Oben + AbstandVertikal
    Next iGruppe
  End If
  GruppeMax = GruppeMax - 1
ende:
End Sub

Private Sub CB_Schliessen_Click()
  Unload Me
End Sub

Private Sub UserForm_Activate()
  Dim ii As Integer
  Gruppe1 = 10: GruppeMax = 19
  Oben = Oben1
  For ii = Gruppe1 To GruppeMax Step 1
    Call GruppeHinzu(ii, Oben)
    Oben = Oben + AbstandVertikal
  Next
End Sub

Private Sub GruppeHinzu(GruppeNr As Integer, iOben As Double)
  'Elemente einer Gruppe erzeugen
  Dim tbox As Integer
  'Label mit GruppenNr
  Links = Links1
  Set element = Me.Controls.Add(bstrprogid:="Forms.Label.1", _
      Name:="LabelGr" & Format(GruppeNr, "00") & "1")
  element.Top = iOben
  element.Left = Links
  element.Width = 15
  element.Caption = Format(GruppeNr, "00")
  Links = Links + 20
  'Textboxen 1 bis 3
  For tbox = 1 To 3
    Set element = Me.Controls.Add(bstrprogid:="Forms.TextBox.1", _
        Name:="Textbox" & Format(GruppeNr, "00") & Format(tbox, "0"))
    element.Top = iOben
    element.Left = Links
    element.Width = 25
    element.Value = GruppeNr * 10 + tbox 'testwertzuweisung
    Links = Links + 35
  Next tbox
End Sub




  

Betrifft: AW: change-ereignis bei dynamischen Controls / Tei von: Thomas
Geschrieben am: 22.03.2008 15:51:37

Hallo liebe Experten,

vielleicht seid ihr bitte so nett, euch mein Beispiel anzusehen. Ihr seht bestimmt, wo bei mir der Wurm drin liegt.
https://www.herber.de/bbs/user/50934.zip

Auf Tabelle 'Rechnung' klicken,
in der ListBx die erste Zeile markieren
dann 'Wählen' klicken
und schließlich 'Positionen'

Bei vorhandenen Daten:
Besonderen Wert lege ich darauf, daß Änderungen der Menge, oder des Preises sofort in die Summen auf der UserForm u n d in der Tabelle übernommen werden.

Wenn eine Position hinzu gefügt wurde:
Das ist leider etwas holprig. Ich mußte die Feststellung machen, daß zunächst alle Wete auf '0' gesetz werden müssen, damit auch mit der neuen Position gerechnet wird.

Löschen einer Position:
Dabei scheitere ich schon am markieren des Frames. Am liebsten würde ich ihn rot umranden.
Wie kann man dann nach der Bestätigung des Löschens den ganzen Frame löschen?
Und wie kann ich dann die Controls wieder einlesen, daß die Positionen auf der UserForm wider mit denen in der Tabelle wieder übereinstimmen?


Liege ich denn völlig falsch, oder ist mein Ansatz wenigstens ein bisschen richtig?

Viele Grüße
Thomas


  

Betrifft: AW: change-ereignis bei dynamischen Controls / Tei von: fcs
Geschrieben am: 23.03.2008 03:52:59

Hallo Thomas,

ich hab mir deine Userformen mal angesehen.

Das Problem bei der Anzeige aller Positionen ist, dass während der Initialisierung des Userform bereits die Berechnungen gestartet werden obwohl noch nicht alle Steuerelemente einer Position angelegt sind. Dadurch kommt es zum Abbruch, wenn von diesen noch fehlenden Steuerelementen Werte ausgelesen werden sollen.
Abhilfe:
Steuere über eine Boolsche Variable, dass während der Formblattinitialisierung die Berechnungen nicht ausgeführt bzw. übersprungen werden.
In der Textdatei findest du den UF-Code entsprechend modiifziert. Die Zeilen hab ich mit '###fcs markiert.

Bei mir unter Excel97 hab ich dann mehrfach noch Probleme weil die Rechenfunktionen einen Text oder Leerstrings verarbeiten müssen. Das hab ich aber nicht bereinigt.

Ich hab in der zweiten Datei das UF Positionen mal komplett anders aufgebaut.
Die Positionen werden in einer Listbox angezeigt und nur die Daten der jeweils selektierte Position werden in einem Satz Steuerelemente angezeigt.
Mit dieser Methode ist es kein Problem Positionen einzufügen oder zu löschen.
Das ganze beruht darauf, dass alle Daten einer Rechnung in einem Range-Objekt (rngRechnung) verwaltet werden. Dieses Range-Objekt, das ja nicht anderes als ein Auszug aus der Gesamttabelle ist, wird dann benutzt um die Auswahlliste zu füllen und samtliche Summenberechnungen durchzuführen.
Das UF Rechnungen hab ich um etwas Funktionalität ergänzt. Per Schieberegler kann man durch die Positionen scrollen und Daten editieren. Die Löschfunktion funktioniert hier genau so wie im UF Positionen.
Im Moment werden die Eingaben/Änderungen nicht direkt in die Tabelle geschrieben sondern erst nach Klick auf den Button. Dies kann man aber relativ einfach ändern, wobei evtl. nicht das Change sondern das Exit-Ereignis für die Aktualisierung genutzt werden sollte. Für die Textboxen (Menge, Einzelpreis und EZ Einzelpreis wird beim Verlassen (Exit-Ereignis) geprüft, ob eine Zahl eingegeben ist. Dadurch gibt es bei der Weiterverarbeitung der Eingabe weniger Probleme.

Auf die Klassen-Module für die Text- bzw. Combobox hab ich verzichtet. Für die wenigen jetzt noch betroffenen Steuerelemente kann man den entsprechenden Code ggf. auch direkt im UF-Modul anlegen.

https://www.herber.de/bbs/user/50946.zip

Gruß
Franz


  

Betrifft: AW: change-ereignis bei dynamischen Controls / Tei von: Thomas
Geschrieben am: 23.03.2008 14:21:51

Hallo Franz,

vielen Dank für Deine ausführliche Antwort!

Du hast mich wieder auf den Pfad der Tugend zurück gebracht.
Für mich war die einzige Lösung mehrere Positionen auf einer neuen UserForm einfach Stück für Stück untereinander zu "malen". Dadurch habe ich mich in den Bereich der Klassenmodule verirrt, von dem ich nun gar nichts verstehe und so geriet ich immer weiter in Probleme hinein.
Damit möchte ich mich bei allen anderen die mir in dieser Richtung geholfen haben entschuldigen, denn die wußten ja gar nicht was ich eigentlich wollte.
Deine Lösung ist viel besser! In einer ListBox hat man alle Positionen zusammen schön aufgeführt und die, welche man wirklich ändern möchte, gesondert im Fokus.
Nun muß ich mich Punkt für Punkt mit Deiner Lösung beschäftigen. Wenn ich dazu noch weitere Fragen haben sollte, was ich stark vermute, soll ich dann diese hinter diesen Thread schreiben, oder wie mache ich das?

Nochmals vielen Dank für Deine Mühe

und Viele Grüße
Thomas


  

Betrifft: AW: change-ereignis bei dynamischen Controls / Tei von: fcs
Geschrieben am: 23.03.2008 22:00:17

Hallo Thomas,

solange der Thread noch in der Forums-Liste angezeigt wird solltes du weitere Fragen anhängen.

Später dann neuen Thread anlegen mit Link auf den ursprünglichen Thread.

Ein Tip noch: Falls die Zahl der Datenspalten in der Datentabelle noch nicht endgültig feststeht, dann solltest du die Nr. der letzten Spalte im Modul Basis in einer Public Konstanten festlegen und in allen Anweisungen
Set rngRechnung = Range(Cells(...,1),Cells(...,42))
die 42 durch die Konstante ersetzen. Dann wird die Pflege des Codes ggf. einfacher.

Gruß
Franz


  

Betrifft: Change-Ereignis Teil 3 von: Thomas
Geschrieben am: 30.03.2008 15:55:42

Hallo im Forum,

inzwischen bin ich von den dynamischen Controls wieder abgekommen, aber trotzdem etwas weiter.
Geblieben sind die Probleme mit den Change-Ereignissen.
Am anschaulichsten ist es sicher mit einem Beispiel.
https://www.herber.de/bbs/user/51150.zip

Wird eine vorhandene Rechnung geändert/ergänzt/gedruckt, genügt ein klick auf die ListBox1.
Alle Änderungen werden sofort berechnet, in der UserForm dargestellt und in die Tabelle geschrieben. Beendet wird dieser Vorgang durch den CommandButton "BEENDEN", welcher später das Speichern der Daten beinhalten soll, oder durch die Eingabe einer neuen Rechnung.

Bei der Eingabe einer neuen Rechnung wird der Kunde über die ComboBox0 gewählt, wobei unterschieden wird, ob es sich um einen Kunden mit eigener Konto-Nr. handelt, oder einen "Diversen", für welchen durch klicken des CommandButton "i" die Daten eingegeben werden.
Danach wird sofort eine Daten-Zeile mit der Anschrift des Kunden in die Tabelle geschrieben.
Nun sollen wie oben die Daten Position für Position eingegeben werden können und während der Eingabe fortlaufend berechnet werden.
Beendet soll dieser Vorgang wie bei der vorhandenen Rechnung werden. Wobei die neue Rechnung ohnehin nach Eingabe der KundenDaten, wie eine vorhandene behandelt werden soll.

Woran mir besonders liegt, ist das Problem ohne weitere CommandButtons, wie etwa "Änderung berechnen" und/oder "Eingabe beenden" o.ä. zu lösen.

Bei der Berechnung ist wichtig zu wissen, daß nicht nur die Variante Menge * Stückpreis = Gesamtpreis, sondern auch nur ein Gesamtpreis möglich sein sollte. In diesem Fall sollte die Stelle des Stückpreises leer bleiben.

Was meint Ihr zu meinem Ansatz, bin ich auf dem richtigen Weg?

Viele Grüße
Thomas


 

Beiträge aus den Excel-Beispielen zum Thema "change-ereignis bei dynamischen Controls / Teil 2"