How to compare cells one by one between two Excel sheets? - excel

I'm trying to write a VBA code and I'm having some issues.
Here's the context, I have an Excel spreadsheet with two sheets, "Sheet1" and "Sheet2"
I want my VBA code to compare two rows of cells.
Here's what my Sheet1 looks like:
And here's what my Sheet2 looks like:
As you can see, I have the same number of cells to compare however, one of them is not the same.
What I want my VBA code to do, is to compare one by one the cells between Sheet1 and Sheet2. And once the code spots two cells who are not identical, a MsgBox appears saying "Cells are not the same". In that case, it is for cells "D1"
It sounds pretty basic and simple to do, but I'm really struggling.
Here are the first lines of code I have but it doesn't work:
Dim RangeSheet1 As Range, RangeSheet2 As Range
Set RangeSheet1 = Worksheets("Sheet1").Range("A1")
Set RangeSheet2 = Worksheets("Sheet2").Range("A1")
Do While RangeSheet1.Value = RangeSheet2.Value
RangeSheet1.Offset(0,1)
RangeSheet2.Offset(0,1)
Loop
MsgBox "Cells are not the same"
Do you guys have any idea how I can do it the right way?
Thank you very much for your help.

I wrote a solution that compares all the cells in the sheets using a for loop. It exits the for loop when two cells are not equal, but if you need to compare more cells you can just remove that row. There are more efficient macros but this is a solution that I think should work for your needs.
Sub compareSheets()
Dim sht1 As Worksheet, sht2 As Worksheet, cell As Object
Set sht1 = Worksheets("Sheet1")
Set sht2 = Worksheets("Sheet2")
For Each cell In sht1.Cells
Dim currentCellAddress As String
currentCellAddress = Replace(cell.Address, "$", "")
If Not cell.Value = sht2.Range(currentCellAddress).value Then
MsgBox "The cell " & currentCellAddress & " is not the same in both sheets."
Exit For
End If
Next cell
End Sub
EDIT:
I saw you to collect all the non-equal cells in a message box at the end. Then in that case, something like this should do the trick:
Sub compareSheets()
Dim sht1 As Worksheet, sht2 As Worksheet, cell As Object, refArray() As String, refCount As Integer
refCount = 0
Set sht1 = Worksheets("Sheet1")
Set sht2 = Worksheets("Sheet2")
For Each cell In sht1.Cells
Dim currentCellAddress As String
currentCellAddress = Replace(cell.Address, "$", "")
If Not cell.Value = sht2.Range(currentCellAddress).Value Then
ReDim Preserve refArray(0 To refCount)
refArray(refCount) = currentCellAddress
refCount = refCount + 1
End If
Next cell
Dim resultText As String, ref As Variant
For Each ref In refArray
resultText = resultText & " " & ref
Next ref
MsgBox "The following cells are not equal " & vbCrLf & resultText
End Sub

Related

Auto fill a formula down a column but skipping already populated cells

After numerous failed attempts I am really hoping someone can with my problem. It theory what I am trying to do sounds easy enough but I have spent hours on it today with no success.
I have tried all the possible solutions from this thread but to no avail: Excel vba Autofill only empty cells
Also looked here : https://www.mrexcel.com/board/threads/macro-to-copy-cell-value-down-until-next-non-blank-cell.660608/
I am looking to autofill a formula down a column(a vlookup from another sheet) but if there is already populated cells then to skip and continue the formula in the next available blank cell. For example, in rows A2:A10, row A5 has a value in it, so the formula gets into in A2, then fills to A4, then skips A5, then continues in A6 to A10.
This below code works the first time you use it but then on the second run it debugs with a "Run-time error '1004' - No cells were found". I noticed it it putting the formula into the first cell (B2) and then debugging out.
Sub FillDownFormulaOnlyBlankCells()
Dim wb As Workbook
Dim ws1, ws2 As Worksheet
Dim rDest As Range
Set wb = ThisWorkbook
Set ws1 = Sheets("Copy From")
Set ws2 = Sheets("Copy To")
ws2.Range("A1").Formula = "=IFERROR(IF(VLOOKUP(A2,'Copy From'!A:B,2,FALSE)=0,"""",VLOOKUP(A2,'Copy From'!A:B,2,FALSE)),"""")"
Set rDest = Intersect(ActiveSheet.UsedRange, Range("B2:B300").Cells.SpecialCells(xlCellTypeBlanks))
ws2.Range("B2").Copy rDest
End Sub
Please, try the next code:
Sub FillDownFormulaOnlyBlankCells()
Dim wb As Workbook, ws1 As Worksheet, rngBlanc As Range
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("Copy From")
On Error Resume Next
Set rngBlanc = ws1.Range("B2:B" & ws1.rows.count.End(xlUp).row).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rngBlanc Is Nothing Then
rngBlanc.Formula = "=IFERROR(IF(VLOOKUP(A2,'Copy From'!A:B,2,FALSE)=0,"""",VLOOKUP(A2,'Copy From'!A:B,2,FALSE)),"""")"
Else
MsgBox "No blanc rows exist in B:B column..."
End If
End Sub
After running it once and do not create any empty cell, of course there will not be any blanc cells, anymore, at a second run...
Thanks to FaneDuru for his suggestion but I actually came up with an alternative solution to my problem which I though I would post as it might help others with a similar issue.
On a separate sheet, I created 3 columns, first column is names I already have, 2nd column are the new names and the 3rd column is there to combine the first 2 columns together, then use this code to combine first 2 columns :
Sub MergeColumns()
Dim wb As Workbook
Dim ws1 As Worksheet
Dim LastRow As Long, i As Long
Set ws1 = Sheets("Your Sheet Name")
LastRow = ws1.Range("F" & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
If ws1.Range("G" & i) <> "" Then
ws1.Range("I" & i) = ws1.Range("H" & i).Text & "" & ws1.Range("G" & i).Text
Else: ws1.Range("I" & i) = ws1.Range("H" & i)
End If
Next i
End Sub
Obviously changing the sheet name and columns letter to suit your requirements.

How to use VBA to combine 3 cells from one sheet into 1 cell in another sheet?

So I've been doing this process manually but I need to automate it with a macro but using this formula:
='Sheet1'!C2&"|"&'Sheet1'!D2&"|CM"&'Sheet1'!H2
I need to pull 3 cells of data into one cell in Sheet2 separated by a break. As well as doing that for the next 96 lines. So far I've tried to do it this way:
Dim SheetName As Worksheet1
Set SheetName = Worksheets("Sheet1")
Worksheets("Sheet2").Range("B2:B97").Formula = Worksheets(2).Range("C2:C97") & "|" & Worksheets(2).Range("D2:D97") & "|CM" & Worksheets(2).Range("H2:H70")
Worksheets(2) = "Sheet1"
Keep getting a object defined error.
but I keep getting a
Like this, making sure to double up quotes in the formula:
Worksheets("Sheet2").Range("B2:B97").Formula = "='Sheet1'!C2&""|""&'Sheet1'!D2&""|CM""&'Sheet1'!H2"
Remove the lines
Dim SheetName As Worksheet1
Set SheetName = Worksheets("Sheet1")
...
Worksheets(2) = "Sheet1"
as they don't make any sense.
Here is an example of how you would do this where all the ranges are on the same sheet. You pretty much just need to nest your existing formula here and double quote your bar separator
Sub try()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Range("D1:D3").Formula = "=A1 & ""|"" & B1 & ""|"" & C1"
End Sub

Search table for all instances of a word "Yes" in all cells, create row with each "Yes" found in new sheet

I want to look through a table in a sheet. Find each cell with "Yes" in it, when one is found. Paste a Yes to A1, when another is found A2, etc...
I was trying to modify this code to search all cells instead of just Row A
Following code should give you the headstart
Sub Text_search()
Dim Myrange As Range
Set Myrange = ActiveSheet.UsedRange
For Each cell In Myrange
If InStr(1, cell.Value, "YES") > 0 Then
'do something
Else
'do something else
End If
Next
End Sub
Further to #isomericharsh's answer, if it's a table you're looking through, that simplifies defining the range; just use DataBodyRange.
If the table 'Table1' is on 'Sheet1' and the results are to be posted on 'Sheet2' then I'd do as follows:
Sub Search_for_Yes()
Dim YesAmt As Long ' - Amount of yes's found
YesAmt = 0 'to start with
Dim ws1 As Worksheet
Set ws1 = Sheets("Sheet1")
Dim ws2 As Worksheet
Set ws2 = Sheets("Sheet2")
'It's always safer to use specific references rather than ActiveSheet
For Each cell In ws1.ListObjects("Table1").DataBodyRange 'The data in the table excluding headings and totals
If cell.Value = "YES" Then 'might need to add wildcards to this if you want to include cells that contain yes as part of larger text string. Also note that it's case-specific.
ws2.Cells(1 + YesAmt, 1).Value = "Yes" 'so that each time a yes is found it will log it further down
YesAmt = YesAmt + 1
End If
Next
x = MsgBox(YesAmt & " values found and listed", vbOKOnly + vbInformation)
End Sub
Does that help?

How to use cell contents as inputs for range formulas in Excel VBA?

Excel VBA range formula is something like Sheet2.Range("A1").value.
You can, for example, refer to this address and change the value in that cell.
Now what I am looking for is to build this formula by using the contents of two cells; one cell says "Sheet2" and the other says "A1". How can I refer to these two cells in a formula so that it works the same way?
I have tried various dims and now end up without an error but not with the desired result. The current formula simply returns "Sheet2.Range("A1").value instead of its contents.
Sub AddressInCells()
'This is just for one reference. In reailty there is a table of references to loop through.
'For this example cell A1 in Sheet2 = "Text to take to sheet1"
Dim SheetSel As String
Dim CellSel As String
Dim ReferSel As String
With Sheet1
SheetSel = Cells(1, 1).Value
CellSel = Cells(1, 2).Value
ReferSel = SheetSel & ".range(" & Chr(34) & CellSel & Chr(34) & ").value"
MsgBox ReferSel
Sheet1.Range("D1").Value = ReferSel 'Results in "Sheet2.range("A1").value
Sheet1.Range("D2").Value = Sheet2.Range("A1").Value 'Results in Text to take to sheet1'
End With
End Sub
The expected result is that the formula works the "usual" way. It now simply returns a string.
I believe, instead you want to do:
ReferSel = Sheets(SheetSel).range(CellSel).value
You could try:
Option Explicit
Sub test()
Dim ws As Worksheet
Dim rng As Range
'With statement where the data are store. Change name if needed
With ThisWorkbook.Worksheets("Sheet1")
Set ws = ThisWorkbook.Worksheets(.Range("A1").Value)
Set rng = ws.Range(.Range("A2").Value)
End With
Debug.Print rng.Address
Debug.Print rng.Worksheet.Name
End Sub
You're trying to build a formula string, which follows this convention:
'<sheet name>!'<address>
The single-quotes are only strictly required if the sheet name contains a space, so this would be a valid formula:
=Sheet1!$A$1
But it's just good habit to always include them, so, you need to build your string from the values in those cells:
' offset the sheet name in single quotes, separate the sheet & address with !
ReferSel = "='" & SheetSel "'!" & CellSel
Sheet1.Range("D1").Formula = ReferSel

Count number of rows in worksheet

I want to count number of rows in Sheet1, from the Sheet2 code module.
In the sheet1 code module, the following code works fine
ctr = Range("B2", Range("B2").End(xlDown)).Count
I tried the same code in the Sheet2 code module
recct = ThisWorkbook.Sheets("Sheet1").Range("B2", Range("B2").End(xlDown)).Count
I am getting run time error 1004 Application -Defined or Defined error
Thanks
The error occurs in the 2nd range reference in recct. Because you are referencing a different sheet, you need to tell VBA the sheet name in both range references.
Try this instead:
With ThisWorkbook.Sheets("Sheet1")
recct = .Range("B2", .Range("B2").End(xlDown)).Rows.Count
End With
Alternatively, this will work as well (though a bit sloppier).
recct = ThisWorkbook.Sheets("Sheet1").Range("B2", ThisWorkbook.Sheets("Sheet1").Range("B2").End(xlDown)).Rows.Count
Update
Since there is a lot of discussion around what you actually mean by number of rows on the sheet, use the above code to literally start at B2 and count the number of contiguous cells directly underneath
However, if you want to find the last "real" used cell in column B (by real, I mean with data in it) do this:
With ThisWorkbook.Sheets("Sheet1")
recct = .Range("B2", .Range("B" & .Rows.Count).End(xlUp)).Rows.Count
End With
You can use this for example:
rowsInThere = Sheets("Sheet1").UsedRange.Rows.Count
This works without ranges. Also you might use ActiveSheet as a sheet to check, in case you would need to change current sheet and check its rows count.
Two things
When working off sheet you need to fully qualify your range
Always measure the last cell bottom up rather than top down - you may have gaps
code
Sub GetB()
Dim ws As Worksheet
Set ws = Sheets(1)
Dim lngCnt As Long
lngCnt = ws.Range(ws.[b2], ws.Cells(Rows.Count, "b").End(xlUp)).Count
End Sub
more robust
To handle all situations cleanly then Find is easier
Sub GetB()
Dim ws As Worksheet
Dim rng1 As Range
Set ws = Sheets(1)
Set rng1 = ws.Range("B:B").Find("*", ws.[b1], xlValues, , , xlPrevious)
If Not rng1 Is Nothing Then
Select Case rng1.Row
Case 1
MsgBox "Only B1 has data", vbCritical
Case 2
MsgBox "No used cells past B2"
Case Else
MsgBox rng1.Row - 1 & " cells between B2 and B" & rng1.Row
End Select
Else
MsgBox ws.Name & " column B Is blank", vbCritical
End If
End Sub
Don't know if this will help but I use this in my modules all the time:
Dim TR as long, TC as long
TR = [Sheet1!A1].CurrentRegion.Rows.count
TC = [Sheet1!A1].CurrentRegion.Columns.count
If I know that if the dataset I'm dealing with doesn't have an empty row or column, like an extract from another program or something, then it's quick and works great!
From this I can specify a range select or perform a vlookup.
TR = [Sheet1!A1].CurrentRegion.Rows.count
[I2] = "=vlookup($C2,'sheet1'!A$2:B$" & TR & ",2,FALSE)"

Resources