Dieses Forum nutzt Cookies
Dieses Forum verwendet Cookies, um deine Login-Informationen zu speichern, wenn du registriert bist, und deinen letzten Besuch, wenn du es nicht bist. Cookies sind kleine Textdokumente, die auf deinem Computer gespeichert werden. Die von diesem Forum gesetzten Cookies werden nur auf dieser Website verwendet und stellen kein Sicherheitsrisiko dar. Cookies aus diesem Forum speichern auch die spezifischen Themen, die du gelesen hast und wann du zum letzten Mal gelesen hast. Bitte bestätige, ob du diese Cookies akzeptierst oder ablehnst.

Ein Cookie wird in deinem Browser unabhängig von der Wahl gespeichert, um zu verhindern, dass dir diese Frage erneut gestellt wird. Du kannst deine Cookie-Einstellungen jederzeit über den Link in der Fußzeile ändern.

Höchsten Wert ermitteln und niedrigere löschen (VBA)
#1
Hallo!
Ich hoffe ihr könnt mir mal wieder helfen.
Ich habe eine Tabelle (tbl_base) die von A:Q befüllt ist.
In Q wird die jeweilige Versionsnummer der Spalten definiert.
Hier soll die höchste Nummer bestimmt werden und alle Spalten, die einen Wert drunter haben, sollen gelöscht werden.
Entsprechend sollen alle Spalten nach oben rutschen, fall die obere gelöscht wurde.
Wie kriege ich das genau hin, mit VBA?
Kann ich vor der If Schleife einer Variable definieren, die den höchsten Wert von Spalte Q ermittelt?
Entsprechend löscht dann die If Schleife alle Werte dadrunter.
Oder Wie würdet ihr da rangehen?
Antworten Top
#2
Hallo joshua,

so ganz habe ich die Frage nicht verstanden. Kannst du einmal eine Beispieldatei hochladen. Ein Blatt mit den Ausgangsdaten in dem du die zu vergleichenden Werte markierst. Und ein Blatt mit dem gewünschten Ergebnis.

Für mein Verständnis :

a) könnenSpalten nicht nach oben rutschen, sondern nur Zeilen.

b) gibt es keine IF-Schleifen, sondern If-Verzweigungen und For-Schleifen.
helmut

Für mich ist die Möglichkeit in Excel an Zellen und Bereichen Namen zu vergeben die wichtigste Funktionalität.
Sie macht Formeln und den VBA-code verständlicher. Für Makros gilt die Regel: "Nur über benannte Bereiche auf den Inhalt der Zellen zugreifen."
Und wofür sind Regeln da? Um nachzudenken bevor man sie bricht.





Antworten Top
#3
Entschuldige, ich habe mir falsch ausgedrückt.

Ich habe eine Tabelle wo in Spalte Q die Version steht.
Hier soll die höchste Zahl ermittelt werden und alle Zeilen, die einen Wert unter dieser Zahl haben, sollen gelöscht werden. Dabei sollen die restlichen Zeilen jeweils nach oben rutschen.

Beispieldatei im Anhang.


Beste Grüße


Angehängte Dateien
.xlsx   Base.xlsx (Größe: 9,95 KB / Downloads: 5)
Antworten Top
#4
Hallo,

das ginge ohne VBA sehr schnell:

Deine Tabelle braucht überschriften und in R folgende Formel:

Arbeitsblatt mit dem Namen 'Tabelle1'
 ABCDEFGHIJKLMNOPQR
1u1u2u3u4u5u6u7u8u9u10u11u12u13u14u15u16u17u18
2AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter1FALSCH
3AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter1FALSCH
4AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter2FALSCH
5AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter2FALSCH
6AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter2FALSCH
7AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter3WAHR
8AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter3WAHR
9AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter3WAHR
10AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter3WAHR
11AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter1FALSCH
12AutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfterAutoMotorGetriebeLüfter1FALSCH

ZelleFormel
R2=Q2=MAX($Q$2:$Q$12)
Diese Tabelle wurde mit Tab2Html (v2.4.1) erstellt. ©Gerd alias Bamberg

Dann den Autofilter aufrufen und Spalte R nach Falsch filtern.
Den Gefilterten Bereich auswählen und Zeilen löschen wählen.

Das Ganze, kannst Du auch mit dem Makro rekorder aufzeichnen, wenn Du es per Vba für wiederkehrende Aufgaben brauchst.
Gruß Atilla
Antworten Top
#5
Code:
Sub M_snb()
    Cells(30, 1).Resize(, 17) = Range("A1:Q1").Offset([match(max(Q1:Q200),Q1:Q200,0)] - 1).Value
End Sub
[-] Folgende(r) 1 Nutzer sagt Danke an snb für diesen Beitrag:
  • joshua
Antworten Top
#6
Und einmal mit einfacher Programmierung:


Code:
Private Sub cbLoeschen_Click()
Dim varDaten As Variant
Dim strRange As String
Dim lngSpalte As Long
Dim lngAltZeile As Long
Dim lngNeuZeile As Long
Dim lngAnzZeilen As Long
Dim lngAnzSpalten As Long
Dim dblAktMax As Double
Dim dblAktWert As Double
Const intWertSpalte As Integer = 17


strRange = "A2:" & Range("A2").SpecialCells(xlCellTypeLastCell).Address
varDaten = Range(strRange).Value
dblAktMax = -1
lngAnzZeilen = UBound(varDaten, 1)
lngAnzSpalten = UBound(varDaten, 2)
lngNeuZeile = 0

For lngAltZeile = 1 To lngAnzZeilen
    dblAktWert = varDaten(lngAltZeile, intWertSpalte)
    If dblAktWert >= dblAktMax Then
        If dblAktWert = dblAktMax Then
            lngNeuZeile = lngNeuZeile + 1
        Else
            lngNeuZeile = 1
            dblAktMax = dblAktWert
        End If
        For lngSpalte = 1 To lngAnzSpalten
            varDaten(lngNeuZeile, lngSpalte) = varDaten(lngAltZeile, lngSpalte)
        Next lngSpalte
    End If
Next lngAltZeile
For lngAltZeile = lngNeuZeile + 1 To lngAnzZeilen
    For lngSpalte = 1 To lngAnzSpalten
        varDaten(lngAltZeile, lngSpalte) = ""
    Next lngSpalte
Next lngAltZeile

Range(strRange).Value = varDaten

End Sub


Angehängte Dateien
.xlsm   Kopie von Base.xlsm (Größe: 22,86 KB / Downloads: 3)
helmut

Für mich ist die Möglichkeit in Excel an Zellen und Bereichen Namen zu vergeben die wichtigste Funktionalität.
Sie macht Formeln und den VBA-code verständlicher. Für Makros gilt die Regel: "Nur über benannte Bereiche auf den Inhalt der Zellen zugreifen."
Und wofür sind Regeln da? Um nachzudenken bevor man sie bricht.





[-] Folgende(r) 1 Nutzer sagt Danke an Ego für diesen Beitrag:
  • joshua
Antworten Top
#7
Vielen Dank snb und Ego,

leider funktioniert das Makro von snb nicht, weiß einer woran das liegen mag?

Danke Ego, für das ausführliche Makro (:

Blicke da so nicht ganz durch.

Ich würde gerne das Makro für tbl_Daten anwenden und beim öffnen der Datei über Workbook_Open das makro automatisch ablaufen lassen.

Wie weise ich nun dem Makro die tbl_Daten zu?


Beste Grüße
Antworten Top
#8
Hallo,

wenn es unbedingt per VBA gehen soll, dann ginge folgendes:


Code:
Sub ati()
  Dim i As Long, j As Long, k As Long
  Dim lngMax As Long
  Dim lngAnzahlm As Long
  Dim feld
  Dim arr()
  With Sheets("Tabelle1")
    lngMax = Application.Max(.Columns("Q"))
    lngAnzahlm = Application.CountIf(.Columns("Q"), lngMax)
    feld = .Range("A2").CurrentRegion
    ReDim arr(lngAnzahlm - 1, 16)
      For i = 0 To .Range("A2").CurrentRegion.Rows.Count - 1
        If feld(i + 1, 17) = lngMax Then
          For j = 0 To 16
            arr(k, j) = feld(i + 1, j + 1)
          Next j
          k = k + 1
        End If
      Next i
    .Range("A2").CurrentRegion.ClearContents
    .Range("A2:Q" & 2 + k - 1) = arr
  End With
End Sub

Die Prozedur kann aus jeder anderen Prozedur mit "Call ati" oder nur "ati" aufgerufen werden.
Es ist auch möglich die Original Tabelle beizubehalten und die gefilterten Werte in eine andere Tabelle zu schreiben.
Dazu müssen nur die letzten zwei Zeilen im Code angepasst werden.


snb's Code macht nicht das, was Du möchtest.
Er sucht den ersten Treffer und schreibt diesen in Zeile 30. Also immer nur eine Zeile.

Wie unten ergänzt, würde der Code in einer nach Spalte Q sortierten Liste alle Treffer ab Zeile 30 schreiben:

Code:
Sub M_snb()
  Dim x As Long
  x = Application.CountIf(Columns("Q"), [max(Q1:Q200)])
  Cells(30, 1).Resize(x, 17) = Range("A1:Q1").Offset([match(max(Q1:Q200),Q1:Q200,0)] - 1).Resize(x, 17).Value
End Sub
Gruß Atilla
Antworten Top
#9
Hallo Joshua,

a) zu deiner Frage:
Wenn du den code in ein WorkbookOpen Makro einbauen willst must du wie in atillas Code
1. nach der Deklaration ein  "With Sheets()" und vor dem Ende ein "End With" einbauen und
2. vor jedem Range-Objekt eine Punkt setzen.

b) Generell solltest du einen code, den du nicht verstanden hast, oder der dir nicht genau erklärt wurde, insbesondere wenn er Daten löscht oder verändert nicht einfach übernehmen.

Hier einmal ein Vergleich der beiden VBA Vorschläge:


1) Beide Vorschläge löschen keine Zeilen, sondern schreiben nur die Zeilen mit den Maximalwerten nach oben und löschen den Inhalt der unteren Zeilen.
Wenn du Zeilen -warum auch immer- unterschiedlich formatierst, werden diese Formate nicht mitgenommen.

2) In attilas Beispiel werden die ersten 17 Spalten berücksichtigt, in meinem Beispiel alle genutzten Spalten.
Falls neben deiner Liste noch weitere Daten vorhanden sind, werden sie mit meinem Makro auch gelöscht oder verschoben.
Falls deine Liste hinter der 17. Spalte noch Werte hat, werden sie in attilas Makro nicht berücksichtigt. 

3) In attilas Beispiel werden alle Zeilen bis zur nächsten Leerzeile (CurrentRegion) berücksichtigt, in meinem Beispiel alle genuzten Zeilen (...LastCell)
Falls unter deiner Liste noch weitere Daten vorhanden sind, werden sie in meinem Makro auch bei der Ermittlung des Maximums und beim Löschen und verschieben berücksichtigt.
Falls deine Liste Leerzeilen enthält hört attilas Makro auf die Zeilen mit Maximalwerten zu kopieren. Hier ist attilla nicht konsequent. Zur Ermittlung des Maximums wird die gesamte Spalte Q berücksichtigt.

Generell ist attilas Makro ein richtiges Excel-Makro das die Funktionalität von Excel effectiver nutz und meins eine Programm das zu Beginn Daten aus dem Arbeitsblatt liest und zum Ende Daten in das Arbeitsblatt schreibt.
helmut

Für mich ist die Möglichkeit in Excel an Zellen und Bereichen Namen zu vergeben die wichtigste Funktionalität.
Sie macht Formeln und den VBA-code verständlicher. Für Makros gilt die Regel: "Nur über benannte Bereiche auf den Inhalt der Zellen zugreifen."
Und wofür sind Regeln da? Um nachzudenken bevor man sie bricht.





Antworten Top
#10
Hallo Helmut,

einiges hast Du leider nicht richtig wiedergegeben.
Deswegen möchte ich folgendes ergänen, damit Andere, die sich mit Codes auseinder setzten es nicht falsch verstehen:


Code:
1) Beide Vorschläge löschen keine Zeilen, sondern schreiben nur die Zeilen mit den Maximalwerten nach oben und löschen den Inhalt der unteren Zeilen.

Das ist so nicht richtig. Ich lösche den gesamten zusammenhängenden Bereich ab Zelle A2. Wenn Überschriften diese Zelle berühren, werden diese auch gelöscht.
Nach dem Löschen, schreibe ich ab A2 die sozusagen gefilterten Werte in die Tabelle zurück.


Code:
2) In attilas Beispiel werden die ersten 17 Spalten berücksichtigt, in meinem Beispiel alle genutzten Spalten.

Bei Dir aber auch mit dieser Zeile in Deinem Code:

Code:
Const intWertSpalte As Integer = 17


Code:
3) In attilas Beispiel werden alle Zeilen bis zur nächsten Leerzeile (CurrentRegion) berücksichtigt, in meinem Beispiel alle genuzten Zeilen (...LastCell)


CurrentRegion liest einen zusammenhängenden Bereich ein. Ich muss gestehen, dass das damit auch in die Hose gehen kann.
Das sollte man bewußt einsetzen und wissen, dass man einen zusammenhängenden Bereich hat.
Hier war ich Faul, sonst bevorzuge ich das Aiuslesen der letzten belegten Zelle mit (xlUp).Row


Code:
Falls deine Liste Leerzeilen enthält hört attilas Makro auf die Zeilen mit Maximalwerten zu kopieren. Hier ist attilla nicht konsequent. Zur Ermittlung des Maximums wird die gesamte Spalte Q berücksichtigt.

Richtig, siehe meine Einlassung über dem Zitat.


Hier dann das zuletzt Erwähnte berücksichtigende Code:

Code:
Sub ati()
 Dim i As Long, j As Long, k As Long
 Dim lngZ As Long
 Dim lngMax As Long
 Dim lngAnzahlm As Long
 Dim feld
 Dim arr()
 With Sheets("Tabelle1")
   lngZ = .Cells(.Rows.Count, 1).End(xlUp).Row
   lngMax = Application.Max(.Columns("Q"))
   lngAnzahlm = Application.CountIf(.Columns("Q"), lngMax)
   feld = .Range("A2:Q" & lngZ)
   ReDim arr(lngAnzahlm - 1, 16)
     For i = 0 To lngZ - 2
       If feld(i + 1, 17) = lngMax Then
         For j = 0 To 16
           arr(k, j) = feld(i + 1, j + 1)
         Next j
         k = k + 1
       End If
     Next i
   .Range("A2:A" & lngZ).CurrentRegion.ClearContents
   .Range("A2:Q" & 2 + k - 1) = arr
 End With
End Sub
Gruß Atilla
Antworten Top


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste