The code below will create a new sheet for each cell in column A. The second module will copy all rows that have a specific value in column A to a specific destination.
I created this so each work order number gets its own sheet and all rows with that work order number is copied over to the sheet named that work order number.
The issue is there are 604 unique work order numbers and I have to edit the second module for each work order in order for it to work.
Is there some way I could have it loop through all the values in column A and maybe compare it to a set variable and then copy the rows to the sheet that has that work order number? I don't know how to make the destination sheet be whatever new value is found in column A.
I'm new to VBA, so this question probably doesn't make much sense. And yes I have seen code for creating and naming a sheet based on each new work order in one module but it generally won't compile so I split the process out to 2 modules.
Anyway, to better understand what I mean: say column A has 4 rows for work order number 1234. I'd need the macro to copy all 4 rows for 1234 into the sheet that is named 1234. Then move on to the next work order number.
The range it is checking for work orders in is A2:A39986, but the full range is A2:F39986.
Thank you for your time.
Option Explicit
Sub parse_data()
Dim xRCount As Long
Dim xSht As Worksheet
Dim xNSht As Worksheet
Dim I As Long
Dim xTRow As Integer
Dim xCol As New Collection
Dim xTitle As String
Dim xSUpdate As Boolean
Set xSht = ActiveSheet
On Error Resume Next
xRCount = xSht.Cells(xSht.Rows.Count, 1).End(xlUp).Row
xTitle = "A60:A604"
xTRow = xSht.Range(xTitle).Cells(1).Row
For I = 2 To xRCount
Call xCol.Add(xSht.Cells(I, 1).Text, xSht.Cells(I, 1).Text)
Next
xSUpdate = Application.ScreenUpdating
Application.ScreenUpdating = False
For I = 1 To xCol.Count
Call xSht.Range(xTitle).AutoFilter(1, CStr(xCol.Item(I)))
Set xNSht = Nothing
Set xNSht = Worksheets(CStr(xCol.Item(I)))
If xNSht Is Nothing Then
Set xNSht = Worksheets.Add(, Sheets(Sheets.Count))
xNSht.Name = CStr(xCol.Item(I))
Else
xNSht.Move , Sheets(Sheets.Count)
End If
xSht.Range("A" & xTRow & xRCount).EntireRow.Copy xNSht.Range("A60")
xNSht.Columns.AutoFit
Next
xSht.AutoFilterMode = False
xSht.Activate
Application.ScreenUpdating = xSUpdate
End Sub
and the module that copies data to a specific destination:
Sub CopyColumnOver()
Dim wsSource As Worksheet
Dim wsDestin As Worksheet
Dim lngDestinRow As Long
Dim rngSource As Range
Dim rngCel As Range
Set wsSource = Sheets("Sheet1") 'Edit "Sheet1" to your source sheet name
Set wsDestin = Sheets("11556")
With wsSource
'Following line assumes column headers in Source worksheet so starts at row2
Set rngSource = .Range(.Cells(2, "A"), .Cells(.Rows.Count, "A").End(xlUp))
End With
For Each rngCel In rngSource
If rngCel.Value = "11556" Then
With wsDestin
'Following line assumes column headers in Destination worksheet
lngDestinRow = .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).Row
rngCel.EntireRow.Copy Destination:=wsDestin.Cells(lngDestinRow, "A")
End With
End If
Next rngCel
End Sub
Related
I have a huge list of data and column 3 contains email addresses.
I'm trying to copy rows based on a mailing list. As long as the row contains one of the email addresses in the mailing list it should be copied to a new sheet.
I have code to copy data based on one email at a time.
I have a userform set up for several email addresses, but this is not efficient.
Here is my code that uses one email address at a time.
Private Sub CommandButton1_Click()
a = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To a
If Worksheets("Sheet1").Cells(i, 3).Value = "<#gmail.com>" Then
Worksheets("Sheet1").Rows(i).Copy
Worksheets("Sheet2").Activate
b = Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row
Worksheets("Sheet2").Cells(b + 1, 1).Select
ActiveSheet.Paste
Worksheets("Sheet2").Activate
End If
Next
Application.CutCopyMode = False
End Sub
How to copy rows based on multiple emails addresses?
I would suggest using the Advanced Filter The destination range will get written in a single step. If you can minimize the number of times your code reads/writes to/from a worksheet, the faster it will run.
Sheet 1
Read the comments in the code as they will be important for modifying it to your real data.
In particular, if your column 3 list does not have the same format as what you have shown in your code, you will need to modify the Criteria range to account for that. The Advanced Filter can also accept wild-cards in the criteria, so this might be another possible approach if your column 3 contains actual email addresses.
Option Explicit
Sub copyWithEmail()
Dim wsSrc As Worksheet, wsDest As Worksheet
Dim rSrc As Range, rDest As Range, rCrit As Range
Dim arrCrit As Variant
Dim I As Long
Set wsSrc = Worksheets("sheet1")
Set wsDest = Worksheets("sheet2")
With wsDest
.Cells.Clear 'optional
Set rCrit = .Cells(1, 250) 'someplace off the screen view
Set rDest = .Cells(1, 1)
End With
'assumes original data starts in A1
'assumes first row is a header row
Set rSrc = wsSrc.Cells(1, 1).CurrentRegion
'can get list of desired emails from user form; range someplace in the workbook; or hard-coded as we have here
arrCrit = Array("gmail.com", "abc.com")
For I = 0 To UBound(arrCrit)
'creating formula that mimics what you show in your code above.
arrCrit(I) = "=" & """=<#" & arrCrit(I) & ">"""
Next I
'create criteria range
'header is same header as in Source Data column 3
Set rCrit = rCrit.Resize(2 + UBound(arrCrit))
rCrit(1) = rSrc(1, 3)
rCrit.Offset(1).Resize(rCrit.Rows.Count - 1) = WorksheetFunction.Transpose(arrCrit)
'Activate wsDest since we will be copying here
wsDest.Activate
rSrc.AdvancedFilter Action:=xlFilterCopy, _
CriteriaRange:=rCrit, CopyToRange:=rDest, Unique:=False
rDest.CurrentRegion.EntireColumn.AutoFit
rCrit.Clear 'get rid of this range
End Sub
Sheet 2
May be something like having Sheet3 of mialList and then
Private Sub CommandButton1_Click()
Dim Sh1 As Worksheet, Sh2 As Worksheet, Sh3 As Worksheet, fnd As Range, cl As Range
Set Sh1 = Worksheets("Sheet1")
Set Sh2 = Worksheets("Sheet2")
Set Sh3 = Worksheets("Sheet3")
Dim mailList As Range
x = Sh3.Range("A" & Sh3.Rows.Count).End(xlUp).Row
Set mailList = Sh3.Range("A2:A" & x)
'Assuming headers in row 1
For Each cl In mailList
b = Sh2.Range("A" & Sh2.Rows.Count).End(xlUp).Row + 1
Set fnd = Sh1.Columns(3).Find(cl)
If Not fnd Is Nothing Then
Sh2.Rows(b).Value = Sh1.Rows(fnd.Row).Value
End If
Next
End Sub
I am new to VBA and I am trying to write some code to copy data from one worksheet to another one. I have checked various sites and tried to write the code, but until I always get an error. The setting is as follows:
I have various worksheets, most of them are worksheets based on different teams (I will call them Team-Worksheets), one sheet is the data I import from an external databank (I will call it Import-Worksheet).
The code should loop through all the Team-Worksheets and based on the Name of the Team, which is always located in Cell “A2” it should find all stories that belong to the team in the “Import-Worksheet”(comparing it with “Team Name Column”) and ONLY copy the “ID” located in the “ID Column” and paste it into the second row of “ID Column” of the ListObject 1 of the corresponding "Team-Worksheet". Then it should find the next ID of that Team in the “Import-Worksheet” and copy-paste it into the next row of ListObject 1(all sheets have multiple listobjects, with varying length and start points). After it went through all the rows it should continue with the next “Team-Worksheet”.
I am unsure if I should run a 1) "for-loop" + "for-loop" 2) “for-loop” + an “advanced-filter”, or 3) “for-loop” + “for-loop combined with index/match”?
I used if B4 = Epic Id Link as I don't want to apply this to all the worksheets
Example 1:
Sub AddContent()
Dim sht As Worksheet
Dim i As Variant
Dim x As Long
Dim y As Worksheet
Dim rw As Range
Application.ScreenUpdating = False
For Each sht In ThisWorkbook.Worksheets
sht.Activate
i = sht.Range("A2")
Set y = ActiveSheet
If sht.Range("B4").Value = "EPIC ID Link" Then
Sheets("Jira Import").Select
' Find the last row of data
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
' Loop through each row
For x = 5 To FinalRow
' Decide if to copy based on column D
ThisValue = Cells(x, 19).Value
If ThisValue = i Then
Cells(x, 4).Copy
y.ListObjects(1).ListColumns("US ID").Select
NextRow = Cells(Rows.Count, 1).End(xlUp).Row + 1
Cells(NextRow, 1).Select
ActiveSheet.Paste
Sheets("Jira Import").Select
End If
Next x
End If
Next sht
Application.ScreenUpdating = True
End Sub
Example 2:
Sub AddContent()
Dim sht As Worksheet
Dim i As Variant
Dim rgData As Range, rgCriteria As Range, rgOutput As Range
Application.ScreenUpdating = False
For Each sht In ThisWorkbook.Worksheets
sht.Activate
Set i = ActiveSheet.Range("A2")
If sht.Range("B4").Value = "EPIC ID Link" Then
Set rgData = ThisWorkbook.Worksheets("Jira Import").Range("S5").CurrentRegion
Set rgCriteria = i
Set rgOutput = ActiveSheet.ListObjects(1).ListColumns("US ID").DataBodyRange
rgData.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=rgOutput, Unique:=True
End If
Next sht
Application.ScreenUpdating = True
End Sub
Solving this would save me plenty of manual work!
The following code seems to run smoothly but nothing was copied onto the desired page
Sub a2()
Sheets.Add.Name = "25 degree"
Sheets("25 degree").Move after:=Sheets("data")
Dim x As Long
For x = 2 To 33281
If Cells(x, 1).Value = 25 Then
Cells("x,1:x,2:x,3:x,4:x,5:x,6").Copy
Worksheets("25 degree").Select
ActiveSheet.Paste
End If
Next x
End Sub
I highly recommend not to use .Select or ActiveSheet instead specify the sheet for each Cells() object according to How to avoid using Select in Excel VBA.
Option Explicit
Public Sub DoSomeCoypExample()
Dim wsSource As Worksheet
Set wsSource = ThisWorkbook.ActiveSheet
'better define by name
'Set wsSource = ThisWorkbook.Worksheets("source sheet")
Dim wsDestination As Worksheet
Set wsDestination = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Worksheets("data")) 'add at the correct position and set it to a variable
wsDestination.Name = "25 degree" 'so you can use the variable to access the new added worksheet.
Dim iRow As Long
For iRow = 2 To 33281 'don't use fixed end numbers (see below if you meant to loop until the last used row)
If wsSource.Cells(iRow, 1).Value = 25 Then
With wsSource
.Range(.Cells(iRow, 1), .Cells(iRow, 6)).Copy Destination:=wsDestination.Range("A1")
'this line will copy columns 1 to 6 of the current row
'note you need to specify the range where you want to paste
'if this should be dynamic see below.
End With
End If
Next iRow
End Sub
If you want to loop until the last used row you can get that with something like
Dim LastRow As Long
LastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row 'last used row in column A
If you want to paste into the next free row in your destination worksheet instead of a fixed range Destination:=wsDestination.Range("A1") you can use the same technique as above to finde the next free row:
Dim NextFreeRow As Long
NextFreeRow = wsDestination.Cells(wsDestination.Rows.Count, "A").End(xlUp).Row + 1
So you can use that in your paste destination:
Destination:=wsDestination.Range("A" & NextFreeRow)
I'm working with two workbooks. In the first I search for the value in the cell to the right of "Charge Number". Take that value and search the second workbooks pivot table for the matching row, copy it and go back to first work book and paste the data. This works great once. But I'm unable to get a loop to look for the next instance of "Charge Number" and repeat the process. The loop I have in the code isn't right because it finds the first value fine but then searches every next row for the same Charge Number.
Sub FindChargeNo()
Dim Loc As Range
Dim ChgNum As String
Dim SrchRng2 As String
Dim pvt As PivotTable
Dim wb As Workbook, ws As Worksheet
Dim FstWB As Workbook
Dim SecWB As Workbook
Dim rng As Range
Set FstWB = Workbooks("First.xlsm")
Set SecWB = Workbooks("Second_test.xlsx")
Set ws1 = FstWB.Worksheets("New Development")
Set ws = SecWB.Worksheets("Aug 18 Report")
Set pvt = ws.PivotTables(1)
lastRow = FstWB.Worksheets("New Development").Range("J" & Rows.Count).End(xlUp).Row
For i = 1 To lastRow
Set Loc = ws1.Cells.Find(What:="Charge Number")
If Not Loc Is Nothing Then
ChgNum = Loc.Offset(0, 1).Value
Debug.Print ChgNum
Debug.Print SrchRng
With pvt.PivotFields("Project WBS").PivotItems(ChgNum).LabelRange
Set rng = ws.Range(.Resize(.Rows.Count, pvt.TableRange1.Columns.Count).Address)
ws.Range(rng.Address).Copy
End With
SrchRng2 = Loc.Offset(0, 5).Address
FstWB.Worksheets("New Development").Range(SrchRng2).PasteSpecial
Set Loc = ws1.Cells.FindNext(Loc)
Loop While Loc.Address <> firstAddress
End If
Next
End Sub
I've got a database with a long list of names, and unique values associated with the names. What I want to do is create one worksheet for each individual, and then copy only their data to a specified range in their worksheet, then proceed to the next individual, copy their data to their worksheet etc.
Here is a link to an example worksheet (in google docs form, note - I am actually using Excel 2010, not google docs).
I've been able to create all the worksheets through using the following code in a new sheet I called "Employee". All I did to this sheet was remove the duplicate name values so I could have a list of all the names for the worksheets.
Any help is much appreciated. Thanks in advance.
Sub CreateSheetsFromAList()
Dim nameSource As String 'sheet name where to read names
Dim nameColumn As String 'column where the names are located
Dim nameStartRow As Long 'row from where name starts
Dim nameEndRow As Long 'row where name ends
Dim employeeName As String 'employee name
Dim newSheet As Worksheet
nameSource = "Employee"
nameColumn = "A"
nameStartRow = 1
'find the last cell in use
nameEndRow = Sheets(nameSource).Cells(Rows.Count, nameColumn).End(xlUp).Row
'loop till last row
Do While (nameStartRow <= nameEndRow)
'get the name
employeeName = Sheets(nameSource).Cells(nameStartRow, nameColumn)
'remove any white space
employeeName = Trim(employeeName)
' if name is not equal to ""
If (employeeName <> vbNullString) Then
On Error Resume Next 'do not throw error
Err.Clear 'clear any existing error
'if sheet name is not present this will cause error that we are going to leverage
Sheets(employeeName).Name = employeeName
If (Err.Number > 0) Then
'sheet was not there, so it create error, so we can create this sheet
Err.Clear
On Error GoTo -1 'disable exception so to reuse in loop
'add new sheet
Set newSheet = Sheets.Add(After:=Sheets(Sheets.Count))
'rename sheet
newSheet.Name = employeeName
'paste training material
Sheets(employeeName).Cells(1, "A").PasteSpecial
Application.CutCopyMode = False
End If
End If
nameStartRow = nameStartRow + 1 'increment row
Loop
End Sub
Bare bones approach - could be optimized for better performance, but it will do the job.
Sub SplitToSheets()
Dim c As Range, ws As Worksheet, rngNames
With ThisWorkbook.Sheets("EmployeeData")
Set rngNames = .Range(.Range("A1"), .Cells(Rows.Count, 1).End(xlUp))
End With
For Each c In rngNames.Cells
Set ws = GetSheet(ThisWorkbook, c.Value)
c.EntireRow.Copy ws.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next c
End Sub
Function GetSheet(wb As Workbook, wsName As String, _
Optional CreateIfMissing As Boolean = True) As Worksheet
Dim ws As Worksheet
On Error Resume Next
Set ws = wb.Sheets(wsName)
On Error GoTo 0
If ws Is Nothing And CreateIfMissing Then
Set ws = wb.Sheets.Add(after:=wb.Sheets(wb.Sheets.Count))
ws.Name = wsName
End If
Set GetSheet = ws
End Function