get the differences between 2 Integer columns into third column - excel

I have to calculate the difference between the values of 2 columns(firstCol and lastCol) and set those differences in a different column(NextColumn). The row count keeps changing, so I have to calculate the rowCount before calculating the difference. I'm trying to write a loop using Range so that the difference can be calculated but it doesn't seem to work.
For i = 3 To lastRow
Range(Cells(3, NextColumn), Cells(lastRow, NextColumn)).FormulaR1C1 = "=Range(Cells(i, firstCol),Cells(i,firstCol)).Value - Range(Cells(i, lastCol),Cells(i,lastCol)).Value"
Next i
Any help would be greatly appreciated!
Thank you
Nick

For any input of "i" into the formula, you need to use " & i & " when using using a formula="", such as:
"=A" & i & "+B" & i
When you change to just a formula that doesn't input a formula to the cell (math happens in VBA), you can ignore the Excel formatting and "" blocking, such as:
= Cells(i,"A").Value + Cells(i,"B").Value
Make sure to use your loop variable where appropriate, so that you would have an outcome in a loop like:
Dim i as Long
For i = 1 to 10
Cells(i,"C").Formula = Cells(i,"A").Value + Cells(i,"B").Value
Next i

Why looping ? Unless I misunderstood the question, something like this should do the trick:
Range("X3:X"& lastrow).Formula = "=C3-D3"
The formula will adjust.

vba needs to be outside the quotes and you do not need the loop:
Range(Cells(3, NextColumn), Cells(lastRow, NextColumn)).Formula = "=" & Cells(3, firstCol).Address(0, 0) & "-" & Cells(3, lastCol).Address(0, 0)
No loop needed. Excel will change the relative references as needed.

Related

Compute countif in column Range & combine if with count if

I have two formulas that I need to transfer to VBA.
On Excel, my formula would be =countif(A$2:A2,A2) so I transferred that using this formula but everything is returning to 1. The rows didn't become dynamic and I want only the values to be displayed.
For a = 2 To lrow
ws.Range("T" & a).Formula = "=CountIf(A$2&"":""&A2)"",""&A2)"
Next a
Next formula that I use in Excel is
=IF(COUNTIF(A:A,A2)>Q2,"Check","Ok")
I tried this formula in VBA:
For i = 2 to lrow
If Countif(ws.Range("A2:A" & lrow), "A2") > ws.Range("Q2:Q", & lrow) Then
ws.Range("T" & i).Value = "Check"
Else
ws.Range("T" & i).Value = "Ok"
End If
Next i
You could populate column T with your first formula with this line of code:
ws.Range("T2:T" & lrow).FormulaR1C1 = "=COUNTIF(R2C[-19]:RC[-19],RC[-19])"
I can't advise on your second formula unless you clarify where you want to write it...

Can you explain how this line of code work (worksheet function)

Hello I'm new to vba and I have a project which at first seems quite simple but when I started to look at the range references I was totally lost. The Goal is to make a sum of multiple columns with one or two criterias.
For j = 9 To 12
For i = 3 To 6
datecol = 3
Cells(i, j).FormulaR1C1 = "=SUMIFS(R3C" & datecol & ":R" & Lastrow2 & "c" & datecol & ", R3C2:R" &
Lastrow2 & "C2, R" & i & "C8"
Next i
datecol = datecol + 1
Next j
End sub
What I have understand is that Cells(i,j) is where the output of my formula will be write.
.FormulaR1C1 return the formula as a string in the cell (i,j) -I think this is why we have ="=sumifs()-
Then we have SUMIFS(R3C" & datecol & ":R" & Lastrow2 & "c" & datecol & ") but what ":R", "c", & " mean ?
I know that this argument is the range use by the formula to make the sum but I don't understand the way ranges are referenced, and I have the same question for R3C2:R" "C2, R".
Help would be very appreciated, thank you.
Review and Suggestions
What do :R, c, & mean ?
In the context of R1C1 style R means row and C column. The & is a concatenation operator used to join the values ​​of two variables or constants. Very common used to create String variables.
For the macro you are trying to code you don't need to complicate yourself with .FormulaR1C1 use .Formula instead.
The line datecol = datecol + 1 is useless because datecol = 3 is inside the loop, so datecol will go back to 3 everytime the macro is looping. To solve this, datecol = 3 should be outside the loop.
When working with VBA is better to use functions that are meant to be runned in VBA and not in Excel, unless you wish to insert Excel formulas in cells. For instance the SUMIF function in VBA is: application.worksheetfunction.sumif(range,criteria,sum_range) Example of use: SumIfResult = Application.WorksheetFunction.SumIf(Range("A1:A10"), "In", Range("B1:B10"))
Descriptive Variables: use name or letters for your variables that describe them. It is easy to write software that works satisfactory. But it is very hard to write reliable, understandable and maintainable code. One important aspect is using good variable and function names. For instance, in the code below I changed the variables i and j for col and row_number.
I don't really get what you are trying to do, but I modified a little bit your code so you can maybe take some useful ideas.
Sub sum_columns()
'descriptive variable examples
Dim col As Long
Dim row_number As Long
Dim date_col As Long
Dim last_row2 As Long
date_col = 3
For col = 9 To 12
For row_number = 3 To 6
'this looks very complicated try to code it as simple as possible
'Cells(i, j).FormulaR1C1 = "=SUMIFS(R3C" & datecol & ":R" & Lastrow2 & "c" & datecol & ", R3C2:R" & Lastrow2 & "C2, R" & i & "C8"
'example
Cells(row_number, col).Formula = "=SUMIF(D" & row & ":D" & row + 3,">100)"
'another idea
Cells(row_number, col) = _
Application.WorksheetFunction.SumIf(Range("A1:A10"), "In", Range("B1:B10"))
Next row_number
date_col = date_col + 1
Next col
End Sub
Note
The code above is ONLY meant for explanation purposes (concepts, examples and ideas) NOT for executing it.

Dynamic column as a criterion in sumif function

Basically, i am trying to use sumif function in vba. Instead of using fixed rows and columns, i am trying to make everything dynamic. here is the code i wrote to accomplish the task but failed.
sh.Range("V" & StartRowData + j).Value = Application.WorksheetFunction.SumIf _
(MettBeheer.Range("A1", "A" & LastRowMettBeheer), sh.Range("A" & StartRowData + j).Value, MettBeheer.Range("K1", "K" & LastRowMettBeheer))
the first two parameter of the function are ok. this part of the code Range("K1", "K" & LastRowMettBeheer) where i want to make it dynamic. instead of a fixed k range, it could be from a to end of the used columns in the sheet based on the criteria give from this code sh.Range("A" & StartRowData + j).Value
any suggestion or help is highly appreciated?

WorksheetFunction.AverageIf of a range to include condition based on cell.interior.color

I am trying to find the average of a column with undefined number (i) of values (range is likely to be between 3-20 cells in column I, row 24 up to undefined number - j = 23 + i). The code previously included only the standard average function.
Now, I'd like it to average those cells in the give range, only including those cells in the proposed range. Hence, ignoring the identified outliers that are above and/ or below LFe, UFe. Location of that averaged value is Range("E" & m).
Is this even possible in the given worksheetfunction? And if so, what do I need to change to get this working?
I have tried to use existing solutions based on conditions such as 'average only cells that are positive' or 'only those that do not include N/A', but can't seem to get it working.
'Identifying outliers based on interquartile range
qe1 = Application.Quartile(Range("E24:E" & j), 1)
qe3 = Application.Quartile(Range("E24:E" & j), 3)
IQRe = qe3 - qe1
UFe = qe3 + (IQRe * 1.5)
LFe = qe3 - (IQRe * 1.5)
'[EDIT] Currently I have it as follows:
Range("E" & m).Value = Application.WorksheetFunction.AverageIfs(Range("E24:E" & j), "<" & UFe, Range("E24:E" & j), ">" & LFe, Range("E24:E" & j))
Which returns: #VALUE! without the .WorksheetFunction, and 'run error '424' Object required' as written above.
The only option that functioned, BUT not with my variable ranges is formatting it similarly as following: (How can this otherwise be adapted to work for my variable ranges, including 'j' etc.?)
Range("E" & m).Select
ActiveCell.FormulaR1C1 = "=AVERAGEIF(R[-6]C[4]:R[-3]C[4],"">""& 4.3,R[-6]C[4]:R[-3]C[4])"
Not enough rep to comment (sorry!), but here are a few ideas I had:
1) As SJR has mentioned, if there is a numeric value you're basing the color-coding from, you can use that in your code instead of a color. I'm thinking UFe & LFe are the upper and lower thresholds. So you could just have cells with formulas to automate the UFe & LFe via formulas instead and then use "AVERAGEIFS".
2) Alternatively, you could integrate your variables into a ".formula" instead, like:
Sheet1.Range("E" & m).Formula = "=AVERAGEIFS($E$24:$E$" & j & ",$E$24:$E$" & j & ","">" & LFe & """,$E$24:$E$" & j & ",""<" & UFe & """)"
Just change "Sheet1" to whatever sheet you're referencing

Create new Excel rows based on column data

Good afternoon all,
I have an issue where I have users who have multiple bank account details. I need to try and create a new row for each employee who has more than one bank account, with the second bank account being allocated a new row.
Employee Number User ID BSB Account number
10000591 WOODSP0 306089,116879 343509,041145273
10000592 THOMSOS0 037125 317166
I need it to look something like this:
Employee Number User ID BSB Account number
10000591 WOODSP0 306089 343509
10000591 WOODSP0 116879 041145273
10000592 THOMSOS0 037125 317166
Any thoughts? Your input is greatly appreciated!
Screenshots are here to demonstrate:
Right click on the tab and choose "View Code"
Paste this code in:
Sub SplitOnAccount()
Dim X As Long, Y As Long, EmpNo As String, UserID As String, BSB As Variant, AccNo As Variant
Range("F1:I1") = Application.Transpose(Application.Transpose(Array(Range("A1:D1"))))
For X = 2 To Range("A" & Rows.Count).End(xlUp).Row
EmpNo = Range("A" & X).Text
UserID = Range("B" & X).Text
BSB = Split(Range("C" & X).Text, ",")
AccNo = Split(Range("D" & X).Text, ",")
For Y = LBound(AccNo) To UBound(AccNo)
Range("F" & Range("F" & Rows.Count).End(xlUp).Row).Offset(1, 0).Formula = EmpNo
Range("G" & Range("G" & Rows.Count).End(xlUp).Row).Offset(1, 0).Formula = UserID
Range("H" & Range("H" & Rows.Count).End(xlUp).Row).Offset(1, 0).Formula = BSB(Y)
Range("I" & Range("I" & Rows.Count).End(xlUp).Row).Offset(1, 0).Formula = AccNo(Y)
Next
Next
End Sub
Close the window to go back to excel
Press ALT-F8
Choose SplitOnAccount and click run.
Note, this is going to populate the split data to rows F to I, make sure there is nothing in there. If there is post back and we can change it.
Also format columns F - I as text before you run it or Excel will strip leading zeros off as it will interpret it as a number.
Here is another sub that appears to perform what you are looking for.
Sub stack_accounts()
Dim rw As Long, b As Long
Dim vVALs As Variant, vBSBs As Variant, vACTs As Variant
With ActiveSheet '<-define this worksheet properly!
For rw = .Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
vVALs = .Cells(rw, 1).Resize(1, 4).Value
vBSBs = Split(vVALs(1, 3), Chr(44))
vACTs = Split(vVALs(1, 4), Chr(44))
If UBound(vBSBs) = UBound(vBSBs) Then
For b = UBound(vBSBs) To LBound(vBSBs) Step -1
If b > LBound(vBSBs) Then _
.Rows(rw + 1).Insert
.Cells(rw - (b > LBound(vBSBs)), 1).Resize(1, 4) = vVALs
.Cells(rw - (b > LBound(vBSBs)), 3).Resize(1, 2).NumberFormat = "#"
.Cells(rw - (b > LBound(vBSBs)), 3) = CStr(vBSBs(b))
.Cells(rw - (b > LBound(vBSBs)), 4) = CStr(vACTs(b))
Next b
End If
Next rw
End With
End Sub
I was originally only going to process the rows that had comma delimited values in columns C and D but I thought that processing all of them would allow the macro to set the Text number format and get rid of the Number as text error warnings and keep the leading zero in 041145273.
        
You Can definitely use Power Query to transform the data to generate new rows using split column option.
Check this article it explains the process in detail.
Load Data in Power Query section of excel.
Create an Index (Not required step)
Use Split column function with advance options and split them into new rows.
Save this result into new table for your use.
I did it myself and it worked like a charm.
A formula solution:
Delimiter: Can be a real delimiter or an absolute reference to a cell containing only the delimiter.
HelperCol: I have to use a helper column to make it work. You need to give the column letter.
StartCol: The column letter of the first column containing data.
SplitCol: The column letter of the column to be splitted.
Formula1: Used to generate the formula for the first column not to be splitted. You can fill this formula down and then fill to right.
Formula2: Used to generate the formula for the column to be splitted(only support split one column).
Formula3: Used to generate the formula for the Helper column.
(If the title of the column to be splitted contains the delimiter, you must change the first value of the helper column to 1 manually.)
Formula1:=SUBSTITUTE(SUBSTITUTE("=LOOKUP(ROW(1:1),$J:$J,A:A)&""""","$J:$J","$"&B2&":$"&B2),"A:A",B3&":"&B3)
Formula2:=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE("=MID($M$1&LOOKUP(ROW(A1),$J:$J,F:F)&$M$1,FIND(""艹"",SUBSTITUTE($M$1&LOOKUP(ROW(A1),$J:$J,F:F)&$M$1,$M$1,"&"""艹"",ROW(A2)-LOOKUP(ROW(A1),$J:$J)))+1,FIND(""艹"",SUBSTITUTE($M$1&LOOKUP(ROW(A1),$J:$J,F:F)&$M$1,$M$1,""艹"",ROW(A2)-LOOKUP(ROW(A1),$J:$J)+1))-FIND(""艹"",SUBSTITUTE($M$1&LOOKUP(ROW(A1),$J:$J,F:F)&$M$1,$M$1,""艹"",ROW(A2)-LOOKUP(ROW(A1),$J:$J)))-1)&""""","$M$1",IF(ISERROR(INDIRECT(B1)),""""&B1&"""",B1)),"$J:$J","$"&B2&":$"&B2),"F:F",B4&":"&B4)
Formula3:=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE("=SUM(E1,LEN(B1)-LEN(SUBSTITUTE(B1,$H$1,"""")))+1","B1",B4&1),"$H$1",IF(ISERROR(INDIRECT(B1)),""""&B1&"""",B1)),"E1",B2&1)
Helper must filled one row more than the data.
How to use:
Copy the formula generated by the above three formula.
Use Paste Special only paste the value.
Make the formula into effect.
Fill the formula.
Bug:
Numbers will be converted to Text. Of course you can remove the &"" at the end of the formula, but blank cells will be filled with 0.
ps. This method may by very hard to comprehend. But once you master it, it can be very useful to solve relative problems.

Resources