VLookup range in another worksheet dynamically - excel

I am trying to use a function that will allow me to import a range from a previous worksheet. I am not sure that my current macro allows this. I can call the previous worksheet manually, but not with the function that I have.
Here is the function that works fine when I manually input the worksheet name:
=IFERROR(VLOOKUP(D3,Aug9Daily!$D$3:$F$50,3, FALSE),"")
Here is the function that I am attempting to use:
=IFERROR(VLOOKUP(D3,NextSheetName()$D$3:$F$50,3, FALSE),"")
This is the VBA that I am using for the NextSheetName macro:
Function NextSheetName(Optional WS As Worksheet = Nothing) As String
Application.Volatile True
Dim S As String
Dim Q As String
If IsObject(Application.Caller) = True Then
Set WS = Application.Caller.Worksheet
If WS.Index = WS.Parent.Sheets.Count Then
With Application.Caller.Worksheet.Parent.Worksheets
Set WS = .Item(1)
End With
Else
Set WS = WS.Next
End If
If InStr(1, WS.Name, " ", vbBinaryCompare) > 0 Then
Q = "'"
Else
Q = vbNullString
End If
Else
If WS Is Nothing Then
Set WS = ActiveSheet
End If
If WS.Index = WS.Parent.Worksheets.Count Then
With WS.Parent.Worksheets
Set WS = .Item(1)
End With
Else
Set WS = WS.Next
End If
Q = vbNullString
End If
NextSheetName = Q & WS.Name & Q
End Function
What am I doing wrong? Is there a better way to select a range from another worksheet dynamically?

Try this to see if it works for you to fix your function's output:
NextSheetName = Q & WS.Name & Q & "!"
And then you will need to concatinate the output inside of an indirect function like this:
=IFERROR(VLOOKUP(D3,INDIRECT(NextSheetName() & "$D$3:$F$50"),3, FALSE),"")

I've found this little UDF to be handy:
Function sheet_offset(rng As Range, i As Integer) As Range
Application.Volatile 'necessary since value can change even when values of parameters do not
Set sheet_offset = rng.Worksheet.Parent.Worksheets.Item(rng.Worksheet.Index + i).Range(rng.Address)
End Function
which offsets rng by i sheets - eg, i=0 means the same sheet, i=-1 means the previous sheet, and i=1 means the next sheet.
In your example, you'd use:
IFERROR(VLOOKUP(D3,sheet_offset($D$3:$F$50,1),3, FALSE),"")
which would offset the range to reference the next worksheet.
Note that to make references relative to the current sheet (like yours) you would not specify the worksheet. To make absolute references, just specify a worksheet in the reference (eg 'Sheet1'!$D$3:$F$50) and that becomes your origin (the sheet referenced when i=0)

Related

How to find a Excel cell has hyperlink

I have data in Column A in excel..I am iterating through column and i need to find if a cell value has hyperlink init.
LR=Activeworkbook.Worksheets("Emp").Range("A65000").End(xlup).Row
for j=1 to LR
if Thisworkbooks.Worksheets("Emp").cells(j,1)="" then 'Logic to find hyperlink
'Function
end if
next
Identify Cells Containing Hyperlinks
As Red Hare already mentioned in the comments, it is best tested with something like the following:
Dim cell As Range: Set cell = Sheet1.Range("A1")
If cell.Hyperlinks.Count > 0 Then ' has a hyperlink
Else ' has no hyperlink
End If
that is, using the Hyperlinks.Count property of the Hyperlinks object returned by the cell's Hyperlinks property which is a collection of hyperlinks in a range (in this case, a single cell). For a single cell, the Count property will return only 0 or 1 so you could actually use
If cell.Hyperlinks.Count = 1 Then ' has a hyperlink
instead.
Example Code
Option Explicit
Sub IdentifyCellsWithHyperlink()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' If it's not, modify accordingly.
Dim ws As Worksheet: Set ws = wb.Worksheets("Emp")
Dim rg As Range
Set rg = ws.Range("A2", ws.Cells(ws.Rows.Count, "A").End(xlUp))
Dim cell As Range
For Each cell In rg.Cells
If cell.Hyperlinks.Count > 0 Then ' has a hyperlink
Else ' has no hyperlink
End If
Next cell
End Sub
Here is something that can be used to run through each row to determine if it can be set as a hyperlink. Kinda hard to figure out what the range of possible solutions are that will work for you without fully understanding the context...
Private Sub cmdFollowLink_Click()
CreateHyperlink Me!cmdFollowLink, Me!txtSubAddress, _
Me!txtAddress
End Sub
Sub CreateHyperlink(ctlSelected As Control, _
strSubAddress As String, Optional strAddress As String)
Dim hlk As Hyperlink
Select Case ctlSelected.ControlType
Case acLabel, acImage, acCommandButton
Set hlk = ctlSelected.Hyperlink
With hlk
If Not IsMissing(strAddress) Then
.Address = strAddress
Else
.Address = ""
End If
.SubAddress = strSubAddress
.Follow
.Address = ""
.SubAddress = ""
End With
Case Else
MsgBox "The control '" & ctlSelected.Name _
& "' does not support hyperlinks."
End Select
End Sub

VBA partial string CountIf inside of cell formulas (not Values)

So I have a worksheet with a bunch of linked cells set to a UNC path. For example, lets say that Cell A1 is equal to:
='\\corp\StackOverflow\[Example01.xlsx]TestSheet'!$A$1
and Cell A2 is equal to:
='\\corp\StackOverflow\[Example02.xlsx]TestSheet'!$A$1
Is there a way to have a CountIf for a partial string of "StackOverflow" for the entire worksheet? It would return a 2.
Sub Search()
Dim r As Range, s As String, i As Long
Dim ws As Worksheet
s = "StackOverflow"
For Each ws In ActiveWorkbook.Worksheets
Set r = ws.Cells
i = Application.WorksheetFunction.CountIf(r, "*" & s & "*")
MsgBox ("i: " & i)
Next ws
End Sub
This is what I am using, but it always returns a 0 because I think it only looks at the Values. I want it to look inside of the formula (even if that cell normally returns a #REF! error). And yes, if it could look at the entire worksheet's cells, because I want to use it on a For Each ws basis.
One can search the text of formula cells for a specific string and increase the counter.
Sub Search()
Dim r As Range, s As String, i As Long
Dim ws As Worksheet
s = lcase("StackOverflow")
For Each ws In ActiveWorkbook.Worksheets
For Each rng In ws.Cells.SpecialCells(xlCellTypeFormulas)
If LCase(rng.Formula) Like "*" & s & "*" Then i = i + 1
Next
Next ws
MsgBox ("i: " & i)
End Sub

Getting Error messages on ranges

I am getting error messages i that state that variable isn't defined. And VB is coloring this code red If LCase(wb.Range("Q" & i) = "y" Then .AutoFilter and I don't know why.
It's really important that only rows with a "y" in column Q in each range is pasted, and not everything else.
I had to change i to 2 To 500, and j = 2 To 20, but am worried that I might get columns that I don't want pasted into Sheet2(Materials_Estimate). I just want the range columns to be pasted.
The ranges include Sheet2 information as shown in the picture below (B=text, c=text, D=text, F=up to 3 numbers, G=a letter y, H=text, I=a calculation copied from Sheet 1 of the qty*cost)
Can anyone assist me?
[Code]
Option Explicit
Sub Estimating2()
Application.ScreenUpdating = False
'naming the workbook and worksheets and ranges
Dim ProjectBudgeting1 As Workbook
Dim Materials_Budget As Worksheet
Dim Materials_Estimate As Worksheet
Dim LowesFax As Worksheet
Dim HomeDepotFax As Worksheet
Dim SBath1 As Range
Dim SBath2 As Range
Dim SBed1 As Range
Dim SBed2 As Range
Dim SBed3 As Range
Dim SBed4 As Range
Dim SHall As Range
Dim SFP As Range
Dim SRP As Range
Dim SKit As Range
Dim SGar As Range
Dim BuyOA As Range
Dim SFlorida As Range
Dim TargetRange As Range
Dim ActiveWorksheet As Worksheet
'naming the worksheets and ranges in code
Set ProjectBudgeting1 = ActiveWorkbook
Set Materials_Budget = Worksheets("Materials_Budget")
Set Materials_Estimate = Worksheets("Materials_Estimate")
Set LowesFax = Worksheets("LowesFax")
Set HomeDepotFax = Worksheets("HomeDepotFax")
Set SBath1 = Range("Materials_Budget!Supplies_Bathroom1")
Set SBath2 = Range("Materials_Budget!Supplies_Bathroom2")
Set SBed1 = Range("Materials_Budget!Supplies_Bedroom1")
Set SBed2 = Range("Materials_Budget!Supplies_Bedroom2")
Set SBed3 = Range("Materials_Budget!Supplies_Bedroom3")
Set SBed4 = Range("Materials_Budget!Supplies_Bedroom4")
Set SHall = Range("Materials_Budget!Supplies_Hallway")
Set SFP = Range("Materials_Budget!Supplies_FrontPorch")
Set SRP = Range("Materials_Budget!Supplies_RearPorch")
Set SKit = Range("Materials_Budget!Supplies_Kitchen")
Set SGar = Range("Materials_Budget!Supplies_Garage")
Set SFlorida = Range("Materials_Budget!Supplies_Florida")
'Here I'm calling out the column q and looking for a "Y"
Set BuyOA = Range("Materials_Budget!Buy_OrderApproval")
'Here I'm naming the source of the information that gets copied into other sheets
Set ActiveWorksheet = Materials_Budget
'Here is the sheet where the source cells are pasted
Set TargetRange = Range("Materials_Estimate!EstimateTableArea1")
'Looking for the "Y" in column q for duplicating and printing corresponding rows (i) and columns (j)
For i = 12 To 520
Cells("Q", i) = "Row " & i & " Col " & j
For j = 2 To 20
If LCase(wb.Range("Q" & i) = "y" Then .AutoFilter
i = i + 1
Range("Q" & i).Select
i = i - 1
Next q
Next i
For j = 1 To 5
Cells(i, j) = "Row " & i & " Col " & j
End Sub
Application.ScreenUpdating = True
End With
End Sub
[Code/]
I see many errors.
A) You have not declared your objects. For example, you need to declare SBath1, SBath2 etc.. as Range
B) You have declared ProjectBudgeting1 as workbook but then you are using it as a worksheet object.
C) When setting range, fully qualify them
D) Your wb object is undeclared. I would strongly suggest that you use Option Explicit at the top of your code
E) You have an extra bracket ) in wb.Range("Q12:Q" & LastRow))
F) Avoid the use of .Select INTERESTING READ
G) Finally, I would highly recommend on forgetting one word in vba and that is using End to stop a code. Reason is quite simple. It's like Switching your Computer using the POWER OFF button. The End statement stops code execution abruptly. Also the Object references held (if any) by other programs are invalidated.
Here is a basic gist on how your code should look like
Sub Estimating2()
Dim wb As Workbook
Dim ws As Worksheet
Dim rng1 As Range, rng2 As Range
Set wb = ActiveWorkbook '~~> Or ThisWorkbook?
Set ws = wb.Sheets("Sheet1")
With ws
Set rng1 = .Range("Supplies_Bathroom1")
Set rng2 = .Range("Supplies_Bathroom2")
'
'~~> And so on
'
End With
End Sub

excel vba : why is this function looping infinitely?

I've written the following function to search a worksheet for the last available blank row.
Function findlastLog_Row() As Integer
Dim i As Integer
i = 1 'start at row 1
Do Until Sheets("Log").Cells(i, 1) = ""
i = i + 1
Loop
findlastLog_Row = i
End Function
Any ideas why its looping over and over. It seems to start all over on the second to last line findlastLog_Row = i. This last line is to return the value of i. Am I oversimplifying this?
Is this what you are trying?
Sub Sample()
Debug.Print findlastLog_Row
End Sub
Function findlastLog_Row() As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Log")
With ws
findlastLog_Row = .Range("A" & .Rows.Count).End(xlUp).Row
End With
End Function
Try changing it to Sheets("Log").Cells(i, 1).Value (hence the .Value at the end). .Cells() will return a Range object. I'm not entirely sure what the default property of a range is, but it might just not be the .Value property.

Entereing multiple values in a single cell in excel

I want to enter multiple values in a single cell in excel sheet based on the certain condition as in if there are multiple sheets in the workbook then if any of the sheet starting with name TC contains color in it then I've to enter the information in Read Me Section of the Excel Workbook a another worksheet. The problem with my code is that its not displaying unique sheets which contain coloring...Suppose Sheet "TC_1" and "TC_3" contains color in any of the cell then its displaying the output as ";TC_3;TC_3;TC_3;" although the expected output over here is "TC_1;TC_3".
Here, is the code:
Sub ErrorInSheet()
Dim Row
Dim Names As String
Names = ""
For Row = 2 To tsheet.UsedRange.Rows.Count
For Chkcol = 1 To tsheet.UsedRange.Columns.Count
If tsheet.Cells(Row, Chkcol).Interior.ColorIndex = 3 Then
Names = Names & ";" & tsheet.Name
End If
Next
Next Row
Sheets("Read Me").Cells(13, 5).Value = Names
End Sub
Sub iterateSheets()
For Each sheet1t In Worksheets
If InStr(1, sheet1t.Name, "TC") Then
Set tsheet = sheet1t
Call ErrorInSheet
End If
Next
End Sub
I think this will work for you - I tested it and worked for me.
Sub FindErrors()
Dim sht As Worksheet, cl As Range, shtNames As String
shtNames = vbNullString
For Each sht In Worksheets
If Left$(sht.Name, 2) = "TC" Then
For Each cl In sht.UsedRange.Cells
If cl.Interior.ColorIndex = 3 Then
shtNames = IIf(shtNames = vbNullString, sht.Name, shtNames & ";" & sht.Name)
End If
Next cl
End If
Next sht
Worksheets("Read Me").Cells(13, 5) = shtNames
End Sub
Notes:
I've explicitly declared the variables
I am assuming all your sheets start with "TC" so I've used Left$ but you can use InStr if you like
I've used the ternary IIF statement to stop you getting a leading ;
I've put all the code in one Sub but you can split it out if you like

Resources