6.2k Aufrufe
Gefragt in Tabellenkalkulation von florian1010 Mitglied (754 Punkte)
Hallo zusammen,

ich würde wieder eure Hilfe benötigen.

In einem Excelsheet habe ich eine Userform mit vielen TextBoxen. Unter anderem möchte ich m², sprich Länge x Breite errechnen lassen. Für die korrekte Anzeige habe ich auch noch die Höhe mit eingebaut

Dabei habe ich mehrere TextBoxen zur Verfügung (Textbox 101 - 103 (jeweils immer LxBxH), Textbox 201 - 203 usw. bis Textbox 1301 - 1303)

Wie ist es möglich, die TextBoxen aus der UserForm zu multiplizeren und als Summe in einer Zelle (Spalte "K") der aktiven Zeile wiederzugeben? Dabei wäre es wichtig, dass beim aufrufen der Userform die einzelnen Zahlen in den Textboxen wieder zurück gegeben werden. Ist es hier nötig, für jede der TextBoxen eine eigene Zelle zu reservieren, oder würde eine Zelle reichen bzw. benötigt man überhaupt eine Zelle?

Es werden nicht in allen TextBoxen Werte (Zahlen) stehen.

Vielen Dank schon mal für eure Hilfe

VG Florian

26 Antworten

0 Punkte
Beantwortet von
Hallo Florian,

ich versuche mal zu verstehen, was du machen willst. Du hast also ein Userform und möchstest, dass die Textboxen beim Öffnen des Formulars bereits gefüllt sind? Doppelklicke dafür auf das Userform und wähle oben rechts das Initalize Ereignis. Der Code im Form könnte z.B. so aussehen:
Private Sub UserForm_Initialize()
TextBox101.Value = 5: TextBox102.Value = 10: TextBox103.Value = 2
TextBox201.Value = 5: TextBox202.Value = 10: TextBox203.Value = 2
'usw.
End Sub

Wie ist es möglich, die TextBoxen aus der UserForm zu multiplizeren und als Summe in einer Zelle (Spalte "K") der aktiven Zeile wiederzugeben?

Dazu musst du jede Textbox einzeln auswerten. Wenn du das durch den Klick auf eine OK Button auslöst dann doppelklicke auf den Button um das Ereignis zu generieren. Der hinterlegte Code sieht z.B. so aus:
Private Sub BtnOK_Click()
Erg = TextBox101.Value * Textbox102.Value * Textbox103.Value
Erg = Erg + TextBox201.Value * Textbox202.Value * Textbox203.Value
'usw.
Range("K" & ActiveCell.Row).Value = 5
End Sub

Liege ich damit in etwa richtig?

Mr. K.
0 Punkte
Beantwortet von
Alternativ kannst du natürlich die Berechnung auch gleich im Userform hinter jeder Zeile durchführen. Lege dazu eine vierte Spalte an Textboxen an. Dann kannst du folgenden Code verwenden:

Private Sub TextBox101_Change()
Textbox104.Value = Textbox101.Value * textbox102.Value * textbox103.Value
End Sub
Private Sub TextBox102_Change()
Textbox104.Value = Textbox101.Value * textbox102.Value * textbox103.Value
End Sub
Private Sub TextBox103_Change()
Textbox104.Value = Textbox101.Value * textbox102.Value * textbox103.Value
End Sub
Private Sub TextBox201_Change()
Textbox204.Value = Textbox201.Value * textbox202.Value * textbox203.Value
End Sub
Private Sub TextBox202_Change()
Textbox204.Value = Textbox201.Value * textbox202.Value * textbox203.Value
End Sub
Private Sub TextBox203_Change()
Textbox204.Value = Textbox201.Value * textbox202.Value * textbox203.Value
End Sub

Um die Summe zu aktualisieren müsstest du dann in jeder der Subs eine Sub SummeAktualisieren ansprechen in der du dann die x04er Textboxen zusammenrechnest.

Einen einfacheren Weg gibt es leider nicht. Man kann zwar die Textboxereignisse vereinheitlichen, das ist aber zunächst etwas aufwendig und kompliziert anzulegen. Das erkläre ich dir lieber ein anderes mal.

L.G. Mr. K.
0 Punkte
Beantwortet von
Ich sehe grad: In Antwort 1 muss die letzte Codezeile lauten:
Range("K" & ActiveCell.Row).Value = Erg

Sorry für den Fehler!
Mr. K.
0 Punkte
Beantwortet von florian1010 Mitglied (754 Punkte)
Hallo,

vielen Dank schon mal für eure Antworten. Da es glaub ich besser ist, das ganze zu sehen, hab ich eine Datei vorbereitet, wie es denn aussehen soll.

Mit nem Doppelklick auf die Spalte B öffnet sich die "neue" UserForm, die ich zukünftig benutzen möchte. Ein Teil geht schon (Alles bis einschl. Info3). Mit Hilfe der UserForm sollen neue Einträge eingetragen, bei bestehenden Einträgen Änderungen gemacht werden können. Hier ist allerdings noch ein Änderungsschutz eingebau, der zukünftig bei Änderungen über die UserForm außer kraft gesetzt werden.

Die Bezeichnungen sollen zukünftig (hier auch nur die beschriebenen) mit einem "+" getrennt in Info1 geschrieben werden.
Die Gewicht sollen zusammengefasst und als Summe bei Gewicht eingetragen werden.


Mit nem Doppelklick auf die Spalte J (Größe) öffnet sich die UserForm 1 mit der Eingabe der Maße. Dieses soll zukünftig wegfallen.



UserForm Testdatei


Vielen Dank für eure Hilfe

VG Florian
0 Punkte
Beantwortet von
Hallo Florian,

das sieht doch schon gut aus. Hier ein Beispiel, wie du die Artikelmatrix etwas übersichtlicher gestalten kannst:

Füge ein neues Klassenmodul "Klasse1" ein.
Dort gibst du folgenden Code ein:
Const zeilen = 13

Public WithEvents Länge As MSForms.TextBox
Public WithEvents Breite As MSForms.TextBox
Public WithEvents Höhe As MSForms.TextBox

Public WithEvents Tons As MSForms.TextBox
Private Flaeche As Double

Private Sub Tons_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
TBKeyPress KeyAscii
End Sub
Private Sub Länge_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
TBKeyPress KeyAscii
End Sub
Private Sub Breite_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
TBKeyPress KeyAscii
End Sub
Private Sub Höhe_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
TBKeyPress KeyAscii
End Sub

Private Sub TBKeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case 44, 48 To 57
Case Else: KeyAscii = 0
End Select
End Sub

Private Sub Tons_Change()
'Berechnet das Gesamtgewicht in Tonnen

Dim Erg As Double

If Tons.Parent.Controls("TextBox5007").Value = "" Then Tons.Parent.Controls("TextBox5007").Value = 0

For z = 1 To 13
Erg = Erg + IIf(Tons.Parent.Controls("TextBox" & Trim(Str(7000 + z))).Value = "", 0, Tons.Parent.Controls("TextBox" & Trim(Str(7000 + z))).Value)
Next z
Tons.Parent.Controls("TextBox5007").Value = Erg

End Sub
Private Sub Länge_Change()
LBH 1
End Sub
Private Sub Breite_Change()
LBH 2
End Sub
Private Sub Höhe_Change()
LBH 3
End Sub
Private Sub LBH(sp)
'Berechnet die Summe aller Flächen

Dim Erg As Double

If Länge.Parent.Controls("TextBox5012").Value = "" Then Länge.Parent.Controls("TextBox5012").Value = 0

For z = 1 To zeilen
If Länge.Parent.Controls("Textbox" & Trim(Str(z)) & "01").Value = "" And Breite.Parent.Controls("Textbox" & Trim(Str(z)) & "02").Value = "" _
Or Länge.Parent.Controls("Textbox" & Trim(Str(z)) & "01").Value = "" And Höhe.Parent.Controls("Textbox" & Trim(Str(z)) & "03").Value = "" _
Or Breite.Parent.Controls("Textbox" & Trim(Str(z)) & "02").Value = "" And Höhe.Parent.Controls("Textbox" & Trim(Str(z)) & "03").Value = "" Then
Erg = Erg + 0
Else
Erg = Erg + IIf(Länge.Parent.Controls("Textbox" & Trim(Str(z)) & "01").Value = "", 1, Länge.Parent.Controls("Textbox" & Trim(Str(z)) & "01").Value) _
* IIf(Breite.Parent.Controls("Textbox" & Trim(Str(z)) & "02").Value = "", 1, Breite.Parent.Controls("Textbox" & Trim(Str(z)) & "02").Value) _
* IIf(Höhe.Parent.Controls("Textbox" & Trim(Str(z)) & "03").Value = "", 1, Höhe.Parent.Controls("Textbox" & Trim(Str(z)) & "03").Value)
End If
Next z

Länge.Parent.Controls("TextBox5012").Value = Erg

End Sub

Anschließend fügst du ganz oben im Userform3_Codefenster
(oberhalb der ersten Sub!) diese 2 Zeilen ein:
Const zeilen = 13
Dim Artikel(zeilen) As New Klasse1

Schließlich noch im Userform3_Initialize Ereignis diesen Codeblock:
For z = 1 To zeilen
Set Artikel(z).Tons = Controls("Textbox" & Trim(Str(7000 + z)))
Set Artikel(z).Länge = Controls("Textbox" & Trim(Str(z)) & "01")
Set Artikel(z).Breite = Controls("Textbox" & Trim(Str(z)) & "02")
Set Artikel(z).Höhe = Controls("Textbox" & Trim(Str(z)) & "03")
Next z


Damit kannst du dir sämtliche anderen Ereignishandler für die 13 Artikelzeilen sparen. Der Code im Klassenmodul wird von jedem Feld ausgelöst. Die Set-Anweisung im Initalize-Ereignis verknüpft die Textboxen auf das Klassenmodul

Achtung: Der letzte Code im Klassenmodul geht davon aus, dass du im Formular noch ein Textfeld "Textbox5012" anlegst. Dort wird die Summe der 13 Flächen wiedergegeben, welche du beim Schließen des Formulars dann in Spalte K übernehmen kannst.

Ich hoffe ich habe dein Anliegen damit jetzt verstanden. Falls weitere Probleme bestehen, melde dich einfach nochmal.

Gruß Mr. K.
0 Punkte
Beantwortet von florian1010 Mitglied (754 Punkte)
Hallo Mr. K.,

erst mal vielen Dank.

... Or Breite.Parent.Controls("Textbox" & Trim(Str(z)) & "02").Value = "" And Höhe.Parent.Controls("Textbox" & Trim(Str(z)) & "03").Value = "" Then ...

und

... * IIf(Höhe.Parent.Controls("Textbox" & Trim(Str(z)) & "03").Value = "", 1, Höhe.Parent.Controls("Textbox" & Trim(Str(z)) & "03").Value) ...

habe ich rausgelöscht, da ich nur L x B errechnet brauche.

Jetzt hab ich allerdings noch die problematik, dass es mir die 13 zeilen nicht von der UserForm aufs Sheet überträgt, bzw. beim öffnen der UserForm vom Sheet.


Zudem splittet es beim wiederaufruf mit dem der UserForm die Gewichte nicht wieder je "Zeile" auf.

VG Florian
0 Punkte
Beantwortet von
Hallo Florian,

Du wolltest, dass die Summe der Tonnen und der Fläche in EINER Zeile erscheint. Das macht mein Makro mit Umweg über eine Textbox im Formularkopf, aus Gründen der Übersichtlichkeit. Diese Textbox kann bei Klick auf Übernehmen in das Sheet eingetragen werden. Den Code dafür bekommst du selbst hin. Darüberhinaus bietet der Code die Artikelzeilen als Datenarray an, sodass eine weitere Bearbeitung recht einfach ist. Wenn du nun (wie in deiner Ausgangsfrage beschrieben) beim Neuöffnen des Formulars, wieder die einzelenen Artikel sehen willst, benötigst du mindestens noch eine Spalte für die einzelnen Gewichte. Ich nutze hierfür mal Spalte V, die Bezeichnungen in O und die Maße in J:

In Klasse 1 solltest du oben die neue Variable Public WithEvents Info1 As MSForms.TextBox definieren und folgende Sub hinzufügen:
Private Sub Info1_Change()
Dim bez As String

For z = 1 To zeilen
bez = bez + Info1.Parent.Controls("Textbox" & Trim(Str(6000 + z))).Value & IIf(Info1.Parent.Controls("Textbox" & Trim(Str(6000 + z))).Value <> "", " / ", "")
Next z

Info1.Parent.Controls("Textbox5010").Value = Left(bez, Len(bez) - 3)
End Sub


Außerdem solltest du unbedingt in Sub TBKeyPress als erste Zeile das hier einzufügen:
If Info1.Value = "" Then MsgBox "Geben Sie zuerst eine Bezeichnung ein", vbInformation, ActiveWorkbook.Name
Damit kannst du verhindern, dass Maßangaben gespeichert werden, für die keine Bezeichnung existiert, da sonst das Programm beim Neuöffnen die Daten durcheinander würfeln würde.

In Userform3 wird am Ende von CommandButton1_Click (aber natürlich vor Unload me) das hier eingefügt:
For ze = 1 To zeilen
If Artikel(ze).Info1 <> "" Then LBH = LBH & Artikel(ze).Länge & " x " & Artikel(ze).Breite & " x " & Artikel(ze).Höhe & " / "
If Artikel(ze).Info1 <> "" Then Tn = Tn & Artikel(ze).Tons & " / "
Next ze

Cells(z, 10) = Left(LBH, Len(LBH) - 3)
Cells(z, 22) = Left(Tn, Len(Tn) - 3)

Zu guter Letzt ersetzt du im Initialize-Ereignis die For-To-Next-Schleife durch diesen Code:
InputTons = Split(Cells(ActiveCell.Row, 22), " / ")
InputLBH = Split(Cells(ActiveCell.Row, 10), " / ")
InputBez = Split(Cells(ActiveCell.Row, 15), " / ")

For z = 1 To zeilen
Set Artikel(z).Tons = Controls("Textbox" & Trim(Str(7000 + z)))
Set Artikel(z).Länge = Controls("Textbox" & Trim(Str(z)) & "01")
Set Artikel(z).Breite = Controls("Textbox" & Trim(Str(z)) & "02")
Set Artikel(z).Höhe = Controls("Textbox" & Trim(Str(z)) & "03")
Set Artikel(z).Info1 = Controls("Textbox" & Trim(Str(6000 + z)))

If z <= UBound(InputTons) + 1 Then Artikel(z).Tons = InputTons(z - 1)
If z <= UBound(InputLBH) + 1 Then
PartLBH = Split(InputLBH(z - 1), " x ")
Artikel(z).Länge = PartLBH(0)
Artikel(z).Breite = PartLBH(1)
Artikel(z).Höhe = PartLBH(2)
End If
If z <= UBound(InputBez) + 1 Then Artikel(z).Info1.Value = InputBez(z - 1)
Next z


Ich denke mit diesen Infos bekommst du den Rest selbst hin. Du hast ja bereits gut vorgearbeitet.

L.G. Mr. K.
0 Punkte
Beantwortet von
Soeben habe ich noch einen Bug entdeckt.
Ersetze die For-To-Next-Schleife im Initalize-Ereignis lieber durch diesen Code (Änderung fettgedruckt). Dann klappts:
InputTons = Split(Cells(ActiveCell.Row, 22), " / ")
InputLBH = Split(Cells(ActiveCell.Row, 10), " / ")
InputBez = Split(Cells(ActiveCell.Row, 15), " / ")

For z = 1 To zeilen
Set Artikel(z).Tons = Controls("Textbox" & Trim(Str(7000 + z)))
Set Artikel(z).Länge = Controls("Textbox" & Trim(Str(z)) & "01")
Set Artikel(z).Breite = Controls("Textbox" & Trim(Str(z)) & "02")
Set Artikel(z).Höhe = Controls("Textbox" & Trim(Str(z)) & "03")
Set Artikel(z).Info1 = Controls("Textbox" & Trim(Str(6000 + z)))

If z <= UBound(InputTons) + 1 Then Artikel(z).Tons = InputTons(z - 1)
If z <= UBound(InputLBH) + 1 Then
PartLBH = Split(InputLBH(z - 1), " x ")

If UBound(PartLBH) > 0 Or PartLBH(0) > 0 Then Artikel(z).Länge = PartLBH(0)
If UBound(PartLBH) > 0 Or PartLBH(0) > 0 Then Artikel(z).Breite = PartLBH(1)
If UBound(PartLBH) > 0 Or PartLBH(0) > 0 Then Artikel(z).Höhe = PartLBH(2)
End If
If z <= UBound(InputBez) + 1 Then Artikel(z).Info1.Value = InputBez(z - 1)
Next z


Gruß Mr. K.
0 Punkte
Beantwortet von
Uups. Im Codeblock wird wohl kein Fettdruck unterstützt. Ignoriere und
0 Punkte
Beantwortet von
Ich meinte ignoriere b und /b (in eckigen Klammern)
...