Live-Forum - Die aktuellen Beiträge
Datum
Titel
24.04.2024 19:29:30
24.04.2024 18:49:56
24.04.2024 17:19:09
Anzeige
Archiv - Navigation
1888to1892
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

CountIf und SpecialCells ...

CountIf und SpecialCells ...
03.07.2022 11:06:38
Kalle
Hallo zusammen,
das Wetter ist schön, aber ein Excel Problem lässt mich nicht raus. Im Rahmen meines Projekts strebe ich eine beschleunigte Prüfung gewisser Bedingungen an, die über Change-Ereignisse erfasst werden. Ziel: CountIf nur über sichtbare Spalten laufen lassen und entpsrechende Berechnungen/Aktualisierungen beschleunigen. Konkret: gesetzte "x" und gesetzte "p" bestimmen und weiterverwerten.
Ich habe bereits für meine Zwecke eine 100% lauffähige Variante erstellt (auskommentiert); der Versuch, das ganze über Areas und SpecialCells zu verschlanken wirft zwar keine Fehler aus, rechnet aber nur Unsinn (keine korrekten Summen, egal ob "x" oder die Zeiten) ... und ich habe keine Ahnung, wo der Denkfehler liegt. In der Demo einfach mit "x" und "p" etwas herumprobieren. Die Zeiten für die Einzeltestdauer zieht er sich aus Zeile 2. Hier der kommentierte Code für beide Varianten und die Demo https://www.herber.de/bbs/user/153948.xlsm :
Danke für Eure Hilfe ... bin ja mal gespannt, woran es liegt
VG Kalle

Private Sub Worksheet_Change(ByVal Target As Range)
Dim DValue, UValue, PValue As String
DValue = Format(Date, "dd.mm.yy")
UValue = Left(Environ$("USERNAME"), 2)
Dim i, tt, td, count_p, count_x, slr As Long
slr = Sheets("TESTPLANUNG").Cells(Rows.Count, 1).End(xlUp).Row
If Not Intersect(Range("M6:AF" & slr), Target) Is Nothing Then
Cells(1, 33) = "          letzte Planung: " & UCase(Environ$("USERNAME")) & ", " & DValue
If Target.Count = 1 Then
Application.EnableEvents = False
Application.ScreenUpdating = False
'funktioniert so wie es soll, aber hoher Prüfaufwand
Target.Value = LCase(Target.Value)
If Target.Value = "p" Then
Target.Value = Target.Value & UValue 'jeder Testleiter bekommt seine Initialien an das "p"
End If
'        'Vorgang 1: bestimme alle x und p? in der Target-Zeile über alle Spalten mit Tests
'            With ActiveSheet
'            count_x = Application.CountIf(.Range(.Cells(Target.Row, 13), .Cells(Target.Row, 32)), "x")
'            count_p = Application.CountIf(.Range(.Cells(Target.Row, 13), .Cells(Target.Row, 32)), "p?")
'            Cells(Target.Row, 33).Value = count_x 'aktualisiere offene Tests "x" in Spalte AH
'            If count_p = 0 Then
'            Cells(Target.Row, 34).ClearContents 'leere Zelle, wenn kein Test geplant ist
'            End If
'        'Vorgang 2: bei Veränderung wird die Gesamnttestdauer aus Reihe 2 in Spalte AG über alle sichtbaren Spalten mit "p?" gebildet
'            For i = 13 To 32
'            If Cells(Target.Row, i).Value Like "p?" Then
'            tt = tt + Cells(2, i).Value
'            Cells(Target.Row, 34).Value = tt / (24 * 60) 'Umrechnung in verständliches Zeitmaß
'            End If
'            Next i
'            End With
'        'Ende von funktioniert so wie es soll, aber hoher Prüfaufwand
'neuer Vorschlag, aber rechnet nicht richtig ...
Dim plan_data_row As Range
Dim cell_check As Range
'Vorgang 1: bestimme alle x und p? in der Target-Zeile in allen sichtbaren Spalten
Set plan_data_row = Range(Cells(Target.Row, 13), Cells(Target.Row, 32)).SpecialCells(xlCellTypeVisible)
For Each cell_check In plan_data_row.Areas
count_x = Application.WorksheetFunction.CountIf(cell_check, "x")
count_p = Application.WorksheetFunction.CountIf(cell_check, "p?")
Next cell_check
Cells(Target.Row, 33).Value = count_x 'aktualisiere offene Tests "x" in Spalte AH
If count_p = 0 Then
Cells(Target.Row, 34).ClearContents 'leere Zelle, wenn kein Test geplant ist
End If
'Vorgang 2: bei Veränderung wird die Gesamnttestdauer aus Reihe 2 in Spalte AH über alle sichtbaren Spalten mit "p?" gebildet
For Each cell_check In plan_data_row.Areas
If Target.Value Like "p?" Then
tt = tt + Cells(2, Target.Column).Value
Cells(Target.Row, 34).Value = tt / (24 * 60) 'Umrechnung in verständliches Zeitmaß
End If
Next cell_check
End If 'target count
End If 'intersect
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub

7
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: CountIf und SpecialCells ...
03.07.2022 11:48:44
Luschi
Hallo Kalle,
würdest Du mit den Möglichkeiten des Vba-Debuggers arbeiten:
- Haltepunkte setzen (F9-Taste)
- Vba-Code schrittweise weiter schalten (F8-Taste)
- weiter bis Cursor debuggen (Strg+F8)
- und einige Möglichkeiten mehr
hättest Du sofort bemerkt, das nach diesem Befehl:
Cells(1, 33) = " letzte Planung: " & UCase(Environ$("USERNAME")) & ", " & DValue
das Ereignis 'Worksheet_Change' noch einmal aufgerufen wird, obwohl die anderen Vba-Schritten noch gar nicht abgearbeitet wurden.
Hier fehlt die Benutzung der Einstellung: Application.EnableEvents = False
Damit wird erreicht, daß Zelländerungen durch Vba-Befehle diese Kreislaufwirtschaft NICHT in Gang setzen, denn dies würde sonst bei jenen neuen Vba-Befehl mit Zelländerung eintreten und natürlich den Gesamtprozeß wesentlich verlangsamen!.
Es gibt noch ein paar Einstellungen, die da die Geschwindigkeitsbremse lösen können. Suche im Browser Deines Vertrauens nach: Excel Vba GetMoreSpeed
Gruß von Luschi
aus klein-Paris
Anzeige
AW: CountIf und SpecialCells ...
03.07.2022 15:21:59
Daniel
Hi
Schau doch mal genau hin mit

count_x = Application.WorksheetFunction.CountIf(cell_check, "x")
überschreibst du doch immer nur die Variable, so dass diese nach Ende der Schleife nicht die Summe der Areas enthält, sondern nur den Wert der letzten Area.
Wenn du die Gesamtsumme über alle Areas haben willst, dann brauchst du

count_x = count_x + App...
Etwas weiter unten im Vorgang 2 machst du es bei tt richtig.
Kleiner Tipp noch:
Wenn du in Auswertungen den Filterzustand berücksichtigen willst, dann füge der Tabelle einfach eine Spalte hinzu mit der Formel:

=Teilergebnis(103;A6)
Wobei A6 eine Zelle mit Inhalt in derselben Zeile sein muss.
Das Ergebnis ist 1, wenn die Zeile sichtbar ist und 0 wenn sie ausgeblendet ist.
Das kannst du bei Funktionen wie SummeWenns, ZählenWenns oder Summenprodukt als Bedingung mit hinzunehmen um den Filterzustand zu berücksichtigen und du kannst die Auswertung direkt machen, ohne die Schleife über die Areas des sichtbaren Bereichs.
Gruß Daniel
Gruß Daniel
Anzeige
AW: CountIf und SpecialCells ...
03.07.2022 23:36:08
Kalle
Guten Abend Luschi und Daniel,
zunächst Danke für Eure äußerst hilfreichen Tipps! Dieses GetMoreSpeed Script aus Herber ist ja mal der helle Wahnsinn; als ob VBA von HDD auf eine SSD umgezogen ist ... das habe ich jetzt "flächendeckend" im Gesamtprojekt gemäß der Event-Auslöse-Logik eingebettet. Boostet wirklich enorm.
Den Variablen-Additionsfehler im CountIf habe ich berichtigt; die "x" werden ordnungsgemäß aktualisiert. Aber Vorgang 2 spinnt immer noch: obwohl ich bei "tt" richtig summiere, stimmt die EndZeit am Ende in Spalte AH nicht. Die Ausgabe habe ich aus der Next-Schleife herausgenommen, was keine Änderung bringt. Muss ich die Range vielleicht doppelt deklarieren, weil Excel sonst beim Zählen durcheinander kommt?
Demo: https://www.herber.de/bbs/user/153974.xlsm
LG Kalle
Anzeige
AW: CountIf und SpecialCells ...
04.07.2022 00:01:04
Daniel
Hi
Ich kennen jetzt die Aufgabe nicht, deswegen kann ich dir nicht helfen.
Vielleicht solltest du uns nochmal genau beschreiben, was da aufsummiert werden soll.
Mir fällt nur auf, dass du da eine Schleife erstellt hast, in der der Schleifenzähler nicht verwendet wird.
Schleifen die den Schleifenzähler nicht verwenden, sind zu 99% Unsinn.
Gruß Daniel
AW: CountIf und SpecialCells ...
04.07.2022 07:45:40
Kalle
Moin Daniel,
die Demo ist Bestandteil einer größeren Mappe, die als Steuerungstool für individualisierte psychologische Testdiagnostik in der Reha eingesetzt wird.
Was soll in "Testplanung" passieren?
In Zeile M2 bis AF2 stehen die Zeiten, die der jeweilige psychometrische Test pro Durchführung grundsätzlich braucht. Die "x" je Patient sind die von Psychologen (meine Kollegen und ich) beauftragten Tests. Die ausführenden Testleiter und Assistenten müssen nun Gruppen "bauen" (planen) und geben "p" für die "x" ein. Effekt 1: die Anzahl offener, beauftragter Tests (alle x in Reihe) wird in AG kleiner (läuft)
Effekt 2: In Spalte AH wird die Gesamtdauer der geplanten Testreihe (alle "p" in Reihe) gebildet.
Effekt 2 klappt über alle Spalten mit:

For i = 13 To 32
If Cells(Target.Row, i).Value Like "p?" Then
tt = tt + Cells(2, i).Value
Cells(Target.Row, 34).Value = tt / (24 * 60) 'Umrechnung in verständliches Zeitmaß
End If
Next i
... ich bin aber, v.a. weil ich was lernen möchte, an einer Lösung interessiert, mit der diese Abfrage nur über die sichtbaren Spalten gelingt. Die Demo rechnet aber nur Unsinn:

'Festlegung des Prüfbereichs: nur sichtbare Spalten
Set plan_data_row = Range(Cells(Target.Row, 13), Cells(Target.Row, 32)).SpecialCells(xlCellTypeVisible)
For Each plan_data_cell In plan_data_row.Areas 'schaue in jede sichtbare Zelle des Prüfbereichs
If Target Like "p?" Then 'wenn Eingabe "p?"
tt = tt + Cells(2, Target.Column).Value "hole zugehörige Testzeiten aus Zeile 2 und addiere auf
Cells(Target.Row, 34).Value = tt / (24 * 60) 'Ausgabe der Gesamttestdauer inkl. Umrechnung in verständliches Zeitmaß
End If
Next plan_data_cell
Ich habe den Eindruck, der Lösung nahe zu sein ... aber ohne Hilfe komme ich nicht weiter.
LG Kalle
Anzeige
AW: CountIf und SpecialCells ...
04.07.2022 09:57:21
Daniel
Hi
naja, hier tt = tt + Cells(2, Target.Column).Value
summierst du immer den Wert der Zelle in Zeile 2 in der Spalte, in welcher der Anwender die Änderung durchgeführt hat und die somit das Makro ausgelöst hat.
Target.Columm ist immer gleich und verändert sich nicht im verlauf der Schleife, also summierst du immer den selben Wert auf.
ich denke nicht, dass das beabsichtigt ist.
wenn die erste Schleife funktionierrt, könntest du da noch die Abfrage mit einbauen, ob die Zelle ein- oder ausgeblendet ist:

if Columns(i).Hidden = False Then
Gruß Daniel
Anzeige
AW: CountIf und SpecialCells ...
04.07.2022 17:38:35
Kalle
Dickes Danke! Läuft jetzt wie gewollt und mit der Hidden Abfrage wirklich sehr flott.
VG Kalle

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige