Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1964to1968
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Fehler von VBA-Lösung finden

Fehler von VBA-Lösung finden
18.02.2024 09:32:16
erichm
Hallo,

ich habe eine Datei mit 2 Tabellen:
- Bestellungen
- Warengruppen

In der Tabelle Bestellungen soll täglich geprüft werden, aus welchen Warengruppen die Bestellungen eingehen. Dafür habe ich beginnend in der Zelle I13 folgende Formel, die funktioniert:

=WENN(Warengruppen!$A1="";"";SUMME(ZÄHLENWENN(I$2:I$11;Warengruppen!$A1:$J1)))
Diese Formel wird nach rechts und unten kopiert, weswegen die Spalten bzw. die Zeilen fixiert sind.

Da das Gesamtprojekt sehr viele Daten umfasst, möchte ich diese Formel per VBA lösen. Dazu habe ich mir zunächst per Makro die VBA-Lösung aufzeichnen lassen:

Sub Aufzeichnung()

With Worksheets("Bestellungen")
Range("I13").Select
ActiveCell.Formula2R1C1 = _
"=IF(WARENGRUPPEN!R[-12]C1="""","""",SUM(COUNTIF(R2C:R11C,WARENGRUPPEN!R[-12]C1:R[-12]C10)))"
Range("I14").Select

End With

End Sub

Funktioniert soweit.

Jetzt möchte diese Formel per VBA auf die Zellen I13 : S15 erweitern. Ich habe nach diversen Versuchen zwei Lösungen, die als Sub akzeptiert werden, beim Ausführen kommen aber Fehlermeldungen:

Fehler beim Kompilieren:
Falsche Anzahl an Argumenten oder ungültige Zuweisung zu einer Eigenschaft

Das sind meine Lösungsansätze:
Sub Formel_7()
Dim i As Integer, j As Integer
Dim result As Variant
With Worksheets("Bestellungen")
For i = 13 To 15
For j = 9 To 19
If Worksheets("WARENGRUPPEN").Cells(i - 12, 1).Value > "" Then
result = WorksheetFunction.CountIf(Range(Cells(i - 12, 0), (Cells(i - 2, 0)), Worksheets("WARENGRUPPEN").Cells(i - 12, 1).Value))
Else
result = ""
End If
Cells(i, j).Value = result
Next j
Next i
End With
End Sub

Sub Formel_8()
Dim i As Integer, j As Integer
Dim result As Variant
With Worksheets("Bestellungen")
For i = 13 To 15
For j = 9 To 19
If Worksheets("WARENGRUPPEN").Cells(i - 12, 1).Value > "" Then
result = WorksheetFunction.CountIf(Cells(i - 12, 0), (Cells(i - 2, 0)), Worksheets("WARENGRUPPEN").Cells(i - 12, 1).Value)
Else
result = ""
End If
Cells(i, j).Value = result
Next j
Next i
End With
End Sub

Hier noch meine Musterdatei:
https://www.herber.de/bbs/user/167124.xlsm

Wo liegen meine Fehler?

Vielen Dank für eine Hilfe.

mfg

18
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Fehler von VBA-Lösung finden
18.02.2024 10:30:29
hary
Moin
Du hast 2 Klammern falsch gesetzt.
Hier korrigiert.
 WorksheetFunction.CountIf(Range(Cells(i - 12, 0), (Cells(i - 2, 0))), Worksheets("WARENGRUPPEN").Cells(i - 12, 1).Value)

Was du noch aendern musst ist:
Cells(i - 12, 0)
und
(Cells(i - 2, 0)

Es gibz keine Spalte 0 (Null)
gruss hary
AW: Fehler von VBA-Lösung finden
20.02.2024 19:13:10
daniel
Hi
wenn mit VBA bei großen Datenmengen, dann auch richtig.
hier kann das Dictionary-Objekt zum Einsatz kommen, um die Daten in einem Durchlauf auszuzählen.

Sub test()


Dim WGrng As Range
Dim WGarr
Dim BESTrng As Range
Dim BESTarr
Dim ERGrng As Range
Dim ERGarr
Dim DATrng As Range
Dim DATarr
Dim GRPrng As Range
Dim GRParr
Dim z As Long, s As Long

Dim WGdic As Object
Dim dic As Object

Dim ID As String

Set WGrng = Sheets("WarenGruppen").Range("A1:L5")
Set BESTrng = Sheets("Bestellungen").Range("I2:S11")
Set ERGrng = Sheets("Bestellungen").Range("I13:S17")
Set DATrng = Sheets("Bestellungen").Range("I1:S1")
Set GRPrng = Sheets("Bestellungen").Range("B13:B17")


WGarr = WGrng.Value
BESTarr = BESTrng.Value
ReDim ERGarr(1 To ERGrng.Rows.Count, 1 To ERGrng.Columns.Count)
DATarr = DATrng.Value
GRParr = GRPrng.Value

'--- Gruppenzuordnung einlesen
Set WGdic = CreateObject("scripting.dictionary")

For s = 1 To UBound(WGarr, 2) - 2
For z = 1 To UBound(WGarr, 1)
WGdic(WGarr(z, s)) = WGarr(z, UBound(WGarr, 2))
Next
Next

'--- Mengen pro Tag und Gruppe zählen
Set dic = CreateObject("scripting.dictionary")

For s = 1 To UBound(BESTarr, 2)
For z = 1 To UBound(BESTarr, 1)
ID = DATarr(1, s) & "|" & WGdic(BESTarr(z, s))
dic(ID) = dic(ID) + 1
Next
Next

'--- Ergebnis zurückschreiben
For s = 1 To UBound(ERGarr, 2)
For z = 1 To UBound(ERGarr, 1)
ID = DATarr(1, s) & "|" & GRParr(z, 1)
ERGarr(z, s) = dic(ID)
Next
Next

ERGrng = ERGarr

End Sub


die Zellbereiche musst du von hand anpassen, das habe ich jetzt noch nicht automatisiert.

Gruß Daniel
Anzeige
AW: Fehler von VBA-Lösung finden
21.02.2024 11:40:03
erichm
Hallo Daniel,

DANKE für die Alternative. Wenn ich die Bereiche zur Berechnung erweitere, werden immer nur die letzten 5 Zeilen in der Tabelle Bestellungen berechnet. Leider gelingt es mir nicht, dies anzupassen.

Ich habe eine Musterdatei erstellt:
1 Modul "kurz", das entspricht dem Umfang meiner Eingangsfrage
1 Modul "danielZZ1000", das bedeutet, dass ich den zu berechnenden Bereich bis zur Spalte ZZ und Zeile 1000 erweitert habe
1 Modul "danielIHG2000", Erweiterung bis IHG und Zeile 2000

Ich habe jeweils die Zeitmessung eingebaut.
https://www.herber.de/bbs/user/167205.xlsm

Vielen Dank, wenn der Code so angepasst werden kann, dass nicht nur die letzten 5 Zeilen berechnet werden. Ich habe deswegen die Frage auf offen gestellt, auch wenn ich eigentlich bereits eine Lösung habe.
mfg
Anzeige
AW: Fehler von VBA-Lösung finden
21.02.2024 12:08:20
daniel
Hi

ich bin davon ausgegangen, dass du viele Bestellnummern (dreistellig) und nur wenige Gruppen hast, so dass jede Bestellnummer nur genau einer Gruppe zugeordnet wirst.
du weist hier aber eine Bestellnummer 399 Guppen zu.
Das war aber aus deiner Beispieldatei nicht vorhersehbar.
daher habe ich den Code auch so geschrieben, dass eine Bestellnummer nur eine Gruppe bekommt.
weist du einer Bestellnummer mehrere Gruppen zu, so werden diese immer überschrieben so dass immer nur die letzte Zuweisung zur Anwendung kommt.
daher bekommst du nur in den letzten Gruppen ein Ergebnis.
die Frage ist, was du jetzt wirklich willst, oder ob du dein Beispiel nur unsinnig erweiterst hast.

Gruß Daniel
Anzeige
AW: Fehler von VBA-Lösung finden
21.02.2024 14:54:55
erichm
Hallo Daniel,

also die Projektdatei ist so aufgebaut:
Tabelle Warengruppen:
In der Spalte L werden ab Zeile 1 bis Zeile XXX alle Gruppen aufgelistet: jede Gruppennummer gibt es nur 1x! Derzeit sind wir bei 2.000 Gruppen, es können aber auch noch mehr werden.

Die Bestellnummern (Spalten A bis J) können mehrmals vorkommen;
die Nummern sind von A bis J immer aufsteigend;
in einer Gruppe kann eine Bestellnummer nicht 2x vorkommen
eine Nummernkombination (A bis J) kann nicht 2x vorkommen (bei meiner Musterdatei habe ich insofern unsinnig erweitert, da ich nicht dachte, dass dies für den Code relevant ist - SORRY!)

Tabelle Bestellungen:
Pro Tag in den Zeilen 2 bis 11 sind immer 10 unterschiedliche Bestellnummern
es wäre möglich, dass Tage mit identischen Bestellnummern vorkommen

Ich hoffe, ich habe mich verständlich ausgedrückt - weiß aber nicht wie aufwändig dies wäre, den Code anzupassen.
Auffällig war bei dem bisherigen Code, dass er schnell durchgelaufen ist, auch wenn nicht alle Zeilen geschrieben wurden.
Was noch hilfreich wäre, wenn das Ergebnis NULL ist, dass dann auch die Ziffer 0 eingetragen wird; derzeit bleibt die Zelle leer.

Besten Dank, falls eine Überarbeitung möglich ist.

mfg
Anzeige
AW: Fehler von VBA-Lösung finden
21.02.2024 15:53:19
daniel
Hi

nochmal die Frage: kann eine Bestellnummer (dreistellig) auch mehreren Gruppen zugeordnet werden oder gehört eine Bestellnummer immer zu genau einer Gruppe?
wenn eine Bestellnummer zu mehreren Gruppen gehören kann, soll sie dann auch für jede Gruppe gezählt werden?
dann wäre am Schluss die Gesamtanzahl pro Tag höher als 10, weil ja jede Bestellung mehrfach gezählt wird.
vielleicht solltest du doch mal die Echtdaten zeigen.



wenn du eine 0 statt Leer haben willst, dann erweitere das Rückschreiben ins Ergebnisarray so:

'--- Ergebnis zurückschreiben

For s = 1 To UBound(ERGarr, 2)
For z = 1 To UBound(ERGarr, 1)
ID = DATarr(1, s) & "|" & GRParr(z, 1)
if dic.Exists(ID) then
ERGarr(z, s) = dic(ID)
else
ERGarr(z, s) = 0
end if
Next
Next


Gruß Daniel
Anzeige
AW: Fehler von VBA-Lösung finden
21.02.2024 22:10:35
erichm
nochmal die Frage: kann eine Bestellnummer (dreistellig) auch mehreren Gruppen zugeordnet werden oder gehört eine Bestellnummer immer zu genau einer Gruppe?

JA, eine Bestellnummer kann mehreren Gruppen zugeordnet werden

wenn eine Bestellnummer zu mehreren Gruppen gehören kann, soll sie dann auch für jede Gruppe gezählt werden?
dann wäre am Schluss die Gesamtanzahl pro Tag höher als 10, weil ja jede Bestellung mehrfach gezählt wird.
vielleicht solltest du doch mal die Echtdaten zeigen.


Es soll immer nur pro Gruppe verglichen werden, also Gruppe 1 mit Gruppe 1; Gruppe 2 mit Gruppe 2 usw.. (pro Zeile nach unten).

Ich habe jetzt die Datei mit Realzahlen bestückt:
Warengruppen: 2.000 Zeilen
Bestellungen: 30 Spalten ab Spalte I, (zzgl. Spalte ZZ und Spalte IHG) - damit die Datei nicht zu groß wird.
https://www.herber.de/bbs/user/167234.xlsm

Besten Dank nochmal.

mfg
Anzeige
AW: Fehler von VBA-Lösung finden
18.02.2024 10:55:57
erichm
Danke hary,

der Code läuft jetzt durch; die Spalte 0 habe ich auf 9 abgeändert.

Allerdings kommt als Ergebnis immer 0 - was aber nicht stimmt.

Habe jetzt festgestellt, dass der 2. Teil
Worksheets("WARENGRUPPEN").Cells(i - 12, 1).
nicht stimmen kann, weil hier trotzdem der Wert der Tabelle Bestellungen aus Zelle A1 herangezogen wird;

richtig ist aber, dass mit den Werten aus
Warengruppen A1 bis J1
Warengruppen A2 bis J2
Warengruppen A3 bis J3
usw.
gerechnet werdern muss.

Wie kann ich das anpassen?

Danke nochmals.

mfg
Anzeige
AW: Fehler von VBA-Lösung finden
18.02.2024 11:26:50
hary
Moin
Versuch mal:
WorksheetFunction.CountIf(Range(Cells(i - 12, j), (Cells(i - 2, j))), Worksheets("WARENGRUPPEN").Cells(i - 12, j - 8).Value)

ausserdem nutzt du die with Anweisung. Dann musst du einen Punkt vor Range und Cells vorsetzen. Ansonsten heisst es ohne Punkt, es gilt das aktive Blatt.
Gruss hary
AW: Fehler von VBA-Lösung finden
18.02.2024 12:07:13
erichm
OK, passt noch nicht ganz: Es wird im zweiten Teil nicht auf das Worksheet "Warengruppen" zugegriffen, da liegt noch der Fehler. Ich habe jetzt die Anweisungen
With
If
weggelassen und habe folgendes Makro:

Sub Formel_10()
Dim i As Integer, j As Integer
Dim result As Variant
For i = 13 To 15
For j = 9 To 19
result = WorksheetFunction.CountIf(Range(Cells(i - 11, j), (Cells(i - 2, j))), Worksheets("WARENGRUPPEN").Range(Cells(i - 12, j - 8), (Cells(i - 12, j + 1))).Value)
Cells(i, j).Value = result
Next j
Next i
End Sub

Bei Ausführung kommt jetzt "Laufzeitfehler 1004": Anwendungs- oder objektdefinierter Fehler

Ich denke das betrifft den zweiten Teil Worksheets("WARENGRUPPEN").Range(Cells(i - 12, j - 8), (Cells(i - 12, j + 1)))

Besten Dank für eine nochmalige Hilfe.

mfg
Anzeige
AW: Fehler von VBA-Lösung finden
18.02.2024 14:14:41
ralf_b
was dein VBA angeht, da hast du nicht richtig gelesen was der Kollege dir geschrieben hat. Vor jedem!! Cells oder Range gehört die Blattbezeichnung wenn sie vom aktuellen Blatt abweicht. Deshalb die Punkte setzen und eine With-Klammer.
Ich konnt's nicht lassen und hab deine Formel in VBA umgesetzt Zugegeben nicht die eleganteste Lösung, aber elegant liest sich meist schlecht für Ungeübte.
die Formel hab ich mit Zeilenumbrüchen etwas aufgelockert. bei Reinkopieren pass auf das der VBA editor die nicht verschluckt.
Sub Formel_8()

Dim i&, j&, lrow&, lmaxCol&, lminCol&
Dim shBestell As Worksheet
Dim rngWaGrp As Range, rngWGRef As Range
Dim wf

Set wf = WorksheetFunction
Set shBestell = ThisWorkbook.Worksheets("Bestellungen")

lminCol = Columns("I").Column
lmaxCol = shBestell.Cells(1, Columns.Count).End(xlToLeft).Column
lrow = shBestell.Cells(Rows.Count, 2).End(xlUp).Row

With ThisWorkbook.Worksheets("WARENGRUPPEN")
Set rngWaGrp = .Range("$A$1:$I$5")
Set rngWGRef = .Range("$L$1:$L$5")
End With

Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False

For i = 2 To lrow
If Left(Cells(i, 2), Len("Gruppe ")) = "Gruppe " Then
For j = lminCol To lmaxCol
On Error Resume Next
Cells(i, j).Value = wf.Sum( _
wf.CountIf( _
shBestell.Cells(2, j).Resize(10), _
wf.Index( _
rngWaGrp, _
wf.Match( _
Cells(i, 2), _
rngWGRef, _
0 _
) _
, 0) _
) _
)
If Err > 0 Then Cells(i, j).Value = "Fehler" & Err.Number: Err.Clear
Next j
End If
Next i

Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

End Sub
Anzeige
AW: Cells(j-12, 0) oder minus gibt es nur so:
18.02.2024 18:24:10
Piet
Nachtrag

Range("C10").Cells(1, 0) entspricht Range("B10") -- Range("C10").Cells(0, 1) entspricht Range("C9")
Cells(-2, -2) usw. ist auch möglich, wenn davor ein Range steht, so das Cells nicht die Zelle A1 ist!
Den Trick mit minus Werten bei Cells benütze ich durchaus, man darf aber nicht über das Blattende kommen!

mfg Piet

AW: Fehler von VBA-Lösung finden
20.02.2024 10:42:38
erichm
Vielen Dank für den Service!! Perfekte Lösung.

Rückmeldung hat jetzt länger gedauert, weil ich das (modifizierte) Makro bereits in einer Kopie der umfangreichen Projektdatei (Makro berechnet ca. 6.000 Spalten mit ca. 2.000 Zeilen) getestet habe: reibungslos durchgelaufen.

Ich habe einen Timer eingebaut, der ca. 36 Minuten für einen Durchlauf des Makros mißt. Der Vorteil ist jetzt jedoch, dass die Datei statt ca. 100 MB nur noch ca. 35 MB hat. Vielleicht kann ich noch ein paar kleinere Formeln in Makros umbauen, dann wirds noch besser.

Also vielen Dank nochmals!!

mfg
AW: Fehler von VBA-Lösung finden
20.02.2024 18:40:54
ralf_b
versuchs mal damit. die 36 Minuten scheinen etwas viel. das erste Makro rechnet nicht richtig weil die Warengruppen nur bis i und nicht bis Spalte j eingebunden war.
Aber das hast du sicher selbst beim anpassen der Bereiche gemerkt.

Sub Formel_Arr()


Dim i&, j&, lrow&, lmaxCol&, lminCol&, cnt&, e&, r&, s&, erg&, frstrow&
Dim shBestell As Worksheet
Dim varrWaGrp, varrWGRef, varrData, varrTmp, varrB, varrErg
Dim wf

Set wf = WorksheetFunction
Set shBestell = ThisWorkbook.Worksheets("Bestellungen")

lminCol = Columns("I").Column
lmaxCol = shBestell.Cells(1, Columns.Count).End(xlToLeft).Column
lrow = shBestell.Cells(Rows.Count, 2).End(xlUp).Row

With ThisWorkbook.Worksheets("WARENGRUPPEN")
varrWaGrp = .Range("$A$1:$J$5").Value
varrWGRef = .Range("$L$1:$L$5").Value
End With

Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False

'bereich Bestellungen
varrData = shBestell.Cells(2, lminCol).Resize(10, lmaxCol).Value

For i = 2 To lrow
'zeile mit "Gruppe x"

If Left(Cells(i, 2), Len("Gruppe ")) = "Gruppe " Then
If frstrow = 0 Then frstrow = i
cnt = cnt + 1
'speicher für ergebniszeile
If cnt = 1 Then
ReDim varrErg(1 To lmaxCol - lminCol + 1, 1 To 1)
Else
ReDim Preserve varrErg(1 To lmaxCol - lminCol + 1, 1 To cnt)
End If
'WAgruppe finden und Wagr zeile im tmp
For e = 1 To UBound(varrWGRef)
If varrWGRef(e, 1) = Cells(i, 2) Then varrTmp = wf.Index(varrWaGrp, e, 0): Exit For
Next

'die ergebniszeile von links nach rechts
For r = LBound(varrErg) To UBound(varrErg)

' aktuelle spalte der bestellungen
varrB = wf.Index(varrData, 0, r)

erg = 0
'schleife über die auszuwertenden teilbereiche
For j = LBound(varrB) To UBound(varrB)
For s = LBound(varrTmp) To UBound(varrTmp)
'addition der Funde
If varrB(j, 1) = varrTmp(s) Then erg = erg + 1: Exit For
Next s
Next j
varrErg(r, cnt) = erg
Next r

Else

End If
Next i

'Ergebnisarray drehen
varrErg = Application.Transpose(varrErg)

'werte in Tabelle schreiben
Cells(frstrow, lminCol).Resize(UBound(varrErg), UBound(varrErg, 2)) = varrErg

Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

End Sub


AW: Fehler von VBA-Lösung finden
23.02.2024 14:10:10
erichm
Hallo Ralf,

habe den Code zwischenzeitlich mehrmals geprüft. Er rechnet länger, benötigt aber wesentlich mehr Zeit. Z.B. bis zur Spalte DBZ war der Code erst nach 99 Minuten fertig. Insofern bleibe ich bei dem bisherigen, der funktioniert ja bereits.

Danke.

mfg
AW: Fehler von VBA-Lösung finden
23.02.2024 23:15:42
ralf_b
ja ,sorry, ist mir auch schon aufgefallen. hab leider noch nicht rausgefunden wo hier der Haken ist.
AW: Cells(j-12, 0) oder minus gibt es nur so:
18.02.2024 18:52:02
erichm
Vielen, vielen Dank für die Rückmeldungen - ich muss das jetzt "verarbeiten" und melde mich spätestens morgen wieder!!

mfg
AW: Fehler von VBA-Lösung finden
18.02.2024 18:13:49
Piet
Hallo

ich gehe davon aus, das es sich hier um einen zusammenhängenden Befehl handelt. Du machst daraus zwei getrennte Befehle!
result = WorksheetFunction.CountIf(Range(Cells(i - 11, j), (Cells(i - 2, j))), _ (Hier gehört ein _ Zeichen hin!)
Worksheets("WARENGRUPPEN").Range(Cells(i - 12, j - 8), (Cells(i - 12, j + 1))).Value)

Bei einem zusammenhändenden Befehl, der in zwei Zeilen steht, gehört hinter dem Komma ein _ Zeichen als Zeilenumbruch!
Alternativ kannst du es so machen, über eine Variable für die Warengruppe. Der Code wird so übersichtlicher.
Wert = Worksheets("WARENGRUPPEN").Range(Cells(i - 12, j - 8), (Cells(i - 12, j + 1))).Value)
result = WorksheetFunction.CountIf(Range(Cells(i - 11, j), (Cells(i - 2, j))), Wert)

mfg Piet

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige