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

Performance erhöhen - Zelleninhalte leeren

Performance erhöhen - Zelleninhalte leeren
Mexsalem
Hallo werte Excelaner,
ich habe folgenden Code in einer Tabelle mit ca. 1000 Zeilen und etwa 28.000 Zellen, der durch das Ereignis "Zelländerung" ausgelöst wird.
Das Problem :
Der Code ist nicht schnell genug, da er die nachfolgenden Eingaben in die ungeschützten Zellen spürbar verzögert.
Die Frage :
Gibt es vielleicht eine schnellere Alternative für Part "Leeren nicht geschützten Zellen" (siehe For next Schleife) ? Ich habe den Code zumindest auf das Durchsuchen nur der genutzten Spalten (und nicht des gesamten UsedRange bzw. die gesamte Zeile) begrenzt. Oder einen anderen Ansatz mit demselben Ergebnis ?
Gruß
Mexsalem
Option Explicit
Sub HideRowIFWahr()
'Alle Zeilen, deren Wert in Spalte A WAHR ist,
'sollen "en bloc" ausgeblendet und deren
'nicht geschützte Zellen geleert werden.
On Error Resume Next
With Application
.ScreenUpdating = False
.Calculation = xlManual
.Cursor = xlWait
.EnableEvents = False
End With
Dim rng As Range
Dim iRow As Integer
Dim iRowL As Integer
Dim Zelle As Range
Dim rngNotLocked As Range
Dim LetzteSpalte As Integer
' erstmal alle Zeilen einblenden
Cells.EntireRow.Hidden = False
' dann letzte Zeile mit Wert in Spalte A bestimmen
iRowL = Cells(Rows.Count, 1).End(xlUp).Row
For iRow = 1 To iRowL
' Letzte Spalte der aktuellen Zeile iRow ermitteln
LetzteSpalte = ActiveSheet.Cells(iRow, 256).End(xlToLeft).Column
' Dann alle Zellen in Spalte A mit WAHR finden
If Cells(iRow, 1).Value = True Then
For Each Zelle In ActiveSheet.Range(Cells(iRow, 1), Cells(iRow, LetzteSpalte))
If Zelle.Locked = False Then
If rngNotLocked Is Nothing Then
Set rngNotLocked = Zelle
End If
Set rngNotLocked = Application.Union(rngNotLocked, Zelle)
End If
Next Zelle
' Inhalt der Gefundenen Zellen leeren
rngNotLocked.Value = ""
' Alle Zeilen mit WAHR in SPALTE A finden
' Wenn WAHR zum ersten Mal vorkommt
If rng Is Nothing Then
Set rng = Cells(iRow, 1)
' Wenn WAHR mehrfach vorkommt, bilde Mehrfachselektion
Else
Set rng = Application.Union(rng, Cells(iRow, 1))
End If
End If
Next iRow
' Falls gar keine Zeile zum Ausblenden gefunden wurde
If rng Is Nothing Then GoTo errorhandler
' Ansonsten blende die gefundene(n) Zeile / Zeilen aus
rng.EntireRow.Hidden = True
errorhandler:
With Application
.ScreenUpdating = True
.Calculation = xlAutomatic
.Cursor = xlDefault
.EnableEvents = True
.StatusBar = ""
End With
End Sub

AW: Performance erhöhen - Zelleninhalte leeren
12.05.2012 00:08:04
Josef

Hallo Mex,
ohne nähere Kenntnis deiner Tabelle ist es schwierig, Optimierungsmöglichkeiten zu finden.
Versuche es mal so.
Sub HideRowIFWahr()
  Dim rng As Range, rngC As Range, rngR As Range, rngHide As Range, rngDel As Range
  Dim lngCalc As Long
  
  On Error GoTo ErrExit
  
  With Application
    .ScreenUpdating = False
    .EnableEvents = False
    lngCalc = .Calculation
    .Calculation = xlCalculationManual
    .DisplayAlerts = False
  End With
  
  With ActiveSheet
    .Rows.Hidden = False
    On Error Resume Next
    Set rng = .Columns(1).SpecialCells(xlCellTypeFormulas, xlLogical)
    On Error GoTo ErrExit
    If Not rng Is Nothing Then
      For Each rngC In rng.Cells
        If rngC = True Then
          If rngHide Is Nothing Then
            Set rngHide = rngC.EntireRow
          Else
            Set rngHide = Union(rngHide, rngC.EntireRow)
          End If
          For Each rngR In rngC.EntireRow.SpecialCells(xlCellTypeConstants).Cells
            If Not rngR.Locked Then
              If rngDel Is Nothing Then
                Set rngDel = rngR
              Else
                Set rngDel = Union(rngDel, rngR)
              End If
            End If
          Next
        End If
      Next
    End If
  End With
  
  If Not rngHide Is Nothing Then rngHide.EntireRow.Hidden = True
  If Not rngDel Is Nothing Then rngDel = ""
  
  ErrExit:
  
  With Err
    If .Number <> 0 Then
      MsgBox "Fehler in Prozedur:" & vbTab & "'HideRowIFWahr'" & vbLf & String(60, "_") & _
        vbLf & vbLf & IIf(Erl, "Fehler in Zeile:" & vbTab & Erl & vbLf & vbLf, "") & _
        "Fehlernummer:" & vbTab & .Number & vbLf & vbLf & "Beschreibung:" & vbTab & _
        .Description & vbLf, vbExclamation + vbMsgBoxSetForeground, _
        "VBA - Fehler in Modul - Modul2"
      .Clear
    End If
  End With
  
  On Error GoTo 0
  
  With Application
    .ScreenUpdating = True
    .EnableEvents = True
    .Calculation = lngCalc
    .DisplayAlerts = True
  End With
  
  Set rng = Nothing
  Set rngC = Nothing
  Set rngR = Nothing
  Set rngHide = Nothing
  Set rngDel = Nothing
End Sub



« Gruß Sepp »

Anzeige
AW: Performance erhöhen - Zelleninhalte leeren
12.05.2012 00:34:50
Mexsalem
Hallo Josef,
also deine Performance stimmt auf jeden Fall schon mal .... so schnell hätte ich nicht mit einer Reaktion gerechnet ! Vielen Dank.
Leider steigt der Code laut Einzelschritt-Debugger beim zweiten Durchlauf bei

For Each rngR In rngC.EntireRow.SpecialCells(xlCellTypeConstants).Cells
aus -> ErrExit.
Fehlermeldung : Code 1004 - Microsoft konnte keine Zellen des angegebenen Typs finden. Markieren Sie nur eine einzelne Zelle und führen Sie dne Befehl erneut aus. Wenn nur eine Zelle markiert ist, durchsucht Microsoft Excel die ganze Tabelle.
Ich muss gestehen, deinen Code auf die Schnelle nicht nachvollziehen zu können (bin nunmal kein Programmierer). Was kann im Code Abhilfe schaffen oder hängte es an meiner Tabelle (ich benutze immer noch Excel 97 und auch verbundene Zellen) ?
Gruß
Mexsalem
Anzeige
AW: Performance erhöhen - Zelleninhalte leeren
12.05.2012 00:43:17
Josef

Hallo Mex,
dann so.
Sub HideRowIFWahr()
  Dim rng As Range, rngC As Range, rngR As Range, rngZ As Range, rngHide As Range, rngDel As Range
  Dim lngCalc As Long
  
  On Error GoTo ErrExit
  
  With Application
    .ScreenUpdating = False
    .EnableEvents = False
    lngCalc = .Calculation
    .Calculation = xlCalculationManual
    .DisplayAlerts = False
  End With
  
  With ActiveSheet
    .Rows.Hidden = False
    On Error Resume Next
    Set rng = .Columns(1).SpecialCells(xlCellTypeFormulas, xlLogical)
    On Error GoTo ErrExit
    If Not rng Is Nothing Then
      For Each rngC In rng.Cells
        If rngC = True Then
          If rngHide Is Nothing Then
            Set rngHide = rngC.EntireRow
          Else
            Set rngHide = Union(rngHide, rngC.EntireRow)
          End If
          On Error Resume Next
          Set rngZ = rngC.EntireRow.SpecialCells(xlCellTypeConstants).Cells
          On Error GoTo ErrExit
          If Not rngZ Is Nothing Then
            For Each rngR In rngZ.Cells
              If Not rngR.Locked Then
                If rngDel Is Nothing Then
                  Set rngDel = rngR
                Else
                  Set rngDel = Union(rngDel, rngR)
                End If
              End If
            Next
          End If
        End If
      Next
    End If
  End With
  
  If Not rngHide Is Nothing Then rngHide.EntireRow.Hidden = True
  If Not rngDel Is Nothing Then rngDel = ""
  
  ErrExit:
  
  With Err
    If .Number <> 0 Then
      MsgBox "Fehler in Prozedur:" & vbTab & "'HideRowIFWahr'" & vbLf & String(60, "_") & _
        vbLf & vbLf & IIf(Erl, "Fehler in Zeile:" & vbTab & Erl & vbLf & vbLf, "") & _
        "Fehlernummer:" & vbTab & .Number & vbLf & vbLf & "Beschreibung:" & vbTab & _
        .Description & vbLf, vbExclamation + vbMsgBoxSetForeground, _
        "VBA - Fehler in Modul - Modul2"
      .Clear
    End If
  End With
  
  On Error GoTo 0
  
  With Application
    .ScreenUpdating = True
    .EnableEvents = True
    .Calculation = lngCalc
    .DisplayAlerts = True
  End With
  
  Set rng = Nothing
  Set rngC = Nothing
  Set rngR = Nothing
  Set rngZ = Nothing
  Set rngHide = Nothing
  Set rngDel = Nothing
End Sub




« Gruß Sepp »

Anzeige
AW: Performance erhöhen - Zelleninhalte leeren
12.05.2012 00:53:24
Mexsalem
Hallo Josef,
dein Code funktioniert jetzt. Hut ab.
Die Performance scheint sich ebenfalls verbessert zu haben (gefühlt 1 Sekunde pro Eingabe). Genau kann ich es nicht sagen, habe leider kein "Zeitmessmakro" verfügbar.
Wie kann ich die Auslösung des Makros (Private Sub Worksheet_Change(ByVal Target As Range)) statt pauschal über alle veränderten Zellen nur auf die relevanten Bereiche beschränken (z.B. Range("G6:H6,G8:K8,G12:K12,T34:V34,X34:AA34,X36:AA36,T36:V36,T40:V40,X40:AA40,H44:O58,Y299:AC307") ?
Danke nochmal für deine schelle Hilfe !
und trink bloss keinen Kaffee mehr .... es ist fast 1 Uhr.
Mexsalem
Anzeige
AW: Performance erhöhen - Zelleninhalte leeren
12.05.2012 01:34:51
CitizenX
moin,

If Not Intersect(Target, _
Range("G6:H6,G8:K8,G12:K12,T34:V34,X34:AA34,X36:AA36,T36:V36,T40:V40,X40:AA40,H44:O58,Y299: _
AC307 ")) Is Nothing Then
'dein code
End If
Grüße
Steffen
AW: Performance erhöhen - Zelleninhalte leeren
12.05.2012 21:44:46
Mexsalem
Hallo Steffen,
besten Dank für deine Antwort - war wohl gestern doch etwas spät für mich geworden, um selbst drauf zu kommen. Dein Code funktioniert.
Gruß
Mexsalem
AW: Performance erhöhen - Zelleninhalte leeren
12.05.2012 00:43:35
Mexsalem
Frage nochmal als offen markiert

302 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige