VBA Excel/ search & replace value in next column double variables - excel

I have the feeling I am close, yet I feel really far.
I have one sheet called temp.
In M2 there's a unique identifier so I know which row I need to find in my other sheet which is called specs.
The value of G2 of the sheet temp needs to be pasted 3 columns to the right on the searched value (in the sheet specs).
I came this far but now I am stuck :/
Sub search()
Dim indexnr As String
Dim rngFind As Range, rngLookUp As Range
indexnr = Sheets("temp").Range("m2")
Data = Sheets("temp").Range("g2")
Set rngLookUp = Range("D1:D1000")
Set rngFind = rngLookUp.Find(indexnr, LookIn:=xlValues).Offset(0, 1)
End Sub

Instead of using the range.find method, a For Each Next Statement should do what you need.
The range.find method returns another range object which would not paste the values inside the cell.
Try something like this:
For Each i in [D1:D1000]
tempString = i.value2
if Instr(1,tempString,indexr,0) <> 0 then
i.offset(0,3).value2 = tempString
end if
next i

Related

Is there a function in macro or VBA to extract data from cell with conditions

I am trying to find a way, if there is such, to compare two columns where in column A there are numbers, and in column B there is data. In Column B the data is something like "1 - the link to publication is missing; 2 - no signature given; 5 - no references;".
If the first character from Column B matches the number in Column A, then extract from Column A starting from the matching number to ";".
I am pretty sure this can be done on Python, but have no idea about VBA or in macro in Excel, as I've been working a lot with Excel lately.
Thank you for your time and help!
Cheers.
You're asking if VBA has Loops and can evaluate boolean expressions? Yes, it has those. For , ForEach, Do, While, If
You would be looking for something like:
Sub Example()
Dim MyValuesFromSheet1 As Collection
Set MyValuesFromSheet1 = GrabValues(Sheet1)
End Sub
Function GrabValues(WS As Worksheet) As Collection
Dim SavedValues As New Collection
Dim LastRow As Long
LastRow = WS.Columns(1).Cells(WS.Rows.Count).End(xlUp).Row
Dim SearchRange As Range
Set SearchRange = WS.Range("A1:A" & LastRow)
Dim Cell As Range
For Each Cell In SearchRange
If Cell.Value <> "" And Cell.Value = Left(Cell.Offset(, 1), 1) Then SavedValues.Add "that extracted region you described"
Next
Set GrabValues = SavedValues
End Function

Including a formula based on a function in a dynamic defined cell

I need to concatenate a dynamic range using VBA.
My best guess so far was to create a function and then calling the function via VBA to a specific cell. Here is the code i'm using:
Sub test()
I used this method to declare the variable just to shorten the code. Basically the last column that may contain data will always vary and is never the same. I already have the code working in order to determine the last column that contains data so let's just say in this case the last column is column G (or column 7)
Dim LASTCOLUMN As Integer: LASTCOLUMN = 7
What i need is to get the concatenated range in cell A1. My best guess is the following code but i also tried several other options and all of them failed. Can someone please help me with this line of code? It needs to be dynamic in order to incorporate the dynamic variable LASTCOLUMN.
Range("A1").Formula = "=ConcatRange(Cells(2, 1):Cells(LASTCOLUMN, 1)" End Sub
This is the function that concatenates a given range
Function ConcatRange(myrange As Range) As String
Dim CurrentRange As String
Dim r As String
CurrentRange = ""
For Each cell In myrange
If cell <> "" Then
r = cell
CurrentRange = CurrentRange & r
End If
Next cell
ConcatRange = CurrentRange
End Function

Result of volatile UDF isn't shown if I edit another Sheet and switch back

I'm using a volatile UDF which is working basically as it should. I pass a range to it and if a value in this range changes, it recalculates as it should. But when I switch to another sheet and edit for example a cell and then switch back, I see no output of this UDF.
I've I change a cell value on the sheet containing the UDF or save the file, it shows the output of the UDF again. I also can do a
' Refresh all Calculations if Sheet is activated
Private Sub Worksheet_Activate()
Application.CalculateFull
End Sub
But I don't think this is a nice solution if not critically needed, as the sheet contains hundreds of formulas.
I've also checked UDF #Value! when switching sheets which seems to be similar problem (with no real answer).
' Returns Tags-String based on Range/Threshold
Public Function GetTagsString(rngRange As Range) As String
' Define Variables
Dim strTags As String
Dim strTagSeparator As String
Dim strTag As String
Dim intTagRow As Integer
Dim intTagValue As Integer
Dim dblTagMinScore As Double
Dim rngCell As Range
' Initialize Values
intTagRow = Sheets("Locations").Range("TagsRow").Value
dblTagMinScore = Sheets("Settings").Range("TagMinScore").Value
strTagSeparator = Sheets("Settings").Range("TagSeparator").Value
strTags = ""
' Loop through all Cells in Range
For Each rngCell In rngRange
intTagValue = rngCell.Value
strTag = Cells(intTagRow, rngCell.Column).Value
' Include Tag if equal/greater than Tag-Threshold
If (intTagValue >= dblTagMinScore) Then
If (Not strTags = "") Then
' String contains already Tags => append Tag-Separator
strTags = strTags & strTagSeparator & strTag
Else
strTags = strTag
End If
End If
Next rngCell
' Return Tags-String
GetTagsString = strTags
End Function
I'm calling this UDF by:
=GetTagsString(INDIRECT(ADDRESS(ROW();COLUMN(TagAmusement);4)):INDIRECT(ADDRESS(ROW();COLUMN(TagFun);4)))
TagAmusement and TagFun are named cells. I know using INDIRECT is maybe not the best solutions, but because of several reasons I need to be this dynamic. I'm doing this in a lot formulas, but without using an UDF and without the same problem. The problem must have to do something with the UDF, but I don't think it's because of this function parameters. It must have something to do with changing another sheet and switching back to the original sheet.
And yes, I read some values from the sheet, but I've also tried to pass them too and it doesn't make a difference (I also don't change(d) them).
The only thing what works (on an automated base) is:
' Refresh all Calculations if Sheet is activated
Private Sub Worksheet_Activate()
Application.CalculateFull
End Sub
The problem only occurs if I change the sheet and do "something" (like editing a cell) there.
Is this a bug of Excel or what do I overlook?
strTag = Cells(intTagRow, rngCell.Column).Value is the same as strTag = ActiveSheet.Cells(intTagRow, rngCell.Column).Value
So if rngRange is on "Sheet1" but you then switch to "Sheet2" and edit a cell (which triggers a recalculation), the value read into strTag will come from Sheet2 and not from Sheet1. If the corresponding cells on Sheet2 happen to be empty then it will look as though the UDF isn't returning anything.
To prevent this, specify the worksheet that the call to Cells applies to:
strTag = rngRange.Worksheet.Cells(intTagRow, rngCell.Column).Value
or wrap the whole For Each loop in a With...End With block and make the call to Cells use that object:
With rngRange.Worksheet
For Each rngCell In rngRange
'...
strTag = .Cells(intTagRow, rngCell.Column).Value
'...
Next rngCell
End With

Excel VBA Vlookup issue

I'm a complete beginner to Excel VBA.
The following is code I've written that should iterate through a column in a sheet, filling values by referring to the column value to it's left and referring to another sheet in the same workbook to find what the correct corresponding value should be.
I've used a While loop so i can apply this VLOOKUP macro to each cell in the column ( only the lookup value, changes, which should be a variable denoting the column to the left) :
Dim result As String
Dim sheet As Worksheet
Dim rownum As Integer
Dim iterator As Integer
Dim lookup_value As String
Dim vlookupString1 As String
Set sheet = ActiveWorkbook.Sheets("datasheet")
rownum = sheet.Range("A1").End(xlDown).Row
Set iterator = 3
While iterator < rownum
lookup = "M" & iterator
vlookup1String = "=VLOOKUP(" & lookup & ",'GICS Sub-industry codes'!$A$2:$B$155,2,FALSE)"
With ActiveSheet.Cells
Range("N" & iterator).Select
Selection.Value = vlookup1String
End With
iterator = iterator + 1
End While
I'm getting an error # end while saying "expected if or select or sub..."
1) Have i made a syntax error?
2) Is my approach correct. I have observed this string approach to designing VLOOKUPS in vba only in one other place. It seemed best suited.
Fixing your code
You should use Wend not End While for your loop.
Cleaner Alternative
But you can fill an entire range in a single shot as below
It is better to "loop up" a range from the bottom using End(xlup) than to look down with End(xlDown) (which relies on no spaces)
You almost never need to use Select in VBA
Further explanation
rng1 sets a working range from the last used cell in column A in sheet datasheet to A3
rng1.Offset(0, Range("N1").Column - 1) says offset rng1 (which is column A) by 13 columns to use column N (ie OFFSET A by 14-1) for the formula insertion
I used the macro recorder to get the code you needed in column N for this part "=VLOOKUP(RC[-1],'GICS Sub-industry codes'!R2C1:R155C2,2,FALSE)".
IN R1C1 speak, RC[-1] means refer to the cell in the same row, but one column to the left. So in N3, the formula will start as =VLOOKUP(M4..), So in N30, the formula will start as `=VLOOKUP(M30..) etc
Suggested code
Sub QuickFill()
Dim ws As Worksheet
Dim rng1 As Range
Set ws = Sheets("datasheet")
Set rng1 = ws.Range(ws.[a3], ws.Cells(Rows.Count, "A").End(xlUp))
rng1.Offset(0, Range("N1").Column - 1).FormulaR1C1 = "=VLOOKUP(RC[-1],'GICS Sub-industry codes'!R2C1:R155C2,2,FALSE)"
End Sub

Using Match and Address functions within Macro or VBA

I have two worksheets, I want to use a value in sheet to_approve to lookup against column A in sheet submitted, then identify the cell reference so I can paste a value in the cell adjacent (column B).
I have used the following to identify the cell reference, but I don't know how to use it in VBA code.
=ADDRESS(MATCH(To_Approve!D19,Submitted!A:A,0),1,4,1,"submitted")
While many functions can be used in VBA using Application.WorksheetFunction.FunctionName ADDRESS is not one of these (MATCH is)
But even it it was available I would still use a Find method as below as it:
gives you the ability to match whole or part strings, case sensitive or not
returns a range object to work with if the value is found
readily handles a no match
you can control the point in the range being search as to where the search starts
multiple matches can be returned with FindNext
something like
Sub GetCell()
Dim ws As Worksheet
Dim rng1 As Range
Set ws = Sheets("submitted")
Set rng1 = ws.Columns("A").Find(Sheets("To_Approve").[d19], , xlValues, xlWhole)
If Not rng1 Is Nothing Then
MsgBox rng1.Address & " in sheet " & ws.Name
Else
MsgBox "not found", vbCritical
End If
End Sub
This example should give you an idea of how to find a corresponding value on another sheet and place a second value in the the column to the left. When using VBA, it is not necessary to select cells and then paste; you can directly enter a value into a range (cell) object.
Sub TransferValue()
Dim rngSearch As Range
Dim rngFind As Range
Dim dValue As Double
' initialization
Set rngSearch = Worksheets("to_approve").Range("D19")
dValue = Date
' find the match & insert value
Set rngFind = Worksheets("submitted").Columns(1).Find(What:=rngSearch.Value)
If Not rngFind Is Nothing Then
rngFind.Offset(ColumnOffset:=1).Value = dValue
End If
End Sub
(Note: dValue is a placeholder for whatever value you want to enter.)

Resources