Can't get my Ranges set up from my spreadsheet using VBA - vba

My overall goal here is to grab the values and row indices of three different columns on the original spreadsheet, evaluate them, and then save them to a new spreadsheet. I am wanted to accomplish this by using a macro initiated by a button on the original spreadsheet.
The plan to accomplish this was to
create a Range for each column
Loop through the most significant Range to grab and evaluate the each cell value
perform nested loops within the first loop to further evaluate the other two Ranges and grab their values
assign values to variables
create the new spreadsheet from a template
write the values to the respective columns
save the new spreadsheet
When I run the code below I get the error listed below. I'm confused because I thought this is how you reference an entire column:
Sub Transfer2NewWorkbook()
Dim currentsheet As String
Dim newsheet As String
Dim analysisDate As String
Dim initial As String
Dim aInitial() As String
Dim analystInit As String
Dim batchNo As String
Dim wb As Object
Dim dataRangeA As Range, dataRangeB As Range, dataRangeI As Range
Set dataA = CreateObject("Scripting.Dictionary")
' Grab and Create filenames
currentsheet = ActiveWorkbook.Name
newsheet = currentsheet & "-" & "uploadable"
' Grab data from original spreadsheet
analysisDate = ActiveWorkbook.Sheets(1).Cells(1, 9).Value
initial = ActiveWorkbook.Sheets(1).Cells(1, 2).Value
aInitial = Split(initial, "/")
analystInit = aInitial(1)
Set dataRangeA = Range("A4:A").Select ' <-- Line causing error
Set dataRangeB = Range("B4:B").Select
Set dataRangeI = Range("I4:I").Select
For i = 1 To dataRangeA.Rows.Count
dataA.Add Key:=i, Item:=dataRangeA.Cells.Value
Next i
Set wb = Workbooks.Add("C:\Users\dalythe\documents\uploadtemp.xlsx")
ActiveWorkbook.Sheets(1).Cells(3, 2).Value = analysisDate
ActiveWorkbook.Sheets(1).Cells(3, 4).Value = analystInit
ActiveWorkbook.SaveAs (newsheet & ".xlsx")
End Sub

try this:
Set dataRangeA = Range("A:A").Select
Set dataRangeB = Range("B:B").Select
Set dataRangeI = Range("I:I").Select
For i = 4 To dataRangeA.Rows.Count
dataA.Add Key:=i, Item:=dataRangeA.Cells.Value
Next i

After removing the .Select, my ranges were accepted.
Set dataRangeA = Range("A:A")
Set dataRangeB = Range("B:B")
Set dataRangeI = Range("I:I")
For i = 4 To dataRangeA.Rows.Count
dataA.Add Key:=i, Item:=dataRangeA.Cells.Value
Next i
Thanks for the input YowE3k. Now I have to think on how I want my loop to end. Because doing it the way I have it above will cause it to run out of memory. The spreadsheet will not have a "predefined" number of rows. I guess I will have to have the user type "End" in the cell of the last row or something.

Your problems with the particular line throwing the error are caused by two things:
"A4:A" is not a valid address in Excel. You can either use "A:A" for the entire column or define the end of the range, e.g. "A4:A272".
The Range.Select method does not return an object, so Set dataRangeA = Range("A4:A").Select is effectively Set dataRangeA =.
To fix your specific error, you could do something like:
Set dataRangeA = Range("A4", Cells(Rows.Count, "A").End(xlUp))
However, using unqualified Cells and Range and Rows is a dangerous habit to get into once you have more than one worksheet / workbook being used in your code, because those objects default to referring to the ActiveSheet in the ActiveWorkbook and that may not be the one you are expecting it to be.
The code below ensures that each object is qualified, plus makes some other improvements to your code (such as the inevitable out-of-memory error that would arise in populating the Dictionary).
Sub Transfer2NewWorkbook()
Dim currentsheet As String
Dim newsheet As String
Dim analysisDate As String
Dim initial As String
Dim aInitial() As String
Dim analystInit As String
Dim batchNo As String
Dim wb As Object
Dim dataRangeA As Range, dataRangeB As Range, dataRangeI As Range
Dim dataA As Object ' declare this, unless you have declared it at a higher
' level scope
Set dataA = CreateObject("Scripting.Dictionary")
' Grab and Create filenames
currentsheet = ActiveWorkbook.Name
newsheet = currentsheet & "-" & "uploadable"
'Use a With block to avoid having to constantly refer
' to "ActiveWorkbook.Sheets(1)"
With ActiveWorkbook.Sheets(1)
' Grab data from original spreadsheet
analysisDate = .Cells(1, 9).Value
initial = .Cells(1, 2).Value
aInitial = Split(initial, "/")
analystInit = aInitial(1)
Set dataRangeA = .Range("A4", .Cells(.Rows.Count, "A").End(xlUp))
Set dataRangeB = .Range("B4", .Cells(.Rows.Count, "B").End(xlUp))
Set dataRangeI = .Range("I4", .Cells(.Rows.Count, "I").End(xlUp))
'This loop is making every entry in the Dictionary contain the value of
'every cell in the range - i.e. each of the 1048573 entries in the Dictionary
'would have contained an array which was dimensioned As (1 To 1048573, 1 To 1)
'For i = 1 To dataRangeA.Rows.Count
' dataA.Add Key:=i, Item:=dataRangeA.Cells.Value
'Next i
Dim cel As Range
For Each cel in dataRangeA
dataA.Add Key:=cel.Row, Item:=cel.Value
'or
'dataA.Add Key:=cel.Row - 3, Item:=cel.Value
'if you wanted A4's value to have a key of 1
Next
'Note: If you just wanted an array of values, you could have used
' Dim dataA As Variant
' dataA = Application.Transpose(.Range("A4", .Cells(.Rows.Count, "A").End(xlUp)))
'and then access each value using dataA(1) for the value from A4,
'dataA(2) for the value from A5, etc.
'This then gets rid of the need for dataRangeA, and the need for a
' dictionary object, and the need for the loop populating the dictionary.
End With
Set wb = Workbooks.Add("C:\Users\dalythe\documents\uploadtemp.xlsx")
With wb.Worksheets(1)
.Cells(3, 2).Value = analysisDate
.Cells(3, 4).Value = analystInit
End With
wb.SaveAs newsheet & ".xlsx"
End Sub

Related

Assigning values to array vba

I don't have experience using arrays in VBA and I got lost. What I try to do is the following:
In the column A I have ~15 strings (number is not fixed sometimes it is more sometimes less)
I remove duplicates and then for each name in the column A I would like to create separate sheet in the file.
I created an array to which I tried to assign each name from A with this loop:
Sub assigningvalues()
Dim i As Integer
Dim myArray(20) As Variant
Dim finalrow As Long
ActiveSheet.Range("A1", Range("A1").End(xlDown)).RemoveDuplicates Columns:=Array(1)
finalrow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlDown).Row
'For i = 2 To finalrow -> I get overflow error when I use this range
For i = 2 To Cells(20, 1)
myArray(i) = Cells(i, 1).Value
Next i
'I check with the lines below if values were assigned
Cells(2, 4).Value = myArray(4)
Cells(3, 4).Value = myArray(2)
End Sub
Nevertheless values from the cells to do not assign to the array
Moreover when I try to use finalrow as range for the loop I get overflow error (It is not a big problem as there are workarounds, although it would be nice to know what I've done wrong)
Try the code below:
Option Explicit
Sub assigningvalues()
Dim i As Long
Dim myArray(20) As Variant
Dim FinalRow As Long
Dim Sht As Worksheet
Set Sht = ThisWorkbook.Sheets("Sheet1") ' modify "Sheet1" to your sheet's name
With Sht
.Range("A1", .Range("A1").End(xlDown)).RemoveDuplicates Columns:=Array(1)
FinalRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' get last row in column "A"
For i = 2 To FinalRow
myArray(i) = Cells(i, 1).Value
Next i
'I check with the lines below if values were assigned
.Cells(2, 4).Value = myArray(4)
.Cells(3, 4).Value = myArray(2)
End With
End Sub
Note: you can read the contents of the Range to a 1-D Array without a For loop, using Application.Transpose, you need to change the line you define it to:
Dim myArray As Variant
and populate the entire array using:
myArray = Application.Transpose(.Range("A2:A" & FinalRow))
Try the code below:
Sub assigningvalues()
Dim myArray As Variant
ActiveSheet.Range("A1", Range("A1").End(xlDown)).RemoveDuplicates Columns:=Array(1)
myArray = ActiveSheet.Range("A1", Range("A1").End(xlDown))
For Each element In myArray
ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)).Name = element
Next element
End Sub
NOTES: The problem with your above code was, that
ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlDown).Row
returned the absolut number of rows in the sheet, not the used ones. Since your array has length 20 and the sheet about 1 Mio. rows, you have an overflow. you can check this by using
Debug.Print ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlDown).Row
In the above code, after you remove dublicates, you again go down from A1 to the end and save the range to an array. The array myArray now contains all the cell values in your reduced range.
Now you loop over the elements with
For Each element in myArray
and create a new sheet with Workbook.Sheets.Add and assign the name my setting Sheets(index).name = element
The above code should work for you. Few remarks:
Instead of using "ActiveSheet", ThisWorkbook, etc. You should always start a Sub with this:
Dim wb As Workbook
Set wb = ThisWorkbook 'for the workbook containing the code
Set wb = Workbooks(workbookName) 'to reference an other Workbook
'And for all the sheets you are using
Dim ws As Worksheet
Set ws = wb.Sheets(sheetName) 'this way you avoid problems with multiple
workbooks that are open and active or
unactive sheets.

If cell = value then copy and paste cell below with addition

I have a spreadsheet with values starting at A5 and running across to column AI, there could be any number of entries to the rows.
Row A contains an Item code (e.g. 000-0000)
I am looking to produce some code to complete the following two actions:
If column AI = yes, then copy entire row and paste below. With every copy add a sequential alphabetised letter to the code in column A (e.g. 000-0000a)
Any help would be greatly appreciated. Everything i've found expands to copying to another sheet and i'm struggling to break down the code.
Thanks
Edit:
Please see below current code I have been trying to get to work which works up to the point of copying the row however fails to paste it.
Sub NewItems(c As Range)
Dim objWorksheet As Worksheet
Dim rngNewItems As Range
Dim rngCell As Range
Dim strPasteToSheet As String
'Used for the new worksheet we are pasting into
Dim objNewSheet As Worksheet
Dim rngNextAvailbleRow As Range
'Define the worksheet with our data
Set objWorksheet = ThisWorkbook.Sheets("Sheet1")
'Dynamically define the range to the last cell.
'This doesn't include and error handling e.g. null cells
'If we are not starting in A1, then change as appropriate
Set rngNewItems = objWorksheet.Range("A5:A" & objWorksheet.Cells(Rows.Count, "A").End(xlUp).Row)
'Now loop through all the cells in the range
For Each rngCell In rngNewItems.Cells
objWorksheet.Select
If rngCell.Value <> "Yes" Then
'select the entire row
rngCell.EntireRow.Select
'copy the selection
Selection.Copy
'Now identify and select the new sheet to paste into
Set objNewSheet = ThisWorkbook.Sheets("Sheet1" & rngCell.Value)
objNewSheet.Select
'Looking at your initial question, I believe you are trying to find the next available row
Set rngNextAvailbleRow = objNewSheet.Range("A1:A" & objNewSheet.Cells(Rows.Count, "A").End(xlUp).Row)
Range("A" & rngNextAvailbleRow.Rows.Count + 1).Select
ActiveSheet.Paste
End If
Next rngCell
objWorksheet.Select
objWorksheet.Cells(1, 1).Select
'Can do some basic error handing here
'kill all objects
If IsObject(objWorksheet) Then Set objWorksheet = Nothing
If IsObject(rngBurnDown) Then Set rngNewItems = Nothing
If IsObject(rngCell) Then Set rngCell = Nothing
If IsObject(objNewSheet) Then Set objNewSheet = Nothing
If IsObject(rngNextAvailbleRow) Then Set rngNextAvailbleRow = Nothing
End Sub
So there are lots of things to address with your code. Many of which I have touched on. But the main thing to observe is that you are testing Column A not Column AI for the presence of "Yes" - so there may not be a match hence no copy.
As the paste destination is determined by a concatenation to create a sheet name you should have a test to ensure that sheet exists.
For testing I simply ensured a sheet called Sheet1a existed, that Sheet1 cell A5 had "a" in it, and there was a "Yes" in column AI. This could be improved but is enough to get you going.
This line is looping column A:
Set rngNewItems = objWorksheet.Range("A5:A" & lastRow)
Whereas this line is testing column AI:
If rngCell.Offset(, 35).Value <> "Yes"
Note <> means Not Equal as opposed to =
So perhaps you wanted:
If rngCell.Offset(, 35).Value = "Yes"
Consider the following re-write.
Option Explicit
Public Sub NewItems() 'c As Range) 'I have commented out parameter which isn't currently used.
Dim rngBurnDown As Range ' not used but also not declared
Dim objWorksheet As Worksheet
Dim rngNewItems As Range
Dim rngCell As Range
Dim strPasteToSheet As String
Dim objNewSheet As Worksheet
Dim lastRowTargetSheet As Long
Set objWorksheet = ThisWorkbook.Sheets("Sheet1")
Dim lastRow As Long
lastRow = objWorksheet.Cells(Rows.Count, "A").End(xlUp).Row
Set rngNewItems = objWorksheet.Range("A5:A" & lastRow)
Dim copiedRange As Range 'for union
For Each rngCell In rngNewItems.Cells
'Debug.Print rngCell.Address 'shows where looping
If rngCell.Offset(, 35).Value = "Yes" Then
Set objNewSheet = ThisWorkbook.Sheets("Sheet1" & rngCell.Value)
Dim nextTargetCell As Range
lastRowTargetSheet = objNewSheet.Cells(Rows.Count, "A").End(xlUp).Row
Set nextTargetCell = objNewSheet.Range("A" & lastRowTargetSheet)
rngCell.EntireRow.Copy nextTargetCell
Set objNewSheet = Nothing 'clear inside loop as you are setting in loop
lastRowTargetSheet = 0
Set nextTargetCell = Nothing
End If
Next rngCell
objWorksheet.Cells(1, 1).Select
End Sub
As for your lettering:
There are lots of examples online to generate these. Here is one way, by #harfang, from here:
Sub List_A_to_ZZZZ()
Dim i As Long
For i = 1 To 20 ' I have shortened this QHarr. Original end was 475254 ' ColXL("ZZZZ")
Debug.Print Right("---" & XLcL(i), 4)
Next i
End Sub
Function XLcL(ByVal N As Long) As String
Do While N > 0
XLcL = Chr(vbKeyA + (N - 1) Mod 26) & XLcL
N = (N - 1) \ 26
Loop
End Function
Function ColXL(ByVal abc As String) As Long
abc = Trim(Replace(UCase(abc), "-", ""))
Do While Len(abc)
ColXL = ColXL * 26 + (Asc(abc) - vbKeyA + 1)
abc = Mid(abc, 2)
Loop
End Function

Pasting multiple ranges to another sheet in vba

I'd like the code to paste 'cashb' underneath 'rngcel', but every time
I run the code 'cashb''s value appears above 'rngCel'.value. Rngcell's range is from A2:A34, I'd like 'Cashb' to appear right below it at A35. I tried putting 'A35' in the
range but it does not work.
This is the code that I want to appear below rngcel.value.
Sheets(" Price").Range("A35").Resize(Cashb.Rows.Count).Value = Cashb.Value
I'd also like to return the column that's 5 columns to the right of "cashb"range
I appreciate any help that I receive.
This is the code that I have.Thanks in advance.
Sub liveP()
Application.ScreenUpdating = False
Dim rngTicker As Range
Dim rngCel As Range
Dim Cashb As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets.Add(After:= _
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = "Live"
Set rngTicker = Worksheets("prices").Range("H16:H200")
Set Cashb = Sheets("prices").Range("cashbalances")
For Each rngCel In rngTicker
If rngCel.Font.ColorIndex = 33 Then
Worksheets("Live").Cells(Rows.Count, 1).End(xlUp).offset(1).Resize(1, 2).Value = Array(rngCel.offset(, "-7").Value, rngCel.Value) ' this is range cell value'
WorkSheets("Live").Range("A35").Resize(Cashb.Rows.Count).Value = Cashb.Value.offset ' this is the value I'd like to appear under rngcel value
'New data that im posting on the Live sheet'
Sheets("Live").Range("C2:H33").Formula = "=($B2 +$C5)"
Sheets("Live").Range("A1") = "Header1"
Sheets("Live").Range("B1") = "Header2"
Sheets("Live").Range("C1") = "Header3"
Sheets("Live").Range("D1") = "Header4"
Sheets("Live").Range("E1") = "Header5"
Sheets("Live").Range("F1") = "Header6"
End If
Next
Application.ScreenUpdating = True
End Sub
Try This
Sub liveP()
Application.ScreenUpdating = False
Dim rngTicker As Range
Dim rngCel As Variant 'used in for each this should be variant
Dim Cashb As Range
Dim ws As Worksheet
Dim LastRow As Long 'dimensioned variable for the last row
Dim CashbRows As Long 'dimensioned variable for Cashb rows
Set ws = ThisWorkbook.Sheets.Add(After:= _
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = "Live"
Set rngTicker = Worksheets("prices").Range("H16:H200")
Set Cashb = Sheets("prices").Range("cashbalances")
'Assuming "cashbalances" is a named range in the worksheet
CashbRows = Cashb.Rows.Count
For Each rngCel In rngTicker
If rngCel.Font.ColorIndex = 33 Then
With Worksheets("Live")
LastRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1 'set lastrow variable
.Cells(LastRow, 1) = rngCel.Offset(0, -7).Value 'putting value 7 columns before into live worksheet column A
.Cells(LastRow, 2) = rngCel.Value 'putting value into live worksheet column B
.Range(.Cells(35, 1), .Cells(35 + CashbRows, 1)) = Cashb.Offset(, 5).Value 'im not really sure if this line is going to work at all
'New data that im posting on the Live sheet'
.Range("C2:H33").Formula = "=($B2 +$C5)"
.Range("A1") = "Header1"
.Range("B1") = "Header2"
.Range("C1") = "Header3"
.Range("D1") = "Header4"
.Range("E1") = "Header5"
.Range("F1") = "Header6"
End With
End If
Next
Application.ScreenUpdating = True
End Sub
Modifications:
rngCel is now a variant not a range
Using a LastRow Variable to get away from offset
Removed the array when placing data into "LIVE" because why not
CashbRows will now only be calculated one time before the loop. Saving time
The With Worksheets("Live") statement is a time saving measure.
You were calling A35 as a range, which it is not, then resizing to a range maybe? Hard to know when I cant tell what "cashbalances" is. If "cashbalances is only 1 row or may ever be 1 row, then you will need to add an If Then Else control to handle it.
Also A35 gets overwritten every single loop... so not sure what you want to do there.
I hope I was able to understand your questions well enough to get you going in the right direction.
EDIT
Stop treating "cashbalances" as a named range. I believe VBA is hanging onto the original row numbers of the range, similar to how Variant arrays start at 1 when assigned as I do in the following. It does not look like you are modifying "cashbalances" so create a variant array before the loop but after CashbRows.
EXAMPLE:
Dim CB() as variant, j as long
with sheets("PUT THE SHEET NAME OR INDEX HERE")
CB = .range(.cells(1,6), .cells(CashbRows,6)).value 'address to whatever .offset(,5) is
'i assumed cashb was in column A
Instead of .Range(.Cells(35, 1), .Cells(35 + CashbRows, 1)) = Cashb.Offset(, 5).Value Use:
For j = 1 to CashbRows
.cells(34 + j, 1) = CB(j)
Next j

How to iterate through rows in sheet1 given cell value in sheet2 and replace row in sheet1 with row in sheet 2?

I have to find and replace rows in sheet 1 given matching cell value in the same column in sheet2. The column number is 4.
HELPPP!!!
This is what I have right now and I get an error on next x.
Sub DeleteRows()
Dim wb As Workbook
Dim ws As Worksheet
Dim ws2 As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheets(Sheet1)
Set ws2 = Sheets(sheet2)
With wb
For i = 1 To ws2.Cells(Rows.Count, 4).End(xlUp).Row
Dim lookupvalue As String
lookupvalue = ws2.Cells(i, 4).Value
For x = 1 To ws1.Cells(Rows.Count, 4).End(xlUp).Row
Dim rng As range
For Each rng In range("D:D")
If InStr(1, rng.Value, "lookupvalue") > 0 Then
rng.Delete
End If
Next x
exitloop:
Next i
End With
End Sub
As A.S.H. said, the code needs a little improvement:
1) The two inner loops need to be combined.
2) The new inner loop should go from the bottom up, due to the fact that you are deleting the cell, This is probably why you have the second inner loop but that just adds time to the sub.
3) you are currently only deleting the one cell at a time, any data around it will remain. This may be what you want and so I left it, but if you meant to delete the entire row then uncomment the line that does that.
4) when testing with the instr function the variable should not be in quotes, with the variable in quotes it will look for that specific word "lookupvalues" and not the value assigned to that variable.
5) The with block that was being used did nothing. when using the with block the line that use it need to start with a '.' for example: on your code the with was with the workbook so every time a worksheet is used it should start with a "." like .ws1... and so forth. But by declaring the sheets using the workbook, this is no longer needed.
Sub DeleteRows()
Dim wb As Workbook
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim rng As Range
Dim lookupvalue As String
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Sheet1")
Set ws2 = wb.Sheets("sheet2")
For i = 1 To ws2.Cells(Rows.Count, 4).End(xlUp).Row
lookupvalue = ws2.Cells(i, 4).Value
For x = ws.Cells(Rows.Count, 4).End(xlUp).Row To 1 Step -1
Set rng = ws.Cells(x, 4)
If InStr(1, rng.Value, lookupvalue) > 0 Then
rng.Delete 'this only deletes the cell
'You may want this instead
'rng.entirerow.delete
End If
Next x
Next i
End Sub
I would like to propose an alternative way to handle this using a For Each Loop and the Find Method of the Range object.
Sub DeleteRows()
Dim wb As Workbook
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim lookup_rng As Range
Dim lookupvalue As String
Dim search_rng As Range
Dim rng As Range
Dim match_rng As Range
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Sheet1")
Set ws2 = wb.Sheets("Sheet2")
Set lookup_rng = Application.Intersect(ws2.Range("D:D"), ws.UsedRange)
Set search_rng = Application.Intersect(ws.Range("D:D"), ws2.UsedRange)
For Each rng In lookup_rng.Cells
lookupvalue = rng.Value
With search_rng
Set match_rng = .Find(lookupvalue, LookIn:=xlValues, LookAt:=xlPart, SearchDirection:=xlPrevious)
Do Until NoMoreMatches(match_rng)
match_rng.Delete 'Or match_rng.EntireRow.Delete if you want to delete the entire row.
Set match_rng = .FindPrevious
Loop
End With
Next
End Sub
Private Function NoMoreMatches(MatchRng As Range) As Boolean
NoMoreMatches = MatchRng Is Nothing
End Function
This approach is a little bit more wasteful then that of Scott Craner since the Find method always starts from the end of the range. However, I think it has the advantage that it is easier to read, i.e. that the code more directly shows what it is supposed to do.
Moreover, using this version you could extract the loops into a separate Sub you can use for arbitrary lookup and search ranges.

Compare two separate documents VBA

So what I want to do is have a macro in Workbook A that opens Workbook B and C. After that it goes through column A of Workbooks B and C and where the two values are equal it takes the value from workbook C and pastes it into column A of workbook A.
I have written the below code, however it you think it's easier to do it another way please feel free to write your own one. Thank you and please help me :)
Sub ReportCompareAlta()
'
' ReportCompareAlta Macro
' Adds instances where column D is "ALTA"
Dim varSheetA As Variant
Dim varSheetB As Variant
Dim varSheetC As Variant
Dim StrValue As Variant
Dim strRangeToCheck As String
Dim iRow As Long
Dim iCol As Long
Dim WbkA As Workbook
Dim WbkB As Workbook
Dim WbkC As Workbook
Dim counter As Long
Set WbkA = Workbooks.Open(Filename:="G:\Reporting\AH_MISSE_FEB2013.xls")
Set WbkB = Workbooks.Open(Filename:="G:\Reporting\AH_MISSE_MAR2013.xls")
Set WbkC = Workbooks.Open(Filename:="G:\Reporting\ReportCompare.xls")
Set varSheetA = WbkA.Worksheets("LocalesMallContratos")
Set varSheetB = WbkB.Worksheets("LocalesMallContratos")
Set varSheetC = WbkC.Worksheets("Sheet1")
strRangeToCheck = "A1:IV65536"
Debug.Print Now
varSheetA = WbkC.Worksheets("Sheet2").Range(strRangeToCheck) 'may be confusing code here
varSheetB = WbkC.Worksheets("Sheet3").Range(strRangeToCheck) 'may be confusing code here
Debug.Print Now
counter = 0
For iRow = LBound(varSheetA, 1) To UBound(varSheetA, 1)
If varSheetB(iRow, "B") = varSheetA(iRow, "B") & varSheetB(iRow, "B") <> "GERENCIA" & varSheetB(iRow, "B").Value <> "" & varSheetB(iRow, "D") = "ALTA" Then
StrValue = ""
varSheetB.Range("iRow:B").Select
Selection = StrValue
ActiveSheet = varSheetC
Range("A1").Select
Selection.Offset(counter, 0).Value = StrValue
counter = counter - 1
Else
MsgBox ("Done")
End If
Next iRow
End Sub
You need to use the word 'AND' instead of the '&' symbol in your code. Using '&' just concatenates the values, which will cause your if statement to fail.
I see some obvious errors as Mat Richardson points out, using the & is not equivalent shorthand for the AND operator, it's a concatenator, which is not likely what you want when you say:
If varSheetB(iRow, "B") = varSheetA(iRow, "B") & varSheetB(iRow, "B") <> "GERENCIA" & varSheetB(iRow, "B").Value <> "" & varSheetB(iRow, "D") = "ALTA" Then
Which brings me to another error:
varSheetB (and A, and C for that matter) are Variant/Array variables. You cannot index these by iRow, "B" because you cannot use a non-numeric index. Perhaps you mean (iRow, 2).
On a related note: varSheetB.Range("iRow:B").Select this will also fail, because you cannot .Select a Variant. This is not a Range variable. Further, iRow:B is not correct for either of a Variant array or a Range variable. Also, at this point, varSheetB is no longer a Worksheet object variable.
Which brings me to probably the biggest error: You are using the variables varSheetA, varSheetB, and varSheetC to represent (at different times in this code) both a Worksheet Object and a Variant array of values. This is confusing, and probably causing you the errors described above. A variable cannot be both of these things at the same time, so you need to be treating your variants like variants when they are variants, and like worksheets when they are worksheets, or better yet: use worksheet variables for worksheets and variants for arrays, don't use the same variable for multiple purposes.
Sub ReportCompareAlta()
'
' ReportCompareAlta Macro
Dim varSheetA As Worksheet
Dim varSheetB As Worksheet
Dim varSheetC As Worksheet
Dim RangeToCheck As Range
Dim cl as Range
Dim iRow As Long
Dim iCol As Long
Dim WbkA As Workbook
Dim WbkB As Workbook
Dim WbkC As Workbook
Dim counter As Long
Set WbkA = Workbooks.Open(Filename:="G:\Reporting\AH_MISSE_FEB2013.xls")
Set WbkB = Workbooks.Open(Filename:="G:\Reporting\AH_MISSE_MAR2013.xls")
Set WbkC = Workbooks.Open(Filename:="G:\Reporting\ReportCompare.xls")
Set varSheetA = WbkA.Worksheets("LocalesMallContratos")
Set varSheetB = WbkB.Worksheets("LocalesMallContratos")
Set varSheetC = WbkC.Worksheets("Sheet1")
Set RangeToCheck = varSheetA.Range("A1:A65536") '## I change this because you only indicate you want to compare column A ##'
counter = 0
'## just loop over the cells in the range. ##'
'## This is not the most efficient, but it is the easiest ##'
For each cl in RangeToCheck
'## Do your comparison here, e.g: ##'
'## Ignore cells where .Offset(0,3).Value = "ALTA" Or cl.Value = "" ##'
If not cl.Offset(0,3).Value = "ALTA" Or Not cl.Value = vbNullString Then
If Not cl.Value = varSheetB.Range(cl.Address).Value Then
'## The values are not equal, so do something:
varSheetC.Range(cl.Address) = "not equal"
counter = counter+1
Else:
'## The values are equal, so do something else:
varSheetC.Range(cl.Address) = "equal"
End If
End If
Next
MsgBox "Done! There were " & counter & " mismatch values", vbInformation
End Sub