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
Related
I have been trying to create a function which checks that if Col"B" <> Empty then copy the third cell which is under the same row.
I have this Data:
Where from i want to copy the Col"D" highlighted cells and paste them into same row where Col"B" <> empty.
Here is the final result. Your help will be appreciated in this regards.
Option Explicit
Sub CopyPasting()
Dim ws As Worksheet
Dim r As Long
Dim LastRow As Long
Dim n As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
LastRow = .Range("D" & .Rows.Count).End(xlUp).Row
For r = LastRow To 2 Step -2
If .Cells(r, "B") <> "" Then
.Rows(r + "D").Copy
.Rows(r + "D").PasteSpecial
n = n + 1
End If
Next
End With
End Sub
Please, try the next code:
Sub testRetOffset3()
Dim sh As Worksheet, lastR As Long, rngV As Range, rngFin As Range, c As Range
Set sh = ActiveSheet 'use here the sheet you need
lastR = sh.Range("B" & sh.rows.count).End(xlUp).row 'last sheet row
On Error Resume Next 'if not empty cells in column, it will not return the range and raise an error
Set rngV = sh.Range("B2:B" & lastR).SpecialCells(xlCellTypeConstants)
On Error GoTo 0
If rngV Is Nothing Then Exit Sub 'stop the code if run on a wrong sheet, without empty cells in column B:B
For Each c In rngV.cells 'iterate between the discontinuous range cells
If rngFin Is Nothing Then 'if the final range is not set (first time)
Set rngFin = c.Offset(3, 2) 'set the range = the Offset necessary cell
Else
Set rngFin = Union(rngFin, c.Offset(3, 2)) 'make a Union between existing range and the Offset necessary cell
End If
Next
If Not rngFin Is Nothing Then 'copy both ranges in consecutive columns
rngV.Copy sh.Range("F2")
rngFin.Copy sh.Range("G2")
End If
End Sub
It will return in columns F:G, starting from the second row. It is easy to modify the range where to return...
You can even clear the existing processed columns and return in B:C, or in another sheet.
Edited:
In order to solve the last request, please use the next code:
Sub testRetOffsetMoreRows()
Dim sh As Worksheet, lastR As Long, rngV As Range, rngFin As Range, A As Range
Set sh = ActiveSheet
lastR = sh.Range("B" & sh.rows.count).End(xlUp).row
On Error Resume Next
Set rngV = sh.Range("A2:D" & lastR).SpecialCells(xlCellTypeConstants)
On Error GoTo 0
If rngV Is Nothing Then Exit Sub
For Each A In rngV.Areas 'iterate between the range areas
If rngFin Is Nothing Then
Set rngFin = A.cells(1,2).Offset(3, 3) 'use the second cell of the area
Else
Set rngFin = Union(rngFin, A.cells(1,2).Offset(3, 3))
End If
Next
If Not rngFin Is Nothing Then
rngV.Copy sh.Range("H2")
rngFin.Copy sh.Range("L2")
End If
End Sub
But take care to have continuous ranges when have a value in column B:B. Otherwise, the code may fail... The areas property will return differently.
I wasn't sure where you wanted the output, this will put it into a sheet called "Sheet2". (You'll have to make that before running the code it won't create it for you.)
Dim i As Long
Dim j As Long
Dim lr As Long
Dim srcWS As Worksheet
Dim destWS As Worksheet
Set srcWS = ThisWorkbook.Sheets("Sheet1")
Set destWS = ThisWorkbook.Sheets("Sheet2")
With srcWS
lr = .Cells(.Rows.Count, 4).End(xlUp).Row
j = 2
For i = 2 To lr
If .Cells(i, 2).Value <> "" Then
destWS.Cells(j, 1).Value = .Cells(i, 2).Value
destWS.Cells(j, 2).Value = .Cells(i, 4).Offset(2, 0).Value
j = j + 1
End If
Next i
End With
If you need the colors copied over as well then use this:
.Cells(i, 4).Offset(2, 0).Copy
destWS.Cells(j, 2).PasteSpecial xlPasteAll
instead of:
destWS.Cells(j, 2).Value = .Cells(i, 4).Offset(2, 0).Value
I have been trying to copy the first highlighted row of each new data after empty row and i have looked around to find a way which could do this but cannot find.
I can do this manually by putting name of rows to copy but code should be dynamic because rows order can be changed but there must be empty rows after new data.
Any help will be appreciated.
after copying and pasting the result would be like this.
My try
Sub copynextfirstrow()
lastRow = Sheets("Sheet1").Cells(.Rows.Count, "A").End(xlUp).Row
Sheets("Sheet1").Range("A1:A" & lastRow).Copy
Sheets("Sheet2").Range("A1").Cells.PasteSpecial
End Sub
Try the next code, please:
Sub copynextfirstrow()
Dim sh1 As Worksheet, sh2 As Worksheet, lastRow As Long, i As Long, rngCopy As Range
Set sh1 = Sheets("Sheet1")
Set sh2 = Sheets("Sheet2")
lastRow = sh1.cells(sh1.rows.count, "A").End(xlUp).row
For i = 1 To lastRow
If WorksheetFunction.CountA(sh1.rows(i)) = 0 And WorksheetFunction.CountA(sh1.rows(i + 1)) > 0 Then
If rngCopy Is Nothing Then
Set rngCopy = sh1.rows(i + 1)
Else
Set rngCopy = Union(rngCopy, sh1.rows(i + 1))
End If
ElseIf i = 1 And WorksheetFunction.CountA(sh1.rows(i)) > 0 Then
Set rngCopy = sh1.rows(i)
End If
If Not rngCopy Is Nothing Then
rngCopy.Copy
sh2.Range("A1").cells.PasteSpecial
End If
End Sub
It should be fast enough, firstly making a Union of the rows to be copied and pasting all the range at once.
I couldn't understand that an empty row is one having only a cell in A:A empty, so I created a piece of code which considers an empty row the one not having any record on all columns...
Quick example: search for blank cells and see if offset values exist:
Sub Blah()
Dim Cell As Range
Dim rng As Range
Set rng = Application.Intersect(Sheets("Sheet1").UsedRange, Sheets("Sheet1").Range("A:A")).SpecialCells(xlCellTypeBlanks)
For Each Cell In rng
If Cell.Offset(1, 0) <> "" Then Debug.Print Cell.Offset(1, 0)
Next Cell
End Sub
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
Please i have this issue and i am trying to achieve a solution using vba.
So cell
A1 has value John
A2-A3 blank
A4 has value Mary
A5-A9 blank
A10 has value Mike
A11-A14 blank
And A15 has value David
I wanna autofill only the blank spaces in the column A, like so:
A2-A3 the blanks will be filled with John
A5-A9 will be filled with Mary
A11-A14 with Mike.
So technically, I am auto filling the blank cells with the value from above
One version to do this is:
Sub Autofill1()
Dim ws As Worksheet
Dim lrow As Long
Dim i As Long
Set ws = Worksheets("Sheet1") 'Set your worksheet name
lrow = ws.Cells(Rows.Count, "A").End(xlUp).Row 'Find last row
For i = 1 To lrow 'Loop from 1st row to last row
If ws.Cells(i, "A").Value = "" Then 'If the cell value is blank then...
ws.Cells(i, "A").Value = ws.Cells(i - 1, "A").Value '.. copy the value from previous cell above
End If
Next i
End Sub
Another version is:
Sub Autofill2()
Dim ws As Worksheet
Dim FillRange As Range
Set ws = Worksheets("Sheet1") 'Set your worksheet name
On Error GoTo Errhand 'If range already is filled then go to error handler
For Each FillRange In Columns("A:A").SpecialCells(xlCellTypeBlanks) 'Define range in column A
If FillRange.Cells.Row <= ActiveSheet.UsedRange.Rows.Count Then 'Check if current row is smaller than last row
FillRange.Cells = ws.Range(FillRange.Address).Offset(-1, 0).Value 'Fill the empty cells with the non empty values
End If
Next FillRange
Errhand:
If Err.Number = 1004 Then MsgBox ("Column is already filled")
End Sub
It has been a long time, but if I'm not mistaken, the following should work:
Dim i As Integer, firstcell As Integer, lastcell As Integer
Dim currentValue As String
firstcell = 1
lastcell = 15
currentValue = ""
For i = firstcell To lastcell
If Cell(i,1).Value = "" Then
Cell(i,1).Value = currentValue
Else
currentValue = Cell(i,1).Value
End If
Next i
You loop through the cells and if there is nothing in them you write the last value in them. If they contain data, you update the currentValue
This solution using for each for more efficient looping.
Sub AutoFillIt()
Dim lLastRow As Long 'Last row of the target range
lLastRow = Cells(Rows.Count, "A").End(xlUp).Row 'Get number of rows
Dim rngCurrentCell As Range
Set rngCurrentCell = Range("A1") 'It will used for looping through the range
Dim rngTarget As Range
Set rngTarget = rngCurrentCell.Resize(lLastRow) 'Set the range working in
Dim vLastValue As Variant ' To store the value of the last not emplty cell
Dim v As Variant
For Each v In rngTarget 'looping through the target range
If v = "" Then 'if the cell is empty, write the last value in
rngCurrentCell.Value = vLastValue
Else 'if not empty, store the content as last value
vLastValue = v
End If
Set rngCurrentCell = rngCurrentCell.Offset(1) 'move to the next cell
Next v
End Sub
I found this code on another post that will single out a line - but it deletes all others EXCEPT the specified line.
I work with large numbers of address lists and I need something I can run that will identify and delete rows with addresses that we've been asked not to mail to. I've just discovered VBA some I'm extremely green. But I'd like to have a module that allows me to add multiple addresses as the list grows.
Sub DeleteRows()
Dim i as long, LastRow As long
with activesheet
LastRow = .Cells(.Rows.Count, 1).End(xlUp).row
For i = LastRow to 2 step -1
If .Cells(i, 1).Value <> "certain value" Then
.Rows(i).Delete
End If
Next i
End With
End Sub
Simply change this:
If .Cells(i, 1).Value <> "certain value" Then - where cell value different then "certain value"
to this:
If .Cells(i, 1).Value = "certain value" Then - where cell value equal to "certain value"
Sub DeleteRows()
Dim i As Long, LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.count, 1).End(xlUp).row
For i = LastRow To 2 Step -1
If .Cells(i, 1).value = "certain value" Then
.Rows(i).Delete
End If
Next i
End With
End Sub
You could use Union to gather the qualifying rows in one go and delete. Also, have a separate sheet where you store the addresses to match on. Read those addresses into an array, then loop the sheet where data is to be deleted from and check whether a given address is found in your array. If found, use Union to store that cell for later deletion.
At the end of looping the data to check, delete the rows associated with the stored cells in the union'd range object in one go.
Option Explicit
Public Sub DeleteThemRows()
Dim arr(), unionRng As Range, i As Long, lastRow As Long, rng As Range
Dim wsAddress As Worksheet, wsDelete As Worksheet
Set wsAddress = ThisWorkbook.Worksheets("Addresses")
Set wsDelete = ThisWorkbook.Worksheets("DataToDelete")
With wsAddress '<= Assume addresses stored in column A starting from cell A1
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Select Case lastRow
Case 1
ReDim arr(1, 1): arr(1, 1) = .Range("A1").Value
Case Is >= 2
arr = .Range("A1:A" & lastRow).Value
End Select
arr = Application.WorksheetFunction.Index(arr, 0, 1)
End With
With wsDelete '<==Assume address column to check is column A
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Dim loopRange As Range
Set loopRange = .Range("A1:A" & lastRow)
If Application.WorksheetFunction.CountA(loopRange) = 0 Then Exit Sub
For Each rng In loopRange.SpecialCells(xlCellTypeConstants)
If Not IsError(Application.Match(rng.Value, arr, 0)) Then
If Not unionRng Is Nothing Then
Set unionRng = Union(unionRng, rng)
Else
Set unionRng = rng
End If
End If
Next
End With
If Not unionRng Is Nothing Then unionRng.EntireRow.Delete
End Sub
You could use Debug.Print unionRng.Address first to check what will be deleted.
Sub FastDelete()
Dim rng As Range, rngData As Range, rngVisible As Range
Const CRITERIA$ = "SOME_VALUE"
Set rng = Range("A1").CurrentRegion '//Whole table
With rng '//Table without header
Set rngData = .Offset(1).Resize(.Rows.Count - 1)
End With
'// Filter by column "A"
rng.AutoFilter Field:=1, Criteria1:=CRITERIA
On Error Resume Next '//In case if no values filtered
Set rngVisible = rng.SpecialCells(xlCellTypeVisible)
If Err = 0 Then
rngVisible.EntireColumn.Delete
End If
On Error GoTo 0
End Sub