I am trying to find the row number of the second last instance for a particular value.
See example screenshot below:
The image has 4 values in the column and I am trying to find the second to last instance of a value say GR 3 which is in row 5. I need to find the second last row.
i.e row 3 however I tried using the below code.
Range("E:E").Find(what:="GR 3", after:=Range("E1"), searchdirection:=xlPrevious)
The above code gives me either the last occurrence.
i.e row 5 and if I remove the search direction parameter it gives me only the first occurrence
i.e row 2.
if you filter that value ,you can use this :
ActiveSheet.Range("$A$1:$A$7").AutoFilter Field:=1, Criteria1:="GR 3"
ActiveSheet.AutoFilter.Range.Offset(2).SpecialCells(xlCellTypeVisible).Cells(1, 1).row
it will select the second row in a filtered column value.
The below code will loop through the range and will consider the range from the first cell up to the value of i. In the first "where" i am setting the value of the last occurrence of my desired value in "what". In the second "where" i am finding the previous occurrence of "what" based on the previous value of where which gives me the address of the my second last occurrence and finally the col variable saves the row number from the address stored in where.
Sub Find()
Dim where As Range
Dim col as Long
For i=2 to ThisWorkbook.Sheets("Sheet1").Range("B" & Rows.Count).End(xlUp).row
Set where = Range("E2:E" & i).Find(what:=ThisWorkbook.Sheets("Sheet1").Cells(i, 5).Value, after:=Range("E2"), searchdirection:=xlPrevious)
Set where = ThisWorkbook.Sheets("Sheet1").Range("E2:E" & i).FindPrevious(where)
col = Mid(where.Address(0, 0), 2)
Next i
End Sub
Related
I would like to find the last row in a range that I have selected so that my code is more dynamic and less likely to break if I exceed the range.
I am unsure of the syntax to use.
Instead of P4201, I would like to select the last row with a value within column P, whatever that may be.
Selection.AutoFill Destination:=Range("P2:P4201")
I am just unsure of the last syntax to select the last row with a value with P. Instead of doing P10000, I would like to make it cleaner.
The below macro counts up to the last filled cell in column P, and selects the full range from P2 until P-end.
Sub Select_Range()
Dim I As String
I = Sheet1.Range("P" & Rows.Count).End(xlUp).Row 'Determine last filled cell and count rows
Sheet1.Range("P2" & ":P" & I).Select 'select full filled range in column P.
End Sub
Let me know if this is what you're looking for.
I have an issue with using a formula that contains a fixed cell in VBA. The issue comes when the row number of the variable in the new data changes.
The issue is explained using a simple example as follow. I hope you find it understandable.
Let's say I have a column of numbers (Time) and I want to multiply them by a variable in a cell (The cell below Variable in the following table, $A$2).
First result from first raw data:
The results in the table are calculated using the following formula "=R2C1*RC[-1]" in vba
Now in the next calculation, the row number and variable change and the part of the formula which is using a fixed cell cause problem.
Second raw data to be processed
Because it does not update the row number and use the old row number. I want it to find its location like the second part of the formula (B2 changes to B7).
Thank you for your help!
Cheers,
Aryan
you should reference the found cell row in your formula
ActiveCell.FormulaR1C1 = "=R" & ActiveCell.Row + 1 & "C1*RC[-1]"
but you should also avoid the Activate/ActiveXXX/Select/Selection pattern since is prone to have you quickly lose control over the actually active thing
finally you an use a loop to find all "Time" occurrences (see Here for more info about the pattern)
Option Explicit
Sub main()
Dim f As Range, firstCell As Range
With Worksheets("myWorksheetName") ' reference your worksheet (change myWorksheetName to your actual sheet name)
With .Range("B1", .Cells(.Rows.Count, "B").End(xlUp)) 'reference its column B cells from row 1 down to last not empty one
Set f = .Find("Time", LookIn:=xlValues, lookat:=xlWhole) 'search referenced range for first occurrence of "time"
If Not f Is Nothing Then ' if found...
Set firstCell = f ' store first occurrence cell
Do
f.Offset(1, 1).Resize(4).FormulaR1C1 = "=R" & f.Row + 1 & "C1*RC[-1]" ' populate the range one column to the right of found cell and 4 rows wide with the formula containg the reference of found cell row +1
Set f = .FindNext(f) ' serach for the next "Time" occurrence
Loop While f.Row <> firstCell.Row ' loop till you wrap back to initial occurrence
End If
End With
End With
End Sub
The notation R2C1 is an absolute reference to row 2, column 1.
If you want a reference that is relative to the current cell, you need to use relative reference notation.
RC[-1] points to a cell in the current row and one column to the left
R[1]C points to a cell one row down from the current cell and in the same column as the current cell.
Google for "R1C1 reference". You will find many articles, for e.g. https://smurfonspreadsheets.wordpress.com/2007/11/12/r1c1-notation/
Hi I have a spreadsheet with the following columns :
Transaction_ID counter State File_Date Date_of_Service Claim_Status NDC_9 Drug_Name Manufacturer Quantity Original_Patient_Pay_Amount Patient_Out_of_Pocket eVoucher_Amount WAC_per_Unit__most_recent_ RelayHealth_Admin_Fee Total_Voucher_Charge Raw_File_Name
There are duplicate transaction ID's here. Is there VBA that would highlight where there are differences between two rows? So there may be data with the same Transaction ID but I want to highlight where they may have other fields that are different, therefore they aren't truly duplicates and would like to see what information is different.
thanks!
Excel's find duplicates conditional format should suffice for this. The problem is that it only works well off one column.
So there may be data with the same Transaction ID but I want to highlight where they may have other fields that are different, therefore they aren't truly duplicates
So instead of tracking duplicates in the Transaction ID column alone, you can try adding a new column and, in that new column, concatenate all the columns for which the combined values should be unique - and then run Excel's find duplicates conditional format on that column.
For example if the combination of [Transaction_ID], [File_Date] and [NDC_9] should be unique, make a new column that combines [Transaction_ID], [File_Date] and [NDC_9] column values - assuming your data is in an actual table you could have a table formula like so:
=[#Transaction_ID]&[#File_Date]&[#NDC_9]
and would like to see what information is different.
You can then filter the dupes in that column, and then, looking at the other columns you can see how they are different. It's not really possible to be any more specific than that with the way you've worded your question...
Assuming:
It's an unsorted dataset
column 1 contains the repeatable ID
the first row contains headers
...the following code (in the SHeet's module) will turn any cell yellow that has a value that is totally unique for the ID that appears in the leftmost column...
Option Explicit
Public Sub HighlightUniqueValues()
Dim r As Long, c As Long 'row and column counters
Dim LastCol As Long, LastRow As Long 'right-most and bottom-most column and row
Dim ColLetter As String
Dim RepeatValues As Long
'get right-most used column
LastCol = Me.Cells(1, Me.Columns.Count).End(xlToLeft).Column
'get bottom-most used row
LastRow = Me.Cells(Me.Rows.Count, "A").End(xlUp).Row
'assume first column has the main ID
For r = 2 To LastRow 'skip the top row, which presumably holds the column headers
For c = 2 To LastCol 'skip the left-most column, which should contain the ID
'Get column letter
ColLetter = Split(Cells(1, c).Address(True, False), "$")(0)
' Count the number of repeat values in the current
'column associated with the same value in the
'left-most column
RepeatValues = WorksheetFunction.CountIfs(Range("A:A"), Range("A" & r), Range(ColLetter & ":" & ColLetter), Range(ColLetter & r))
' If there is only one instance, then it's a lone
'value (unique for that ID) and should be highlighted
If RepeatValues = 1 Then
Range(ColLetter & r).Interior.ColorIndex = 6 'yellow background
Else
Range(ColLetter & r).Interior.ColorIndex = 0 'white background
End If
Next c
Next r
End Sub
e.g...
Been searching around and got a bit confused.
I have a sheet (herein called "ModelSpec") filled with data of TVs with a header that starts at A5:Z5 (Example Header Title is "Part Number", "Brand", "Size", "Resolutions"...etc). Some are with data, some are blank cells.
I'd created some USERFORM to allow user to select how they want to search for their Model Specification.
What I'm trying to do now is to pick up a data ("Part Number") located in the USERFORM textbox that the user selected and do a search in the "ModelSpec" sheet for the Part Number (located in Column A6:A?). The number of rows of data may change and I guess we need a FOR loop to stop at empty rows.
Once found, the entire row will be copied and paste value only on A1:Z1 of the same ModelSpec sheet.
So basically I'm currently working on Private Sub within the FORMS and not MODULES.
From there I have another code to extract the details to a form else where.
Please help this confused man.
This is a starting point for you, and has all the elements you'd need to do what you are asking.
What's Happening:
Click event on the userForm launches this code
Get the last row of the sheet containing data
Loop through all rows
Compare the value of txtPartNumber to the value in Column A of the current row in the loop.
If a match is found, display message confirming and copy the row being searched to row 1 of the same sheet.
If no match found, display message.
notes:
There is no handling of user input error. No upper case to lower case, or dropdown box limiting the user's choices. A good thing to do (in another question) would be to create a dynamic drop down or comboBox, that is populated by already existing part numbers, limiting the user input error.
If there is more than one match on the page, it will loop through all of the rows and copy the match to row 1. Then copy over row 1 with any match found after that, so the LAST one will be the only one you see. If you want it to only match the FIRST, then include an End statement right after copying the search row to row 1. I'm assuming your search column has unique IDs / part numbers.
Code:
Private Sub cmdSearch_Click()
Dim lastRow As Long, lCol As Long, lRow As Long
Dim sName As String
sName = "ModelSpec"
lastRow = Sheets(sName).Range("A" & Rows.count).End(xlUp).row
For lRow = 6 To lastRow
'Check to see if A(lRow) = TextBox. Exact match required
If Sheets(sName).Cells(lRow, "A").Text = txtPartNumber.Text Then
MsgBox("Match Found for Part #: " & txtPartNumber.Text)
For lCol = 1 To 26 'Loop through columns A-Z, Copy lRow to Row 1
Sheets(sName).Cells(1, lCol) = Sheets(sName).Cells(lRow, lCol)
Next lCol
Else
MsgBox("No match found for Part #: " & txtPartNumber.Text)
End If
Next lRow
End Sub
I need assistance finding the next instance of an exact string within a cell.
To be precise, I want to look through a series of headings and find the next instance of a declared variable to obtain the column number, and I want to look through that series of headings to find the next empty cell and save that number, and finally, I'd like to take that first column number, and search from second row until I find the first instance of an empty cell, and save that number into a variable. What I have been doing is this:
With Rows(1)
Set found = .Find(what:=Target, After:=.Cells(1, 1))
End With
But it seems that if I accidentally type "s" it will find the first instance of a cell that contains a string that contains the substring "s" (LastName), and not the first cell that contains only "s".
my fear is that if there are columns with " " in them then my program will not function correctly.
Besides that, I sort by a column and when a cell in that column is empty my program pushes it all the way to the bottom of the list and I am trying to delete that empty cell space.
I tried doing Application.WorksheetFunction.Match, HLookup and VLookup and in general the worksheet functions aren't working for me.
So just to give an example of what I want to do:
I have 10 Columns with headings. I want to find the first instance of a column that
contains exactly the string I send into this class. For instance, if the
columns are "FirstName | LastName | Name", I want it to return "Name"
and not "FirstName".
I want to find a column that the user requests as a sort key and verify it's existence
I also want to find a column that is empty (last column)
Finally, I want to find the last row that has a value in relation to the SortColumn.
If you set the lookat parameter to xlWhole, it will only match the whole contents of the cell, so for example:
With Rows(1)
Set found = .Find(what:=target, After:=.Cells(1, 1), lookat:=xlWhole)
End With
To check whether a value was found, you can check whether found is nothing.
Dim exists As Boolean
If Not found Is Nothing Then exists = True
To locate the first empty cell at the end of a row or column of values, I would use the End property to find the last cell in the row/column containing data, then use Offset to find the next cell:
With Rows(1)
Set found = .Find(what:=target, After:=.Cells(1, 1), lookat:=xlWhole)
End With
Dim emptyCell As Range
If Not found Is Nothing Then
Dim col As Integer
col = found.Column
Set emptyCell = Columns(col).End(xlDown)
emptyCell.Offset(1, 0).Select
End If
However, you can't use this if there are some empty cells in the middle of your table of values. (eg if you have values in A1,A2,A3, then A4 is blank and you have more values in A5,A6,A7).
You can use a do loop:
headerToFind = "Name" 'or whatever header you're looking for
x = 1 'or whatever header row is
y = 1 'or whatever first column with header is
Do Until Cells(x,y) = ""
If Cells(x,y) = headerToFind then
MsgBox "The header you are looking for is in row " & x & ", column " & y
Exit Sub
End If
y = y + 1
Loop
MsgBox "Header not found"
In place of the message boxes, put whatever code you want to do with what you find. The first MsgBox will execute if and when the header is found (with x being equal to the row number and y being the column number). The second MsgBox will execute if the desired header is not found.