2012-05-11 13 views
16

Ich habe einen VBA-Makro, der Zeilen von einem Arbeitsblatt in ein anderes kopiert, basierend auf dem Finden von Werten in Zellen in 3 Spalten. Das Makro funktioniert, stürzt jedoch ab, wenn es die Zeile 32767 erreicht. Es gibt keine Formeln oder spezielle Formatierung in dieser Zeile. Außerdem habe ich diese Zeile rausgenommen, aber es stürzt immer noch auf dieser Zeilennummer ab. Ist das eine Einschränkung in Excel? Es gibt einige 43000 in dem Arbeitsblatt, das VerfahrenVBA-Makro stürzt nach 32000 Zeilen ab

Daher wird, frage ich, was mit meinem Makro ist falsch und wie kann ich es das Ende des Arbeitsblatts erhalten erreichen:

Dim LSearchRow As Integer 
Dim LCopyToRow As Integer 
Dim wks As Worksheet 
On Error GoTo Err_Execute 

For Each wks In Arbeitsblatt

LSearchRow = 4 
LCopyToRow = 4 

ThisWorkbook.Worksheets.Add After:=Worksheets(Worksheets.Count) 
Set wksCopyTo = ActiveSheet 
wks.Rows(3).EntireRow.Copy wksCopyTo.Rows(3) 

While Len(wks.Range("A" & CStr(LSearchRow)).Value) > 0 

    If wks.Range("AB" & CStr(LSearchRow)).Value = "Yes" And wks.Range("AK" & CStr(LSearchRow)).Value = "Yes" And wks.Range("BB" & CStr(LSearchRow)).Value = "Y" Then 

     Rows(CStr(LSearchRow) & ":" & CStr(LSearchRow)).Select 
     Selection.Copy 


     wksCopyTo.Select 
     wksCopyTo.Rows(CStr(LCopyToRow) & ":" & CStr(LCopyToRow)).Select 
     wksCopyTo.Paste 

     'Move counter to next row 
     LCopyToRow = LCopyToRow + 1 
     'Go back to Sheet1 to continue searching 
     wks.Select 
    End If 
    LSearchRow = LSearchRow + 1 
Wend 

Application.CutCopyMode = False 
Range("A3").Select 
MsgBox "All matching data has been copied." 
Next wks 
    Exit Sub 
Err_Execute: 
    MsgBox "An error occurred." 

Bitte helfen!

+2

IIRC VBA ist 'Integer' Typ ist 16 Bit breit. Gibt es ein 'Long'? Ich vergesse. – cHao

+0

Nachschlagen Integer in der Hilfe, dann ändern Sie es in Long –

+0

Danke Jungs - noch alles, was ich tun musste, war den Datentyp auf eine lange ändern – Andy5

Antwort

31

Der Typ VBA 'Int' ist ein vorzeichenbehaftetes 16-Bit-Feld und kann daher nur Werte von -32768 bis +32767 enthalten. Ändern Sie diese Variablen in 'Long', das ein 32-Bit-Feld mit Vorzeichen ist und Werte von -2147483648 bis +2147483647 enthalten kann. Sollte für Excel reichen. ;)

+0

Wie würden Sie die Situation erklären, wenn ein Makro, das die Anzahl der Zeilen in Integer-Variablen verwendet (Zeilen überschreiten 32767) nicht nach 32676 zerquetscht, während ein anderes verknallt? – parsecer

4

Das klingt nach einer ganzen Zahl Problem

Die Integer und Längendatentypen sowohl positive oder negative Werte halten kann. Der Unterschied zwischen ihnen ist ihre Größe: Integer-Variablen können Werte zwischen -32.768 und 32.767 enthalten, während Long-Variablen von -2.147.483.648 bis 2.147.483.647 reichen können.

Aber welche Version verwenden Sie? Denn:

Traditionell haben VBA Programmierer ganzen Zahlen verwendet, um kleine Zahlen zu halten, weil sie weniger Speicher benötigt. In den letzten Versionen konvertiert VBA jedoch alle Integer-Werte in Long, auch wenn sie als Typ Integer deklariert sind. Daher gibt mit Integer-Variablen keinen Leistungsvorteil mehr; Tatsächlich können Long-Variablen etwas schneller sein, weil VBA sie nicht konvertieren muss.

Da diese Informationen direkt von MSDN

UPDATE

Bitte beachten Sie auch den ersten Kommentar lesen! Ich habe die MSDN-Informationen falsch interpretiert!

Das ist MSDN irreführend: VBA konvertiert Integer nicht selbst in Long. Unter der Decke konvertiert die CPU ganzzahlig in lang, tut die Arithmetik und wandelt dann die resultierende lange zurück in Ganzzahl um. So VBA ganzen Zahlen kann immer noch nicht halten Zahlen größer als 32 KB - Charles Williams

+7

Das MSDN ist irreführend: VBA konvertiert Integer nicht zu Long. Unter den Deckeln konvertiert die CPU ganzzahlig in lang, führt die Arithmetik durch und wandelt dann die resultierende lange zurück in Ganzzahl um. Also VBA-Ganzzahlen können immer noch nicht halten Zahlen größer als 32K –

+0

danke für diese Information! Das wusste ich nicht. Wird meinen Beitrag aktualisieren! – Neysor

2

Sie können die Integer vs. Lange Problem vermeiden, indem ein jeder Verwendung Für statt Inkrementieren Reihen. Für Jeder ist in der Regel schneller und vermeidet Auswahlbereiche.Hier ist ein Beispiel:

Sub CopySheets() 

    Dim shSource As Worksheet 
    Dim shDest As Worksheet 
    Dim rCell As Range 
    Dim aSheets() As Worksheet 
    Dim lShtCnt As Long 
    Dim i As Long 

    Const sDESTPREFIX As String = "dest_" 

    On Error GoTo Err_Execute 

    For Each shSource In ThisWorkbook.Worksheets 
     lShtCnt = lShtCnt + 1 
     ReDim Preserve aSheets(1 To lShtCnt) 
     Set aSheets(lShtCnt) = shSource 
    Next shSource 

    For i = LBound(aSheets) To UBound(aSheets) 
     Set shSource = aSheets(i) 

     'Add a new sheet 
     With ThisWorkbook 
      Set shDest = .Worksheets.Add(, .Worksheets(.Worksheets.Count)) 
      shDest.Name = sDESTPREFIX & shSource.Name 
     End With 

     'copy header row 
     shSource.Rows(3).Copy shDest.Rows(3) 

     'loop through the cells in column a 
     For Each rCell In shSource.Range("A4", shSource.Cells(shSource.Rows.Count, 1).End(xlUp)).Cells 
      If Not IsEmpty(rCell.Value) And _ 
       rCell.Offset(0, 27).Value = "Yes" And _ 
       rCell.Offset(0, 36).Value = "Yes" And _ 
       rCell.Offset(0, 53).Value = "Yes" Then 

       'copy the row 
       rCell.EntireRow.Copy shDest.Range(rCell.Address).EntireRow 
      End If 
     Next rCell 
    Next i 

    MsgBox "All matching data has been copied." 

Err_Exit: 
    'do this stuff even if an error occurs 
    On Error Resume Next 
    Application.CutCopyMode = False 
    Exit Sub 

Err_Execute: 
    MsgBox "An error occurred." 
    Resume Err_Exit 

End Sub 
+0

Uhh, fummelt mit der Sammlung während eines 'For Each' Laufs - * naughty * ... –

+0

Ganz richtig. Fest. Danke Marcus. –