Find If cell matches in another sheet and count/sum instances - vba

I have been using simple excel array formulas to count certain values on a master sheet but now at the point where I have too many formulas in my document and excel is crashing.
Therefore, I would like to create a macro that can do the same task. I would like to have the code do the following:
IF the activecell in Sheet1 matches to any cell in a column(or range) in Sheet2,
AND IF the cell in the same row in an adjacent column in Sheet2 is not blank,
THEN count all the instances that specific string appears in Sheet2 column A
AND place the value 2 columns to the right of the original active cell in Sheet1.
Here is the original array formula I was using:
=SUM(IF(Sheet1!$A8=Sheet2!$A:$A,IF(SalesF_SignUp_data!$C:$C>1,1,0)))
The formula above is taking the cell A8 in Sheet1 and checking if it matches to any cell in Sheet2 column A,
AND making sure that column C in Sheet2 is not blank in the same row.
If this is TRUE then "add 1" for all the instances
AND place that value in Sheet1.
I believe the best way to do this is a For Next Loop but haven't been able to execute any successful code based on examples I've found.
Im happy to explain further if needed. Since I dont have a reputation of 10 I cant attach images but am willing to send if needed.

This is set up to run for all the cells you've selected in column A of sheet 1.
It looks in Sheet2 column A for the value on Sheet1 column A, then in Sheet1 column B, displays how many times the value appeared in Sheet2 column A along with a value in the same row of column C.
If the answer is helpful, please mark it as such. :-)
Option Explicit
Sub countinstances()
Dim result, counter, loopcount, tocomplete, completed As Integer
Dim findtext As Variant
Dim cell, foundcell, nextcell As Range
'Checks to make sure the sub isn't accidentally run on an invalid range
If ActiveSheet.Name <> "Sheet1" Or ActiveCell.Column <> 1 Or Selection.Columns.Count > 1 Then
MsgBox ("Please select a range in column A of Sheet 1.")
Exit Sub
End If
'In case of selecting the entire column A, curtail the number of blank cells it runs on.
tocomplete = Application.WorksheetFunction.CountA(Selection)
completed = 0
'For each cell in the selected range, searches Sheet2, Column A for the value in the selected cell
For Each cell In Selection
If completed = tocomplete Then Exit Sub
If cell.Value <> "" Then completed = completed + 1
findtext = cell.Value
result = 0
Set foundcell = Sheets("Sheet2").Range("A1")
'Uses the count function to determine how many instances of the target value to search for and check
loopcount = Application.WorksheetFunction.CountIf(Sheets("Sheet2").Range("A:A"), findtext)
'Skips the loop if the target value doesn't exist in column A
If loopcount = 0 Then GoTo NotFound
'For each time the target value was found, check the cell in column C. If it's not blank, increment "result"
For counter = 1 To loopcount
Set nextcell = Sheets("Sheet2").Range("A:A").Find(what:=findtext, lookat:=xlWhole, after:=foundcell)
If nextcell.Offset(0, 2).Value <> "" Then
result = result + 1
End If
Set foundcell = nextcell
Next
'Put the result in column B of Sheet1
NotFound:
cell.Offset(0, 1).Value = result
Blanks:
Next
End Sub

Related

Loop Through Column Using If Statement Checking =isnumber()

I'm just starting to use VBA and I would like some help with writing an IF statement that is searching using =ISnumber() as it loops through all of column A until it encounters an empty cell.
The data I am working with is a text file that is being dropped onto sheet1 and has data that only populates column A.
On sheet2 I would like to press a button that starts a loop. The loop needs to check each row of sheet 1 to see what the first three numbers of the line is for example: =ISNUMBER(SEARCH("101",A1)) If this qualification is met then complete something like: =MID(A1,24,6)
There are two different row starts: 101 and 621.
My pseudo code logic is as follows:
Sub Button1_Click()
IF 'first iteration
Row A1 starts with "101"
THEN Add =MID(A1,24,6) to cell A1 of sheet 2
ELSE IF
Row starts with "621"
THEN Add =MID(A1,55,24) to cell B1 of sheet 2
AND add =MID(A1,30,10) to cell C1 of sheet 2
ELSE
Skip this row
End If
IF 'second iteration
Row A2 starts with "101"
THEN Add =MID(A2,24,6) to cell A2 of sheet 2
ELSE IF
Row starts with "621"
THEN Add =MID(A2,55,24) to cell B2 of sheet 2
AND add =MID(A2,30,10) to cell C2 of sheet 2
ELSE
Skip this row
End If
'iterations continue until empty cell
End Sub
You can do it like this - you may have to change sheet names to suit. That said, you don't need VBA for this, you could do it with formulae.
Sub Button1_Click()
Dim r As Range
With Sheet1
For Each r In .Range("A1", .Range("A" & Rows.Count).End(xlUp))
If Left(r, 3) = "101" Then
Sheet2.Range(r.Address).Formula = "=MID(Sheet1!" & r.Address & ",24,6)"
ElseIf Left(r, 3) = "621" Then
Sheet2.Range(r.Offset(, 1).Address).Formula = "=MID(Sheet1!" & r.Address & ",55,24)"
Sheet2.Range(r.Offset(, 2).Address).Formula = "=MID(Sheet1!" & r.Address & ",30,10)"
End If
Next r
End With
End Sub

Excel VBA find row number based on criteria in two columns, no loop

A little background, my sheet "Data" consists of a table, which my macro is supposed to populate. The table has dates running down the first column (Column P), and a few names as headers. My current macro, as seen below, loops through all my sheets, except the ones specified not to loop through, then in each sheet it loops through each cell in the range W7:W200. It then looks to match the right 10 values in the cell with a date in the column P on sheet "Data" (and sets that row as HdrRow). At the same time, it looks for the value in A9 in whatever sheet it is looping through, in order to match that value to a column header in sheet "Data" (and sets that column as HdrCol). After finding the row and column (intersecting cell), the macro then pastes the values of the cell it is looping through into that intersecting cell.
I am having trouble with this next part, I am looking to add another criteria for finding a row. I would like the macro to not only find a matching date in column P, but also a value in column Q that matches with the value in A1 of whichever sheet it is looping through; and then set that row as HdrRow. If possible, id like to not use a loop for this.
Sub Values()
Dim HdrCol As Range
Dim Site As String
Dim SearchRange As Range
Dim HdrRow As Range
Dim FinDate As Date
Dim ws As Worksheet
Dim rng As Range
' Fill in Actual Value
Sheets("Data").Range("W2:W100000").ClearContents
For Each ws In ActiveWorkbook.Worksheets
'Dont Copy Data from these worksheets
If ws.Name <> "Portfolio" And ws.Name <> "Master" And ws.Name <> "Template" _
And ws.Name <> "Coal" And ws.Name <> "E&P" And ws.Name <> "Gen" _
And ws.Name <> "Hydro" And ws.Name <> "LNG" And ws.Name <> "Midstream" _
And ws.Name <> "Solar" And ws.Name <> "Transmission" _
And ws.Name <> "Wind" And ws.Name <> "Data" Then
For Each cell In ws.Range("W7:W200")
If cell <> " " Then
Site = ws.Range("A9").Value
FinDate = Right(cell, 10)
'Find column ref
Set HdrCol = Sheets("Data").Range("P1:W1").find(Site, lookat:=xlPart)
If Not HdrCol Is Nothing Then
End If
'Find row ref
Set SearchRange = Sheets("Data").Range("P1", Range("P100000").End(xlUp))
Set HdrRow = SearchRange.find(FinDate, LookIn:=xlValues, lookat:=xlWhole)
Application.Goto Reference:=Cells(HdrRow.Row, HdrCol.Column)
If IsEmpty(Sheets("Data").Cells(HdrRow.Row, HdrCol.Column)) Then
cell.Copy Sheets("Data").Cells(HdrRow.Row, HdrCol.Column)
Else
cell.Copy Sheets("Data").Cells(HdrRow.Row, HdrCol.Column).End(xlDown).Offset(1, 0)
End If
End If
Next
End If
Next
End Sub
My first thought for a non-loop version to do this (loop is much simpler), would be to use match(), though if you have multiple values where A=Q or the same date is used, you might run into an issue.
Dim i,j as Integer
i=Application.Match(RefCell1,LookUp1,0).Row
j=Application.Match(RefCell2,LookUp2,0).Row
If i=j Then
HdrRow=i
Else
End If
I am specifically not making that match scenario the If statement condition so it's easier to read and edit.
You would run into issues where you have multiple of the same values, using this approach.
Another approach is to use a nested if statement:
Dim i as integer
i=Application.Match(RefCell1,LookUp1,0).Row
If Application.IfError(i,0)>0 Then
If Cells(i,"Q").Value=Cells(RefCell1Row,"A").Value
HdrRow=i
Else
End If
Else
End If
In the end, I would still recommend a loop so you can assess line per line, which would build on the second approach.
Edit: Per request, to include a loop.
Dim i, j as Integer
For i = 7 to 200 'Used the range you mentioned in your post, which I think is wrong for this example... these are row numbers for Data sheet
For j = 7 to 200 'Row numbers for reference sheets
If Sheet(ARRAY).Cells(j,"Q").Value=Sheets("Data").Cells(i,"A").Value Then
If Cells(j,"P").Value=Cells(i,"B").Value 'Not sure what column the date is in Data sheet
HdrRow=j
Else
End If
Else
End If
Next j
Next i
Ends up being two loops, to account for the cells on both your data sheet, and each sheet you're referencing in the array. Make sure to turn off screen updating, because epilepsy is real!

VBA check for empty cells in column and print value

In column J there are empty rows and rows with a value such as checked.
I have tried to write VBA code that prints "unchecked" where there is an empty cell AND this works, but when it hits a cell with a value (checked) it stops. And it won't go down to the next cell probably because I have formulas in the cell that prints nothing if not fullfilled, but it still contains that formula. In my case I have empty cells until J7 and then it starts again at J15. But this can change from time to time regarding source data.
The reason I want to do it like this is because I have a formula in column J that already have printed some values and then some VBA code that checks for other values in a different column and prints to column J. Column J is the filter master column sort of. So this is the way I have to do it I guess.
My code right now is,
Sub DoIfNotEmpty()
Dim ra As Range, re As Range
With ThisWorkbook.Worksheets("Sheet1")
Set ra = .Range("J:j25")
For Each re In ra
If IsEmpty(re.Value) Then
re.Value = "unchecked"
End If
Next re
End With
End Sub
Can I print to empty cells if the cell contains a formula which in this case has an if statement that is not filled?
Except from #Maxime Porté's points out that it should be .Range("J1:j25"). I guess the cells only look empty, but they are not.
A cell that contains an empty string, "", is not empty anymore, but it looks like it. You can test it like this:
In a new worksheet write in A1: ="" (there is no space in between!)
Copy A1 and special paste values in A1. A1 now looks to be empty.
Run Debug.Print IsEmpty(Range("A1").Value) in VBA and you get a FALSE.
The cell A1 is not empty any more, because it contains an empty string.
What can you do?
Sub DoIfNotEmpty()
Dim ra As Range, re As Range
With ThisWorkbook.Worksheets("Sheet1")
Set ra = .Range("J1:J25")
For Each re In ra
If IsEmpty(re.Value) or re.Value = vbNullString Then
re.Value = "unchecked"
End If
Next re
End With
End Sub
This will mark pseudo empty cells as "unchecked" too. But be aware that it also kills formulas that result in an empty string, "".
You could exploit the Specialcells() method of Range object:
Sub DoIfNotEmpty()
ThisWorkbook.Worksheets("Sheet1").Range("J1:J25").SpecialCells(xlCellTypeBlanks).Value = "unchecked"
End Sub
Or, if you have formulas returning blanks, then AutoFilter() "blank" cells and write in them
Sub DoIfNotEmpty()
With ThisWorkbook.Worksheets("Sheeet1").Range("J1:J25") '<--| reference your range (first row must be a "header")
.AutoFilter Field:=1, Criteria1:="" '<--| filter its empty cells
If Application.WorksheetFunction.Subtotal(103, .cells) > 1 Then .Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible).Value = "unchecked" '<--| if any cell filtered other than headers then write "unchecked" in them
.Parent.AutoFilterMode = False
End With
End Sub

Copy cell value to all cells below it

I don't know how to write a macro that designates a cell within a column as a "master cell" (editable) copy that cells value to all the cells below it in that column, until it reaches a blank/clear formatted cell in column A. So I want it to look at column A to know when to stop copying the cell values in whichever column.
That is, Cell "C5" will be a master cell, the macro will copy it's value from "C6:C" but looking at column A's cell values to see if it has nothing in it and there's no formatting such as color fill, etc. and instead of the macro continuing on in column C to infinity (maximum increment for Excel) it will stop at A column's first blank cell row.
Sub Example()
Dim MasterValue As String
Dim StopRow As Long
Dim i As Long
'Get the master value
MasterValue = Range("C5").Value
'Get the first blank cell in column A
StopRow = Range("A1").End(xlDown).Row
'Start at row 6 and continue to the "Stop Row"
For i = 6 To StopRow
'Set every cell from row 6 in column 3 to the "Master Value"
Cells(i, 3).Value = MasterValue
Next
End Sub

vba searching through rows and their associated columns and highlight if conditions meet

The code below would search through a row and its associated columns.
For Row 7, if it is a "N" or "TR" and if all entries are blank below line 12,the code would hide the entire column.
However, I still need help with some further help!
If there is a "N" or "TR" in row 7. If there is something writen in any cell, (rather than leaving it alone), can I highlight its associated cell in row 7 in yellow?
If ther eis a "Y" in row 7, If there is any empty cells, can I highlight its associated cell in row 7 in yellow?
Thank you so much! special thanks to KazJaw for my previous post about simular issue
Sub checkandhide()
Dim r As Range
Dim Cell As Range
Set r = Range("A7", Cells(7, Columns.Count).End(xlToLeft))
For Each Cell In r
If Cell.Value = "N" Or Cell.Value = "TR" Then
If Cells(Rows.Count, Cell.Column).End(xlUp).Row < 13 Then
Cell.EntireColumn.Hidden = True
End If
End If
Next
End Sub
attached example of spreadsheet
Here you have an improved version of your code (although I might need further clarifications... read below).
Sub checkandhide()
Dim r as Range, Cell As Range, curRange As Range
Set r = Range("A7", Cells(7, Columns.Count).End(xlToLeft))
For Each Cell In r
Set curRange = Range(Cells(13, Cell.Column), Cells(Rows.Count, Cell.Column)) 'Range from row 13 until last row in the given column
If Cell.Value = "N" Or Cell.Value = "TR" Then
If Application.CountBlank(curRange) = curRange.Cells.Count Then
Cell.EntireColumn.Hidden = True
Else
Cell.Interior.ColorIndex = 6 'http://dmcritchie.mvps.org/excel/colors.htm
End If
ElseIf Cell.Value = "Y" Then
If Application.CountBlank(curRange) > 0 Then
Cell.Interior.ColorIndex = 6 'http://dmcritchie.mvps.org/excel/colors.htm
End If
End If
Next
End Sub
I am not sure if I have understood your instructions properly and thus I will describe here what this code does exactly; please, comment any issue which is not exactly as you want and such that I can update the code accordingly:
It looks for all the cells in range r.
If the given cell (which might be in row 7 or in any other row below it) meets one of the conditions, the corresponding actions would be performed.
Part of the conditions depends on curRange, which is defined as all the rows between row number 13 until the end of the spreadsheet.
Specific conditions:
a) If the value of the current cell is N or TR. If all the cells in curRange are blank, the current column is hidden. If there is, at least, a non-blank cell, the background color of the given cell would be set to yellow.
b) If the value of the current cell is Y and there is, at least, one cell in curRange which is not blank, the background color of the background cell would be set to yellow.