VBA Look down column to find specific criteria then SUM cell after criteria met cell - excel

Currently, I'm trying to figure a way to look down a single column to find a specific criterion and in this case, I want to find dates that are less than 4/16/20. Once that criteria is met, I want to SUM the cell below for all met criteria in that column. This is an image of my dataset
.
After doing some googling the closest I found was the code below which leads me to the idea that change information after offset to compute what I want.
Using "If cell contains" in VBA excel
Sub AddDashes()
Dim SrchRng As Range, cel As Range
Set SrchRng = Range("RANGE TO SEARCH")
For Each cel In SrchRng
If InStr(1, cel.Value, "TOTAL") > 0 Then
cel.Offset(1, 0).Value = "-"
End If
Next cel
End Sub
Not sure if I'm on the right track. It would also be nice If I would be able to amend code to check a range vs 1 column, thanks.

In this example you need to select the range of dates (1 row at a time only) to run the code. This also allows you to input the date (I'm assuming it changes over time so this should be helpful)
Sub SumByDate()
Dim DateRange As Range
Dim c As Range
Dim d As Range
Dim SearchDateInput As String
Dim SearchDate As Date
Set DateRange = Application.InputBox("Select a range", "Get Range", Type:=8) 'Select Date Range
SearchDateInput = Application.InputBox("Enter A Date") 'enter as mm/dd/yyyy
SearchDate = DateValue(SearchDateInput) 'this converts date entered as string to date format
For Each c In SrchRng 'for each date in list of dates
Set d = c.Offset(1, 0) 'pionts out cells to sum- in this case the cell beneath the date
If c < SearchDate Then 'if date is less than input date
Sum = Sum + d 'sum the date if true
End If
Next c 'goes to next date in row
DateRange.Cells(1, 1).Offset(2, -1) = Sum 'inputs all summed values into cell that is two down, one to the left of first date cell
End Sub

Sub SumByDate()
Dim SrchRng As Range
Dim c As Range
Dim d As Range
Dim lCol As Long
Dim ColLtr As String
Dim SearchDate As Date
lCol = Cells(2, Columns.Count).End(xlToLeft).Column
ColLtr = Split(Cells(1, lCol).Address, "$")(1)
Set SrchRng = Range("B2:" & ColLtr & "2")
SearchDate = DateValue("04/16/2020")
For Each c In SrchRng
Set d = c.Offset(1, 0)
If c < SearchDate Then
Sum = Sum + d
End If
Next c
Range("A4") = Sum
End Sub

Related

Format cells between two dates with a color of Range B4

I have wrote a code and I want to use conditional formatting to highlight each cell within a row of dates between two dates of Cell C8 , D8 and Percentage B8.
I have added a below pictures where i have been using Conditional Formatting but i want to perform this task through VBA.
Below picture is highlighting the cells based on dates of C8 , D8 and its progress B8.
I want to add one more thing that Code will popup the color in between dates which is available in cell B4
I have wrote this piece of code but unable to complete this if someone could help to complete it. I will really appreciate the help.
Sub updcolor()
Dim rngDates As Range
Dim startd As Range
Dim endd As Range
Dim prog As Range
Dim color As Range
Set startdt = Sheet1.Range("C8")
Set enddt = Sheet1.Range("D8")
Set prog = Sheet1.Range("B8")
Set color = Sheet1.Range("B4")
Set rngDates = Sheet1.Range("I4:BJ4")
Dim rngDateCell As Range
For Each rngDateCell In rngDates.Cells
If Sheet1.Cells(rngDateCell.Row, 4).Value <= rngDateCell.Value And _
Sheet1.Cells(rngDateCell.Row, 4).Value >= rngDateCell.Value Then
rngDateCell.Interior.ColorIndex = Sheet1.range("B4")
End If
Next rngDateCell
End Sub
I assume row 4 has dates although you only show the day number.
Option Explicit
Sub updcolor()
Const DATE_RNG As String = "G4:BJ4"
Dim ws As Worksheet, r As Long, pcent As Single
Dim rng As Range, color As Integer
Set ws = Sheet1
color = Sheet1.Range("B4").Interior.ColorIndex
Dim dtStart As Date, dtEnd As Date, dtEndBar As Date
Dim dur As Integer
' scan down sheet
For r = 8 To 11
pcent = ws.Cells(r, "B")
dtStart = ws.Cells(r, "C")
dtEnd = ws.Cells(r, "D")
dur = DateDiff("d", dtStart, dtEnd) + 1
dtEndBar = DateAdd("d", Int(dur * pcent) - 1, dtStart)
'ws.Cells(r, "A") = dtEndBar
' scan across dates
For Each rng In ws.Range(DATE_RNG)
If rng >= dtStart And rng <= dtEndBar Then
ws.Cells(r, rng.Column).Interior.ColorIndex = color
Else
ws.Cells(r, rng.Column).Interior.ColorIndex = xlNone
End If
Next
Next
End Sub

How do i find the last row index of each duplicates within the same column?

I am trying to create a programme such that it can find the last row index of each duplicates that lie within the same column and store their values. For example in the picture, last row index of names with John,trump,alice and sarah should give me 13,17,23,26 respectively. Currently, my code can only identify the duplicates only so what can i do to find the last row index of each duplicate not only for the picture that i showed but also for all cases?
Sub Testing()
Dim mycell As Range, RANG As Range
With Sheets(1)
' Build a range (RANG) between cell F2 and the last cell in column F
Set RANG = Range(.Cells(2, "A"), .Cells(.Rows.Count, "A").End(xlUp))
End With
' For each cell (mycell) in this range (RANG)
For Each mycell In RANG
' If the count of mycell in RANG is greater than 1, then set the value of the cell 1 across to the right of mycell (i.e. column G) as "Duplicate Found"
If Application.WorksheetFunction.CountIf(RANG, mycell.Value) > 1 Then
'how do i find the last row index of each duplicate here?
Next mycell
End Sub
Could be done a number of way. Used dictionary object in the code (tested) below. Please add Tool -> Reference -> Microsoft Scripting Runtime.
Sub Testing()
Dim mycell As Range, RANG As Range, Dict As Dictionary, Mname As String, Rng As Range
Set Dict = New Dictionary
With Sheets(1)
' Build a range (RANG) between cell F2 and the last cell in column F
Set RANG = Range(.Cells(2, "A"), .Cells(.Rows.Count, "A").End(xlUp))
End With
' For each cell (mycell) in this range (RANG)
For Each mycell In RANG
Mname = mycell.Value
' If the count of mycell in RANG is greater than 1, then set the value of the cell 1 across to the right of mycell (i.e. column G) as "Duplicate Found"
If Application.WorksheetFunction.CountIf(RANG, mycell.Value) > 1 Then
If Dict.Count > 0 And Dict.Exists(Mname) Then
Dict(Mname) = mycell.Row()
Else
Dict.Add Mname, mycell.Row()
End If
End If
Next mycell
'Display result in debug window (Modify to your requirement)
Startrow = 2
For Each Key In Dict.Keys
Set Rng = Sheets(1).Range("A" & Startrow & ":A" & Dict(Key))
Startrow = Dict(Key) + 1
' Now may copy etc the range Rng
Debug.Print Key, Dict(Key), Rng.Address
Next
End Sub
Code modified to give a range object (as understood from comment)
Create a DROPDOWN list with all names in b1 (by data validation)
In c1 paste the below function (to show the row number of where the last value appears)
{=MAX(($A$1:$A$26=$B$1)*ROW($A$A:$A$226))}

Error 1004 Looping through range to get max date

I am currently learning VBA and cant figure this one out. I'm trying to look at the max date in a range (W:AC) of each row and place the result in cell "BU" of the same row. I'm getting a 1004 error on the line defining which cell to place the result. Am I getting the error because I have defined the range as W:AC?
Sub Max_Date()
Dim MaxDate As Date
Dim CellRange As Range
Dim Source As Worksheet: Set Source = ActiveWorkbook.Sheets("Sheet1")
Dim row As Variant
row = Source.Rows.Count
Set CellRange = Source.Range("W:AC")
For Each row In CellRange
MaxDate = Application.WorksheetFunction.Max(CellRange)
Range("BU").Value = MaxDate
Next row
End Sub
As SJR mentioned you cannot paste a value in a row.
But also, you are looking at a max in the entire range, not only the row.
Use an integer (here i) to go through each row.
This should to the trick
Sub Max_Date()
Dim MaxDate As Date
Dim i As Double
Dim Source As Worksheet: Set Source = ActiveWorkbook.Sheets("Sheet1")
Dim row As Variant
row = Source.Rows.Count
For i = 1 To row
MaxDate = Application.WorksheetFunction.Max(Source.Range("W" & i & ":AC" & i))
Range("BU" & i).Value = MaxDate
Next
End Sub

Copy Cells Greater than Zero, and Paste Values in same Cell

I have a table that is filled with formulas tied to another sheet. These formulas grab data from the other table based on whether the date at the top of the column matches the date in a single cell (Week Ending Date). I want to be able to automatically copy only the cells with a value greater than 0, and then paste them back into the same cell as a value. I used the following formula to try and accomplish this, but it didn't quite do what I wanted it to. Be gentle, I'm a novice at best.
Sub CopyC()
Dim SrchRng As Range, cel As Range
Set SrchRng = Range("Table4")
For Each cel In SrchRng
If cel.Value > 0 Then
cel.Copy
cel.PasteSpecial xlPasteValues
End If
Next cel
End Sub
Expected Output: Copy only Cells in my table that are greater than 0 and paste as value.
Goal: Preserve Formulas in cells that are blank
Results from above: Very slowly progressed cell by cell and copied and pasted in all cells, including blanks and 0 values, until it was stopped
Give this a try:
Sub CopyC()
Dim SrchRng As Range, cel As Range
Set SrchRng = Range("Table4")
For Each cel In SrchRng
If IsNumeric(cel.Value) And cel.Value > 0 Then
cel.Value = cel.Value
End If
Next cel
End Sub
EDIT: add an alternative using an array to loop through the data, this should be a bit faster:
Sub CopyC()
Dim SrchRng As Range: Set SrchRng = Range("Table4")
Dim arrSearch As Variant: arrSearch = SrchRng
Dim fRow As Long: fRow = SrchRng.Cells(1, 1).Row - 1
Dim fCol As Long: fCol = SrchRng.Cells(1, 1).Column - 1
Dim R As Long, C As Long
For R = LBound(arrSearch) To UBound(arrSearch)
For C = LBound(arrSearch, 2) To UBound(arrSearch, 2)
If IsNumeric(arrSearch(R, C)) And arrSearch(R, C) > 0 Then Cells(R + fRow, C + fCol).Value = arrSearch(R, C)
Next C
Next R
End Sub

Trim characters in months to show just first three characters

I've written a loop that runs through a range containing month names and to trim any that are greater than three characters as I only need to see the first three ie: Jan instead of January.
The code below works in identifying the cells that contain the longer names but the LEFT function clears the cell rather than just removing the excess characters to show the first three only. Any idea what is amiss in the function? Help is much appreciated.
Many thanks.
Sub TrimMonth()
Application.ScreenUpdating = "False"
Dim rng As Range
Dim i, counter As Integer
Dim lastrow As Long
lastrow = ActiveSheet.Range("A1048576").End(xlUp).row
'Set the range to evaluate.
Set rng = Range("A2:A" & lastrow)
'initialize i to 1
i = 1
'Loop for a count of 1 to the number of rows in
'the range to evaluate.
For counter = 1 To rng.Rows.Count
'If cell i in the range contains more than 3
'characters then trim to 3 characters else increment i
If Len(rng.Cells(i)) > 3 Then
rng.Cells(i).Value = Left(Cells(i).Value, 3)
i = i + 1
Else
i = i + 1
End If
Next
Application.ScreenUpdating = "True"
End Sub
This code adds a formula to column B to return the three letter month text, then copies the values to column A before deleting the formula.
Sub TrimMonth()
Dim rDates As Range
With ThisWorkbook.Worksheets("Sheet1")
'Set reference to range containing month names.
Set rDates = .Range(.Cells(2, 1), .Cells(.Rows.Count, 1).End(xlUp))
'Add formula one column to right.
'This will convert the month name to a real date and then format it
'as three letter month text.
rDates.Offset(, 1).FormulaR1C1 = _
"=TEXT(DATEVALUE(""1-"" & RC[-1]),""mmm"")"
'Replace originals with values from formula.
rDates.Value = rDates.Offset(, 1).Value
'Clear formula.
rDates.Offset(, 1).ClearContents
End With
End Sub
Or to do it without adding the formula:
Sub TrimMonth()
Dim rDates As Range
Dim rCell As Range
With ThisWorkbook.Worksheets("Sheet1")
'Set reference to range containing month names.
Set rDates = .Range(.Cells(2, 1), .Cells(.Rows.Count, 1).End(xlUp))
'Convert each cell in range.
For Each rCell In rDates
rCell.Value = Format(CDate("1-" & rCell), "mmm")
Next rCell
End With
End Sub

Resources