Using last row value in another set of formula - vba

I currently have 3 columns, (AB,AC & AD) . I need to sum Column AB & AC to its last Row as data varies as to number of rows. In column AD, I need to divide the amount of every cell, lets say AB1 to the sum of column AB and then divide it by the sum of column AD, in which sum of both are placed in the last Row of each column.
I already have the formula, however, my problem is after running the macro, in the formula bar, the sum of both AB & AC are hard-coded numbers. it shows like =AB1/200*300 , what i need is to show the cell reference like this =AB1/AB30*AC30 (provided last row is in row30), since sum of both columns may change if i need to add new rows in between or in cases where amount on those cells will be changed.
My current formula is this:
LastRow = Range("AB" & Rows.Count).End(xlUp).Offset(1, 0).Row
Range("AB" & LastRow & ":AC" & LastRow).Formula = "=Sum(AB2:AB" & LastRow - 1 & ")"
Range("AD2:AD" & LastRow - 1).Formula = "=AB2/" & Range("AB" & LastRow) & "*" & Range("AC" & LastRow).Value
Please help. Thank you!
Regards,
Yang

Instead of the .Value return the Address(0,0)
Range("AD2:AD" & LastRow - 1).Formula = "=AB2/" & Range("AB" & LastRow).Address(1,1) & "*" & Range("AC" & LastRow).Address(1,1)
But there is no reason to do that either as you can just concatenate the last row value in:
Range("AD2:AD" & LastRow - 1).Formula = "=AB2/AB$" & LastRow & "*" & "AC$" & LastRow

Related

Automated tool for VLOOK UP

I need to perform many VLookup in a set of excel files, and for that I built a tool that can make automated VLookup from a file to another but I need to be make it scalable and adaptable.
For that, I want to input in some cells of the tool (which is an Excel file) the parameters for the VLookup:
Position of Key Column
Position of "Returned Value" Column
Number of Columns in the range
Do you know how to change my tool in order for it to include these entry parameters ?
a sample of the code here:
For myrow = 3 To lastrow
Range("b" & myrow).FormulaR1C1 = _
"=VLOOKUP(RC[-1], Input!C[-1]:C[2],2,FALSE)"
Next myrow
I'm not well versed in R1C1 notation, but if you were using regular .Formula notation:
The following code assumes that A1 = Key column, A2 = Returned value column, A3 = Number of columns in the range (which is really just your return column).
lastrow = 10 just for the example
Also note - you must be missing a field... since you should have 4 variables - key column for first parameter, 2 column letters for second parameter, and the number of columns for 3rd parameter.
Sub Test()
lastrow = 10
For myrow = 3 To lastrow
'Range("B" & myrow).Formula = "=VLOOKUP(" & Range("A1").Value & myrow & ",Input!$" & Range("A1").Value & ":$" & Range("A2").Value & "," & Range("A3").Value & ",FALSE)"
Debug.Print "=VLOOKUP(" & Range("A1").Value & myrow & ",Input!$" & Range("A1").Value & ":$" & Range("A2").Value & "," & Range("A3").Value & ",FALSE)"
Next myrow
End Sub
Values on ActiveSheet:
Immediate window returns:

vba to copy to different ranges

I have this sheet called Consulta where everytime I change the value on the column K it changes the color of the range E:K to green or white if it's empty.
I also want to if the row is green, copy that row to the sheet called E-mail. This is what I've tried so far and it works:
Sub ChangeColor()
Dim ws As Worksheet, ws1 As Worksheet, i As Long, lastrow As Long
Set ws = Sheets("Consulta")
Set ws1 = Sheets("E-mail")
lastrow = ws.Cells(Rows.Count, "E").End(xlUp).Row
For i = 5 To lastrow
If ws.Range("K" & i) <> "" Then
ws.Range("E" & i & ":K" & i).Interior.ColorIndex = 43
ws.Range("E" & i & ":K" & i).Copy ws1.Range("A" & i & ":G" & i)
Else
ws.Range("E" & i & ":K" & i).Interior.ColorIndex = 2
End If
Next
If ws.Range("E" & i & ":K" & i).Interior.ColorIndex = 2 Then
ws1.Range("A" & i & ":G" & i).Clear
End If
End Sub
My problem is with this line below:
ws.Range("E" & i & ":K" & i).Copy ws1.Range("A" & i & ":G" & i)
I actually want to copy to a different range instead of the corresponding range in the sheet E-mail (for example, if the first match is E3:K3 I want to copy to A2:K2. If the second match is E34:K34 I want to copy it to A3:K3 and so it goes).
I tried using another loop but my Excel got crazy so I think I did it wrong.
Any suggestions will be appreciated.
You only need the upper-left corner cell for a destination. Look from the bottom up for the last used cell and offset down a row.
with ws1
ws.Range("E" & i & ":K" & i).Copy .cells(.rows.count, "A").end(xlup).offset(1, 0)
end with
You might want to put this above the line that applies a fill color or you will be copying the fill color as well.

VBA search for corresponding line and compare values

I am new to VBA programming, and I am looking for a way to search a range of about 2,000 to 3,000 rows to compare quantities where ID numbers match, and generate a message box displaying the ID number if there are any matching ID numbers where quantities do not match. There are 2 matching ID numbers in the data.
I have found and adapted this code
`Dim rng1 As Range, rng2 As Range, rngName As Range, i As Integer, j As Integer
For i = 1 To Sheets("Sheet1 (2)").Range("q" & Rows.Count).End(xlUp).Row
Set rng1 = Sheets("Sheet1 (2)").Range("q" & i)
For j = 1 To Sheets("Sheet1 (2)").Range("q" & Rows.Count).End(xlUp).Row
Set rng2 = Sheets("Sheet1 (2)").Range("q" & j)
Set rngName = Sheets("Sheet1 (2)").Range("q" & j)
If rng1.Value = rng2.Value Then
If rng1.Offset(0, 2).Value <> rng2.Offset(0, 2).Value Then
MsgBox ("Not equal " & rng1 & " Net " & rng1.Offset(0, 2) - rng2.Offset(0, 2))
Exit For
End If
End If
Set rng2 = Nothing
Next j
Set rng1 = Nothing
Next i`
Honestly, this is beyond my current skill level in VBA, and I can't think of any way to use the Macro recorder to help. I want to know if there is any way to optimize this code to run faster, and also if there is a way to adapt it to write out all ID numbers with the amount of variance, instead of displaying the message box for each ID number individually.
Thanks!
If the data is sorted (assumes ID in column Q, quantity in Column R):
Dim ErrorList as String
With Sheets("Sheet1 (2)")
For i = 1 To .Range("q" & Rows.Count).End(xlUp).Row step 2
if .range("R" & i).value <> .range("R" & i+1) then
ErrorList = ErrorList & "ID: " & .range("Q" & I) & " Net: " & _
.range("R" & i).value - .range("R" & i+1).value & vbcrlf
end if
next
end with
'do something like MsgBox with ErrorList
If the data is NOT sorted (same column assumptions):
Dim ErrorList as String
With Sheets("Sheet1 (2)")
For i = 1 To .Range("q" & Rows.Count).End(xlUp).Row
'assume .range("q"
Set Rng = .Range("q:q").Find(what:=.range("q" & i), LookIn:=xlValues, _
lookat:=xlPart, MatchCase:=False)
If .range("Q" & I).value <> rng.cells(1,1).value then
ErrorList = ErrorList & "ID: " & .range("Q" & I) & " Net: " & _
.range("R" & i).value - .range("R" & i+1).value & vbcrlf
end if
next
end with
'do something like MsgBox with ErrorList
The .Find is MUCH quicker than an inner loop through all the rows of data again (someone a week or so ago tested and found something along the lines of 1000x times faster than a loop). Unfortunately, this method will leave you with duplicate IDs in your mismatch list, since it will run through the whole list, finding each of the pairs and discovering that they both don't match:
ID Value
ABC 1
BCD 6
ABC 2
It will loop to ABC/1, find ABC/2, then later in the loop find ABC/2 and discover that it doesn't match ABC/1, and report on both. The sorted data in the first option will work better if you can get your data sorted.
NOTE: No code was tested in the writing of this answer. There may be typos to resolve
You can do this with a formula if there can be at most only two matches: eg if ID is in ColA and Amount in ColB then in ColC enter
=IFERROR(VLOOKUP(A2,A3:B$9,2,FALSE)-B2,0)
and fill down. Result will be zero if no mismatch (or no matching Id), otherwise will be the difference between the two amounts.

Run excel formula through VBA

I am trying to VLOOKUP some value in 2 sheets and if the value is found then i am putting a hyperlink on the Sheet 1 cell to point it to the Sheet 2 cell.
I have written an Excel formula for the same and it is working fine. But I am unable to convert it into a VBA formula. What am I doing wrong?
Excel formula:
=IF(ISERROR(VLOOKUP(RC[7],Sheet2!R1C1:R20C1,1,FALSE)),RC[7],HYPERLINK(CELL("address",INDEX(Sheet2!R1C1:R20C1,MATCH(RC[7],Sheet2!R1C1:R20C1,0))),RC[7]))
VBA formula which i have tried:
Sheets(4).Formula = "= IF(ISERROR(VLOOKUP(RC[7],Sheet2!R4C2:R" & Lrow2 & "C2,1,FALSE)),RC[7],HYPERLINK(CELL(" & """address""" & ",INDEX(Sheet2!R4C2:" & "R" & Lrow2 & "C2,MATCH(RC[7],Sheet2!R4C2:" & "R" & Lrow2 & "C2,0))),RC[7]))"
P.S.: Do not worry about the row and column indexes. I wrote the formula for test file and writing the vba for the master file.
Just a minor mistake you've done.
Sheets(4).Formula = "" represents the formula applied on sheet4.Logically sheet 4 has almost million rows. Where will the formula sit?
Sheet(4).cells(row, column).Formula = ""
Here is one example i have just wrote few min back for sumif
shPivotAdjustmentsIRSPV.Cells(NumRows, NumColumns + 1).Formula =
"=Sum(" & shPivotAdjustmentsIRSPV.Cells(3, NumColumns + 1).Address &
":" & shPivotAdjustmentsIRSPV.Cells(NumRows - 2, NumColumns +
1).Address & ")"
In addition to a range, you need to use the .FormulaR1C1 property if you are going to use R1C1 references:
Sheets(4).Range("A7").FormulaR1C1 = "=IF(ISERROR(VLOOKUP(RC[7],Sheet2!R4C2:R" & Lrow2 & "C2,1,FALSE)),RC[7],HYPERLINK(CELL(""address"",INDEX(Sheet2!R4C2:R" & Lrow2 & "C2,MATCH(RC[7],Sheet2!R4C2:R" & Lrow2 & "C2,0))),RC[7]))"

Use the last row count in a formula

The following code allows me to repeat a formula from row 2 to all rows up to the last active row.
Dim LastRow As Long
With Sheets("C PUR TYPE")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("M2:M" & LastRow).formula = "=IFERROR(RIGHT(SUBSTITUTE(Lookup_concat(A2,$A$2:$A1932,$L$2:$L1932),"" 0,"",""""),LEN(SUBSTITUTE(Lookup_concat(A2,$A$2:$A1932,$L$2:$L1932),"" 0,"",""""))-2),"" - "")"
End With
In this instance there are 1'932 active rows.
Is there a way that I can replace the cell reference :$A1932 and $L1932 in the formula to using the last row count as the row count will be different each time the report runs.
Thanks
Using & will allow you to concatenate the variable into the string:
Dim LastRow As Long
With Sheets("C PUR TYPE")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("M2:M" & LastRow).formula = "=IFERROR(RIGHT(SUBSTITUTE(Lookup_concat(A2,$A$2:$A" & LastRow & ",$L$2:$L" & LastRow & "),"" 0,"",""""),LEN(SUBSTITUTE(Lookup_concat(A2,$A$2:$A" & LastRow & ",$L$2:$L" & LastRow & "),"" 0,"",""""))-2),"" - "")"
End With
Seems to me like you can use a variable similar to how you calculated lastRow.
Example (assuming you don't have any blanks in column A):
dim LookupLastrow as long
LookupLastrow=range("A1").end(xldown).row
then replace the 1932 references in your formula with " & lookuplastrow & ":
.Range("M2:M" & LastRow).formula = "=IFERROR(RIGHT(SUBSTITUTE(Lookup_concat(A2,$A$2:$A" & lookuplastrow & ",$L$2:$L" & lookuplastrow & "),"" 0,"",""""),LEN(SUBSTITUTE(Lookup_concat(A2,$A$2:$A" & lookuplastrow & ",$L$2:$L" & lookuplastrow & "),"" 0,"",""""))-2),"" - "")"