I'm looking for a way to autofill my formula down to the last row in the dataset (which is variable) using a range which is also variable. I have highlighted my issue below at the bottom.
Here is the code that I have now:
Sub MissingData()
Dim LastRow As Long
Dim LastCol As Long
Set ws = Worksheets("Insert Data")
With ws
Last Row = .Cells(.Rows.Count, 1).End(xlUp).Row
Last Col = .Cells(1, .Columns.Count).End(xlToLeft).Column
'Inserting Column Header next to the last column in the data set in row 1"
.Cells(1, LastCol + 1).Value = "Header"
'Inserting Formula next ot the last column in the data set in row 2"
.Cells(2, LastCol + 1).Formula = "=iferror(AJ2,""YES"")"
End With
Dim FoundCell As Range
'Looking for the Last Row in the Dataset"
'Column A:A will always be populated with data and will be the driver
'for how many rows are in the data set"
LR = Worksheets("Insert Data").Range("A:A").End(xlDown).Row
With ws
'I set this and then called it using select because my range above
'and the location of this cell could be variable"
Set FoundCell = .Cells(2, LastCol + 1)
FoundCell.Select
'Here lies my issue. Using this syntax the formula is filled all the way
'to the last row available in Excel which is like 1 million something.
'I just need it filled to the last now that i set above"
Selection.AutoFill Destination:=Range(ActiveCell, ActiveCell.End(xlDown))
End With
End Sub
A better alternative to AutoFill is to enter the formula in the entire range in one go. Is this what you are trying?
Option Explicit
Sub MissingData()
Dim LastRow As Long
Dim LastCol As Long
Dim ws As Worksheet
Dim LastColName As String
Set ws = Worksheets("Insert Data")
With ws
'~~> Find last row
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
'~~> Find last column and add 1 to it
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column + 1
'~~> Get Column name from column number
' https://stackoverflow.com/questions/10106465/excel-column-number-from-column-name
LastColName = Split(.Cells(, LastCol).Address, "$")(1)
'~~> Add header
.Range(LastColName & 1).Value = "Header"
'~~> Add the formula in the entire range in ONE GO
' Example: Range("D2:D" & LastRow).Formula = "=IFERROR(AJ2,""YES"")"
.Range(LastColName & 2 & ":" & LastColName & LastRow).Formula = "=IFERROR(AJ2,""YES"")"
End With
End Sub
Related
I am trying to search within a specific column for a "yes" value and copy the entire row of data if present into a new sheet.
So far I copy and paste a row which doesn't include a "yes". This results in four rows of the same data pasted instead of the four I need.
Dim rng As Range, cell As Range
Dim sht As Worksheet
Set sht = Worksheets("Output")
With sht
lastRow = .Range("R" & .Rows.Count).End(xlUp).Row
End With
If lastRow < 2 Then lastRow = 2
Set rng = sht.Range("R2:R" & lastRow)
For Each cell In rng
If cell.Value = "Yes" Then
ActiveCell.EntireRow.Copy
Worksheets("Callouts").Activate
Range("A" & Rows.Count).End(xlUp).Offset(1).Select
ActiveCell.PasteSpecial Paste:=xlPasteValues
End If
Next
End Sub
First you want iterate through each row, then each cell in the row to find the "Yes". Then you want to copy the row to the new sheet. Consider:
Dim rng As Range, cell As Range
Dim targetLastRow as Range
Dim sht As Worksheet
Set sht = Worksheets("Output")
'capture last row in source
sourceLastRow = sht.Range("R" & Rows.Count).End(xlUp).Row
If sourceLastRow < 2 Then sourceLastRow = 2
'set source rng
Set rng = sht.Range("R2:R" & lastRow)
'Capture last row in target sheet
targetLastRow = Sheets("Callouts").Range("A" & Rows.Count).End(xlUp).Row
'iterate through each row in source range
For each row in rng.rows
'iterate through each cell in row
For Each cell In row
If cell.Value = "Yes" Then
cell.EntireRow.Copy
Sheets("Callouts").Cells(targetLastRow, 1).PasteSpecial Paste:=xlPasteValues
'increment target to next row
targetLastRow = targetLastRow + 1
End If
Next
Next
I want that if cell in column e is not blank but cell in column i is blank then write unregister in column i or else write what ever written in column i.
Please help - I have used below code:
Sub Simple_If()
Dim lastrow As Long
lastrow = Cells(Rows.Count, "F").End(xlUp).Row
If Range("e2:e" & lastrow).Value <> "" And Range("i2:i" & lastrow).Value = "" Then
Range("i2:i" & lastrow).Value = "unregister"
End If
End Sub
The reason your code was not working is because you can't get .value of a .range (Range("e2:e" & lastrow).Value <> ""). Instead, use a for loop to iterate through each cells value individually.
I have commented each line of the code below to help you understand what is happening.
To make this work, change SO.xlsm to the name of your workbook and 63649177 to the name of your worksheet.
Sub Simple_If()
Dim WB As Workbook ' workbook - full name of the file containing data.
Dim WS As Worksheet ' worksheet - worksheet within workbook containing data.
Dim lRow As Long ' last row - find last row containing data
Dim i As Long ' iteration - used for loop
Set WB = Workbooks("SO.xlsm") ' set the name of the workbook here
Set WS = WB.Worksheets("63649177") ' set the name of the worksheet here
lRow = WS.Cells(WS.Rows.count, "E").End(xlUp).Row ' find the last row of E in the WS object, not user defined.
Set Rng = WS.Range("E2:E" & lRow) ' set the initial range
For i = 2 To lRow ' from line 2 to the last row, repeat this loop
If WS.Range("E" & i).Value <> "" And WS.Range("I" & i).Value = "" Then ' if E contains data and I does not then
WS.Range("I" & i).Value = "unregister" ' fill cell with "unregister"
End If ' end if
Next ' cycle through next iteration of loop
End Sub
Output
Loop Through Rows
You were trying to check the values of two ranges "E2:E & LastRow" and "I2:I & LastRow" in one go, but you cannot do that. You have to loop through the rows of the ranges and check each cell i.e. "E2", "E3", "E4" ... "E" & LastRow and "I2", "I3", "I4" ... "I" & LastRow. For this task a For Next loop can used.
The 1st code is showing how it is done using Range.
The 2nd code is showing how it is done using column strings (letters) with Cells.
The 3rd code is showing how it is done using column numbers with Cells.
The 4th code is showing how you can define the column ranges (rng1, rng2) and use Cells with one parameter.
The 5th code is showing how you can define constants to store the so called 'magic' characters and later quickly access (change) them. It is also modified to be able to change the resulting column (tgtCol).
Range might seem easier, but you have to learn Cells, too, e.g. because you cannot loop through columns using Range, you have to use column numbers with Cells.
Study the first three codes closely, and you will learn the differences soon enough.
The Code
Option Explicit
Sub fillSimpleRangeVersion()
' Calculate the last non-blank cell in column "F".
Dim LastRow As Long
LastRow = Range("F" & Rows.Count).End(xlUp).Row
Dim i As Long
' Loop through the rows from 2 to LastRow.
For i = 2 To LastRow ' i will change: "2, 3, 4 ... LastRow"
' Check that current cell in column "E" is not blank and
' that current cell in column "I" is blank:
' If not E2 blank and I2 blank then,
' If not E3 blank and I3 blank then ...
' If not E & LastRow blank and I & LastRow blank then.
If Not IsEmpty(Range("E" & i)) And IsEmpty(Range("I" & i)) Then
' If true, write "unregister" to current cell in column "I".
Range("I" & i).Value = "unregister"
' The Else statement is not needed, because you only write when
' the condition is true.
Else
' If not true, do nothing.
End If
Next i
End Sub
Sub fillSimpleCellsStringsVersion() ' Column Strings E, F, I
Dim LastRow As Long
LastRow = Cells(Rows.Count, "F").End(xlUp).Row
Dim i As Long
For i = 2 To LastRow
If Not IsEmpty(Cells(i, "E")) And IsEmpty(Cells(i, "I")) Then
Cells(i, "I").Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsNumbersVersion() ' Column Numbers 5, 6, 9
Dim LastRow As Long
LastRow = Cells(Rows.Count, 6).End(xlUp).Row
Dim i As Long
For i = 2 To LastRow
If Not IsEmpty(Cells(i, 5)) And IsEmpty(Cells(i, 9)) Then
Cells(i, 9).Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsVersionWithRanges()
Dim LastRow As Long
LastRow = Cells(Rows.Count, "F").End(xlUp).Row
Dim rng1 As Range
Set rng1 = Range("E2:E" & LastRow)
Dim rng2 As Range
Set rng2 = Range("I2:I" & LastRow)
Dim i As Long
For i = 1 To rng1.Rows.Count
If rng1.Cells(i).Value <> "" And rng2.Cells(i).Value = "" Then
rng2.Cells(i).Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsExpanded()
Const FirstRow As Long = 2 ' First Row
Const LastRowCol As Variant = "F" ' The column to Calculate Last Row
Const Col1 As Variant = "E" ' Column 1
Const Col2 As Variant = "I" ' Column 2
Const tgtCol As Variant = "I" ' Target Column, the Column to Write to
' You want to write to the same column "CritCol2 = tgtCol", but if you
' want to write to another column, you can easily change "tgtCol".
Const Criteria As String = "unregister" ' Write Criteria
Dim LastRow As Long
LastRow = Cells(Rows.Count, LastRowCol).End(xlUp).Row
Dim i As Long
For i = FirstRow To LastRow
If Not IsEmpty(Cells(i, Col1)) And IsEmpty(Cells(i, Col2)) Then
Cells(i, tgtCol).Value = Criteria
Else
' The following line is only needed if "CritCol2" is different
' than "tgtCol".
Cells(i, tgtCol).Value = Cells(i, Col2).Value
End If
Next i
End Sub
I am trying to add a button, that adds a new column after the last column with values. This works.
Now I want to copy values to the new column. Values shall be copied from the last column from row 32 to the last one with a value in column A.
Right now Ihave a code for copying the whole column. How do I concentrate on the specific range?
Sub AddMeeting()
Dim ws As Worksheet
Dim lastcol As Long
Set ws = ActiveSheet
lastcol = ws.Cells(32, ws.Columns.Count).End(xlToLeft).Column
Columns(lastcol).Copy Destination:=Columns(lastcol + 1)
Range ((Cells.Columns.Count.End(xlLeft)) & Range(32)), (lastcol + 1) & Cells.Rows.Count.End(xlUp)
Application.CutCopyMode = False
End Sub
Values shall be copied from the last column from row 32 to the last one with a value in column A
Is this what you are trying?
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, lCol As Long
Dim LastColumn As String
Dim rngToCopy As Range
'~~> Set this to the relevant worksheet
Set ws = Sheet1
With ws
'~~> Find last row in Col A
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Find last column in row 32
lCol = .Cells(32, .Columns.Count).End(xlToLeft).Column
'~~> Get Column Name from column number
' https://stackoverflow.com/questions/10106465/excel-column-number-from-column-name
LastColumn = Split(Cells(, lCol).Address, "$")(1)
Set rngToCopy = .Range("A32:" & LastColumn & lRow)
Debug.Print rngToCopy.Address
With rngToCopy
'
' Do what you want here
'
End With
End With
End Sub
I have an excel sheet with a random amount of columns and rows (amount of columns/rows changes every time, as well as the location of each column) where I need to find a certain column with title "Course Info", and then use the CLEAN function on all rows / cells in that column (except for the title row ofcourse).
I have the code for the clean function:
Set Rng = ShData.Range("AB2:AB" & LastRow)
For Each cell In Rng
cell.Value = Application.WorksheetFunction.Clean(cell.Value)
Next cell
Problem here is that Rng is set to column AB, which isn't always that column. I have also made a LastRow & LastCol code to count the amount of rows and columns, but beyond this I'm stuck.
LastRow = ShData.Range(2, Rows.Count).End(xlUp).Row
LastCol = ShData.Range(1, Cols.Count).End(xlToLeft).Column
Use the WorksheetFunction.Match method to get the column number.
Option Explicit
Sub test()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim Col As Double
On Error Resume Next 'next line throws error if "Course Info" was not found
Col = Application.WorksheetFunction.Match("Course Info", ws.Rows(1), 0)
On Error GoTo 0 'always re-activate error reporting
If Col <> 0 Then 'only do it if "Course Info" was found
Dim Cell As Range
For Each Cell In ws.Range(ws.Cells(2, Col), ws.Cells(ws.Rows.Count, Col).End(xlUp))
Cell.Value = Application.WorksheetFunction.Clean(Cell.Value)
Next Cell
End If
End Sub
Here:
Option Explicit
Sub Test()
Dim Rng As Range, Col As Long, cell As Range, LastRow As Long, LastCol As Long
With ShData
LastRow = .Range(.Rows.Count, 2).End(xlUp).Row
LastCol = .Range(1, .Columns.Count).End(xlToLeft).Column
Col = .Rows(1).Find("Course Info").Column 'this is to find the column number
Set Rng = .Range(.Cells(2, Col), .Cells(LastRow, Col))
End With
For Each cell In Rng
cell = Application.WorksheetFunction.Clean(cell)
Next cell
End Sub
I have made a macro that copies two dynamic table columns from one worksheet to another. On the Second worksheet I want to subtract those two columns and paste the result on a separate column/vector. All of this needs to be dynamic since I plan on running the macro once a day.
The closest I have come is the following code:
Sub Makro2()
Dim ws_3 As Worksheet
Set ws_3 = ThisWorkbook.Worksheets(2)
Application.CutCopyMode = False
ws_3.Range("E3:E400").FormulaR1C1 = "=RC[-2]-RC[-1]"
End Sub
So all I need in reality is for E3:E400 to be dynamic since the range of the other two columns change every day.
PS. Rather new at VBA.
This is just basic, ensure you declare your variable.
Dim lRow As Long
lRow = Range("D" & Rows.Count).End(xlUp).Row
Range("E3:E" & lRow).FormulaR1C1 =
You could try:
Option Explicit
Sub test()
Dim wsSource As Worksheet, wsDestination As Worksheet
Dim LastRow1 As Long, LastRow2 As Long, rng1 As Range, rng2 As Range, LastColumn As Long
With ThisWorkbook
Set wsSource = .Worksheets("Sheet1") '<- Data appears here
Set wsDestination = .Worksheets("Sheet2") '<- Data will be copy here
End With
With wsSource
'Let's say the two columns we want to copy is column A & B. Find Last row of A & B
LastRow1 = .Cells(.Rows.Count, "A").End(xlUp).Row
LastRow2 = .Cells(.Rows.Count, "B").End(xlUp).Row
'Create the ranges you want to copy
Set rng1 = .Range("A1:A" & LastRow1)
Set rng2 = .Range("B1:B" & LastRow2)
End With
With wsDestination
'Paste column after the last column of row 1. Find last column row 1
LastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
rng1.Copy
.Cells(1, LastColumn + 1).PasteSpecial xlPasteValues
rng2.Copy
.Cells(1, LastColumn + 2).PasteSpecial xlPasteValues
End With
Application.CutCopyMode = False
End Sub