I am trying to find a way to update the subtotal at the bottom of the table so it includes newly inserted row values.
For example, in the following spreadsheet, I have a button that inserts rows at the end of a table (to add new items). This button utilizes vba. I just inserted row 4 using vba, and it is blank. However, in the subtotal line, the sum function did not change to include the new row. What can I add to the end of my VBA code to modify that sum formula to include the new row (and extend the range down by one cell)? So that whenever I use my button to add a row, it also extended the range by one cell down? (to include b4)
Example Spreadsheet
This code puts a formula in B20 based on the number of cells filled above it:
Sub Formulamaker()
Dim rng As Range
Set rng = Range(Cells(1, "B"), Cells(1, "B").End(xlDown))
Range("B20").Formula = "=SUM(" & rng.Address & ")"
End Sub
In your example the formula is inserted two cells below the data. If you always want the formula to be placed two cells below the data then:
Sub Formulamaker()
Dim rng As Range
Set rng = Range(Cells(1, "B"), Cells(1, "B").End(xlDown))
Cells(rng.Rows.Count + rng.Row + 1, "B").Formula = "=SUM(" & rng.Address & ")"
End Sub
Related
The below code does vlookup then autofills the data then applies the filter to #N/A. Here I need to do another VLOOKUP in the same column with the filter as #N/A but I am not sure about this as how do we select the cells below F1 and apply VLOOKUP on the visible data. Could you help me out with this?
Sub Vlookup()
Worksheets("error rate").Activate
Range("F2") = "=Vlookup(B2,'sales'!B:C,2,0)"
Range("F2").Select
Range("F2").AutoFill Range("F2:F" & Range("B" & Rows.Count).End(xlUp).Row)
Range("F:F").Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("B1").AutoFilter Field:=6, Criteria1:="#N/A"
Range = Rng.Offset(1).SpecialCells(xlCellTypeVisible).Cells(1, 6)
End Sub
Few things
Avoid using Activate/Select. You may want to see How to avoid using Select in Excel VBA
Define and work with objects. Becomes much easier to work with your code.
Instead of entering formula in one cell and then autofilling it, simply enter the formula in the entire range in one go as shown below.
I see the objective is to get all the values. Then there is no need to enter a formula, filter and renter the formula. Use a single nested formula using IFERROR and IF. For example, if the formula "=Vlookup(B2,'sales'!B:C,2,0)" doesn't give you the result and you want to pull up the values from say column D then use the formula =IFERROR(VLOOKUP(B2,Sales!B:C,2,0),VLOOKUP(B2,Sales!B:D,3,0)). I have simply nested VLOOKUP(B2,Sales!B:D,3,0) inside IFERROR(). What the formula does is checks if there is an error with VLOOKUP(B2,Sales!B:C,2,0) and if there is, then it attempts to find the value using VLOOKUP(B2,Sales!B:D,3,0)
CODE
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long
'~~> Set this to the relevant sheet
Set ws = ThisWorkbook.Sheets("error rate")
With ws
'~~> Find last row
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
'~~> Work with the relevant range
With .Range("F2:F" & lRow)
'~~> Enter the formula in the entire range in one go
.Formula = "=IFERROR(VLOOKUP(B2,Sales!B:C,2,0),VLOOKUP(B2,Sales!B:D,3,0))"
'~~> OPTIONAL
'~~> Instead of copy and paste as values use this.
'.Value = .Value
End With
End With
End Sub
I would like to apply a formula to a given range.
However, the number of columns are not fixed and will vary.
Screenshots to visualise what I'm doing.
Screenshot 1: I would like for the code to auto select from column C onwards, and apply the formula in the next image. The number of columns will vary as more students attempt the quiz.
Screenshot 2: This is the formula I wish to apply to the selected range. After that, I would be able to loop through the list of teachers from B31 and below one by one, copy the range of answers for each teacher's students and paste them onto Sheets 3-6 which contain the first set of results I mentioned earlier.
Sub obtainsecond()
Sheets("Question_answers").Select
Range("C31").Select
ActiveCell.Formula2R1C1 = _
"=FILTER(R[-29]C:R[-4]C[3],ISNUMBER(SEARCH(R[-1]C,R[-30]C:R[-30]C[3])))"
End Sub
One approach to solve the problem.
This approach assumes that the last column in row 1 is the last column with a student answer.
Logic:
I check the last column and get the cell reference (i.e. $H1). Then i extract only the column letter. I take the column letter and put it in the formula you want to extend.
Code:
Option Explicit
Sub obtainsecond()
Dim QA_ws As Worksheet 'Declare the worksheet as a variable
Set QA_ws = ActiveWorkbook.Worksheets("Question_answers") 'Decide which worksheet to declare
Dim lCol As Long
Dim LastColumnLetter As String
Dim lColRange As Range
QA_ws.Activate 'Go to the worksheet
lCol = QA_ws.Cells(1, Columns.Count).End(xlToLeft).Column 'Find the last column in the worksheet by checking in row 1
Set lColRange = QA_ws.Cells(1, lCol) 'Set last column to get cell reference, i.e. $H1
'MsgBox lColRange.Address(RowAbsolute:=False) ' $H1
'https://www.exceltip.com/tips/how-to-convert-excel-column-number-to-letter.html (Formula to extract letter: =SUBSTITUTE(ADDRESS(1,B2,4),1,””))
LastColumnLetter = WorksheetFunction.Substitute(lColRange.Address(RowAbsolute:=False), "1", "") 'Get column letter
LastColumnLetter = Replace(LastColumnLetter, "$", "") 'Remove prefix
QA_ws.Range("C31").Formula2 = "=FILTER(C2:" & LastColumnLetter & "27,ISNUMBER(SEARCH(C30,C1:" & LastColumnLetter & "1)))" 'Use relative formula to print in cell (original formula: =FILTER(C2:F27,ISNUMBER(SEARCH(C30,C1:F1))))
End Sub
Have data set in I11:X11 and I want to copy formulas seating I12:I12 into I13:X20 based on data contained in I11:X11.
Starting with I11, if that contains certain value lets say TEST, then want to increment row for that range to next column that is J11 and if J11 <> TEST, then copy J12:X12 to J13:X20.
Further want to skip pasting this entire logic based on flag seating in column H13:H20, for example if H13 = Y, then skip to next row.
Adding a screenshot to further explaining the issue.
Condition should start with first member in range I11:X11, if it encounters first member <> TEST till T11 , then it should start copying from that range. In this case it encountered first <> TEST member at L11, then it should copy from L12:T12 to L13:T24 and V12:X12 to V13:X13. Further this logic should work on the flag contained in column H. If this column H Contains Y,then above logic should not paste in that row, this pasting activity should go on until last value in column H starting from H13.
The condition value from I11:T11 can change between TEST and any other values, not further.
Want to achieve this on a button click using a VBA code.
Adding Code, but it limits to the fixed column H values and Fixed row values.
Sub CopyOnCondition1()
Dim sh1 As Worksheet, c As Range
Set sh1 = Worksheets("SheetNameHere") 'change the sheetname
For Each cel In sh1.Range("I11:T11")
If Not cel.Value = "TEST" Then
sh1.Range(Cells(12, cel.Column), Cells(12, 20)).Copy
sh1.Range(Cells(13, cel.Column), Cells(24, 20)).PasteSpecial xlPasteFormulas
End If
Next
For Each cel In sh1.Range("H13:H24")
If cel.Value = "Y" Then sh1.Range("I" & cel.row & ":T" & cel.row).ClearContents
Next
End Sub
enter image description here
As I could understand from the Question I think you are looking for something like this:
Sub CopyOnCondition1()
Dim sh1 As Worksheet, c As Range
Set sh1 = Worksheets("SheetNameHere") 'change the sheetname
For Each cel In sh1.Range("I11:T11")
If Not cel.Value = "TEST" Then
sh1.Range(Cells(12, cel.Column), Cells(12, 20)).Copy
sh1.Range(Cells(13, cel.Column), Cells(24, 20)).PasteSpecial xlPasteFormulas
End If
Next
For Each cel In sh1.Range("H13:H24")
If cel.Value = "Y" Then sh1.Range("I" & cel.row & ":T" & cel.row).ClearContents
Next
End Sub
First It will paste in the complete Range. Then it wo go and check if H have Y, if yes, then it will delete the formula from that row.
Currently I am using the following code to add a formula to cells in the column for a predefined range of cells. The problem is that the number of cells I need the formula in fluctuates based on how big the data set is.
Range("R9").Select
ActiveCell.FormulaR1C1 = "=IF(RC[-1]<0,""False"",""True"")"
Selection.AutoFill Destination:=Range("R9:R12000")
Range("R9:R62053").Select
What I want to do is for every cell that has a value in say column B, I want the macro to insert the formula in the corresponding cell in column C, and stop once it reaches a point where the cell in column b has no value.
The code below is based off the OP's comments. Where as, his code seems to be targeting R9:R12000"
Dim cell As Range, Target As Range
With Worksheets("Sheet1")
Set Target = .Range("B9", .Range("B" & .Rows.Count).End(xlUp))
For Each cell In Target
If cell.Value <> "" Then cell.Offset(0, -1).Formula = "=IF(RC[-1]<0,""False"",""True"")"
Next
End With
I have the example where I want to write a VBA statement which will select all data in a single column, there are no blanks in the column data. The column position will never change e.g. column A, and the data starts in row 3. However the total number of rows in the column will change regularly.
I want the system to dynamically select all the cells in column and then I can run a method against these selected pieces of data.
As an example of performing an action on your range without selecting it:
Public Sub Test()
Dim rColA As Range
With ThisWorkbook.Worksheets("Sheet1")
Set rColA = .Range(.Cells(3, 1), .Cells(.Rows.Count, 1).End(xlUp))
MsgBox "Column A range is " & rColA.Address 'Delete if you want.
rColA.Interior.Color = RGB(255, 0, 0) 'Turn the back colour red.
rColA.Cells(2, 1).Insert Shift:=xlDown 'Insert a blank row at second cell in range
'So will insert at A4.
'If the first cell in your range is a number then double it.
If IsNumeric(rColA.Cells(1, 1)) Then
rColA.Cells(1, 1) = rColA.Cells(1, 1) * 2
End If
End With
End Sub
Try
Dim LastRow as Long, sht as worksheet
Set sht = ThisWorkbook.Worksheets("My Sheet Name")
LastRow = sht.Cells(sht.Rows.Count, 1).End(xlUp).Row
sht.Range("A3:A" & LastRow).Select
Like Darren Bartrup-Cook says, you may not need to select the data, you can almost always perform actions directly which is much faster.
If your column is "isolated" meaning no other nonblank cells touch your data you can use:
Range("firstCellInYourColumn").CurrentRegion.Select
(this works the same way as Ctrl+* from keyboard)
otherwise use:
Range(Range("firstCellInYourColumn"), Range("firstCellInYourColumn").End(xlDown)).Select
both will work if there are really no blanks within your data.
You should also prepend all Range with worksheet expression, I omitted this.