2017-02-28 3 views
1

Mithilfe der Post here konnte ich ein VBA-Makro erstellen, um Zellen zwischen Arbeitsblättern zu vergleichen, um meine Zwecke zu erfüllen. Bis jetzt habe ich es jedoch nicht mit einem Bereich getestet, der nicht bei A1 beginnt.Vergleichen von Zellen zwischen Arbeitsblättern, Bereich beginnt nicht auf A1

Bei einem Bereich wie B1: X50 tritt ein Problem auf, bei dem der LBound der Spaltendimension des Blattarrays 1 ist, während die Spalte am Anfang des angegebenen Bereichs 2 (B) ist. Hier ist ein Teil des Codes Ich arbeite mit:

'Define the range to be checked 
strRangeToCheck = Summary_ws.Range("I2").Value 

'Store the range to be checked on each sheet in an array 
varSheetA = New_Data_ws.Range(strRangeToCheck) 
varSheetB = Old_Data_ws.Range(strRangeToCheck) 

'Clear current highlighted cells on data tabs 
New_Data_ws.Cells.Interior.Color = xlNone 
Old_Data_ws.Cells.Interior.Color = xlNone 

'Initialize counter 
Counter = 0 
Counter_rng.Value = Counter 

For iRow = LBound(varSheetA, 1) To UBound(varSheetA, 1) 
    For iCol = LBound(varSheetA, 2) To UBound(varSheetA, 2) 
     On Error GoTo Err_Handler 
     If IsError(New_Data_ws.Cells(iRow, iCol).Value) Or IsError(Old_Data_ws.Cells(iRow, iCol).Value) Then 
      Counter = Counter + 1 
      Error_Flag = True 
      Call Flag_Changes 
     ElseIf varSheetA(iRow, iCol) = varSheetB(iRow, iCol) And _ 
       Len(varSheetA(iRow, iCol)) = Len(varSheetB(iRow, iCol)) Then 
       'Cells are identical and lengths match 
       'Do Nothing 
     Else 'Cells are different 
      Counter = Counter + 1 'increment counter 
      Error_Flag = False 
      Call Flag_Changes 
     End If 
    Next iCol 
Next iRow 

Ich bin in der Lage, die strRangeToCheck zu bewerten, um festzustellen, ob es in Spalte A beginnt oder nicht. Wäre es dann möglich, basierend auf dieser Bestimmung den LBound des Blattes manuell auf die Startspalte in strRangeToCheck zu setzen?

+0

diese Linie würde ein Problem für Sie erstellen, da es nur eine Zelle 'ist strRangeToCheck = Summary_ws.Range („I2“). Value' Ihr Bereich eine Zelle immer oder es könnte als eine Zelle mehr sein? – Ibo

+0

Diese Zelle enthält eine Zeichenfolge, die von dem Benutzer zur Verfügung gestellt, wie A1: Z100. Wenn sie einen ungültigen Bereich angeben, wird ein Fehler ausgelöst. – kschindl

Antwort

1

In Antwort auf die Frage "Wäre es dann möglich, den LBound des Blattes manuell an die Startspalte anzupassen" lautet die Antwort nein. Range.Value wird immer ein Array mit einer unteren Grenze von 1 zurückgeben - Excel ist verantwortlich für die Erstellung der zurückgegebenen Array, und Sie können dieses Verhalten nicht über VBA ändern (und würde nicht wollen, auch wenn Sie aus verschiedenen anderen Gründen könnten).

Die Lösung ist ein Range aus der übergebenen Adresse als Zwischenschritt zu erstellen, bevor Sie die .Value ‚s in den Felder ziehen:

'Store the range to be checked on each sheet in an array 
Dim newRange As Range 
Dim oldRange As Range 
Set newRange = New_Data_ws.Range(strRangeToCheck) 
Set oldRange = Old_Data_ws.Range(strRangeToCheck) 
varSheetA = newRange.Value 
varSheetB = oldRange.Value 

Dann statt Worksheet.Cells in der Schleife zu verwenden, Range.Cells verwenden. Wenn Sie diese in die Arbeitsblattadressierung konvertieren müssen, finden Sie den Offset von A1 von der ersten in der Range. Arbeiten mit dem Beispiel von B1:X50:

Dim example As Range 
Set example = Sheet1.Range("B1:X50") 
Debug.Print example.Columns(1).Column '<-- column 2 
Debug.Print example.Rows(1).Row   '<-- row 1 

Beachten Sie, dass oben in Ihrem Code, sind Sie nur das Arbeitsblatt Indizierung auf einer einzigen Zeile mit (obwohl ich habe keine Ahnung, was Sie in Call Flag_Changes tun):

If IsError(New_Data_ws.Cells(iRow, iCol).Value) Or IsError(Old_Data_ws.Cells(iRow, iCol).Value) Then 

Sie müssen dies überhaupt nicht tun. New_Data_ws.Cells(iRow, iCol).Value ist genau dasselbe wie varSheetA(iRow, iCol). Deshalb ziehen Sie es in ein Array, oder? Ersetzen Sie einfach die Zeile mit diesem:

If IsError(varSheetA(iRow, iCol)) Or IsError(varSheetB(iRow, iCol)) Then 

Schließlich Sie nicht die Deklarationen für iRow enthalten waren und iCol, aber von der ungarischen Notation zu urteilen, wenn sie als Integer deklariert sind Sie sie Long ändern müssen zu vermeiden Überlauffehler. Wenn sie sind als Long erklärt, das ist noch ein weiteres Argument gegen die nicht ungarische Notation zu beginnen ...

+1

Danke für Ihre Hilfe! Ich konnte es zur Arbeit bringen. Außerdem war ich der ungarischen Notation völlig unwissend. That being said, 'iRow' und' iCol' wurden definiert als 'Long', aber ich werde den Code aktualisieren mit Namensstandards einzuhalten. Ich poste meinen aktualisierten Code. – kschindl

0

Ich bin mir nicht sicher, ob dies die eleganteste Art und Weise ist es, die Beratung zu implementieren, aber hier funktioniert Code dank Komintern:

'Store the range to be checked on each sheet in an array 
Set newRange = New_Data_ws.Range(strRangeToCheck) 
Set oldRange = Old_Data_ws.Range(strRangeToCheck) 
varSheetA = newRange.Value 
varSheetB = oldRange.Value 

'Variables used to track difference between array start and given range start 
row_diff = newRange.Rows(1).Row - 1 
col_diff = newRange.Columns(1).Column - 1 

'Loop through given range 
For rngRow = newRange.Rows(1).Row To newRange.Rows.Count + row_diff 
    arrRow = rngRow - row_diff 'increment row of array being evaluated 
    For rngCol = newRange.Columns(1).Column To newRange.Columns.Count + col_diff 
     arrCol = rngCol - col_diff 'increment column of array being evaluated 
     On Error GoTo Err_Handler 
     If IsError(varSheetA(arrRow, arrCol)) Or IsError(varSheetB(arrRow, arrCol)) Then 
      Counter = Counter + 1 
      Error_Flag = True 
      Call Flag_Changes 
     ElseIf varSheetA(arrRow, arrCol) = varSheetB(arrRow, arrCol) And _ 
       Len(varSheetA(arrRow, arrCol)) = Len(varSheetB(arrRow, arrCol)) Then 
       'Cells are identical and lengths match 
       'Do Nothing 
     Else 'Cells are different 
      Counter = Counter + 1 'increment counter 
      Error_Flag = False 
      Call Flag_Changes 
     End If 
    Next rngCol 
Next rngRow 

In meinem Flag_Changes Unter, mache ich Dinge wie die verschiedenen Zellen auf beiden Blatt hervorheben, das Drucken der Adresse der Zelle, die Werte jeder Zelle gedruckt wird, und die Differenz (wenn die Zellen numerisch sind).

Verwandte Themen