Supportnet / Forum / Tabellenkalkulation
Makro in Excel zum zählen von Werten
Frage
Hallo
habe heute mein erstes Makro geschrieben. Nun bekomme ich diverse Fehlermeldungen. Kann mir einer sagen was falsch daran ist?
Was will ich bewirken?
Ich möchte aus einer Spalte Werte zählen.
Bsp:
Sonne
Mond
Sterne
Sonne
Sterne
...
Die Anzahl der möglichen String-Variationen ist offen. Die zu vergleichenden Zeilen sollen später entweder durch Eingabe oder durch Excel selbst (wenn sie leer sind ganz unten) bemerkt werden.
Das Script soll nun zählen wie oft Sonne, Mond oder Sterne in der Spalte auftreten und dieses Ergebnis in Spalte B und C präsentieren. (ist noch nicht ganz fertig das Script )
also:
Sonne 2
Mond 1
Sterne 2
Hier das Script:
[code]Public Sub Werte_zählen()
Dim ncounter As Integer
Dim Wert As String
Dim i As Integer
Dim a As Integer
ReDim Vektor(i) As Integer
ReDim count(i) As Integer
i = 1
For ncounter = 1 To 25
rem (die 25 wird später mal Variable oder Eingabe)
a = i
Wert = Cells(ncounter, 1).Value
If Vektor(i) <> Wert Then
rem ( in dieser Zeile, if vektor(i) ... kommt Fehlermeldung, siehe unten)
If i > 1 Then
i = i - 1
Else
i = a
Vektor(i) = Wert
End If
Else
count(i) = count(i) + 1
End If
i = a + 1
Next ncounter
For i = 1 To a
Cells(i, 2).Value = Vektor(i)
i = i + 1
Next i
End Sub [/code]
* An dieser Stelle kommt die Fehlermeldung :
"Laufzeitfehler ´9´
Index außerhalb des gültigen Bereichs"
Kann wer helfen?
Gruß
SkunK
Antwort 1 von Karlchen
Die Fehlermeldung erhältst Du, weil das Feld Vektor nur 1 Element enthält. Auf dieses kannst Du nur mit dem Index 0 zugreifen. i hat aber zum Zeitpunkt der Fehlermeldung schon den Wert 1 und versucht daher auf ein Element zuzugreifen, welches nicht existiert.
Wenn Du diesen Fehler beseitigst wird ein neuer auftreten.
Vergleicht einen Integer-Wert mit einem String. Du kannst nur gleiche Datentypen miteinander vergleichen.
leider habe ich im Moment keine Zeit, sonst würde ich Dir das Makro schreiben, aber ich hoffe, ich konnte weiterhelfen.
nicht den Mut verlieren
Karlchen
Wenn Du diesen Fehler beseitigst wird ein neuer auftreten.
Zitat:
If Vektor(i) <> Wert Then
If Vektor(i) <> Wert Then
Vergleicht einen Integer-Wert mit einem String. Du kannst nur gleiche Datentypen miteinander vergleichen.
leider habe ich im Moment keine Zeit, sonst würde ich Dir das Makro schreiben, aber ich hoffe, ich konnte weiterhelfen.
nicht den Mut verlieren
Karlchen
Antwort 2 von Saarbauer
Hallo,
der Fehler liegt nicht in der Zeile sonder in den Zeilen davor. "Vektor" ist "Integer" und "Wert" "String" Ausserdem wird der Wert "i" erst nach der ersten Verwendung gesetzt.
nach meiner Meinung sind auch die beiden Funktionen
"ReDim Vektor(i) As String
ReDim Count(i) As Integer"
an der falschen Stelle.
Es sind nach meiner Meinung noch weitere Fehler drin. aber da guckst du vielleicht selber , da ich nicht genau weß was du vorhast.
Gruß
Helmut
der Fehler liegt nicht in der Zeile sonder in den Zeilen davor. "Vektor" ist "Integer" und "Wert" "String" Ausserdem wird der Wert "i" erst nach der ersten Verwendung gesetzt.
nach meiner Meinung sind auch die beiden Funktionen
"ReDim Vektor(i) As String
ReDim Count(i) As Integer"
an der falschen Stelle.
Es sind nach meiner Meinung noch weitere Fehler drin. aber da guckst du vielleicht selber , da ich nicht genau weß was du vorhast.
Gruß
Helmut
Antwort 3 von Skunk
hmm,, danke erst mal für eure antworten, aber das mit dem Array versteh ich anscheind nicht ganz. Das mit dem "ReDim Vektor(i) As Integer" hat ich nur zu testzwecken mit zahlen.
Aber wie meint ihr das, dass i am anfang null hat oder so?
Was ich erreichen will ist, eine Variable mit x möglichen "Speicherfeldern" also zB Vector(20), kann 20 Zahlen bzw. Werte beeinhalten.
zB. Vector(1) = Sonne, Vector(2) = Mond, Vector(i) = xxx
Daher will ich eine Variable bzw. einen Vektor, der i - verschiedene Strings speichern kann. Oder muss ich vorher die Größe des Vectors angeben also
um dann später in der Berechnung Vektor(i) für 0 <= i <=100 die Speicherfelder nutzen zu können?
Aber wie meint ihr das, dass i am anfang null hat oder so?
Was ich erreichen will ist, eine Variable mit x möglichen "Speicherfeldern" also zB Vector(20), kann 20 Zahlen bzw. Werte beeinhalten.
zB. Vector(1) = Sonne, Vector(2) = Mond, Vector(i) = xxx
Daher will ich eine Variable bzw. einen Vektor, der i - verschiedene Strings speichern kann. Oder muss ich vorher die Größe des Vectors angeben also
ReDim Vektor(100) As String
um dann später in der Berechnung Vektor(i) für 0 <= i <=100 die Speicherfelder nutzen zu können?
Antwort 4 von cmkatz
Hi,
hab hier mal was gebastelt. Einziger Makel: in Spalte B wird noch einma die ganze Werteliste der Spalte A aufgeführt.
Hab das noch nicht wirklich hinbekommen...
Aber ein Anfang ist es! ;-)
Also hier der Code:
Gruß
cmkatz
hab hier mal was gebastelt. Einziger Makel: in Spalte B wird noch einma die ganze Werteliste der Spalte A aufgeführt.
Hab das noch nicht wirklich hinbekommen...
Aber ein Anfang ist es! ;-)
Also hier der Code:
Public Sub Werte_zählen()
Dim ncounter As Integer
Dim i As Integer
Dim a As Integer
Dim y As Integer
ReDim Vektor(1 To 500) As String
ReDim Count(1 To 500) As Integer
Dim ZelleLeer As Boolean
Dim written As Boolean
´ Vektor füllen:
´=============================
ZelleLeer = False
i = 0
Do Until ZelleLeer = True
i = i + 1
Vektor(i) = Cells(i, 1).Value
If Cells(i + 1, 1).Value = "" Then
ZelleLeer = True
End If
Loop
´Counter füllen:
´=============================
For a = 1 To i
y = 1
For ncounter = 1 To i
If Vektor(a) = Cells(ncounter, 1).Value Then
Count(a) = y
y = y + 1
Else
Count(a) = Count(a)
End If
Next ncounter
Next a
´Spalten B und C mit Vektoren fuellen:
´==============================
For a = 1 To i
Cells(a, 2).Value = Vektor(a)
Cells(a, 3).Value = Count(a)
Next a
End Sub
Gruß
cmkatz
Antwort 5 von Saarbauer
Hallo,
wenn du die Funktion
ReDim
so anordnest, dass sie erhöht wird wenn ein neuer wert kommt hast du das erreicht was du willst..
du kannst i mit in Prinzip mit null anfangen lassen, aber
ReDim Vektor( i) As Integer
ReDim count( i) As Integer
könnte Schwierigkeiten bereiten.
Gruß
Helmut
wenn du die Funktion
ReDim
so anordnest, dass sie erhöht wird wenn ein neuer wert kommt hast du das erreicht was du willst..
du kannst i mit in Prinzip mit null anfangen lassen, aber
ReDim Vektor( i) As Integer
ReDim count( i) As Integer
könnte Schwierigkeiten bereiten.
Gruß
Helmut
Antwort 6 von Skunk
danke danke Leute ihr seid echt spitze ;)
allerdings hab ichs schon selbst fast geknackt.
ok. also cmkatz, dein Code sehr gut, hab in der zeit auch noch´n bissl rum gespielt. Hat eigentlich geklappt. er gab mir die Werte aus. Allerdings immer nur den ersten. Denk ma, dass da ein i oder a falsch läuft und nur i=1 ausgegeben wird. letzte schleife vermutlich.
Dein Code nutzt einen Trick nicht aus, weshalb er alle (im maximalen Fall) 500 Stringsätze ausgibt.
Ich möchte aber, dass er nur die Strings anzeigt die unterschiedlich sind. d.h. ich erklärs nochma
Folgender Excel-Datensatz
Sonne
Mond
Sonne
Angenommen er ist beim dritten ncounter Durchlauf. Nun wird a = i (also 3) gesetzt. Jetzt wird der Wert in Zeile 3 ausgelesen Wert = "Sterne". Nun kommt er in die Schleife wo Vektor(i) mit i=3 mit dem Wert ("Sterne") verglichen wird. Vektor(3) besitzt allerdings noch keinen Wert und gibt ein TRUE weiter (Leeres Feld ist ungleich Wert("Sterne")). Daher springt er in die nächste Schleife wo überprüft wird ob i noch größer als 1 ist. Mit i=3 gibts TRUE zieht vom i eins ab i = 3 - 1 = 2 und verläßt die schleife. Nun wird der Vektor(i) mit i=2 überprüft. d.h. er vergleicht 2Sonne" mit "Mond" bekommt TRUE , gleiche Prozedur wie eben und zieht wieder eins ab i=1. Nun wird wieder getestet Vector(1) mit Wert also "Sonne" mit "Sonne". Das gibt FALSE weil is ja nicht ungleich. daher wird mit zu diesem count(1) eins dazugezählt und Count(1) = 2, also 2x die Sonne.
bis ncounter abgelaufen ist immer so weiter.
Die Ausgabe is ja dann klar. i wird wieder eins gesetzt und läuft bis a (maximale i Zahl, also bei dem Beispiel nur 2) und gibt dann
Der VOrteil dabei, es werden nur die Felder mit Counts angezeigt, die im Vektor i einmalig enthalten sind.
Aber wieso bekomm ich jetzt nur die erste Zeile angezeigt?
Hier nochmal mein neuer code zum testen.
rem =========== Code ==========
Public Sub Werte_zaehlen()
Dim ncounter As Integer
Dim Wert As String
Dim i As Integer
Dim a As Integer
ReDim Vektor(100) As String
ReDim Count(100) As Integer
i = 1
For ncounter = 1 To 4
Rem (die 25 wird später mal Variable oder Eingabe)
a = i
Wert = Cells(ncounter, 1).Value
If Vektor(i) <> Wert Then
If i > 1 Then
i = i - 1
Else
i = a
Vektor(i) = Wert
End If
Else
Count(i) = Count(i) + 1
End If
i = a + 1
Next ncounter
For i = 1 To a
Cells(i, 2).Value = Vektor(i)
Cells(i, 3).Value = Count(i)
i = i + 1
Next i
End Sub
========= Code Ende ============
danke für eure Hilfe !
gruß Skunk
allerdings hab ichs schon selbst fast geknackt.
ok. also cmkatz, dein Code sehr gut, hab in der zeit auch noch´n bissl rum gespielt. Hat eigentlich geklappt. er gab mir die Werte aus. Allerdings immer nur den ersten. Denk ma, dass da ein i oder a falsch läuft und nur i=1 ausgegeben wird. letzte schleife vermutlich.
Dein Code nutzt einen Trick nicht aus, weshalb er alle (im maximalen Fall) 500 Stringsätze ausgibt.
Ich möchte aber, dass er nur die Strings anzeigt die unterschiedlich sind. d.h. ich erklärs nochma
Folgender Excel-Datensatz
Sonne
Mond
Sonne
Angenommen er ist beim dritten ncounter Durchlauf. Nun wird a = i (also 3) gesetzt. Jetzt wird der Wert in Zeile 3 ausgelesen Wert = "Sterne". Nun kommt er in die Schleife wo Vektor(i) mit i=3 mit dem Wert ("Sterne") verglichen wird. Vektor(3) besitzt allerdings noch keinen Wert und gibt ein TRUE weiter (Leeres Feld ist ungleich Wert("Sterne")). Daher springt er in die nächste Schleife wo überprüft wird ob i noch größer als 1 ist. Mit i=3 gibts TRUE zieht vom i eins ab i = 3 - 1 = 2 und verläßt die schleife. Nun wird der Vektor(i) mit i=2 überprüft. d.h. er vergleicht 2Sonne" mit "Mond" bekommt TRUE , gleiche Prozedur wie eben und zieht wieder eins ab i=1. Nun wird wieder getestet Vector(1) mit Wert also "Sonne" mit "Sonne". Das gibt FALSE weil is ja nicht ungleich. daher wird mit zu diesem count(1) eins dazugezählt und Count(1) = 2, also 2x die Sonne.
bis ncounter abgelaufen ist immer so weiter.
Die Ausgabe is ja dann klar. i wird wieder eins gesetzt und läuft bis a (maximale i Zahl, also bei dem Beispiel nur 2) und gibt dann
Cells(1,2).Value = Veltor(1)
und Cells(1,3).Value = Count(1)
usw.Der VOrteil dabei, es werden nur die Felder mit Counts angezeigt, die im Vektor i einmalig enthalten sind.
Aber wieso bekomm ich jetzt nur die erste Zeile angezeigt?
Hier nochmal mein neuer code zum testen.
rem =========== Code ==========
Public Sub Werte_zaehlen()
Dim ncounter As Integer
Dim Wert As String
Dim i As Integer
Dim a As Integer
ReDim Vektor(100) As String
ReDim Count(100) As Integer
i = 1
For ncounter = 1 To 4
Rem (die 25 wird später mal Variable oder Eingabe)
a = i
Wert = Cells(ncounter, 1).Value
If Vektor(i) <> Wert Then
If i > 1 Then
i = i - 1
Else
i = a
Vektor(i) = Wert
End If
Else
Count(i) = Count(i) + 1
End If
i = a + 1
Next ncounter
For i = 1 To a
Cells(i, 2).Value = Vektor(i)
Cells(i, 3).Value = Count(i)
i = i + 1
Next i
End Sub
========= Code Ende ============
danke für eure Hilfe !
gruß Skunk
Antwort 7 von Skunk
ok.. bin einen schritt weiter .. nur kommt wieder n blöder Fehler. Kann das an den While Do SChleifen liegen? Sind die richtig?
Fehlermeldung bei Vektor(i) = Wert (gelb markiert)
"Laufzeitfehler=´9´:
Index außerhalb des gültigen Bereichs"
ReDim Vektor(100) As String
ReDim Count(100) As Integer
i = 1
b = 1
For ncounter = 1 To 4
Rem (die 25 wird später mal Variable oder Eingabe)
a = i
Wert = Cells(ncounter, 1).Value
While Vektor(i) <> Wert
Do
If i > 1 Then
i = i - 1
Else
i = b
Vektor(i) = Wert
b = b + 1
End If
Count(i) = Count(i) + 1
Loop
Wend
i = a + 1
Next ncounter
i = 1
While i <= b
Do
Cells(i, 2).Value = Vektor(i)
Cells(i, 3).Value = Count(i)
i = i + 1
Loop
Wend
End Sub
gruß Skunk
Fehlermeldung bei Vektor(i) = Wert (gelb markiert)
"Laufzeitfehler=´9´:
Index außerhalb des gültigen Bereichs"
Public Sub Werte_zaehlen()
Dim ncounter As Integer
Dim Wert As String
Dim i As Integer
Dim a As Integer
Dim b As Integer
ReDim Vektor(100) As String
ReDim Count(100) As Integer
i = 1
b = 1
For ncounter = 1 To 4
Rem (die 25 wird später mal Variable oder Eingabe)
a = i
Wert = Cells(ncounter, 1).Value
While Vektor(i) <> Wert
Do
If i > 1 Then
i = i - 1
Else
i = b
Vektor(i) = Wert
b = b + 1
End If
Count(i) = Count(i) + 1
Loop
Wend
i = a + 1
Next ncounter
i = 1
While i <= b
Do
Cells(i, 2).Value = Vektor(i)
Cells(i, 3).Value = Count(i)
i = i + 1
Loop
Wend
End Sub
gruß Skunk
Antwort 8 von SoSollsSein
Dieser Code sollte funktionieren.
ganz wichtig, der Teil mit dem Type muss vor der Sub stehen
Type NameCount
Name As String
Count As Integer
End Type
Public Sub Werte_zaehlen()
Dim ncounter As Integer
Dim Wert As String
´Flag, ob der Eintrag in der Liste gefunden wurde
Dim found As Boolean
Dim i As Integer
´gibt die aktuelle Länge der Liste an
Dim Anzahl As Integer
´Länge der Liste ist noch unbestimmt
Dim Liste() As NameCount
found = False
For ncounter = 1 To 4
Wert = Cells(ncounter, 1).Value
´Test, ob überhaupt etwas in der Zelle stand
If Wert <> "" Then
For i = 1 To Anzahl
´vergleicht Wert mit Name aus Liste
If Liste(i).Name Like Wert Then
´wenn gleich, dann wird der Counter des Elementes erhöht
Liste(i).Count = Liste(i).Count + 1
´Flag wird gesetzt
found = True
´Abbruch der For-Schleife
Exit For
End If
Next i
´wenn nicht gefunden, dann muß die Liste verlängert werden
If found = False Then
Anzahl = Anzahl + 1
´passt Länge der Liste an, ohne die bisherigen Werte zu löschen
ReDim Preserve Liste(Anzahl)
Liste(Anzahl).Name = Wert
Liste(Anzahl).Count = 1
End If
found = False
End If
Next ncounter
´Ausgabe des Ergebnisses
For i = 1 To Anzahl
Cells(i, 2).Value = Liste(i).Name
Cells(i, 3).Value = Liste(i).Count
Next i
End Sub
Gruß
Pete
ganz wichtig, der Teil mit dem Type muss vor der Sub stehen
Type NameCount
Name As String
Count As Integer
End Type
Public Sub Werte_zaehlen()
Dim ncounter As Integer
Dim Wert As String
´Flag, ob der Eintrag in der Liste gefunden wurde
Dim found As Boolean
Dim i As Integer
´gibt die aktuelle Länge der Liste an
Dim Anzahl As Integer
´Länge der Liste ist noch unbestimmt
Dim Liste() As NameCount
found = False
For ncounter = 1 To 4
Wert = Cells(ncounter, 1).Value
´Test, ob überhaupt etwas in der Zelle stand
If Wert <> "" Then
For i = 1 To Anzahl
´vergleicht Wert mit Name aus Liste
If Liste(i).Name Like Wert Then
´wenn gleich, dann wird der Counter des Elementes erhöht
Liste(i).Count = Liste(i).Count + 1
´Flag wird gesetzt
found = True
´Abbruch der For-Schleife
Exit For
End If
Next i
´wenn nicht gefunden, dann muß die Liste verlängert werden
If found = False Then
Anzahl = Anzahl + 1
´passt Länge der Liste an, ohne die bisherigen Werte zu löschen
ReDim Preserve Liste(Anzahl)
Liste(Anzahl).Name = Wert
Liste(Anzahl).Count = 1
End If
found = False
End If
Next ncounter
´Ausgabe des Ergebnisses
For i = 1 To Anzahl
Cells(i, 2).Value = Liste(i).Name
Cells(i, 3).Value = Liste(i).Count
Next i
End Sub
Gruß
Pete
Antwort 9 von Event
Hallo
hier mein kurzer Vorschlag:
Private Sub CommandButton1_Click()
Dim c As Object, i As Long
Range("A1:" & Range("A65535").End(xlUp).Address).Select
For Each c In Selection
If c.Value <> "" Then i = i + 1: Names.Add Name:=c.Value, RefersTo:="$b$" & CStr(i)
Next c
i = 2 ´beginne in Zeile 2
For Each c In ActiveSheet.Names
Cells(i, 2) = Right(c.Name, Len(c.Name) - InStr(c.Name, "!"))
Cells(i, 3).FormulaLocal = "=Zählenwenn(" & Selection.Address & " ; B" & CStr(i) & ")"
i = i + 1
Next c
End Sub
Gruß
hier mein kurzer Vorschlag:
Private Sub CommandButton1_Click()
Dim c As Object, i As Long
Range("A1:" & Range("A65535").End(xlUp).Address).Select
For Each c In Selection
If c.Value <> "" Then i = i + 1: Names.Add Name:=c.Value, RefersTo:="$b$" & CStr(i)
Next c
i = 2 ´beginne in Zeile 2
For Each c In ActiveSheet.Names
Cells(i, 2) = Right(c.Name, Len(c.Name) - InStr(c.Name, "!"))
Cells(i, 3).FormulaLocal = "=Zählenwenn(" & Selection.Address & " ; B" & CStr(i) & ")"
i = i + 1
Next c
End Sub
Gruß