Vlookup Dates in Excel VBA - vba

I am working with 3 excel sheets. In sheet Start Page i have Dates starting from column A4 going down. The macro Vlooks up in sheet Fund Trend for the same Dates which are locate in column A11 to lastrow and offsets 3 columns , and copies the Value into sheet "Accrued Expenses" starting from Range("C7"). Macro loops until the lastrow in sheets("Start page") Range("A4") .
The Problem is that the macro is not populating the values into sheet Accrued expenses, on some occasions. OR its not finding the Date. My code is below:
Sub NetAsset_Value()
Dim result As Double
Dim Nav_Date As Worksheet
Dim fund_Trend As Worksheet
Dim lRow As Long
Dim i As Long
Set Nav_Date = Sheets("Start page")
Set fund_Trend = Sheets("Fund Trend")
lRow = Sheets("Start page").Cells(Rows.Count, 1).End(xlUp).row
For i = 4 To lRow
result = Application.WorksheetFunction.VLookup(Nav_Date.Range("A" & i), fund_Trend.Range("A11:C1544"), 3, False)
Sheets("Accrued Expenses").Range("C" & i + 3).Value = result
Sheets("Accrued Expenses").Range("C" & i + 3).NumberFormat = "0.00"
Sheets("Accrued Expenses").Range("C" & i + 3).Style = "Comma"
Next i
End Sub
Error Trap:
On Error Resume Next
result = Application.WorksheetFunction.VLookup(Nav_Date.Range("A" & i), fund_Trend.Range("A11:C1544"), 3, False)
If Err.Number = 0 Then
Sheets("Accrued Expenses").Range("C" & i + 3).Value = result
Sheets("Accrued Expenses").Range("C" & i + 3).NumberFormat = "0.00"
Sheets("Accrued Expenses").Range("C" & i + 3).Style = "Comma"
End If
On Error GoTo 0
To over come the Date issue i have this sub dont know if this is efficient?
Sub dates()
Sheets("Start page").Range("A4", "A50000").NumberFormat = "dd-mm-yyyy"
Sheets("Fund Trend").Range("A11", "A50000").NumberFormat = "dd-mm-yyyy"
End Sub
The issue that i am now having is that when enter a date like 11/02/2015 it switches to 02/11/2015. But its not happening to all Dates
Overcoming the Problem. I am placed a worksheet function to force the date columns to text. Which is currently working.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Sheets("Start page").Range("A4", "A50000").NumberFormat = "#"
Sheets("Fund Trend").Range("A11", "A50000").NumberFormat = "#"
End Sub

To avoid the 1004 error you can use the Application.VLookup function, which allows an error type as a return value. Use this method to test for an error, and if no error, return the result.
To do this, you'll have to Dim result as Variant since (in this example) I put a text/string value in the result to help identify the error occurrences.
If IsError(Application.Vlookup(Nav_Date.Range("A" & i), fund_Trend.Range("A11:C1544"), 3, False)) Then
result = "date not found!"
Else
result = Application.WorksheetFunction.VLookup(Nav_Date.Range("A" & i), fund_Trend.Range("A11:C1544"), 3, False)
End If
The "no result printed in the worksheet" needs further debugging on your end. Have you stepped through the code to ensure that the result is what you expect it to be, for any given lookup value? If there is no error, then what is almost certainly happening is that the formula you have entered is returning a null string and that value is being put in the cell.

Related

VBA - check if a string is is 1 of those in a column of a different sheet, in an if statement

Hello i want to simpify the formula from
If InStr(1, Sheets("Le 2250").Cells(i, 1).Value, "250-") Or _
If InStr(1, Sheets("Le 2250").Cells(i, 1).Value, "135-") Or _
If InStr(1, Sheets("Le 2250").Cells(i, 1).Value, "700-")
to have the "250-" be 1 of the values in a column of a specific sheet, rather than having to put many "Or if ()" functions with the numerous strings i have to lpok for
Any help appreciated.
Here is an alternative that uses the Evaluate method...
If Evaluate("OR(ISNUMBER(MATCH({""*250-*"",""*135-*"",""*700-*""},{""" & Sheets("Le 2250").Cells(i, 1).Value & """},0)))") Then
Note, however, the number of characters used with the Evaluate method cannot exceed 255, otherwise an error will be returned.
Basically, build an array of your test values, and loop that array until you find something.
Something like this
Sub Demo()
Dim ws As Worksheet
Dim rTestStings As Range, TestStings As Variant
Dim TestValue As Variant
Dim idx As Long
Dim Found As Boolean
'Get Test Strings from Sheet. Adjust to suit your data
With rTestStings = Worksheets("specific sheet")
Set rTestStings = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With
TestStings = rTestStings.Value2
Set ws = Sheets("Le 2250")
'I'm guessing you are doing something like this
For i = SomeValue To SomeOtherValue
TestValue = ws.Cells(i, 1).Value
Found = False
For idx = LBound(TestStings, 1) To UBound(TestStings, 1)
If Not IsEmpty(TestStings(idx, 1)) Then 'incase there are gaps in your test data
If InStr(TestValue, TestStings(idx, 1)) Then
Found = True
Exit For
End If
End If
Next
If Found Then
MsgBox "Found " & TestStings(idx, 1) & " in cell " & ws.Cells(i, 1).Address
' do something ...
End If
Next i
End Sub

Trying to Highlight Used Range of a Column

I'm running into trouble highlighting a column's used range. The following code creates copies of two worksheets, removes some values and then is supposed to highlight certain columns.
Sub CreateAnalysisSheets()
Dim cell, HlghtRng As Range
Dim i As Integer
Dim ref, findLast, findThis As String
Dim lastRow As Long
findLast = "2016"
findThis = "2017"
Application.ScreenUpdating = False
Sheets(1).Copy After:=Sheets(2)
ActiveSheet.Name = Left(Sheets(1).Name, InStr(1, Sheets(1).Name, " ")) & "Analysis"
Sheets(2).Copy After:=Sheets(3)
ActiveSheet.Name = Left(Sheets(2).Name, InStr(1, Sheets(2).Name, " ")) & "Analysis"
Sheets("RM Analysis").Select
For Each cell In ActiveSheet.UsedRange
If cell.Value = "NULL" Then
cell.ClearContents
End If
Next cell
For Each cell In Range("1:1")
ref = cell.Value
lastRow = Range("R" & Rows.Count & "C" & cell.Column).End(xlUp).Row
Set HlghtRng = Range(Cells(1, cell.Column) & Cells(lastRow, cell.Column))
If InStr(1, ref, findLast) > 0 And InStr(1, ref, "YTD") = 0 Then
HlghtRng.Interior.ColorIndex = 8
End If
Next cell
For Each cell In Sheets(4).UsedRange
If cell.Value = "NULL" Then
cell.ClearContents
End If
Next cell
Sheets("RM Analysis").Select
Application.ScreenUpdating = True
End Sub
The problem comes at lastRow = Range("R" & Rows.Count & "C" & cell.Column).End(xlUp).Row where I get an Method 'Range' of Object '_Global' Failed. I've tried searching for ways to fix this issue, but everything I've tried (ActiveSheet.Range and Sheets("RM Analysis").Range) has yet to work.
Anyone see where I'm going wrong here?
The xlR1C1 syntax is fouling up your request for the last non-blank cell.
lastRow = Cells(Rows.Count, cell.Column).End(xlUp).Row
I would highly recommend that you avoid relying on the ActiveSheet and use explicit parent worksheet references. This can be made quite simple using With ... End With and preceding all Range and Cells with a . like .Range(...) or .Cells(...).
Once you within a With ... End With statement, all of the references need to be prefaced with a .. Additionally, the following is not a string concatenation (e.g. &) but as .Range(starting cell comma ending cell) operation.
with worksheets("RM Analysis")
...
Set HlghtRng = .Range(.Cells(1, cell.Column), .Cells(lastRow, cell.Column))
...
end with
this should do
Columns(1).Interior.ColorIndex = 3
change the number of column as to the column you wanna highlit

Compare 4 columns in one excel sheet using vba

I need your help please, I have 4 columns in an excel sheet and I need to compare them 2 by 2 i will explain to you :
In column A i have users(user1,user2,user3 ...)
In column B i have functionalities ( fonc1, fonc2, fonc3.....)
In column C i have users(user1,user2,user3 ...)
In column D i have functionalities ( fonc1, fonc2, fonc3.....)
The columns C and D are a new version of columns A and B in the columns C and D the users may change order or change functionalities .
When i execute my code i put the result in other new columns:
column F where i have the users
column G where i put the Deleted_functionalities
column H where i put the New_functionalities
The first problem is that the code doesn't get the users it get only the new and deleted functionalities. The second problem is that when the column A is more than column C where the users are stocked the code doesn't work. Can you please help me to find a solution? Thank you in advance .
Here is my code and the file I am working on :
Private Sub CommandButton2_Click()
Dim rngCell As Range
For Each rngCell In Range("B2:B2000")
If WorksheetFunction.CountIf(Range("D2:D2000"), rngCell) = 0 Then
Range("G" & Rows.Count).End(xlUp).Offset(1) = rngCell
End If
Next
For Each rngCell In Range("D2:D2000")
If WorksheetFunction.CountIf(Range("B2:B2000"), rngCell) = 0 Then
Range("H" & Rows.Count).End(xlUp).Offset(1) = rngCell
End If
Next
End Sub
and this is the excel file
http://www.cjoint.com/c/FCxnwjp22rv
try this
Private Sub CommandButton2_Click()
Dim ws As Worksheet
Dim cell As Range, funcCell As Range
Dim oldUserRng As Range, newUserRng As Range, reportRng As Range
Dim iReport As Long
Dim oldFunc As String, newFunc As String
Set ws = ThisWorkbook.Worksheets("users") '<== adapt it to your needs
With ws
Set oldUserRng = .Columns(1).Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeConstants, xlTextValues)
Set newUserRng = .Columns(3).Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeConstants, xlTextValues)
Set reportRng = .Range("F1:I1") '<== added one report column to account for unchanged functions
End With
reportRng.Value = Array("user", "deleted", "new", "same")
iReport = 1
For Each cell In oldUserRng
With cell
oldFunc = .Offset(, 1).Value
Set funcCell = FindAndOffset(newUserRng, .Value, 1)
If funcCell Is Nothing Then
reportRng.Offset(iReport) = Array(.Value, "", "", oldFunc)
Else
newFunc = funcCell.Value
If newFunc = oldFunc Then
reportRng.Offset(iReport) = Array(.Value, "", "", newFunc)
Else
reportRng.Offset(iReport) = Array(.Value, oldFunc, newFunc, "")
End If
End If
iReport = iReport + 1
End With
Next cell
For Each cell In newUserRng
With cell
Set funcCell = FindAndOffset(oldUserRng, .Value, 1)
If funcCell Is Nothing Then
reportRng.Offset(iReport) = Array(.Value, "", .Offset(, 1).Value, "")
iReport = iReport + 1
End If
End With
Next cell
End Sub
Not so sure it does what you need.
you'd better provide screenshots of "before" and "after" scenarios.
BTW, is it safe to assume that both old and new user columns cannot hold duplicates (i.e.: two or more "userX" in column A and/or column C?)
But it does speed up thing considerably since it iterates only through non empty cells.
I hope I get what you want to achieve. Does the following solve your problem?
Private Sub CommandButton2_Click()
Dim rngCell As Range
For Each rngCell In Range("A2:A20000")
If WorksheetFunction.CountIf(Range("C2:C20000"), rngCell) > 0 Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 1) = rngCell.Offset(0, 1).Value
Range("F" & Rows.Count).End(xlUp).Offset(0, 2) = Application.WorksheetFunction.VLookup(rngCell.Value, Range("C2:D20000"), 2, 0)
ElseIf (rngCell <> "") Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 1) = rngCell.Offset(0, 1).Value
End If
Next
For Each rngCell In Range("C2:C20000")
If (WorksheetFunction.CountIf(Range("A2:A20000"), rngCell) = 0 And rngCell <> "") Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 2) = rngCell.Offset(0, 1).Value
End If
Next
End Sub
A user is only included in column F when he appears both in columns A and C.In case you want to include every user that is either in column A or C the code has to be altered.

Store location of cell address to variable in VBA

I'm using VBA in Excel and I'm using a function to find the first empty row then adding some values, after that I need to pass the address of the cell to another function but using the code below I get a runtime error. firstEmptyRow is a function that returns a range,e.g. $A$280.
Dim addCell as Range
'Find first empty row in the table
With firstEmptyRow
'Enter Values
.Value = taskID
.Offset(0, 1).Value = jobID
.Offset(0, 2).Value = jobName
.Offset(0, 6).Value = taskTypeID
.Offset(0, 8).Value = taskName
.Offset(0, 9).Value = desc
.Offset(0, 11).Value = estMins
.Offset(0, 13).Value = "No"
set addCell = .Address //Gives a runtime error
End With
What is the correct way to save the address of the cell so I can pass it to another function? Below is the code for firstEmptyRow
Public Function firstEmptyRow() As Range 'Returns the first empty row in the Schedule sheet
Dim i, time As Long
Dim r As Range
Dim coltoSearch, lastRow As String
Dim sheet As Worksheet
Set sheet = Worksheets("Schedule")
time = GetTickCount
coltoSearch = "A"
For i = 3 To sheet.Range(coltoSearch & Rows.Count).End(xlUp).Row
Set r = sheet.Range(coltoSearch & i)
If Len(r.Value) = 0 Then
Set firstEmptyRow = sheet.Range(r.Address)
'r.Select
Exit For 'End the loop once the first empty row is found
End If
Next i
'Debug.Print "firstEmptyRow time: " & GetTickCount - time, , "ms"
End Function
The .Address property returns a string so you'll need to to set the addCell variable like so:
Set addCell = Worksheets("Schedule").Range(.Address)
I am a total "noob" at vba and learning by trying code snipits and routines that appear to to me to answer to a problem I am stuck on. When I tried the code posted by Vityata I encountered "Run-time error '424': Object Required
at the following stmts:
Set myCell = Sheet.Range(coltoSearch & i)
Set FirstEmptyRow = Sheet.Range(coltoSearch & i + 1)
Changing the stmts as follows resolved the errors for me:
Set myCell = wks.Range(coltoSearch & i)
Set FirstEmptyRow = wks.Range(coltoSearch & i + 1)
I also added a Debug.Print stmt between the last End If and the End Function stmts so I could quickly see the result when testing as follows:
End If
Debug.Print "The 1st empty cell address is "; coltoSearch & i
End Function
If I have violated some posting rule, please accept my apology. Hopefully sharing this will avoid future confusion by others who use a similar learning process.
You do not need to overcomplicate the code with something like Set addCell = Worksheets("Schedule").Range(.Address) because it really makes the readability a bit tough. In general, try something as simple as this: Set FirstEmptyRow = myCell. Then the whole code could be rewritten to this:
Public Function FirstEmptyRow() As Range
Dim myCell As Range
Dim coltoSearch As String, lastRow As String
Dim wks As Worksheet
Set wks = Worksheets(1)
coltoSearch = "A"
Dim i As Long
For i = 3 To wks.Range(coltoSearch & Rows.Count).End(xlUp).Row
Set myCell = sheet.Range(coltoSearch & i)
If IsEmpty(myCell) Then
Set FirstEmptyRow = myCell
Exit For
End If
Next i
If i = 2 ^ 20 Then
MsgBox "No empty rows at all!"
Else
Set FirstEmptyRow = sheet.Range(coltoSearch & i + 1)
End If
End Function
The last part of the code makes sure, that if there is no empty cell before the last row and row number 3, then next cell would be given as an answer. Furthermore, it checks whether this next row is not the last row in Excel and if it is so, it gives a MsgBox() with some information.

VBA - How does one print just the values into a given cell?

I'm trying to print just the values of the yahoo function into the 39th cell with the input being from the first column of the sheet. The function returns a single string. Evaluate, .Value, and .Formula don't workout for me. I'm getting multiple errors and syntax errors. Any input would be much appreciated! I'm a newbie at VBA.
Sub Button2_Click()
Dim LastRow As Long
If Range("A5") <> vbNullString And Range("A6") <> vbNullString Then
LastRow = Range("A5").End(xlDown).Row
End If
With Range("AN5:AN" & LastRow)
Dim texttmp As String: textmp = Evaluate("yahoo(RC[-39])")
'.FormulaR1C1 = "=yahoo(RC[-39])"
'.FormulaR1C1 = "yahoo(MID(RC[-39],1,LEN(RC[-39]))"
'.Value2 = "=yahoo(RC[-39])"
'.Value = "yahoo"
'.Value2 = Evaluate("yahoo(RC[-39])")
End With
End Sub
Use the whole range in one go, fill it with the formula, then overwrite it with the calculated value.
With Range("AN5:AN" & LastRow)
.FormulaR1C1= "=yahoo(RC[-39])"
.Value = .Value
End With