Sorting a Large Excel Spreadsheet by Date - Fails on 3rd Iteration - vba

I am new to VBA as a language, and I'm having issues sorting a large spreadsheet. The sheet is roughly 400,000 rows by 8 columns. The relevant data begins on row 5. In Column C, I changed the format of the date and rounded it down to give a single integer representing the day.
The goal is to find where the data changes days, and cut and paste all of that day's data to a seperate tab. The code I have written successfully does this for the first 2 days, but the 3rd iteration and beyond will not work properly. I have used a color code (blue) to represent the last row for each day, and I'm using this color change as my loop condition. The 3rd loop ignores the 1st color change and instead cuts and pastes 2 day's worth of data, and the 4th loop moves 3 days.
Would there be a more efficient way to move each day's data to a new tab? Each day represents 28800 rows by 6 columns. It should be noted that an additional macro is run before this in order to simply organize the raw data. The portion of the code giving me issues are the loops following the "Sort the data by date" comment.
Any help would be greatly appreciated! Thanks in advance. Attached is my code and a sample of the data
Sub HOBO_Split_v2()
'Before this code can be run, you must run "Hobo_Organize" 1 time. Press 'Ctrl + Shift + O' to do this
'The purpose of this code is to separate the hobo data by day. Weekends and evenings will be removed.
'This will create smaller data sets, which allows for easier data manipulation
Application.ScreenUpdating = False
'Find the last row
Lastrow = Range("C" & Rows.Count).End(xlUp).Row
'Set the known parameters
Dim days As Range
Set days = Worksheets("Full Data Set").Range("C5:C" & Lastrow)
Dim daychanges As String
daychanges = 0
'Maximum of 3 weeks of data, 21 different sheets
Dim sheetnum(1 To 21) As Integer
For i = 1 To 21
sheetnum(i) = i
Next i
'Loop through the day index (Col C), counting the number of day changes
For Each cell In days
If cell.Value <> cell.Offset(1).Value Then
cell.Interior.ColorIndex = 37
daychanges = daychanges + 1
End If
Next cell
'Add new sheets for each day and rename the sheets
Sheets.Add after:=ActiveSheet
ActiveSheet.Name = "Day 1"
For i = 2 To daychanges
Sheets.Add Before:=ActiveSheet
ActiveSheet.Name = "Day " & sheetnum(i)
Next i
Sheets("Full Data Set").Select
'Sort the data by date
For Each cell In days
If cell.Interior.ColorIndex = 37 Then
cell.Select
Range(Selection, Selection.End(xlUp)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Cut
Worksheets(Worksheets.Count).Select
ActiveSheet.Range("B2").Select
ActiveSheet.Paste
Application.CutCopyMode = False
ActiveSheet.Move Before:=Sheets("Full Data Set")
Sheets("Full Data Set").Select
Range("C4").Select
Selection.End(xlDown).Select
Range(Selection, Selection.End(xlDown)).Select
Set days = Selection
End If
Next cell
Application.ScreenUpdating = True
End Sub
Example of the data

I'd not pass through any cell coloring and use RemoveDuplicates() method of Range object as like follows:
Option Explicit
Sub HOBO_Split_v2()
Dim datesRng As Range, dataRng As Range, cell As Range
Dim iDay As Long
Application.ScreenUpdating = False
With ThisWorkbook.Worksheets("Full Data Set")
Set datesRng = .Range("C5", .Cells(.Rows.Count, 3).End(xlUp)) '<--| set dates range
Set dataRng = datesRng.offset(-1).Resize(datesRng.Rows.Count + 1, 6) '<--| set data range as dates one extended to next 5 columns
With datesRng.offset(, .UsedRange.Columns.Count) '<--| use a helper column out of current used range
.value = datesRng.value '<--| copy dates value in helper column
.RemoveDuplicates Columns:=Array(1) '<--| remove duplicates and have only unique values in helper column
For Each cell In .Cells.SpecialCells(xlCellTypeConstants, xlNumbers) '<--| iterate through remaining (unique) day values in helper column
iDay = iDay + 1 '<--| update "current day" counter
dataRng.AutoFilter Field:=1, Criteria1:=Format(cell, "#.00") '<--| filter data by "current day", format the criteria as the actual column C cells format
dataRng.offset(1).Resize(dataRng.Rows.Count - 1).SpecialCells(xlCellTypeVisible).Copy Destination:=SetWorkSheet(ThisWorkbook, "Day " & iDay).Range("B2") '<--| copy filtered data and paste the into "current day" corresponding sheet
Next cell
.Parent.AutoFilterMode = False '<--| remove autofilter
.Clear '<--| clear helper column
End With
End With
Application.ScreenUpdating = True
End Sub
Function SetWorkSheet(wb As Workbook, SheetName As String) As Worksheet
On Error Resume Next
Set SetWorkSheet = wb.Worksheets(SheetName)
On Error GoTo 0
If SetWorkSheet Is Nothing Then
Set SetWorkSheet = wb.Worksheets.Add(after:=wb.Worksheets(wb.Worksheets.Count))
SetWorkSheet.Name = SheetName
Else
SetWorkSheet.UsedRange.Clear '<--| clear preceeding values in already existent sheet
End If
End Function

There is no need to iterate over the list twice. GetWorkSheet create the new worksheets for you if they don't exist and handle any errors.
Sub HOBO_Split_v2()
Application.ScreenUpdating = False
Dim cell As Range, days As Range
Dim lFirstRow As Long, Lastrow As Long
Dim SheetName As String
Dim ws As Worksheet
With Sheets("Full Data Set")
Lastrow = Range("C" & Rows.Count).End(xlUp).Row
Set days = .Range("C5:C" & Lastrow)
For Each cell In days
If c.Text <> SheetName Or c.Row = Lastrow Then
If lFirstRow > 0 Then
Set ws = getWorkSheet(SheetName)
.Range("A" & lFirstRow, "A" & cell.Row).EntireRow.Copy ws.Range("A1")
End If
SheetName = c.Text
lFirstRow = i
End If
Next
End With
Application.ScreenUpdating = True
End Sub
Function getWorkSheet(SheetName As String) As Worksheet
Dim ws As Worksheet
On Error Resume Next
Set ws = Worksheets(SheetName)
If ws Is Nothing Then
Set ws = Worksheets.Add(after:=ActiveSheet)
ws.Name = SheetName
End If
On Error GoTo 0
Set getWorkSheet = ws
End Function

Related

VBA code to add days from one column to another

I'm having the following columns in Excel: Document Date (all cells have values) & Initial Disposition Date (there're blanks within the column).
Each Document Date cell corresponds to an Initial Disposition Date cell.
For any blank Initial Disposition Date cells, I'd like to set them to be 7 days from the corresponding Document Date. (Strictly blank cells)
Ex: Document Date = 10/01/2018. Desired Initial Disposition Date = 10/08/2018.
Is there a code to execute such action? (I have approximately 55,000 rows and 51 columns by the way).
Thank you very much! Any suggestions or ideas are highly appreciated!
Looping through a range is a little quicker in this case. I am assuming your data is on Sheet1, your Document Date is on Column A and your Initial Deposition is on Column B.
Last, you need to determine if you want that 7 days to be inclusive of weekends or not. I left you a solution for both. You will need to remove one of the action statements (in middle of loop)
Option Explicit
Sub BetterCallSaul()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim LRow As Long, iRange As Range, iCell As Range
LRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
Set iRange = ws.Range("B2:B" & LRow)
Application.ScreenUpdating = False
For Each iCell In iRange
If iCell = "" Then
iCell = iCell.Offset(, -1) + 7 'Includes Weekends
iCell = WorksheetFunction.WorkDay(iCell.Offset(, -1), 7) 'Excludes Weekends
End If
Next iCell
Application.ScreenUpdating = True
End Sub
If your Document Date is on Column A and you Initial Disposition Date in Column B, then the following would achieve your desired results:
Sub foo()
Dim ws As Worksheet: Set ws = Sheets("Sheet1")
'declare and set the worksheet you are working with, amend as required
Lastrow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
'get the last row with data on Column A
For i = 2 To Lastrow
'loop from row 2 to the last row with data
If ws.Cells(i, "B").Value = "" Then
'if there is no value in Column B then
ws.Cells(i, "B").Value = ws.Cells(i, "A").Value + 7
'add seven days to the date from Column A
End If
Next i
End Sub
A formula on all blanks would avoid the delays looping through the worksheet column(s).
Sub ddPlus7()
Dim dd As Long, didd As Long
With Worksheets("sheet1")
'no error control on the next two lines so those header labels better be there
dd = Application.Match("Document Date", .Rows(1), 0)
didd = Application.Match("Desired Initial Disposition Date", .Rows(1), 0)
On Error Resume Next
With Intersect(.Columns(dd).SpecialCells(xlCellTypeConstants, xlNumbers).EntireRow, _
.Columns(didd).SpecialCells(xlCellTypeBlanks).EntireRow, _
.Columns(didd))
.FormulaR1C1 = "=rc[" & dd - didd & "]+7"
End With
On Error GoTo 0
End With
End Sub

Looping and finding similar number in VBA

I am very new to VBA. Just started reading it up 2 days ago. I am wondering how could I write a VB codes assigned to a button to read through the whole column and search for similar numbers.
After that identifying similar numbers, it would need to move on to another column to check if the character in the column are same too.
If both of the logic = true . How can i change the cell of the value of another column?
Sample data
For the current example. The code should know that the first column had matching numbers. After that it will check for the name which is "a" in the example. After that it will automatically change the point to 1 and 0. If there are 3 same ones it will be 1,0,0 for the point
You may try recording whatever you want to do with record macros first, then filter out the codes that are not necessary. If you do not know how to record it using macros, click on the link below. You can learn from the recorded macros and slowly improvise your codes in the future from the experience you may gain.
Here's [a link] (http://www.dummies.com/software/microsoft-office/excel/how-to-record-a-macro-in-excel-2016/)
As per image attached in image I am assuming numbers are in Column A, column to check characters is Column J and result needs to be displayed in Column O then try following code.
Sub Demo()
Dim dict1 As Object
Dim ws As Worksheet
Dim cel As Range, fCell As Range
Dim lastRow As Long, temp As Long
Dim c1
Set dict1 = CreateObject("Scripting.Dictionary")
Set ws = ThisWorkbook.Sheets("Sheet2") 'change Sheet2 to your data sheet
With ws
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row 'last row with data in Column A
c1 = .Range("A2:A" & lastRow)
For i = UBound(c1, 1) To 1 Step -1 'enter unique values with corresponding values in dict1
dict1(c1(i, 1)) = .Range("J" & i + 1) '+1 for Row 2
Next i
Set fCell = .Range("A2")
For Each cel In .Range("A2:A" & lastRow) 'loop through each cell in Column A
temp = WorksheetFunction.CountIf(.Range(fCell, cel.Address), cel) 'get count
If temp > 1 Then
If cel.Offset(0, 9) = dict1(cel.Value) Then
cel.Offset(0, 14).Value = 0
Else
cel.Offset(0, 14).Value = 1
End If
Else
cel.Offset(0, 14).Value = 1
End If
Next cel
End With
End Sub
EDIT
Sub Demo()
Dim ws As Worksheet
Dim lastRow As Long
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Sheet2") 'change Sheet3 to your data range
With ws
lastRow = .Cells(.Rows.count, "A").End(xlUp).Row 'last row with data in Column A
.Range("O2").Formula = "=IF(MOD(SUMPRODUCT(($A$2:$A2=A2)*($J$2:$J2=J2)),3)=1,1,0)" 'enter formula in Cell O2
.Range("O2").AutoFill Destination:=.Range("O2:O" & lastRow) 'drag formula down
.Range("O2:O" & lastRow).Value = .Range("O2:O" & lastRow).Value 'keep only values
End With
Application.ScreenUpdating = True
End Sub

VBA Code to Actively Find Range for Excel Graph

I'm currently building a VBA code to actively define the range for a graph.
Sub ABC()
Dim count As Integer
Dim countAll As Integer
Dim i As Integer
Dim j As Integer
Dim filter As Variant
Dim exfilter As Variant
Dim ws As Worksheet
Set ws = Worksheets(1)
Dim n As Integer
'Cancel updating
Application.ScreenUpdating = False
'Clear oldsheet
Sheets("FLAGGED rest # list").Activate
Range("a3:a9999").ClearContents
'Autofilter sheet and copy range
Sheets("restaurant performance 2016").Activate
Range("a7:ah7").Select
Selection.AutoFilter
ActiveSheet.Range("$A$7:$AH$510").AutoFilter Field:=11, Criteria1:="<>"
ActiveSheet.AutoFilter.Range.Copy
'Paste to new sheet
Sheets("FLAGGED rest # list").Activate
Cells(2, 1).Select
ActiveSheet.Paste
'
'Clean out irrelevant data
Range("b2:az9999").Clear
'Count number of restaurants
Sheets("flagged rest # list").Activate
Cells(3, 1).Select
Sheets("flagged rest # list").Range(Selection, Selection.End(xlDown)).Select
count = Application.WorksheetFunction.CountA(Selection)
'Count number of weeks
Sheets("12 week trend").Activate
Cells(2, 2).Select
'Create Chart
n = 2 + count
rangestring = "$C$3:$O$" & n
rangestring2 = "'12 week trend'!" & rangestring
Sheets("12 week trend").Activate
Range(rangestring).Select
ActiveSheet.Shapes.AddChart2(332, xlLineMarkers).Select
ActiveChart.SetSourceData Source:=Range(rangestring2)
For i = 3 To n
legendString = "$B$" & i
legendString2 = "='12 week trend'!" & legendString
ActiveChart.FullSeriesCollection(i - 2).Name = legendString2
Next i
ActiveChart.FullSeriesCollection(1).XValues = "='12 Week Trend'!$C$2:$O$2"
'Turn on updating
Application.ScreenUpdating = True
End Sub
My main hurdle seems to be the fact that I need the code to be able to accommodate data being added to new columns. For example, in this code: the data range is hardcoded to column "O", but I'd like to build a model which would be able to determine which column the range stops at.
The variable rangestring2 dynamically calculates how many rows of data we possess, but at the moment, can't calculate the same for columns.
This is my first time asking for help in this forum! Thank you for your time guys!
You could use one of the usual "find last column" methods, such as
Dim c As Long
With Sheets("12 week trend")
c = .Cells(2, .Columns.Count).End(xlToLeft).Column
End With
and then use that to determine your appropriate range strings such as
Dim HdgString As String
rangestring = Range(Cells(3, "C"), Cells(n, c)).Address
HdgString = Range(Cells(2, "C"), Cells(2, c)).Address
rangestring2 = "'12 week trend'!" & rangestring
'...
ActiveChart.FullSeriesCollection(1).XValues = "='12 Week Trend'!" & HdgString

Excel VBA filter, deleting data & updating

Could someone please help with my code, I am not a million miles away from what I am looking to do but I have now come unstuck and reached a dead end. I have no programming experience & am no expert with VBA so what I have done might not make sense, or look silly; please bear with me as I am learning.
What I want to do is be able to:
Filter Column H in sheet “master” to select dates before a date
which I will input in Range “B9”.
Delete the filtered lines
Go to sheet “update”
Copy from A:18 dynamically to last column & last row
Paste everything in the last row in sheet “master”
Problem I have is that the filter for the date is not working
Sub AUTODATE()
Dim dDate As Date
Dim dbDate As Double
lastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1
dbDate = DateSerial(Year(dbDate), Month(dbDate), Day(dbDate) + 1)
Application.ScreenUpdating = False
Sheets("master").Select
If IsDate(Range("B9")) Then
dbDate = Range("B9")
dbDate = DateSerial(Year(dbDate), Month(dbDate), Day(dbDate)) + _
TimeSerial(Hour(dbDate), Minute(dbDate), Second(dbDate))
Range("H11").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.AutoFilter
Range("$11:$11").AutoFilter Field:=8, Criteria1:=">" & dbDate
Range("$12:12").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.SpecialCells _
(xlCellTypeVisible).EntireRow.Delete
Range("A11").Select
On Error Resume Next
ActiveSheet.ShowAllData
Sheets("update").Select
ActiveSheet.ShowAllData
Range("$18:$18").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("master").Select
Range("A" & lastRow).Select
Selection.PasteSpecial
End If
Application.ScreenUpdating = False
End Sub
The codes a bit messy near the bottom, and some thing's I'd normally push out to a separate function (find last cell for example).
Sub AutoDate()
Dim lastRow As Long
Dim lastUpdateRow As Long
Dim wrksht As Worksheet
Dim rFilterRange As Range
Set wrksht = ThisWorkbook.Worksheets("master")
'Any statement that starts with a '.' applies to wrksht (With... End With)
With wrksht
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
'The range to be filtered - currently columns A:J (columns 1 - 10)
Set rFilterRange = .Range(.Cells(11, 1), .Cells(lastRow, 10))
'Turn off the autofilter if it's already on.
If .AutoFilterMode Then
wrksht.AutoFilterMode = False
End If
'Apply filter to correct range.
rFilterRange.AutoFilter
If IsDate(.Range("B9")) Then
'Apply filter.
rFilterRange.AutoFilter Field:=8, Criteria1:=">" & .Range("B9")
If .FilterMode Then
'Resize to ignore header row & delete visible rows.
rFilterRange.Offset(1).Resize(rFilterRange.Rows.Count - 1) _
.SpecialCells(xlCellTypeVisible).EntireRow.Delete Shift:=xlUp
.ShowAllData
End If
'Find new last row.
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row + 1
Set rFilterRange = .Range(.Cells(11, 1), .Cells(lastRow, 10))
lastUpdateRow = ThisWorkbook.Worksheets("Update").Cells(Rows.Count, "A").End(xlUp).Row
rFilterRange.Offset(1).Resize(rFilterRange.Rows.Count - 1).Copy _
Destination:=ThisWorkbook.Worksheets("Update").Cells(lastUpdateRow, 1)
End If
End With
End Sub
Requirements:
Filter Column H in sheet master to select dates before a date located in same sheet at B9
Delete filtered lines
Copy from sheet update range A:18 dynamically to last column & last row
Paste range from previous point in the last row + 1 of sheet master
Assumptions: (in line with code posted):
Data range in sheet master starts at A11 and all cells in columns 8 of the data range have same NumberFormat
Data range in sheet update starts at A18
Data ranges in both sheets are continuous (i.e. no blank rows nor blank columns in between)
Copy of the data includes formulas & formats
Thy this code:
Option Explicit
Sub Rng_AutoFilter_Delete_And_Paste()
Dim WshMaster As Worksheet, WshUpdate As Worksheet
Dim rMaster As Range, rUpdate As Range
Dim dDate As Date
Dim rTmp As Range
Rem Application Settings - OFF
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
Rem Set Worksheet Object - End Procedure If any of them is not present
With ThisWorkbook
On Error GoTo ExitTkn
Set WshMaster = .Sheets("master")
Set WshUpdate = .Sheets("update")
On Error GoTo 0
End With
If IsDate(WshMaster.Range("B9")) Then
Rem Cleared Records in Wsh Master
With WshMaster
Rem Set Date to Filter By
dDate = .Range("B9")
Rem Set Data Ramge in Wsh Master
'Assumes range start at `A11` and it's continuous (i.e. no blank rows nor blank columns in between)
Set rMaster = .Range("A11").CurrentRegion
Rem Set AutoFilter
'Use the `AutoFilter` property instead of the `AutoFilterMode` property
If Not (.AutoFilter Is Nothing) Then .Cells(1).AutoFilter
rMaster.AutoFilter
End With
With rMaster
Rem Filter and Delete Records in Wsh Master
'Uses the `NumberFormat` to build the Filter Criteria
'Assumes all cells in has same `NumberFormat`
.AutoFilter Field:=8, Criteria1:=">" & Format(dDate, .Cells(2, 8).NumberFormat)
'Sets a Temp Range to grab the Filter results
On Error Resume Next
Set rTmp = .Offset(1).Resize(-1 + .Rows.Count).Columns(8).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
'If Temp Range is `Nothing` then there is `Nothing` to delete
If Not (rTmp Is Nothing) Then rTmp.EntireRow.Delete
.Worksheet.ShowAllData
End With
Rem Set Data Range in Wsh Update
With WshUpdate
Rem Set Data Range in Wsh Update
'Assumes range start at `A18` and it's continuous (i.e. no blank rows nor blank columns in between)
Set rUpdate = .Range("A18").CurrentRegion
Rem Set AutoFilter
If Not (.AutoFilter Is Nothing) Then .Cells(1).AutoFilter
rUpdate.AutoFilter
End With
Rem Paste Records from Wsh Update into Wsh Master
rUpdate.Copy
'In line with code posted this assumes OP wants to copy the data as it is (i.e. including formulas & format)
rMaster.Offset(rMaster.Rows.Count).Resize(1, 1).PasteSpecial
Application.CutCopyMode = False
Application.Goto WshMaster.Cells(1), 1
End If
ExitTkn:
Rem Application Settings - ON
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.EnableEvents = True
End Sub
Suggest to read the following pages to gain a deeper understanding of the resources used:
Excel Objects, On Error Statement, Range Object (Excel), Variables & Constants,
Worksheet.AutoFilter Property (Excel), Worksheet.AutoFilterMode Property (Excel),
Worksheet Object (Excel), With Statement
I have also done a review of your code see below (including only lines with comments):
'lastRow variable is not declared.
'Suggest to always have Option Explicit at the begining of the module
'To do it goto Main Menu \ Options \ Tab: Editor \ Check: Require Variable Declaration
lastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1 'This is done too early as it will change after deletion of filtered rows
dbDate = DateSerial(Year(dbDate), Month(dbDate), Day(dbDate) + 1) 'Have no purpose as no value have been assigned to the variable as yet
Application.ScreenUpdating = False 'this should be done at the beginning
Sheets("master").Select 'should be qualified
dbDate = DateSerial(Year(dbDate), Month(dbDate), Day(dbDate)) + _
TimeSerial(Hour(dbDate), Minute(dbDate), Second(dbDate)) 'This line achieves nothing.
Range("H11").Select 'Select should be avoided, instead work with objects
Selection.AutoFilter 'Sould check first is the AutoFilter is ON
Range("$11:$11").AutoFilter Field:=8, Criteria1:=">" & dbDate 'Should filter the entire range
On Error Resume Next 'On error should be used for specific purposes and cleared after with On Error Goto 0
Selection.PasteSpecial 'After paste the Clipboard must be cleared with Application.CutCopyMode = False

Copy/Paste multiple rows in VBA

I am attempting to do a simple copy row, paste row within a workbook. I've searched threads and tried changing my code multiple times to no avail.
The one that comes closest to working is this but it only copies a single instance of matching criteria.
I am trying to create a loop that will copy all of the rows that has a match in one of the columns.
So, if 8 columns, each row with matching value in column 7 should copy to a named sheet.
Sub test()
Set MR = Sheets("Main").Range("H1:H1000")
Dim WOLastRow As Long, Iter As Long
For Each cell In MR
If cell.Value = "X" Then
cell.EntireRow.Copy
Sheets("X").Range("A" & Rows.Count).End(xlUp).PasteSpecial
End If
If cell.Value = "Y" Then
cell.EntireRow.Copy
Sheets("Y").Range("A" & Rows.Count).End(xlUp).PasteSpecial
End If
If cell.Value = "Z" Then
cell.EntireRow.Copy
Sheets("Z").Range("A" & Rows.Count).End(xlUp).PasteSpecial
End If
If cell.Value = "AB" Then
cell.EntireRow.Copy
Sheets("AB").Range("A" & Rows.Count).End(xlUp).PasteSpecial
End If
Application.CutCopyMode = False
Next
End Sub
I like this because I need to target multiple destination sheets with different criteria but I need all rows that match criteria to copy over.
EDITED CODE IN RESPONSE TO NEW REQUEST:
The code below will copy all of the rows in Sheet Main and paste them into the corresponding worksheets based on the value in Column 7.
Do note: If there is a value in Column 7 that does NOT match to an existing sheet name, the code will throw an error. Modify the code to handle that exception.
Let me know of any additional needed help.
Sub CopyStuff()
Dim wsMain As Worksheet
Dim wsPaste As Worksheet
Dim rngCopy As Range
Dim nLastRow As Long
Dim nPasteRow As Long
Dim rngCell As Range
Dim ws As Worksheet
Const COLUMN_TO_LOOP As Integer = 7
Application.ScreenUpdating = False
Set wsMain = Worksheets("Main")
nLastRow = wsMain.Cells(Rows.Count, 1).End(xlUp).Row
Set rngCopy = wsMain.Range("A2:H" & nLastRow)
For Each ws In ActiveWorkbook.Worksheets
If UCase(ws.Name) = "MAIN" Then
'Do Nothing for now
Else
Intersect(ws.UsedRange, ws.Columns("A:H")).ClearContents
End If
Next ws
For Each rngCell In Intersect(rngCopy, Columns(COLUMN_TO_LOOP))
On Error Resume Next
Set wsPaste = Worksheets(rngCell.Value)
On Error GoTo 0
If wsPaste Is Nothing Then
MsgBox ("Sheet name: " & rngCell.Value & " does not exist")
Else
nPasteRow = wsPaste.Cells(Rows.Count, 1).End(xlUp).Row + 1
wsMain.Range("A" & rngCell.Row).Resize(, 8).Copy wsPaste.Cells(nPasteRow, 1)
End If
Set wsPaste = Nothing
Next rngCell
Application.ScreenUpdating = True
End Sub
Your current code is pasting to the same row in each sheet over and over, to the last row with a value in column A. Range("A" & Rows.Count).End(xlUp) says, roughly "go to the very bottom of the spreadsheet in column A, and then jump up from there to the next lowest cell in column A with contents," which gets you back to the same cell each time.
Instead, you could use lines of the pattern:
Sheets("X").Range("A" & Sheets("X").UsedRange.Rows.Count + 1).PasteSpecial
Where UsedRange is a range containing all of the cells on the sheet with data in them. The + 1 puts you on the following row.
You could make this a little prettier using With:
With Sheets("X")
.Range("A" & .UsedRange.Rows.Count + 1).PasteSpecial
End With