I am trying to set up an archiving system whereby when a user selects "Yes" from a column dropdown and click an 'Archive' button, all entries that have been selected to be archived will be moved to another sheet. The problem I am facing however is each time an entry is archived, it just overwrites the previous entry that was archived so there is only ever 1 row on the archive sheet. This is the code I am currently working with
Sub Archive_Yes()
Dim MatchRow As Long, FirstRow As Long, LastRow As Long
Dim Destination As Range
Dim ws As Worksheet
Dim i As Long
Set ws = Sheets("Sales Order Log")
FirstRow = 14
LastRow = ws.Cells(ws.Rows.Count, "AA").End(xlUp).Row
i = FirstRow
Do While i <= LastRow
If ws.Range("AA" & i).Value = "Yes" Then
MatchRow = ws.Range("Z" & i).Row
With Sheets("Archive")
Set Destination = .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0)
End With
ws.Range("A" & MatchRow & ":Z" & MatchRow).Copy Destination
ws.Rows(MatchRow).Delete Shift = xlUp
LastRow = LastRow - 1
Else
i = i + 1
End If
Loop
End Sub
Any guidance would be very much appreciated. Thank you
Move Criteria Rows Using AutoFilter
Sub Archive_Yes()
Const sName As String = "Sales Order Log"
Const sHeaderRowAddress As String = "A13:AA13"
Const CriteriaColumn As Long = 27
Const CriteriaString As String = "Yes"
Const dName As String = "Archive"
Const dFirstCellAddress As String = "A2"
Dim sws As Worksheet: Set sws = ThisWorkbook.Worksheets(sName)
If sws.AutoFilterMode Then sws.AutoFilterMode = False ' turn off AutoFilter
Dim srCount As Long
Dim srg As Range
With sws.Range(sHeaderRowAddress)
Dim slRow As Long
slRow = sws.Cells(sws.Rows.Count, CriteriaColumn).End(xlUp).Row
srCount = slRow - .Row + 1
If srCount < 2 Then Exit Sub ' no data or only headers
Set srg = .Resize(srCount)
End With
Dim scCount As Long: scCount = srg.Columns.Count
Dim sdrg As Range ' exclude headers and last column
Set sdrg = srg.Resize(srCount - 1, scCount - 1).Offset(1)
srg.AutoFilter CriteriaColumn, CriteriaString
Dim svrg As Range
On Error Resume Next
Set svrg = sdrg.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
sws.AutoFilterMode = False
If svrg Is Nothing Then
MsgBox "No filtered rows.", vbExclamation
Exit Sub
End If
Dim dws As Worksheet: Set dws = ThisWorkbook.Worksheets(dName)
Dim dfCell As Range
With dws.Range(dFirstCellAddress)
Dim dlRow As Long
dlRow = dws.Cells(dws.Rows.Count, .Column).End(xlUp).Row
If dlRow < .Row Then
Set dfCell = .Cells
Else
Set dfCell = dws.Cells(dlRow + 1, .Column)
End If
End With
svrg.Copy dfCell
svrg.EntireRow.Delete Shift:=xlShiftUp
MsgBox "Data archived.", vbInformation
End Sub
Please, try the next adapted code:
Sub Archive_Yes()
Dim FirstRow As Long, LastRow As Long, Destination As Range, rngDel As Range
Dim ws As Worksheet, i As Long
Set ws = Sheets("Sales Order Log")
FirstRow = 14
LastRow = ws.cells(ws.rows.count, "AA").End(xlUp).row
For i = FirstRow To LastRow
If ws.Range("AA" & i).value = "Yes" Then
AddRange rngDel, ws.Range("A" & i & ":Z" & i)
End If
Next i
Dim wsA As Worksheet, lastRowA As Long
Set wsA = Sheets("Archive")
lastRowA = wsA.Range("A" & wsA.rows.count).End(xlUp).row + 1
If Not rngDel Is Nothing Then
Debug.Print rngDel.Address, lastRowA: Stop
Application.ScreenUpdating = False: Application.EnableEvents = False
Application.Calculation = xlCalculationManual
rngDel.Copy wsA.Range("A" & lastRowA)
rngDel.EntireRow.Delete
Application.ScreenUpdating = True: Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
End If
End Sub
Sub AddRange(rngU As Range, rngAdd As Range)
If rngU Is Nothing Then
Set rngU = rngAdd
Else
Set rngU = Application.Union(rngU, rngAdd)
End If
End Sub
It should be very fast... Please, send some feedback after testing it.
Related
I'm trying to compare the dates that I choose. I mean I'm trying to take the some items which has a date earlier. So I wrote this on VBA. But I noticed that when I run this code the output was the same as input. So it tries to find the earlier items but it couldn't compare so all items are copied.
Private Sub Macro1()
a = Worksheets("SVS").Cells(Rows.Count, 1).End(xlUp).Row
For i = 3 To a
If Worksheets("SVS").Cells(i, 22).Value < CDate("28/02/2023") Then
Worksheets("SVS").Rows(i).Copy
Worksheets("Summary").Activate
b = Worksheets("Summary").Cells(Rows.Count, 1).End(xlUp).Row
Worksheets("Summary").Cells(b + 1, 1).Select
ActiveSheet.Paste
Worksheets("SVS").Activate
End If
Next i
Application.CutCopyMode = False
ThisWorkbook.Worksheets("SVS").Cells(1, 1).Select
End Sub
What is missing in the code? I wanna learn.
Check you have a valid date to compare with.
Option Explicit
Private Sub Macro1()
Dim wb As Workbook, ws As Worksheet, v
Dim lastrow As Long, i As Long, b As Long, n As Long
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Summary")
b = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
With wb.Sheets("SVS")
lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = 3 To lastrow
v = .Cells(i, 22) ' col V
If IsDate(v) Then
If CDbl(v) < DateSerial(2023, 2, 28) Then
b = b + 1
.Rows(i).Copy ws.Cells(b, 1)
n = n + 1
End If
End If
Next i
End With
MsgBox n & " rows copied to Summary", vbInformation, lastrow - 2 & " rows checked"
End Sub
Append If Earlier Date
Option Explicit
Sub AppendEarlierDate()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim sws As Worksheet: Set sws = wb.Sheets("SVS")
Dim srg As Range
Set srg = sws.Range("V3", sws.Cells(sws.Rows.Count, "V").End(xlUp))
Dim surg As Range, sCell As Range, sValue
For Each sCell In srg.Cells
sValue = sCell.Value
If IsDate(sValue) Then
If sValue < DateSerial(2023, 2, 28) Then
If surg Is Nothing Then
Set surg = sCell
Else
Set surg = Union(surg, sCell)
End If
End If
End If
Next sCell
If surg Is Nothing Then Exit Sub
Dim dws As Worksheet: Set dws = wb.Sheets("Summary")
If dws.FilterMode Then dws.ShowAllData
Dim dlCell As Range, dfCell As Range
Set dlCell = dws.Cells.Find("*", , xlFormulas, , xlByRows, xlPrevious)
If dlCell Is Nothing Then
Set dfCell = dws.Range("A1")
Else
Set dfCell = dws.Cells(dlCell.Row + 1, "A")
End If
surg.EntireRow.Copy dfCell
End Sub
Hi I have recurring text in a column that says: " "command": 16, "
Every time that text occurs I want to insert a set range from sheet 2, 7 rows above
I have this code but can't get it working.. any ideas
Sub Find_Insert()
Application.ScreenUpdating = False
Dim m As Long
Dim Lastrow2 As Long
Sheets("servo commands").Range("B1:B192").Copy 'sheet with set range to copy
Worksheets("Import").Activate
Lastrow2 = Cells(Rows.Count, "A").End(xlUp).Row
For m = Lastrow2 To 1 Step -1
If Cells(m, "A").Value = " ""command"": 16," Then Cells(m, "A").Offset(-7, 0).Select
Selection.Insert Shift:=xlDown
Next
Application.ScreenUpdating = True
End Sub
many thanks in advance
Insert Range With Offset
Sub InsertCells()
Const DST_ROW_OFFSET As Long = 7
Const DST_CRIT_STRING As String = " ""command"": 16,"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Sheets("Servo Commands")
Dim srg As Range: Set srg = sws.Range("B1:B192")
Dim dws As Worksheet: Set dws = wb.Sheets("Import")
Dim dlRow As Long: dlRow = dws.Cells(dws.Rows.Count, "A").End(xlUp).Row
Application.ScreenUpdating = False
Dim dr As Long, dString As String
For dr = dlRow To DST_ROW_OFFSET + 1 Step -1
dString = CStr(dws.Cells(dr, "A").Value)
If StrComp(dString, DST_CRIT_STRING, vbTextCompare) = 0 Then
srg.Copy
dws.Cells(dr, "A").Offset(-DST_ROW_OFFSET).Insert Shift:=xlShiftDown
dr = dr - DST_ROW_OFFSET
End If
Next dr
Application.CutCopyMode = False
Application.ScreenUpdating = True
MsgBox "Cells inserted."
End Sub
I am looking to filter out a set of data with the criteria being if column A has over 5 characters in the string delete it.
However, before I delete it, I want to copy these entries to a sheet named "fixed"
The code I have at the moment works for the first entry, but doesn't loop through and I am unsure how to fix that...
Code:
Dim LR As Long, i As Long
LR = Worksheets("Output Sheet").Range("A" & Rows.Count).End(xlUp).Row
For i = LR To 1 Step -1
If Len(Range("A" & i).Value) >= 5 Then
Rows(i).EntireRow.Cut Worksheets("Fixed").Range("A:D")
Rows(i).Delete
End If
Next i
The data it is copying has 4 columns if that's of any help? I just can't seem to figure out why it doens't look but I am nearly positive it's a simple fix so any pointers would be appreciated.
Dim f As Long
Set Rng = Worksheets("Black List").Range("A1:A" & Range("A" & Rows.Count).End(xlUp).Row)
Application.ScreenUpdating = False
With Worksheets("Output Sheet")
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
For f = Lastrow To 1 Step -1
If Not IsError(Application.Match(.Range("A" & f).Value, Rng, 0)) Then
.Rows(f).Delete
End If
Next f
End With
Application.ScreenUpdating = True
Backup Data
This will add a formula (=LEN(A1)) to an inserted column range (E), to calculate the length of the values of the criteria column (A), and filter this range.
The filtered data (sdvrg) will be copied (appended) to another worksheet (Fixed) and the filtered data's entire rows will be deleted.
Finally, the inserted column (E) will be deleted.
Option Explicit
Sub BackupData()
Const sName As String = "Output Sheet"
Const sCols As String = "A:D"
Const scCol As Long = 1 ' Criteria Column
Const shRow As Long = 1 ' Header Row
Const sLenCriteria As String = ">5"
Const dName As String = "Fixed"
Const dCol As String = "A"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
If sws.AutoFilterMode Then sws.AutoFilterMode = False
Dim slRow As Long
With sws.Columns(sCols).Columns(scCol)
slRow = .Cells(.Cells.Count).End(xlUp).Row
End With
If slRow <= shRow Then Exit Sub ' no data or just headers
Dim srCount As Long: srCount = slRow - shRow + 1
' Source Table Range ('strg') (headers)
Dim strg As Range: Set strg = sws.Rows(shRow).Columns(sCols).Resize(srCount)
' Source Data Range ('sdrg') (no headers)
Dim sdrg As Range: Set sdrg = strg.Resize(srCount - 1).Offset(1)
Dim scCount As Long: scCount = strg.Columns.Count
Application.ScreenUpdating = False
' Source Inserted Column Range ('sicrg') (headers)
Dim sicrg As Range: Set sicrg = strg.Columns(1).Offset(, scCount)
sicrg.Insert Shift:=xlShiftToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Set sicrg = sicrg.Offset(, -1) ' account for 'Insert'
' The formula is also written to the header row which is irrelevant
' to the upcoming 'AutoFilter'.
sicrg.Formula = "=LEN(" & strg.Cells(1, scCol).Address(0, 0) & ")"
sicrg.AutoFilter 1, sLenCriteria
' Source Data Visible Range ('sdvrg') (no headers)
Dim sdvrg As Range
On Error Resume Next ' prevent 'No cells found' error.
Set sdvrg = sdrg.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
sws.AutoFilterMode = False
Dim WasBackedUp As Boolean
If Not sdvrg Is Nothing Then
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
If dws.AutoFilterMode Then dws.AutoFilterMode = False
Dim dfCell As Range
Set dfCell = dws.Cells(dws.Rows.Count, dCol).End(xlUp).Offset(1)
sdvrg.Copy dfCell
sdvrg.EntireRow.Delete Shift:=xlShiftUp ' resizes 'sicrg' appropriately
WasBackedUp = True
End If
sicrg.Delete Shift:=xlShiftToLeft
Application.ScreenUpdating = True
If WasBackedUp Then
MsgBox "Data backed up.", vbInformation
Else
MsgBox "No action taken.", vbExclamation
End If
End Sub
Below code match the string in the specific range (this range contains Headers) if finds then copy the whole column and paste into Sheet2.
I want to add two more condition in below code that are:
Dim FindValue2 As String
Dim FindValue3 As String
FindValue2 = shSummary.Range("A2").Value
FindValue3 = shSummary.Range("B2").Value
and match in Sheet1 Column A for FindValue3 and Column F for FindValue2 after matching these 3 criteria then copy and paste the data.
Your help will be much appreciated.
Sub find()
Dim foundRng As Range
Dim FindValue As String
Dim lastRow As Long
Set shData = Worksheets("Sheet1")
Set shSummary = Worksheets("Sheet2")
FindValue = shSummary.Range("C2")
Set foundRng = shData.Range("G1:Z1").find(FindValue)
With shData
lastRow = .Cells(.Rows.Count, foundRng.Column).End(xlUp).Row
End With
shData.Rows("2:" & lastRow).Columns(foundRng.Column).Copy shSummary.Range("I3")
End Sub
Apply a filter to columns A and F then copy the visible cells.
Option Explicit
Sub Find3()
Dim wb As Workbook, wsData As Worksheet, wsSummary As Worksheet
Dim rngFound As Range, rngData As Range, rngCopy As Range
Dim FindValue As String, FilterA As String, FilterF As String
Dim lastRow As Long, c As Long
Set wb = ThisWorkbook
Set wsData = wb.Worksheets("Sheet1")
wsData.AutoFilterMode = False
Set wsSummary = wb.Worksheets("Sheet2")
With wsSummary
FindValue = .Range("B2")
FilterA = .Range("C2")
FilterF = .Range("A2")
End With
Set rngFound = wsData.Range("G1:Z1").find(FindValue)
If rngFound Is Nothing Then
MsgBox "'" & FindValue & "' not found", vbCritical
Exit Sub
End If
' column matching FindValue
c = rngFound.Column
lastRow = wsData.Cells(Rows.Count, c).End(xlUp).Row
If lastRow = 1 Then
MsgBox "No data in column " & c, vbCritical
Exit Sub
End If
' filter data on colA and F
With wsData
Set rngData = .Cells(2, c).Resize(lastRow - 1)
.UsedRange.AutoFilter
.UsedRange.AutoFilter Field:=1, Criteria1:=FilterA
.UsedRange.AutoFilter Field:=6, Criteria1:=FilterF
' data to copy
On Error Resume Next
Set rngCopy = rngData.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
' copy data
If rngCopy Is Nothing Then
MsgBox "No data to copy from column " & c, vbCritical
.AutoFilterMode = False
Exit Sub
Else
rngCopy.Copy wsSummary.Range("I3")
End If
.AutoFilterMode = False
End With
MsgBox "Done"
End Sub
Copy Data Columns to Another Worksheet
Adjust the values in the constants section.
Delete (out-comment) the Debug.Print lines when done testing.
Option Explicit
Sub ExportDataColumns()
Const sName As String = "Sheet1"
Const sHeadersAddress As String = "G1:Z1"
Const dName As String = "Sheet2"
Const dReadList As String = "A2,B2,C2"
Const dWriteList As String = "F3,A3,I3"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim wsrCount As Long: wsrCount = sws.Rows.Count
Dim shrg As Range: Set shrg = sws.Range(sHeadersAddress)
Debug.Print "Source Header Range: " & shrg.Address(0, 0)
Dim sfRow As Long: sfRow = shrg.Row + 1 ' first row below the headers
Debug.Print "Source First Row: " & sfRow
If sfRow >= wsrCount Then Exit Sub
Dim slRow As Long: slRow = GetLastRow(shrg)
Debug.Print "Source Last Row: " & slRow
If slRow < sfRow Then Exit Sub
Dim sdrg As Range
Set sdrg = shrg.Resize(slRow - sfRow + 1).Offset(1)
Debug.Print "Source Data Range: " & sdrg.Address(0, 0)
Dim dRead() As String: dRead = Split(dReadList, ",")
Dim dWrite() As String: dWrite = Split(dWriteList, ",")
Dim dUpper As Long: dUpper = UBound(dRead)
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim srg As Range
Dim drg As Range
Dim dcrg As Range
Dim srCount As Long
Dim n As Long
For n = 0 To dUpper
Debug.Print "Item " & n + 1
Dim scIndex As Variant
scIndex = Application.Match(dws.Range(dRead(n)).Value, shrg, 0)
If IsNumeric(scIndex) Then
Set srg = sdrg.Columns(scIndex)
Debug.Print "Source Range: " & srg.Address(0, 0)
srCount = srg.Rows.Count
Set drg = dws.Range(dWrite(n)).Resize(srCount)
Debug.Print "Destination Range: " & drg.Address(0, 0)
drg.Value = srg.Value
Set dcrg = drg.Resize(wsrCount - drg.Row - srCount + 1) _
.Offset(srCount)
Debug.Print "Destination Clear Range: " & dcrg.Address(0, 0)
dcrg.ClearContents
End If
Next n
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the worksheet row number of the last non-empty row
' in the range from the first row of a range ('rg')
' through the same sized bottom-most row of the worksheet.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetLastRow( _
ByVal rg As Range) _
As Long
If rg Is Nothing Then Exit Function
Dim lCell As Range
With rg.Rows(1)
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , xlByRows, xlPrevious)
End With
If lCell Is Nothing Then Exit Function
GetLastRow = lCell.Row
End Function
Thought it would be as simple as, but somewhere i am wrong please help! So I am trying to find the values from rng1 in rng2 and have the output next to rng1
Thanks in advance
Sub FindValuestest()
Dim wb As Workbook, wks1, wks2 As Worksheet, rng1, rng2 As Range
Dim lRow1, lRow2 As Long
Dim v, n, r As Variant
On Error Resume Next
Set wb = ThisWorkbook
Set wks1 = wb.Worksheets("FEPR")
Set wks2 = wb.Worksheets("EQUIP")
lRow1 = wks1.Cells(wks1.Rows.Count, "B").End(xlUp).Row
lRow2 = wks2.Cells(wks2.Rows.Count, "A").End(xlUp).Row
Set rng1 = wks1.Range("B2", Cells(Rows.Count, "B").End(xlUp))
Set rng2 = wks2.Range("A1", Cells(Rows.Count, "A").End(xlUp))
lRow1 = lRow1 - 1
For v = 1 To lRow1
For n = 1 To lRow1
If n = rng2.Find(n, , xlValues, xlWhole, , , False) And rng2.Cells(n, 2) = "Commodity Tracking Bag Scanner" Then
'Debug.Print n
rng1.Cells(n, 2) = rng1.Cells(n) & " Scanner OK"
End If
Next
Next
For v = 1 To lRow1
For n = 1 To lRow1
If n = rng2.Find(n, , xlValues, xlWhole, , , False) And rng2.Cells(, 2) = "Radio" Then
rng1.Cells(n, 3) = rng1.Cells(n) & " Radio OK"
End If
Next
Next
End Sub
Match Values
Option Explicit
Sub FindValuestest()
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook
' Source
Dim sws As Worksheet: Set sws = wb.Worksheets("EQUIP")
Dim sLast As Long: sLast = sws.Cells(sws.Rows.Count, "A").End(xlUp).Row
Dim srg As Range: Set srg = sws.Range("A1:A" & sLast)
' Destination
Dim dws As Worksheet: Set dws = wb.Worksheets("FEPR")
Dim dLast As Long: dLast = dws.Cells(dws.Rows.Count, "B").End(xlUp).Row
Dim drg As Range: Set drg = dws.Range("B2:B" & dLast)
' Additional Variables
Dim cIndex As Variant
Dim i As Long
' Write
Application.ScreenUpdating = False
For i = 1 To dLast
cIndex = Application.Match(drg.Cells(i).Value, srg, 0)
If IsNumeric(cIndex) Then
If srg.Cells(cIndex).Offset(, 1) _
= "Commodity Tracking Bag Scanner" Then
drg.Cells(i).Offset(, 1).Value = drg.Cells(i) & " Scanner OK"
ElseIf srg.Cells(cIndex).Offset(, 1) = "Radio" Then
drg.Cells(i).Offset(, 2).Value = drg.Cells(i) & " Radio OK"
End If
End If
Next i
Application.ScreenUpdating = True
End Sub