Excel: search for a word in the column and copy it to another column on the same sheet - excel

I have an excel table with rows of data. The column J contains various descriptions of goods. I need to search all the rows in this column for the word LATEX and when it is found, copy ONLY this word to the column A on the same sheet on the same row. I was trying to find a solution and came up with this macro using Autofilter, but it is not working properly. Can you please help me?
Sub FilterAndCopy()
Dim dataWs As Worksheet
Dim copyWs As Worksheet
Dim totRows As Long
Dim lastRow As Long
Set dataWs = Worksheets("Massiv")
Set copyWs = Worksheets("Massiv")
With dataWs
.AutoFilterMode = False
With .Range("J:J")
.AutoFilter Field:=1, Criteria1:="LATEX"
End With
End With
totRows = dataWs.Range("J:J").Rows.count
lastRow = dataWs.Range("J" & totRows).End(xlUp).Row
dataWs.Range("J:J" & lastRow).Copy
copyWs.Range("A6").PasteSpecial Paste:=xlPasteValues
dataWs.AutoFilterMode = False

With the following changes, your code should work. I've noted the changes in the comments in the code.
With dataWs
.AutoFilterMode = False
With .Range("J:J")
'Use wildcard to search for word LATEX within contents of column J cells
.AutoFilter Field:=1, Criteria1:="*LATEX*"
End With
End With
totRows = dataWs.Range("J:J").Rows.Count
lastRow = dataWs.Range("J" & totRows).End(xlUp).Row
'After filtering, select the visible cells in column A...
Set rng = dataWs.Range("A2:A" & lastRow).SpecialCells(xlCellTypeVisible)
'... and set their values to "LATEX"
rng.Value = "LATEX"
dataWs.AutoFilterMode = False

Related

How to hide all rows which have blank cells in a certain column?

I am trying to hide all rows which have blank cells in a certain column (Column H in the SOW tab).
This same macro (different rows but same syntax) worked on the third tab in this workbook. I checked, each row in the range is correct. Could it be that the range is too long?
Sub HideRowsInSOW_LOOP()
Dim r As Range, c As Range
Set r = Range("H27:H46,H48:H67,H69:H88,H90:H109,H111:H130,H132:H151,H153:H172,H174:H193,H195:H214,H216:H235,H237:H256,H258:H277,H279:H298,H300:H319,H321:H340,H342:H361,H369:H388,H390:H409,H411:H430,H432:H451,H453:H472,H474:H493,H495:H514,H516:H535,H537:H556,H558:H577,H579:H598,H600:H619,H621:H640,H642:H661,H663:H682,H684:H703")
Application.ScreenUpdating = False
For Each c In r
If c.Value = 0 Then
c.EntireRow.Hidden = True
Else
c.EntireRow.Hidden = False
End If
Next c
Application.ScreenUpdating = True
End Sub
When running this, I get the following error:
run-time error '1004' error message: Method 'Range' of object
'_Global' failed
I have a much longer macro which serves the same purpose successfully and am worried about it slowing down my workbook/keep hearing that loop is better anyway.
Your code may not be working for the relevant sheet as the range is not fully qualified. Set r = Range("H27:H46,.... The range is referring to the activesheet.
Here is one way using AutoFilter which will hide the blank rows in a column. This is much faster than looping in a huge dataset.
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long
Dim rngColH As Range
Dim rngToHide As Range
'~~> Chage this to the relevant sheet
Set ws = Sheet1
With ws
'~~> Remove any autofilter if any
.AutoFilterMode = False
'~~> Find last row in Col H
lRow = .Range("H" & .Rows.Count).End(xlUp).Row
'~~> Construct your range
Set rngColH = .Range("H1:H" & lRow)
'~~> Filter on blanks
With rngColH
.AutoFilter Field:=1, Criteria1:="="
'~~> These are your blank rows (i.e if there are any)
Set rngToHide = .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow
End With
.AutoFilterMode = False
'~~> Hide the rows
If Not rngToHide Is Nothing Then rngToHide.Hidden = True
End With
End Sub
Here is how it works...
Using .SpecialCells(xlCellTypeBlanks) as #Mikku suggested is also a good approach :)

Using VBA to filter a table and copy certain columns to a new sheet

I have a table Named "Combined" which is stored on one sheet of a work book.
On a second sheet I have the following Cell Range (in C1:F2)
Delivery | Column Ref | Column Ref | Available
Delivery ID | I | J | YES
I want to be able to use VBA to filter the table based on the values in this cell range
The Data drop column is a cell with a drop down list which uses VLOOKUP to populate the two column ref cells. These are the two columns that need to be filtered.
Column I needs to show all rows that <>"X" while column J needs to show all rows that equal the value in the available column.
I then need to be able to copy columns A,G and the column that appears in the first reference cell to cell A5 in the second sheet.
Is it possible to do this using VBA? I have been attempting to do this using IF statements, but it is very messy.
I have a piece of code I am attempting to modify from here
Sub Sample()
Dim ws As Worksheet, wsTemp As Worksheet
Dim rRange As Range, rngToCopy As Range
Dim lRow As Long
Dim lRow2 As Long
Dim lCol As Long
'Find the last non-blank cell in column A(1)
lRow2 = Cells(Rows.Count, 1).End(xlUp).Row
'~~> Change this to the relevant sheet
Set ws = ThisWorkbook.Sheets("Combined")
With ws
'~~> Set your range for autofilter
Set rRange = .Range("A1:AR" & lRow2)
'~~> Remove any filters
.AutoFilterMode = False
'~~> Filter, copy visible rows to temp sheet
With rRange
.AutoFilter Field:=9, Criteria1:="X"
'~~> This is required to get the visible range
ws.Rows("1:lRow2").EntireRow.Hidden = True
Set rngToCopy = .SpecialCells(xlCellTypeVisible).EntireRow
Set wsTemp = Sheets.Add
rngToCopy.Copy wsTemp.Range("A1")
'~~> Unhide the rows
ws.Rows("1:lRow").EntireRow.Hidden = False
End With
'~~> Remove any filters
.AutoFilterMode = False
End With
Application.DisplayAlerts = False
wsTemp.Delete
Application.DisplayAlerts = True
End Sub
But I do not know how to modify the With rRange section to meet my needs (i.e, Column I <>"X" and column J=F2
Additionally this line ws.Rows("1:lRow2").EntireRow.Hidden = True is giving me a type mismatch error
example of combined table
UPDATE
So my code now looks like this thanks to this thread
Sub AddFilter()
'
' AddFilter Macro
'
Dim rCrit1 As Range, rCrit2 As Range, rCrit3 As Range
Dim copyRange1 As Range, copyRange2 As Range, copyRange3 As Range
Dim filterRange As Range
Dim lastRow As Long
Set src = ThisWorkbook.Sheets("Combined")
Set tgt = ThisWorkbook.Sheets("Dashboard")
lastRow = src.Range("A" & src.Rows.Count).End(xlUp).Row
Set filterRange = src.Range("A1:Z" & lastRow)
Set copyRange1 = src.Range("A2:A" & lastRow)
Set copyRange2 = src.Range("G2:G" & lastRow)
Set copyRange3 = src.Range("I2:I" & lastRow)
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set rCrit1 = Worksheets("Dashboard").Range("Ref_1")
Set rCrit2 = Worksheets("Dashboard").Range("Ref_2")
Set rCrit3 = Worksheets("Dashboard").Range("Ref_3")
Sheets("Dashboard").Range("A1:C3").ClearContents
Sheets("Dashboard").Range("A1:C3").ClearFormats
Selection.AutoFilter
filterRange.AutoFilter Field:=rCrit1, Criteria1:="<>X"
filterRange.AutoFilter Field:=rCrit2, Criteria1:=rCrit_3
copyRange1.SpecialCells(xlCellTypeVisible).Copy tgt.Range("A5")
copyRange2.SpecialCells(xlCellTypeVisible).Copy tgt.Range("B5")
copyRange3.SpecialCells(xlCellTypeVisible).Copy tgt.Range("C5")
End Sub
However the filterRange.Autofilter line is not reading the rCrit_3 value correctly and so is not filtering based on this (Ref_3 is a named range which contains the YES cell in the first part of the problem).
Additionally the copyRange lines are giving me '1004' runtime error, but if I minimise the spreadsheet and run the code from the VBA window, it will run error free.
Can anyone shed some light on these issues?

A clean way to copy a range based on a unique ID in Column A?

Question: How can I copy cells B through Y for all rows based on a unique ID in Column A? I can't copy the entire row, just that range.
screenshot with music data
My method: I copy the sheet > filter > copy visible cells > delete visible cells > move to next filter entry and repeat.
The problem: Some maps (esp. small ones) don't copy. I'd also like a simpler way to do it. I made this file for me just to concat XML together. But now several Mac users are using it and having more problems due to this part of the code.
Sub mapmaker()
Dim LR As Long
Dim Rng As Range
Dim mws As Worksheet
Dim c As Range, i As Long
Dim lastrow As Long, nextrow As Long
Dim cn As Range, rn As Range
Dim output As String
' duplicate sheet with data to copy, set range, see if range contains data
Set rn = Sheets("XML").Range("DR1:DR505")
Application.ScreenUpdating = False
Sheets("Master").Copy After:=Sheets("Master")
ActiveSheet.Name = "MstrCpy"
Sheets("MstrCpy").Select
Range("A1").Select
Set Rng = Worksheets("MstrCpy").Range("A2:A1000")
Set mws = Worksheets("MstrCpy")
If WorksheetFunction.CountA(Rng) < 1 Then Exit Sub
With mws
' count number of entries
i = WorksheetFunction.CountA(Rng)
'turn off any previous filters
If .AutoFilterMode = True Then .AutoFilterMode = False
'loop through cells, filter and copy results
For Each c In .Range("A2:A" & i)
Sheets("XML").Range("A8:X1000").ClearContents
Sheets("MstrCpy").Select
nextrow = Sheets("MstrCpy").Cells(Rows.Count, "A").End(xlUp).Row
lastrow = .Cells(Rows.Count, "A").End(xlUp).Row
.Range("A1").AutoFilter Field:=1, Criteria1:="=" & Range("A2").Value
.Range("B2:Y" & lastrow).SpecialCells(xlCellTypeVisible).Copy Sheets("XML").Range("A8")
.Range("A2").Copy Sheets("XML").Range("B4")
.Range("B2:Y" & lastrow).SpecialCells(xlCellTypeVisible).EntireRow.Delete
Sheets("MstrCpy").Select
.AutoFilterMode = False
Sheets("XML").Select
output1 = Range("BB2").Value
output2 = Range("BB3").Value
Open output1 For Output As #1
For Each cell In rn
Print #1, cell.Value & Chr(10)
Next
Close
Name output1 As output2
Sheets("MstrCpy").Select
Next c
'turn off filtering
.AutoFilterMode = False
End With
Application.DisplayAlerts = False
Sheets("MstrCpy").Delete
Sheets("Master").Select
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
I tend to write things less backwards now. But I don't know VBA well enough to figure this out and my attempts have failed. The similar questions I've seen don't seem to be useful here. Any help would be greatly appreciated and would aid more people than just myself. Thank you!
-Sean

Copy rows in Excel if cell contains name from an array

I have an Excel sheet that contains entries for ~150 employees. Each row contains the name as well as hours worked, pay, team, etc etc etc etc. The B column in each row contains the employees name in Last,First format. About half the employees on the sheet are part time employees. What i'm trying to do is write a macro in VB that copies the entire row if the name in the B column matches one of the names of the part time employees so that one of my coworkers can simply run the macro and paste all of the rows of copied users into a new sheet each week. Here's what I currently have. (I have all of the employees names in the array however I have censored them out) I really don't understand much of the last 50% of the code. This stuff was stuff I found online and have been messing around with.
`Sub PartTime()
Dim strArray As Variant
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim NoRows As Long
Dim DestNoRows As Long
Dim I As Long
Dim J As Integer
Dim rngCells As Range
Dim rngFind As Range
Dim Found As Boolean
nameArray = Array(NAMES CENSORED)
Set wsSource = ActiveSheet
NoRows = wsSource.Range("A65536").End(xlUp).Row
DestNoRows = 1
Set wsDest = ActiveWorkbook.Worksheets.Add
For I = 1 To NoRows
Set rngCells = wsSource.Range("C" & I & ":F" & I)
Found = False
For J = 0 To UBound(strArray)
Found = Found Or Not (rngCells.Find(strArray(J)) Is Nothing)
Next J
If Found Then
rngCells.EntireRow.Copy wsDest.Range("A" & DestNoRows)
DestNoRows = DestNoRows + 1
End If
Next I
End Sub`
This code should work for what you are looking for. It is important to note that the string names in your array must be identical to that in Column B (with the exception of leading and trailing spaces), so if the names are written "LastName, FirstName" then your input data must be identical. This code could be tweaked to not have this requirement, but for now I've left it as such. Let me know if you'd prefer the code be adjusted.
Option Explicit
Sub PartTimeEmployees()
Dim NewSheet As Worksheet, CurrentSheet As Worksheet, NameArray As Variant
Set CurrentSheet = ActiveWorkbook.ActiveSheet
Set NewSheet = Sheets.Add(After:=Sheets(Worksheets.Count))
NewSheet.Name = "Part Time Employees"
NameArray = Array("NAMES CENSORED")
'Pulling headers from the first row
CurrentSheet.Rows(1).EntireRow.Copy
NewSheet.Select 'Redundant but helps avoid the occasional error
NewSheet.Cells(1, 1).Select
ActiveSheet.Paste
CurrentSheet.Select
Dim NextRow As Long
NextRow = 2
'Writing this code to not assume that the data is continuous
Dim Count As Long
'Iterating to the end of the data in the sheet
For Count = 2 To CurrentSheet.UsedRange.Rows.Count
If Not IsEmpty(CurrentSheet.Cells(Count, 2)) Then
For Counter = 1 To UBound(NameArray)
'Performing string operations on the text will be faster than the find method
'It is also essential that the names are entered identically in your array
If UCase(Trim(CurrentSheet.Cells(Count, 2).Value)) = UCase(NameArray(Counter)) Then
CurrentSheet.Rows(Count).Copy
NewSheet.Select
NewSheet.Cells(NextRow, 1).Select
ActiveSheet.Paste
CurrentSheet.Select
NextRow = NextRow + 1
Exit For
End If
Next Counter
End If
Next Count
End Sub
No need to loop through the array if you use a Range.AutoFilter Method with the array as criteria.
See comment for each line of operational code.
Option Explicit
Sub partTimers()
Dim nameArray As Variant
'construct an array of the part-time employees' names
nameArray = Array("Trgh, Evtfk", "Mtre, Sdnrm", _
"Sfgd, Pxduj", "Lsds, Qwrml", _
"Eqrd, Oqtts")
With Worksheets("Sheet1") 'you should know what worksheet the names are on
'turn off AutoFilter is there is one already in operation
If .AutoFilterMode Then .AutoFilterMode = False
'use the 'island' of cells radiating out from A1
With .Cells(1, 1).CurrentRegion
'apply AutoFilter using array of names as criteria
.AutoFilter field:=2, Criteria1:=nameArray, Operator:=xlFilterValues
'check if there is anything to copy
If Application.Subtotal(103, .Columns(2)) > 1 Then
'copy the filtered range
.Cells.Copy
'create a new worksheet
With .Parent.Parent.Worksheets.Add(After:=Sheets(Sheets.Count))
'paste the filtered range, column widths and cell formats
.Cells(1, 1).PasteSpecial Paste:=xlPasteColumnWidths
.Cells(1, 1).PasteSpecial Paste:=xlPasteFormats
.Cells(1, 1).PasteSpecial Paste:=xlPasteValues
End With
End If
End With
'turn off the AutoFilter
If .AutoFilterMode Then .AutoFilterMode = False
'turn off active copy range
Application.CutCopyMode = False
End With
End Sub

Moving rows based on column values

I need to scan through all of the rows in the "Master" worksheet, find any cells with the value "Shipped" in the column "Status", then cut and paste each entire row to another sheet. The pasted rows need to be placed after the last row also.
I found this post (pasted below) which I slightly modified to delete rows successfully. But I can not figure out how to move rows instead. Should I try an entirely new method?
Sub DeleteRows()
Dim rng As Range
Dim counter As Long, numRows as long
With ActiveSheet
Set rng = Application.Intersect(.UsedRange, .Range("C:C"))
End With
numRows = rng.Rows.Count
For counter = numRows to 1 Step -1
If Not rng.Cells(counter) Like "AA*" Then
rng.Cells(counter).EntireRow.Delete
End If
Next
End Sub
I do not know VBA. I only kind of understand it because of my brief programming history. I hope that is okay and thank you for any help.
There's a couple of ways you could do it, can you add a filter to the top columns, filter by the value of 'Shipped'? Does it need to be copy and pasted into a new sheet?
It's not the most concise code but it might work
sub Shipped_filter()
dim wsSheet as worksheet
dim wsOutputSheet as worksheet
dim BottomRow as integer
Set wsSheet = worksheets("Sheet1") 'change to the sheet name
set wsOutputSheet = worksheets("Sheet2") 'change to the sheet name
'*****************************
'* Delete old data on Sheet2 *
'*****************************
wsoutputsheet.activate
Activesheet.cells.clearall
wsSheet.range("A1").select
selection.autofilter
BottomRow = wsSheet.range("A90000").end(xlup).row ' or another column you guarantee will always have a value
activesheet.range("$A$1:$Z$"&BottomRow).AutoFilter field:=1, Criteria1:="Shipped" ' change field to whatever column number Status is in
'********************************
'* Error trap in case no update *
'********************************
if activesheet.range("A90000").end(xlup).row = 1 then
msgbox("Nothing to ship")
exit sub
end if
wsSheet.range("A1:Z"&Bottomrow).select
selection.copy
wsOutputSheet.range("A1").select
selection.pastespecial Paste:=xlpastevalues
application.cutcopymode = false
msgbox('update complete')
end sub
I haven't tried it so it might need updating
I ended up combining the code I was originally using (found here) with an AutoFilter macro (found here). This is probably not the most efficient way but it works for now. If anyone knows how I can use only the For Loop or only the AutoFilter method that would be great. Here is my code. Any edits I should make?
Sub DeleteShipped()
Dim lastrow As Long
Dim rng As Range
Dim counter As Long, numRows As Long
With Sheets("Master")
'Check for any rows with shipped
If .Range("R:R").Find("Shipped", , xlValues, xlWhole, , , False) Is Nothing Then
MsgBox "No shipped plates found. ", , "No Rows Moved": Exit Sub
Else
Application.ScreenUpdating = False
'Copy and paste rows
lastrow = .Range("A" & Rows.Count).End(xlUp).Row
lastrow2 = Worksheets("ShippedBackup").Cells(Rows.Count, "A").End(xlUp).Row + 1
.Range("A1:U" & lastrow).AutoFilter field:=18, Criteria1:="Shipped"
.Range("A2:U" & lastrow).SpecialCells(xlCellTypeVisible).EntireRow.Copy
Sheets("ShippedBackup").Range("A" & lastrow2).PasteSpecial xlPasteValues, xlPasteSpecialOperationNone, False, False
.ShowAllData
'Delete rows with shipped status
Set rng = Application.Intersect(.UsedRange, .Range("R:R"))
numRows = rng.Rows.Count
For counter = numRows To 1 Step -1
If rng.Cells(counter) Like "Shipped" Then
rng.Cells(counter).EntireRow.Delete
End If
Next
MsgBox "All shipped records have been moved to the ""ShippedBackup"" worksheet.", , "Backup Complete"
End If
End With
Hope it helps someone!

Resources