I have a report with Data in columns A-L.
The number or rows in the report is dynamic.
I need to delete every row after the first instance of 0000004473 in column I.
I saw code for a similar question. In my spreadsheet the macro does the opposite and delete every row before 0000004473.
Sub Sample()
Dim rng As Range
Dim sRow As Long, lastRow As Long
With Sheets("Sheet1")
'find Terminations
Set rng = .Range("I:I").Find(what:="0000004473", after:=.Range("I1"))
If Not rng Is Nothing Then
'~~> Get the start row
sRow = rng.Row + 1
'find last row
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastRow = .Cells.Find(what:="*", _
after:=.Range("I1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lastRow = 1
End If
'I use lastRow + 1 to prevent deletion "0000004773" when it is on lastrow
.Range(sRow & ":" & lastRow + 1).Delete Shift:=xlUp
End If
End With
End Sub
Don't use .find to get the last row. If you have data before .range("I1") it will use that as your lastrow value because it stops once it gets a match.
If you put Debug.Print lastRow, sRow where I have it below you can see what the range will be.
Sub Sample()
Dim rng As Range
Dim sRow As Long, lastRow As Long
With Sheets("Sheet1")
'find Terminations
Set rng = .Range("I:I").Find(what:="0000004473", after:=.Range("I1"))
If Not rng Is Nothing Then
'~~> Get the start row
sRow = rng.Row + 1
'find last row
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastRow = .Cells(.Rows.Count, "I").End(xlUp).Row
Else
lastRow = 1
End If
Debug.Print lastRow, sRow
'I use lastRow + 1 to prevent deletion "0000004773" when it is on lastrow
.Range(sRow & ":" & lastRow + 1).Delete Shift:=xlUp
End If
End With
End Sub
Assuming "I" is the column with the most values, if it isn't use whatever column does.
Related
Trying to create a macro that will do a search for a cell value, then when found cut the entire row and past it to another sheet!
Help is appreciated, I've never programmed before in excel....
Sub test2()
Dim cel As Range, lRow As Long
findWhat = InputBox("Enter what you want to find?", "Find what...")
For Each cel In ThisWorkbook.Sheets("Sheet1").Range("W2:W250000" &Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row)
If cel.Value = findWhat Then
lRow = ThisWorkbook.Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
ThisWorkbook.Sheets("Sheet2").Cells(lRow + 1, 1).Value = ThisWorkbook.Sheets("Sheet2").Cells(cel.Row, 1).Resize(, 48)
End If
Next
End Sub
I am just modifying some of your existing code to do what is required, assuming that you want to search only in column W and then copy the entire row if a match is found.
Sub test2()
Dim cel As Range, lRow As Long
findWhat = InputBox("Enter what you want to find?", "Find what...")
'Following loop will only search for the values in column W and between rows 2 to 250000, change the values as required.
For Each cel In ThisWorkbook.Sheets("Sheet1").Range("W2:W250000")
If cel.Value = findWhat Then
currentRow = cel.Row
lRow = ThisWorkbook.Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row
Thisworkbook.Sheets("Sheet1").Rows(currentRow).EntireRow.copy
ThisWorkbook.Sheets("Sheet2").Range("A" & lRow + 1 ).Select
ThisWorkbook.Sheets("Sheet2").Paste
Thisworkbook.Sheets("Sheet1").Rows(currentRow).EntireRow.Delete
End If
Next
End Sub
UPDATE: This code will copy all the rows that matches the given value.
If you're just needing to find the input value once within the range you could use this to copy. If you're wanting to cut the line that you copy from as well then take away the ' from the delete line in the code.
This is for if you just want the first found cell:
Sub test2()
Dim lRow1 As Long, lRow2 As Long, found As Range, findwhat As String
findwhat = InputBox("Enter what you want to find?", "Find what...")
lRow1 = ThisWorkbook.Sheets("Sheet1").Range("W" & Rows.Count).End(xlUp).Row
lRow2 = ThisWorkbook.Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row
Set found = Sheets("Sheet1").Range("W2:W" & lRow1).Find(What:=findwhat, LookIn:=xlValues, lookat:=xlWhole, searchdirection:=xlNext)
If Not found Is Nothing Then
Sheets("Sheet1").Range("W" & found.Row).EntireRow.Copy
Sheets("Sheet2").Range("A" & lRow2 + 1).PasteSpecial
'Sheets("Sheet1").Range("W" & found.Row).EntireRow.Delete
End If
Application.CutCopyMode = False
End Sub
EDIT:
If you're needing every row that is found with that value then use this one. It's just modified from yours which is pretty much the easiest way to do it:
EDIT2: Changed it so now it loops from the bottom up which resolves the issue of skipping some of them after deleting the row.
Sub test2()
Dim lRow1 As Long, lRow2 As Long, findwhat As String, cel As Range, Sh1 As Worksheet, Sh2 As Worksheet, i As Long
findwhat = InputBox("Enter what you want to find?", "Find what...")
lRow1 = ThisWorkbook.Sheets("Sheet1").Range("W" & Rows.Count).End(xlUp).Row
Set Sh1 = ThisWorkbook.Sheets("Sheet1")
Set Sh2 = ThisWorkbook.Sheets("Sheet2")
For i = lRow1 To 2 Step -1
If Sh1.Range("W" & i).Value = findwhat Then
lRow2 = Sh2.Range("A" & Rows.Count).End(xlUp).Row
Sh1.Range("W" & i).EntireRow.Copy
Sh2.Range("A" & lRow2 + 1).PasteSpecial
Sh1.Range("W" & i).EntireRow.Delete
End If
Next i
Application.CutCopyMode = False
End Sub
Goal: Add the string "Z" to a select few columns for all rows except the header. Concatenate only on select headers i.e. headers defined in the array.
Dim header As Range
ArrayCheck = Array("CarTime", "BusTime", "PlaneTime")
LastRow = desWS1.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
lcol = desWS1.Cells(1, Columns.Count).End(xlToLeft).Column
For Each header In desWS1.Range(desWS1.Cells(1, 1), desWS1.Cells(1, lcol))
For i = LBound(ArrayCheck) To UBound(ArrayCheck)
If header = ArrayCheck(i) Then
desWS1.Range(desWS1.Cells(2, header.Column), desWS1.Cells(LastRow, header.Column)) & "Z"
End If
Next i
Next
all entries in these columns are of the form: yyyy-mm-ddThh:mm:ss
#SiddharthRout the current cell is: 2020-09-07T13:08:46, and the output i want is: 2020-09-07T13:08:46Z. So yep, you're right, it's a string. – Jak Carty 2 mins ago
In my below code, I will take a sample of both date and date stored as text. I have commented the code so you should not have a problem understanding it. But if you do then simply post back.
Is this what you are trying?
Code:
WAY 1
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, lCol As Long
Dim ArrayCheck As Variant
Dim i As Long, j As Long
Dim rng As Range
ArrayCheck = Array("CarTime", "BusTime", "PlaneTime")
'~~> Set this to the relevant worksheet
Set ws = Sheet1
With ws
'~~> Find last row
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Find last col
lCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
'~~> Loop though the cell in 1st row
For i = 1 To lCol
'~~> Loop through the array
For j = LBound(ArrayCheck) To UBound(ArrayCheck)
'~~> Check if they match
If .Cells(1, i).Value2 = ArrayCheck(j) Then
'~~> Set your range from cell 2 onwards
Set rng = .Range(.Cells(2, i), .Cells(lRow, i))
'~~> Add "Z" to the entire range in ONE GO i.e without looping
'~~> To understand this visit the url below
'https://stackoverflow.com/questions/19985895/convert-an-entire-range-to-uppercase-without-looping-through-all-the-cells
rng.Value = Evaluate("index(Concatenate(" & rng.Address & ",""Z""" & "),)")
End If
Next j
Next i
End With
End Sub
Note: For the sake of clarity, I am not joining the string ",""Z""" & "),)")
In Action
WAY 2
Introducing a 2nd way
This code writes to array and then works with it.
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, lCol As Long
Dim ArrayCheck As Variant
Dim i As Long, j As Long, k As Long
Dim rng As Range
Dim tmpAr As Variant
ArrayCheck = Array("CarTime", "BusTime", "PlaneTime")
'~~> Set this to the relevant worksheet
Set ws = Sheet1
With ws
'~~> Find last row
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Find last col
lCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
'~~> Loop though the cell in 1st row
For i = 1 To lCol
'~~> Loop through the array
For j = LBound(ArrayCheck) To UBound(ArrayCheck)
'~~> Check if they match
If .Cells(1, i).Value2 = ArrayCheck(j) Then
'~> Set your range
Set rng = .Range(.Cells(2, i), .Cells(lRow, i))
'~~> Store the value in array
tmpAr = rng.Value2
'~~> Work with array
For k = 1 To UBound(tmpAr)
tmpAr(k, 1) = tmpAr(k, 1) & "Z"
Next k
'~~> write the array back to worksheet
rng.Resize(UBound(tmpAr), 1).Value = tmpAr
End If
Next j
Next i
End With
End Sub
In Action
Sub DeleteExtraValues ()
Dim I as Integer, strValueToFind As String, lngRows As Long, she As Worksheet
Set an = ThisWorkbook.ActiveSheet
LngRows = sh.Range(“A1048576”).End(xlUp).Row
strValueToFind = “DCAP”
For I = 1 To lngRows
If InStr(Cells(I,1).Value, strValueToFind) = 0 Then
If Cells(I,1).Value = “” Then
Else
Rows(I).Delete
I = I-1
End If
End If
Next I
End Sub
When running this, it will delete the cells above the data I want to keep and then will stop once it gets to the first cell that contains “DCAP”. I need it also to delete any unnecessary information after the last cell that contains “DCAP”.
Try this code. It removes every row that doesn't contain DCAP in the first column.
Dim r As Long
Dim LastRow As Long
r = 1
LastRow = Cells.Find("*", [A1], , , xlByRows, xlPrevious).Row
Do Until r > LastRow
DoEvents
If InStr(1, Cells(r, 1), "DCAP") > 0 Then
r = r + 1
Else
Cells(r, 1).EntireRow.Delete
LastRow = LastRow - 1
End If
Loop
MsgBox
"done"
Try this...
Dim rng As Range
Set rng = ActiveSheet.Range("A1").CurrentRegion 'depending on your data you may have to change to a specific range using last row and column
' change the `Field` to the column that contains "DCAP"
With rng
.AutoFilter Field:=9, Criteria1:="<>DCAP", Operator:=xlAnd 'select all cells that are not "DCAP"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete 'don't delete the header row
.AutoFilterMode = False
End With
Sub Test1()
Dim LastRow As Range
Dim cfind As Range
'Set WS = ActiveWorkbook.Worksheets("Report")
'With WS
'Set cfind = Cells.Find(what:="Order Status", lookat:=xlWhole, MatchCase:=False)
'End With
LastRow = Cells(Rows.Count, "C").End(xlUp).Row
For i = LastRow To 2 Step -1
If Range("C" & i).Value = "Canceled" Then
Range("C" & i).EntireRow.Delete
End If
Next i
End Sub
I am trying to delete the rows which has a value "Canceled" in a column which has a header "Order Status". I am currently using the column number or name. I am not sure how to use column header (Order Status) to delete the rows.
Can someone help me?
Your LastRow was a range object, should have been a long.
Sub Test1()
'not necessary now but should have been a long
'Dim LastRow As long
'not necessary now
'Dim cfind As Range
Dim col As Variant
With ActiveWorkbook.Worksheets("Report")
col = Application.Match("Order Status", .Rows(1), 0)
If Not IsError(col) Then
For i = .Cells(.Rows.Count, col).End(xlUp).Row To 2 Step -1
If .Cells(i, col).Value = "Canceled" Then
.Rows(i).EntireRow.Delete
End If
Next i
else
msgbox "no 'Order Status' here"
End If
end with
End Sub
I have 100K Excel file that has many employee info, I want to shift all existence data to the first row for this employee, the picture below will be louder than my words, can a VBA code do this? or there is a trick in excel that I am not aware of
Try following code.
Sub Demo()
Dim ws As Worksheet
Dim cel As Range, rng As Range
Dim lastRow As Long, lastCol As Long, i As Long
Dim fOccur As Long, lOccur As Long, colIndex As Long
Dim dict As Object, c1
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Sheet1") 'change Sheet1 to your data range
Set dict = CreateObject("Scripting.Dictionary")
With ws
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row 'last row with data in Column A
lastCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column 'last column with data in Sheet1
Set rng = .Range("A1:A" & lastRow) 'set range in Column A
c1 = .Range("A2:A" & lastRow)
For i = 1 To UBound(c1, 1) 'using dictionary to get uniques values from Column A
dict(c1(i, 1)) = 1
Next i
colIndex = 16 'colIndex+1 is column number where data will be displayed from
For Each k In dict.keys 'loopthrough all unique values in Column A
fOccur = Application.WorksheetFunction.Match(k, rng, 0) 'get row no. of first occurrence
lOccur = Application.WorksheetFunction.CountIf(rng, k) 'get row no. of last occurrence
lOccur = lOccur + fOccur - 1
'copy range from left to right
.Range(.Cells(fOccur, 1 + colIndex), .Cells(lOccur, lastCol + colIndex)).Value = .Range(.Cells(fOccur, 1), .Cells(lOccur, lastCol)).Value
'delete blanks in range at right
.Range(.Cells(fOccur, 1 + colIndex), .Cells(lOccur, lastCol + colIndex)).SpecialCells(xlCellTypeBlanks).Delete Shift:=xlUp 'delte blank rows
Next k
End With
Application.ScreenUpdating = True
End Sub
Try the below. You can amend the below code to match where you want to move the range:
Dim oW As Worksheet: Set oW = ThisWorkbook.Worksheets("Sheet8")
With oW.UsedRange
.Cut .Offset(0, .Columns.Count + 2)
End With