How do I use a VLookup as range parameter in VBA? - excel

I have an IF statement working fine, but I need to use a VLookup as a range, as the cell that is the subject of the IF could be in a different row, but never a different column.
I'm brand new to VBA (but not to excel), so the VLookup was an instinctive move, but I'm not tied to it if I can achieve the same thing another way. I've been trying to find solutions online, but don't seem to actually answer this query.
The below is the original code with a static range.
Sub FINDTOTAL()
Dim Amount As String
Amount = "Subtotal"
thetotal = Application.WorksheetFunction.Vlookup(Amount, Sheet1.Range("G:H"), 2, False)
End Sub
Sub CalculateSubtotal()
If Range("H25") > 10000 Then
Sheets("Billing").Select
Else
Worksheets("Sheet1").Range("H25").Copy
MsgBox "Subtotal has been copied and can be pasted into the quote"
End If
End Sub
The VLookup works, and the IF statement works, I just can't get them to work together. I need the subtotal to be assessed for the IF statement regardless of where it is in the column (in probability, it could be anywhere between rows 3 - 50).

Maybe something like this:
Sub FindTotal()
Dim Total As Variant
Total = Application.VLookup("Subtotal", Sheet1.Range("G:H"), 2, False)
If Not IsError(Total) Then
If IsNumeric(Total) Then
If Total > 10000 Then
' Do one thing
Else
' Do another thing
End If
End If
End If
End Sub
If you want to write the total to another cell elsewhere, you don't need to copy, just a direct value transfer.
Demonstrating a Find/Offset approach:
Sub FindTotal()
Dim rng As Range
Set rng = Sheet1.Columns("G").Cells.Find(What:="Subtotal")
If Not rng Is Nothing Then
Dim totalRng As Range
Set totalRng = rng.Offset(, 1)
If IsNumeric(totalRng.Value) Then
If totalRng.Value > 10000 Then
' Do one thing
Else
' Do another thing
End If
End If
End If
End Sub

Related

Select and copy a cell to another sheet is not working, need advice

This code is supposed to check if conditions in two certain columns are met and if they are it supposed to take a value from another sheet and paste it into the end of the row of the checked row to the source sheet. For testing purpose, I try to at least keep it at a specific range now. I think I know where I'm wrong, the cell. Value most likely and that the range is probably not working as I have imagined it in my mind. Also, it is probably not even looping through the columns. I have like 30 different cell possibilities to copy from for different conditions and I suppose I can adjust them each depending on the conditions, but need to make this first attempt to work, then it will be pancake day, or not..
Sub Update()
Dim Column As Range
Sheets("Q485").Select
Set Column = Range.Select("AV:AW")
If Column("AW") Is cell.Value("P") And Column("AV") Is cell.Value("V") Then
Sheets("Support").Select
Range("C9").Select
Selection.Copy
Sheets("Q485").Select
Range("AY6358").Select
Selection.Paste
' Else
' Other conditions will be written below
end if
End Sub
Testing, testing, testing, but would like some suggestions from experts
Sub MyMacroc ()
Dim rng as range
set rng = sheets("Source").range("A2:A7")
For Each cel In rng.Cells
with cel
'condition -1 '
if .offset(0,1)="P" and .Offset(0,2)="V" then
.offset(0,3) = Sheets("Extract").range("B2")
ElseIF
'your second conition
end if
end with
next
End sub

finding cell value and delete it in excel vba

I want to return the value of the cell it's found in VBA and clear all of it's content with another 3 rows below it as well, but I'm currently stuck. I can find where the cell is coming from, but it's deleting the whole range instead of the specific range (I'm aware the range("A7:H20") was wrong). How do I select the correct range?
Sub Find_and_remove()
For Each cell In Range("A7:H20")
If cell.Value = Range("Q5") Then
'return the range of that cell and deleted it with 3 row below it'
Range("A7:H20").Clear
End If
Next cell
End Sub
Sub Find_and_remove()
Dim rng As Range
For Each rng In Range("A7:H20")
If rng.Value = Range("Q5") Then Range(rng, rng.Offset(3, 0)).Clear
Next cell
End Sub
Another solution:
I am using a sub to which you pass the parameters:
value to be found
range where to look in and clear contents
number of rows below the found value to be cleared.
Furthermore I am looking from the bottom to the top of the range - otherwise cells could be cleared that contain the string to be found - and then below values won't get cleared:
Option Explicit
'>>> example of how to call the findAndRemove-Sub <<<
Public Sub test_FindAndRemove()
With ActiveSheet ' adjust this to your needs
findAndRemove .Range("Q5"), .Range("A7:H20"), 3
End With
End Sub
'>>>> this is the sub that is doing the work <<<<<
Public Sub findAndRemove(strFind As String, _
rgLookup As Range, _
cntDeleteRowsBelow As Long)
Dim i As Long, c As Range
'start from the bottom and go up
'otherwise you could delete further strFind-cells unintentionally
For i = rgLookup.Rows.Count To 1 Step -1
For Each c In rgLookup.Rows(i).Cells
If c.Value = strFind Then
'ATTENTION:
'at this point there is no check if below row contains the strFind-value!
c.Resize(cntDeleteRowsBelow + 1).Clear
End If
Next
Next
End Sub
You could just use cell.Clear, or if you want the cell cleared and the next 3 below it use something like this
For i = 0 To 3
cell.Offset(i, 0).Clear
Next
I think you mean "return the address of that cell", no? Debug.Print(cell.Address) will get you this info. But you don't actually need it here. Instead of Range("A7:H20").Clear write cell.Resize(1 + i, 1).Clear with i = number of rows you want to clear along with cell itself (no need for a loop).

VBA to remove part of the same cell's content on multiple sheets

I need to remove the first half of a formula on multiple sheets throughout a workbook. Four specific cells per sheet (F308, F315, F322, F329) need to have just the first part of the formula removed.
The formula is: ='Project Input - John1'!$D$954*'Project Input - John1'!$D$952
The major catch here is each cells formula on each sheet, while extremely similar, is different. Each sheet referred to is different on each sheet and each referring cell is different in every cell.
I don't want to change the unique second part, just remove the first part: 'Project Input - John1'!$D$954*. or everything before (and including) *.
Is it possible to create a workbook formula to do this where I only have to run it once? If not, is it possible to do it sheet by sheet with a standard reference like, "This sheet"? Thanks!
Edit:
I have tried to record a macro but it applied the last part of the formula from the cell I recorded it in
I tried this VBA:
Sub test()
tx = Split(Cells(6, 315), "4")
For i = LBound(tx) To UBound(tx)
Cells(1, 2) = tx(i)
Next
End Sub
and this:
Dim ichar As Integer ichar = InStr(1, cl.Value, afterString, vbTextCompare)
cl = Left(cl.Value, ichar + Len(afterString) -1)
End Sub
Sub test() Call removetextbefore("*", Sheet11.Cell(f308))
End Sub
I got a compile error
I'm trying to find code that works and have scoured the sites, but nothing is seeming to work.
You may be able to do something like this, using the Split method:
Sub editFormulas()
Dim R As Range
Dim WS As Worksheet
For Each WS In ThisWorkbook.Worksheets
With WS
For Each R In Union(.Cells(308, 6), .Cells(315, 6), .Cells(322, 6), .Cells(329, 6))
R.Formula = "=" & Split(R.Formula, "*")(1)
Next R
End With
Next WS
End Sub

Select non-blank rows in spreadsheet

I am going to try and keep this as short as I can and still explain adequately, here goes :)
I have searched forums, my VBA literature, and cannot find a way to do what I'm trying.
I have a spreadsheet with rowTotal >= 60 rows. The rows either have text data in cells of each column, or the rows are blank with a pattern and colorindex set.
I need a macro to select all non-blank rows.
I first tried looping through the cells of column A (if a cell in column A has text data, then its row should be selected), checking if activecell.value <> empty.
Here's the jist (mix of pseudocode & code):
Range("A1").Select
loop to end
if activeCell.value <> empty then
stringVar = stringVar + cstr(activeCell.row) + ":" + cstr(activeCell.row) + ","
end if
end loop
stringVar = Left(stringVar, (Len(stringVar) - 1))
Range(stringVar).Select
If I have total 10 rows with rows 2 and 8 having data, stringVar would resolve to this: "2:2, 8:8".
Range(stringVar).Select would have same result as writing Range("2:2, 8:8").Select.
If the number of rows to be in the range is <= 45, this works no problem. However, as soon as the number of rows with data in them exceeds 45, the code fails on Range(stringVar).Select.
I tried the macro recorder and it gets around this by using the Union method. And so I thought, "self, you can get this done with Union(). hooray MacroRecorder." But alas, my joy was remiss.
I was thinking I could split the one large string into 1 or more strings; each of these smaller strings would be under the 45 limit mentioned above. Then I can use Union() to group all the ranges (these smaller strings) together into the one desired range.
However, I would have to "build" my Union() code in real time during code execution, after I knew how many of these 45> strings I had.
Anyone know how to take a worksheet and select just rows that contain data; which amounts to having a range of non-contiguous rows where more than a count of 45 rows are selected.
No need for loops - use SpecialCells
For column A only use:
Set rng1 = Columns("A").SpecialCells(xlCellTypeConstants).EntireRow
instead.
Sub QuickSet()
Dim rng1 As Range
On Error Resume Next
Set rng1 = Cells.SpecialCells(xlCellTypeConstants).EntireRow
On Error GoTo 0
If Not rng1 Is Nothing Then
MsgBox "Your working range is " & rng1.Address(0, 0)
Else
MsgBox "No constants found"
End If
End Sub
I first suggest you try using Autofilter. If you're using Excel 2010 (and prob 2007, but I can't check) this is as simple as selecting your data, choosing the "Data" tab, then clicking Filter. Using the drop-down box in your first column, deselect "blanks".
The exact same functionality exists in Excel 2003, under the Data/Filter menu option. I can't really remember it all that well, though; you'll have to experiment, or Google it.
If that doesn't work:
Sub it()
Dim cell As Range
Dim selectRange As Range
For Each cell In ActiveSheet.Range("A:A")
If (cell.Value <> "") Then
If selectRange Is Nothing Then
Set selectRange = cell
Else
Set selectRange = Union(cell, selectRange)
End If
End If
Next cell
selectRange.Select
' selectRange.EntireRow.Select 'If you want to select entire rows
End Sub
Just used this code and it worked a treat - been tracking all other excel forums but couldn't find anything that was as simplified.
I also added that the selected rows were copied and pasted to the next blank row in another sheet, if anyone finds this useful.
Sub copypaste1()
'Find rows that contain any value in column A and copy them
Dim cell As Range
Dim selectRange As Range
For Each cell In ActiveSheet.Range("A:A")
If (cell.Value <> "") Then
If selectRange Is Nothing Then
Set selectRange = cell
Else
Set selectRange = Union(cell, selectRange)
End If
End If
Next cell
selectRange.EntireRow.Select
selectRange.EntireRow.Copy
'Paste copied selection to the worksheet 'mega' on the next blank row
Sheets("mega").Range("A65536").End(xlUp).Offset(1, 0).PasteSpecial _
Paste:=xlPasteValues
End Sub

Write to two cells at same time excel vba

I need to write the same data into two different range of cells for a VBA application that I am writing. I could of course just loop through twice and write the data, but I was hoping to do it in one pass.
This is an example of what I am doing (lot of complexity removed).
Sub WriteData()
WriteOutDivision "Division1",10
WriteOutDivision "Division1",20
End Sub
Private Sub WriteOutDivision(ByVal divisionName, ByVal rowNumber)
Dim curSheet As Worksheet
Set curSheet = Sheets("Company Scorecard")
With curSheet.Cells(rowNumber, 1)
.value = divisionName
.Font.Bold = True
.InsertIndent 1
End With
End Sub
Is there something that I can do to write to both row 10 column 1 and row 20 column 1 at the same time?
You could define a non-contigous range and change the propeties of the range. For example:
Dim curSheet As Worksheet
Dim rngSpecial As Range
Set curSheet = Sheets("Company Scorecard")
Set rngSpecial = curSheet.Range("A1,A3")
rngSpecial.Value = "Whatever"
Will write "Whatever" in A1 and A3.
Could you just pass an array of row numbers instead of one rowNumber, then in your function just loop through each element in the array (I don't remember, I haven't programed in VBA for a while)? Then you could print it to as many rows as you want.

Resources