Need to Identify Certain Cells and then move the whole row to another worksheet - excel

There is a master order form that has several SKU numbers on it such as 22-1,22-99, 11-1,11-22 etc. What I have been struggling to do is identify all the cells that start with the same number and then select the entire row to move them to a new worksheet. The code provided moves a single cell but I have to move the entire row next with that cell.
Sub Findandcut()
Dim row As Long
For row = 2 To 1000
' Check if "save" appears in the value anywhere.
If Range("A" & row).Value Like "*save*" Then
' Copy the value and then blank the source.
Range("I" & row).Value = Range("A" & row).Value
Range("A" & row).Value = ""
End If
Next
End Sub
The output needed would be all the SKUs that start with the same number get moved to a new worksheet.

Take a look at Range.EntireRow : https://learn.microsoft.com/en-us/office/vba/api/excel.range.entirerow
You can select your entire row like this:
ws.Range("*any cell in the row you want*").EntireRow.Select
then do what you want with the row (i.e, move it, copy it, etc)
Edit2: full working code which should do what you want it to do.
Sub Findandcut()
Dim row As Long
For row = 2 To 1000
' Check if "save" appears in the value anywhere.
If Range("A" & row).Value Like "*save*" Then
' Copy the value and then blank the source.
Range("A" & row).EntireRow Cut Sheet2.Range("I" & row) 'cut and paste to Sheet2
Range("A" & row).Value = "" 'delete row for cleanup purposes
End If
Next
End Sub

Sub Findandcut()
Dim rw As Long
Dim lastrow As Long
lastrow = Worksheets("Sheet2").UsedRange.Rows(Worksheets("Sheet2").UsedRange.Rows.Count).row
For rw = 1000 To 2 Step -1
With Worksheets("Sheet1")
' Check if "save" appears in the value anywhere.
If .Cells(rw, 1).Value Like "*11-*" Then
' Cut the value and then blank the source and shift up
.Cells(rw, 2).EntireRow.Cut Destination:=Worksheets("Sheet2").Cells(lastrow, 1)
.Cells(rw, 2).EntireRow.Delete (xlUp)
End If
End With
lastrow = Worksheets("Sheet2").UsedRange.Rows(Worksheets("Sheet2").UsedRange.Rows.Count).row +1
Next
End Sub
I think this should do what you are looking for.

Related

Using a cell in a loop to define a range in vba. I want to basically delete the row of that cell and the next 3 ones

I'm basically writing a clean up program to make it more straight forward to access data. Anywho, I ran into possibly a nomenclature error. I want to use the "current" cell in a "for" loop to delete that row and the next 3 rows. Code looks something like this:
For Each SingleCell In SingleSheet1.Range("a1:a40")
If SingleCell.Value = "S" Or SingleCell.Value = "B" Then
Range(SingleCell.Range, SingleCell.Range.Offset(4, 0)).EntireRow.Delete Shift:=xlUp
Else
End If
Next
I tried to define the range to delete as specified in the code but it gave me a runtime error
Delete backwards looping trough row number:
Sub EXAMPLE_1()
Dim i As Long
For i = 40 To 1 Step 1
If Range("A" & i).Value = "S" Or Range("A" & i).Value = "B" Then Range("A" & i & ":A" & i + 3).EntireRow.Delete Shift:=xlUp
Next i
End Sub
Sub EXAMPLE_2()
Dim i As Long
Dim LR As Long 'in case last row is not always number 40, adapt it dinamically
LR = Range("A" & Rows.Count).End(xlUp).Row
For i = LR To 1 Step 1
If Range("A" & i).Value = "S" Or Range("A" & i).Value = "B" Then Range("A" & i & ":A" & i + 3).EntireRow.Delete Shift:=xlUp
Next i
End Sub
Your code looses the reference for the deleted rows and you should iterate backwards, if you like iteration between cells (which is slow), but a better/faster solution will be to build a Union range and delete all rows at the code end, at once:
Sub testDeleteOffset()
Dim sh As Worksheet, Urng As Range, i As Long
Set sh = ActiveSheet
For i = 1 To 40
If sh.Range("A" & i).Value = "S" Or sh.Range("A" & i).Value = "B" Then
addToRange Urng, sh.Range("A" & i, "A" & i + 3)
i = i + 4
End If
Next i
If Not Urng Is Nothing Then Urng.EntireRow.Delete xlUp
End Sub
If the involved range is huge, a better solution will be to place some markers for the necessary rows (after last existing column), sort on that marker column and delete the (consecutive marked) rows. Another column with the initial order would be necessary to re-sort according to it at the end... The idea is that building a Union range having more than 1000 areas may become slow.

If cell A1 is greater than B1, cut and paste row to first empty row

If cell in column I1-I14 is greater than cell in column J1-J14, I want to cut the entire row and paste values to the first empty row. (From row 16 and down.)
If cell i is greater than cell j, cut row and paste values to first empty row (row 16 in this example)
This code just pastes in the first row:
Sub Knapp6_Klicka()
Dim i As Long
Dim j As Long
j = 1
For i = 3 To 500
If Cells(i, 9).Value > Cells(i, 10).Value Then
Cells(i, 12).EntireRow.Cut Sheets("Blad1").Range("A" & j)
j = j + 1
End If
Next i
End Sub
I tried to combine the paste with two different solutions.
One like this, where I recorded a macro and went to the last cell, then up to the first empty cell:
Range("A1048576").Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
And one solution that I found on an Excel community:
Sub compareresult()
Dim row1 As Integer
Dim row2 As Integer
row2 = 1
For row1 = 8 To 500
If sheet1.Cells(row1, 11).value > sheet1.Cells(row1, 9).value Then
sheet1.Cells(row1, 1).EntireRow.Copy Sheets(11).Cells(row2, 1)
row2 = row2 + 1
End If
Next row1
End Sub
If cell in column I1-I14 is greater than cell in column J1-J14, i want to cut entire row and paste values to the first empty row. (From row 16 and down)
Here is a method which doesn't cut and paste in a loop. Since you are not deleting the row or "cutting and inserting" the row, here is a simple approach. The below code follows a basic logic
Logic
Loop and identify the range.
If found, then copy the range in 1 go.
Finally clear the range which was copied (if copied).
Code
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim rngToCopy As Range
Dim i As Long
'~~> Change this to relevant sheet
Set ws = Sheet1
With ws
'~~> Loop and identify the range
For i = 2 To 14
If .Range("I" & i).Value2 > .Range("J" & i).Value2 Then
If rngToCopy Is Nothing Then
Set rngToCopy = .Rows(i)
Else
Set rngToCopy = Union(rngToCopy, .Rows(i))
End If
End If
Next i
'~~> If found then copy and clear
If Not rngToCopy Is Nothing Then
rngToCopy.Copy .Rows(16)
rngToCopy.Clear
End If
End With
End Sub
EDIT:
To incorporate new edits
Works perfectly! Thanks! :) I failed to fully describe my problem.. What i also need is to paste it as special (only paste the value and not the formulas). Do you got any quick solution for that? – Johl 5 hours ago
Replace
rngToCopy.Copy .Rows(16)
to
rngToCopy.Copy
DoEvents
.Rows(16).PasteSpecial Paste:=xlPasteValues
Have a try with this.
It's based on the range you gave. Skipped over row 1 since you have headers in it.
Dim i As Long, lRow As Long, ws As Worksheet
Set ws = Sheets("Blad1") 'Your sheet name
lRow = ws.Range("I" & Rows.Count).End(xlUp).Row + 1 'Finding the last row
If lRow < 16 Then lRow = 16 'The starting row you want to cut to
For i = 2 To 14 'Your range of rows to check
If ws.Range("I" & i) > ws.Range("J" & i) Then
ws.Range("I" & i).EntireRow.Cut ws.Range("A" & lRow) 'Cutting the whole row so you use column A to cut to
lRow = lRow + 1 'Move down 1 row for where to cut to
End If
Next i
Edit:
Because you only want the values to copy accross we can't use Cut and PasteSpecial xlValues so instead we will duplicate the value of the entire row to the new location, then clear the row (filling in for the cutting part). If clear is too much we can just ClearContents to remove the values in the cells instead of the formatting if that happens. Make sure to always save before running VBA code for the first time.
Dim i As Long, lRow As Long, ws As Worksheet
Set ws = Sheets("Blad1") 'Your sheet name
lRow = ws.Range("I" & Rows.Count).End(xlUp).Row + 1 'Finding the last row
If lRow < 16 Then lRow = 16 'The starting row you want to cut to
For i = 2 To 14 'Your range of rows to check
If ws.Range("I" & i) > ws.Range("J" & i) Then
ws.Range("A" & lRow).EntireRow.Value = ws.Range("I" & i).EntireRow.Value 'Copying the values over
ws.Range("I" & i).EntireRow.Clear 'Clear the row
lRow = lRow + 1 'Move down 1 row for where to cut to
End If
Next i
Your code is doomed to failure because you do not take into consideration that you are cutting the found row. Think about what that means. Your row with the In,Out is row 15 and you wish to paste to row 16. If you cut row 5 (for example) then rows 15 and 16 will become rows 14 and 15. It also means that your next row (which you think will be row 6) will actually be what was row 7 before the cut.

If blank in A, delete cells in column A to J

I'm struggling to adapt my code now I've built out my sheet.
My code to clear the whole row is
Sub dontdeleteallrows()
Dim a
a = [MATCH(TRUE,INDEX(ISNUMBER(A1:A10000),0),0)]
If Not IsNumeric(x) Then Exit Sub
Rows(a & ":" & Rows.Count).Delete
End Sub
What can I replace Rows(a & ":" & Rows.Count).Delete with to delete cells AA to JA?
Do you want to delete the cells or clear them of content?
If you want to delete the cells, other content may need to move left or up. Where do you want it to go?
You might do something like
Range("Aa" & a & ":Ja" & a).clear
If you want to check Column A for empty cell value and delete the entire row you could use the below:
Option Explicit
Sub Delete()
Dim LastRow As Long, i As Long
With ThisWorkbook.Worksheets("Sheet1")
'Find the last row
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
'Loop column A
For i = LastRow To 1 Step -1
'Check if cell is empty
If .Range("A" & i).Value = "" Then
'Delete row
.Rows(i).EntireRow.Delete
End If
Next i
End With
End Sub

How to copy data from a cell in sheet1 to sheet2, looping through each cell?

How can I cycle through sheet1 to see if there is data in that cell?
If there is no data then go to the next cell.
If there is data in the next cell paste it into sheet2.
The criteria are:
I cannot use a set range it will change as the data changes in sheet1.
I can keep sheet names a constant such as sheet1 and sheet2.
I found a way using columns and or rows yet that code has a major issue. If there is no starting data in the first cell it will not copy anything in the entire row and or column.
I am posting the code I worked with to check the data in columns but if there is no starting data it will skip the whole row.
Sub CopytoImport()
Dim wb As Workbook
Dim iCol As Long
Dim ws As Worksheet
Sheets("sheet2").Cells.ClearContents
' Loop through the column
For iCol = 1 To 22 ' Call out columns I cannot set this every time it should look threw all cells
With Worksheets("sheet1").Columns(iCol)
' Check tht column is not empty
If .Cells(1, 1).Value = "" Then
'Nothing in this column
'Do nothing
Else
' Copy the coumn to te destination
Range(.Cells(1, 1), .End(xlDown)).Copy _
Destination:=Worksheets("sheet2").Columns(iCol).Cells(1, 1)
End If
End With
Next iCol
ActiveWorkbook.Save
End Sub
Function runcode()
Call CopytoImport
End Function
Cells(1, 1) is just RANGE.("A1") you are only operating on this cell in your code. You would need Cells(1, iCol) to account for what column you are on during your loop.
You might also need a nested loop since you are looping through rows as well. The basic outline of a nested loop is as follows. Note the Cells(1,1) is replaced with the i and j representing what row and what column we are on. This might not be the fastest way to achieve the results you want but it sounds like this is what you are asking for help with. You will also need to define a lastrow (with a + 1 at the end to get the next blank cell) in your Sheet2 for when you paste the data. You would put this right under where the loop starts going through rows. This is so the lastrow of your sheet2 is recalculated each time data is being moved to that sheet. I am not going to re-write your code since you stated it is not complete but here is an example that should help you.
For j = 5 To lastcolumn
For i = 5 To lastrow
Dim lastrow2 As Long
lastrow2 = Worksheets(1).Range("A" & Rows.Count).End(xlUp).Row + 1
If Worksheets(2).Cells(i, j).Value <> 0 Then
Worksheets(1).Range("C" & lastrow2).Value = Worksheets(2).Cells(i, j).Value
Worksheets(1).Range("B" & lastrow2).Value = Worksheets(2).Cells(2, j).Value
End If
Next i
Next j
To find your lastrow:
dim lastrow as long
lastrow = Range("A" & rows.count).End(xlup).Row ' or whatever column contains the data
To find your last column
Dim lastcolumn As Long
lastcolumn = Worksheets(2).Cells(2, Columns.Count).End(xlToLeft).Column

Excel VBA is Finding Every Other Cell not Every Cell From Method

Excel VBA is finding every other cell using a method to check for Empty Cells. On the next time running the same macro, it then finds the cell that it skipped over on the last run while again skipping the next instance of an empty cell. If I cycle through the macro a few times, eventually every row without data is getting deleted, as per the purpose of the macro. The rows do shift upward upon deletion of the row one at a time, I will try a Union and delete the Range as stated by #BigBen
When a cell that is empty is found, it checks columns A, B, and D to see if formula is applied, and if a formula exists in that row, the entire row gets deleted.
Dim cel, dataCells As Range
Dim rngBlank, dc As Range
Dim lastRow, cForm, c, blnkRange As String
Dim cycleTimes As Integer
On Error Resume Next
Set dataCells = Range("F2:W2").Cells 'This is header of the table of data
cycleTimes = dataCells.Count 'Number of times to cycle through macro
For Count = 1 To cycleTimes 'I don't want to cycle through macro
lastRow = Range("N" & Rows.Count).End(xlUp).Row 'To find end of column
For Each dc In dataCells
c = Split(Cells(1, dc.Column).Address, "$")(1) 'Column Letter
blnkRange = c & "3:" & c & lastRow 'Range to look over for empty cells
Set rngBlank = Range(blnkRange).SpecialCells(xlCellTypeBlanks).Cells
For Each cel In rngBlank '**Skipping Every other Row**
If Not TypeName(cel) = "Empty" Then
cForm = "A" & cel.Row & ",B" & cel.Row & ",D" & cel.Row 'Formula check
If Range(cForm).HasFormula Then
cel.EntireRow.Delete
End If
End If
Next
Next
Next
I was able to use Intersect to find the rows that matched the criteria I was searching for and delete the EntireRow even though the Selection was in separate Rows.
Set dataCells = Range("F2:W2").Cells
lastRow = Range("N" & Rows.Count).End(xlUp).Row 'To find last row to generate range to look through
For Each dc In dataCells 'Have to perform delete row for every column
c = Split(Cells(1, dc.Column).Address, "$")(1)
blnkRange = c & "3:" & c & lastRow
Set rngBlank = Range(blnkRange).SpecialCells(xlCellTypeBlanks).EntireRow
strFormula = "A2:A" & lastRow & ",B2:B" & lastRow & ",C2:C" & lastRow
Set rngFormula = Range(strFormula).SpecialCells(xlCellTypeFormulas)
Intersect(rngFormula, rngBlank).EntireRow.Delete (xlShiftUp) '**THIS helped in deleting Rows**
Next

Resources