VBA insert a formula to add value of cell to another - excel

Im trying and failing to create a VBA formula for a command button which will take the value of cell S2 and add it with the value of the last cell of column G (this column is constantly being added to therefor making the row different each time). I want to place the result in the last cell of column I (again it is always being added to).
Help would be gratefully received, many thanks

This code would do that, you just need to have your command button run this sub:
Sub pasteLast()
Dim lrowG, lrowi As Integer
lrowG = Cells(Rows.Count, 7).End(xlUp).Row
lrowi = Cells(Rows.Count, 9).End(xlUp).Row
Cells(lrowi, 9).offset(1,0) = Range("s2") + Cells(lrowG, 7)
End Sub
just be careful because every time you click the button, it will add a value to column I whether it's unique or not. This would be better handled with a
Sub Worksheet_Change
event, where anytime S2 was changed it would add its value to column I.

Sounds like you need to find the last cell reference in column G, then go to 1 row past the last cell reference in column I, and as the cell reference in column G to S2.
This should work:
Sub addToI()
Dim gTarget As String
Range("G1").Select
Selection.End(xlDown).Select
gTarget = Selection.Address(ReferenceStyle:=xlR1C1)
Range("I1").Select
Selection.End(xlDown).Select
Selection.Offset(1, 0).Select
ActiveCell.FormulaR1C1 = "=" & gTarget & "+R2C19"
End Sub

Related

Use of ' in offset

I have some code, can someone explain how it works and why it works that way? Specifically this line of code:
With Sheets("Sheet2")
.Cells(1, 1).End(xlDown).Offset(1).Value = Format(Date, "dd/mm/yyyy")
Now I get it that the code itself outputs the date in Cells(1,1) and offsets by 1 from the bottom for every subsequent entry. What I don't understand is why in the sheet itself one of the cells is blocked out?
And then the code works fine. But if cell A2 doesn't have '-------- it suddenly doesn't work anymore and gives me Application defined, object defined error. Can someone explain what '-------- does here and why its used?
The idea of the code is: "Jump to the last row that is used in column A, go down 1 row and write the date into it.
What it does:
Go (virtually) to cell A1 and press (also virtually) the key Ctrl+Down. This jumps to the last used cell of a column - but only if there is more than one cell filled, else it will jump to the very last row of the sheet (try this in Excel to understand).
Now if you offset one row from the very last row of a sheet, Excel cannot do anything more than complain.
The solution: Use .Cells(.rows.count, 1).End(xlUp) instead. This works the opposite way: Go to the very last row and press Ctrl+Up. For more details how to find the last used cell, see
Error in finding last used cell in Excel with VBA
What you also should do:
Don't cascade things, use intermediate variables, that helps debugging.
Don't write a date as string (format converts a date into a string). Write the date as date and set the number format of the cell.
With Sheets("Sheet2")
Dim lastCell as Range
Set lastCell = .Cells(.rows.count, 1).End(xlUp)
lastCell.Offset(1).Value = Date
' If needed:
' lastCell.Offset(1).NumberFormat = "dd/mm/yyyy"
End With
When there is no value in A2, it will give you an error because End(xlDown) from A1 will take you to the last cell A65536 in Excel 2003 and A1048576 in Excel 2007+. It is like selecting cell A1 and manually pressing the End key and then the Down arrow key. And of course you can't offset down from the last cell and hence you are getting the Error 1004 - Application-defined or Object-defined error.
I recommend using xlUp to find the last row and then enter the data as shown HERE
Here is an example
Dim lRow As Long
With Sheets("Sheet2")
lRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
.Cells(lRow, 1).Value = Format(Date, "dd/mm/yyyy")
End With

How to flash fill a formula in Excel using a formula

I'm self taught in VBA and wasn't able to decipher the other answers to this question. I have a formula in J6 that I want to fill down to the end of the data.
I have the following code:
Range("j6").Select
ActiveCell.FormulaR1C1 = "=IFERROR(VLOOKUP(RC[-9],R5C14:R6C15,2,FALSE),2)"
Range("J6").Select
Range("J6").AutoFill Destination:=Range("J6:J" & Cells(Rows.Count, "I").End(xlDown).Row)
I thought this would count the rows in column I with data and then fill down that far but it flash fills all the way down.
Range("j6").Select
ActiveCell.FormulaR1C1 = "=IFERROR(VLOOKUP(RC[-9],R5C14:R6C15,2,FALSE),2)"
Range("J6").Select
Range("J6").AutoFill Destination:=Range("J6:J" & Cells(Rows.Count, "I").End(xlDown).Row)
I would like the formula to flash fill to the end of the data set.
Scott Craner's one line fix in the comment above works. The code I'm posting below is not a one line solution, rather it separates the 'applying of the formula' from the defining / finding of the bottom row of column J.
Sub Formuala()
Dim LastRow As Long
'code below finds that last cell in Column J so the formula can be applied from J6 down
'to this "LastRow" which can be different each time the macro is run
LastRow = Worksheets("Sheet1").Range("J" & Rows.Count).End(xlUp).Row
'Code below place the formula on the sheet for the J6 to J"LastRow" range
Worksheets("Sheet1").Range("J6:J" & LastRow).FormulaR1C1 = "=IFERROR(VLOOKUP(RC[-9],R5C14:R6C15,2,FALSE),2"
End Sub
Be sure to change Sheet1 in my code to whatever your worksheet is named.
Good luck and welcome to the site!

VBA User Form - Need it to copy formula from column F, 1 row above

I have a form I made for users to enter data. The data get's inserted into the next available row. That works well, but now I need the formula from the cell above in Column F to be copied into the new cell. Is there a code I could use this to work along with the copying of the input values to the sheet?
Any help with this would be greatly appreciated.
Edit: Method 2 is probably better suited for your purpose as it will adapt the cell references in the previous line to the next line.
Method 1: To set the formula of a cell, use
Sheets("sheet name").cells(row, column).Formula = ....
Row and column must be specified as integer values, I.e. For column F it would be 6. Assuming you have the number of the next free line in a variable called NextFreeLine:
Sheets("sheet name").cells(NextFreeLine, 6).Formula = Sheets("sheet name").cells(NextFreeLine-1, 6).Formula
Method 2: If you insist on literally copying the formula from somewhere else, try this (this will adapt the cell references of the formula for the previous line to the next one-- just like copy/pasting it using Ctrl-C, Ctrl-V):
Sheets("sheet name").cells(NextFreeLine-1, 6).Copy
Sheets("sheet name").cells(NextFreeLine, 6).PasteSpecial Paste:=xlPasteFormulas
The method you are using to put into 'the next available row' would have been nice to see but perhaps you can translate this for your own purposes.
'put the newval into the next available cell in column A
cells(rows.count, 1).end(xlup).offset(1, 0) = newval
'copy the formula in column F to the new row
cells(rows.count, 1).end(xlup).offset(-1, 5).resize(2, 1).filldown
Your value goes into the next available row based on column A. The same column is used in much the same manner but offset up a row and resized to two rows in height before executing the fill down command.

Excel formula in VBA code

So, in Sheet1 I have base of some names and it looks like this:
In Sheet2 I'm working with these names from Sheet1. I'm doing that in a way that I'm entering Code value in column A and in column B I get the Name, in column C I get the Last Name. That looks like this:
I've done this with formulas, entering it in the formula bar. For column A(or Name) I've used this formula: =IFERROR(VLOOKUP(A2;Sheet1!A:C;2;FALSE);"") and for column B(or Last Name) I've used this one: =IFERROR(VLOOKUP(A2;Sheet1!A:C;3;FALSE);""). I've dragged these formulas to row 20 and it works great.
Now, what I'd like to do is to put these formulas into Excel VBA code and them to work for noted range. I've just started to use VBA and I don't know how to do it in it, tried something but doesn't work, ..., I've done this so far. I'm new to this Excel/Macro/VBA thing so any help would be appreciated.
The below code will work if you type in your Code values in sheet2 and highlight them, and run this macro:
Selection.Offset(0, 1).FormulaR1C1 = "=IFERROR(VLOOKUP(RC[-1],Sheet1!C[-1]:C,2,FALSE),"""")"
Selection.Offset(0, 2).FormulaR1C1 = "=IFERROR(VLOOKUP(RC[-2],Sheet1!C[-2]:C,3,FALSE),"""")"
Selection.Offset(0, 1).Value = Selection.Offset(0, 1).Value
Selection.Offset(0, 2).Value = Selection.Offset(0, 2).Value
Edit: If you are wanting to update values as you type use (thank you #PeterAlbert for added optimisation!):
Private Sub Worksheet_Change(ByVal Target As Range)
'end if the user made a change to more than one cell at once?
If Target.Count > 1 Then End
'stop system activating worksheet_change event while changing the sheet
Application.EnableEvents = False
'continue if column 1(A) was updated
'and
'dont continue if header or row 1 was changed
If Target.Column = 1 And Target.Row <> 1 Then
With Target.Offset(0, 1) 'alter the next cell, current column +1 (column B)
'RC1 = current row and column 1(A) e.g. if A2 was edited, RC1 = $B2
'C1:C2 = $A:$B
.FormulaR1C1 = "=IFERROR(VLOOKUP(RC1,Sheet1!C1:C2,2,FALSE),"""")"
.Value = .Value 'store value
End With
With Target.Offset(0, 2) 'alter the next cell, current column +2 (column C)
'C1:C3 = $A:$C
.FormulaR1C1 = "=IFERROR(VLOOKUP(RC1,Sheet1!C1:C3,3,FALSE),"""")"
.Value = .Value 'store value
End With
End If
Application.EnableEvents = True 'reset system events
End Sub
Explinatioin of RC:
The FormulaR1C1 formula types are good to use when referencing a cell with respect to the current cell. There a few rules to remember:
The R stands for Row and C is for Column and the integer after it, if any, defines the row or column;
As a basis the RC formula references itself;
Any number following the R or C wraped in [] is an offset to itself, e.g. if you are in cell A1 and use R[1]C[1] you would be referencing cell B2;
Also any number following the R and C is an exact, e.g. if you reference R2C2 no matter the cell you are in would also point to B2; and
To complicate things if you were in cell C5, e.g. using Range("C5").FormulaR1C1 = and coded the follwing:
"=RC[-1]" references cell B5
"=RC1" references cell A5, more rightly $A5
"=R[1]C[-2]" references cell A6
"=Sum(C[-1]:C5)" is =Sum(B:E), more rightly =Sum(B:$E)
If I understand your question and comments correctly, you want to ensure that columns B&C always show you the right values based on your formula, but also want to protect (and maybe even hide the formula) from the users.
I'd suggest you use sheet protection instead: all you need to do is to unlock the cells you want the users to edit, i.e. select column A and in the _ Format cells_ dialog uncheck "Locked" in the Protection tab. Similarly for columns B&C, check "Hidden". Now right click the sheet name and select Protect Sheet. Once this is done, the user can edit column A - but will not see the formula in B&C and cannot edit those cells.
If for some reasons you need to ensure this in VBA, use the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False 'to prevent endless loop
With Target.Offset(, 2 - Target.Column).Resize(, 2)
.FormulaR1C1 = "=IFERROR(VLOOKUP(RC1,Sheet1!C1:C3,COLUMN(RC),0),"""")"
.Value = .Value
End With
Application.EnableEvents = True
End Sub
You need to place this in the module of the worksheet.

adding new rows in excel without breaking a vba macro that uses Range.Value

I've written a macro in VBA that simply fills in a given cell's value from another cell in that sheet. I do this for lots of cells in the sheet, and I'm doing it like so:
Range("B3").Value = Range("B200")
Range("B4").Value = Range("B201")
'etc.
Now, I am often adding values by inserting new rows, so I might insert a new row
between B200 and B201, which will break the macro because it doesn't autoupdate when
I insert the new row.
How can I code the macro so it autoupdates the cell references when I insert new rows or columns?
My suggestion would be to make sure the ROW you want to retrieve values from has a unique value in it that you can .FIND anytime you want, then grab your values from column B of that found cell's row. So right now you want to get a value in B200 and A200 always has the text in it: "Final Total" and that is unique.
Dim MyRNG As Range
Set MyRNG = Range("A:A").Find("Final Total", LookIn:=xlValues, LookAt:=xlWhole)
Range("B3").Value = Range("B" & MyRNG.Row)
Range("B4").Value = Range("B" & MyRNG.Row + 1)
This is not an answer but an alternative.
Naming your range is the way to go as Shiin suggested but then if you have 500 cells then like I mentioned earlier, naming 500 cells and using them in your code can be very painful. The alternative is to use smart code. Let's take an example
Let's say you have a code like this
Sub Sample()
Range("B3").Value = Range("B200")
Range("B4").Value = Range("B201")
Range("B5").Value = Range("B201")
' And
' So On
' till
Range("B500").Value = Range("B697")
End Sub
The best way to write this code is like this
Sub Sample()
Dim i As Long
For i = 200 To 697
Range("B" & i - 197).Value = Range("B" & i)
Next i
End Sub
and say if you insert a line at say row 300 then simply break the above code in two parts
Sub Sample()
Dim i As Long
For i = 200 To 299
Range("B" & i - 197).Value = Range("B" & i)
Next i
For i = 301 To 698
Range("B" & i - 197).Value = Range("B" & i)
Next i
End Sub
So every time you insert a row, simply break the for loop into an extra part. This looks tedious but is much better than naming 500 cells and using them in your code.
If you are planning to use the macro only once (i.e for 1 time use) then read ahead.
If you are worried that when the user inserts the row then the cells are not updated then you can instead of assigning a value, assign a formula.
For example
Range("B3").Formula = "=B200"
This will put a formula =B200 in cell B3. So next time when you insert a row so that the 200th row moves it's position, you will notice that the formula automatically gets updated in cell B3
HTH
Try giving a name to the range. If you refer to the range by name Excel searches for it and retrieves the rows that defines it. Range names update their definition when new rows are added.
Adding to the above, i think this tutorial illustrates my point:
http://www.homeandlearn.co.uk/excel2007/excel2007s7p6.html this is how to define the name of the range.
This tutorial explains how to use it on macros and vba:
http://excel.tips.net/T003106_Using_Named_Ranges_in_a_Macro.html
I hope this helps :D

Resources