Array not printing to second row of my second worksheet? - excel

I'll just provide snippets. Basically I have two sets of data on a master roster, and they're divided by an X value in column H of the roster. I want X's to be printed to Sheet1 of Wb and Blanks to be printed to Sheet2.
I have it working, but since it declares FinalDest as a singular variable, it doesn't start on row 2 of the Sheet2.
Example: if X's fill to row 10 of Sheet1, it will start Sheet2's data on row 11 instead of 2 (after headers).
Sub Main()
Dim Wb As Workbook
Dim Data, Last, Login, SaveTyping
Dim i As Long, j As Long, k As Long, a As Long
Dim Dest1 As Range, Dest2 As Range, FinalDest As Range
Set Wb = Workbooks("Template.xlsx")
Set Dest1 = Wb.Sheets("Currently Eligible").Range("A2")
Set Dest2 = Wb.Sheets("Newly Eligible").Range("A2")
With ThisWorkbook.Sheets("Roster")
Data = .Range("AA2", .Range("A" & Rows.Count).End(xlUp))
End With
After I declare my array, this is how I separate what's printed to the template.
SaveTyping = Data(i, 8) 'Column my X's and Blanks are
If InStr(SaveTyping, "X") Then
Set FinalDest = Dest1
End If
If SaveTyping = "" Then
Set FinalDest = Dest2
End If
For k = 1 To UBound(Data, 2)
FinalDest.Offset(j, a) = Data(i, k) 'Where I need to tell array to print
a = a + 1
Next
j = j + 1
Next
FinalDest range picks up on the next row after where it left off from Sheet1, how do I prevent that and have it start on Row 2 for both sheets?
Option Explicit
Sub Main()
Dim Wb As Workbook 'Workbook I'm printing each managers employee roster to and saving off a copy to a folder
Dim Data, Last, Login, chkVal 'Data = data I'm printing into template / Last = Manager name / Login = Manager Login ID
Dim i As Long, j As Long, k As Long, a As Long 'i = Data(row) / k = Data(column) / a = Wb(row) / j = Wb(column)
Dim Dest1 As Range, Dest2 As Range, FinalDest As Range 'Dest1 = Sheets(1) of Wb / Dest2 = Sheets(2) of Wb
Set Wb = Workbooks("Template.xlsx") 'Sets template for each file cut
Set Dest1 = Wb.Sheets("Currently Eligible").Range("B2")
Set Dest2 = Wb.Sheets("Newly Eligible").Range("B2")
With ThisWorkbook.Sheets("Sheet1")
Data = .Range("AA2", .Range("A" & Rows.Count).End(xlUp)) 'Raw data
End With
Wb.Activate
Application.ScreenUpdating = False
For i = 1 To UBound(Data) 'Row 1 to Ubound of Data(rows)
If Data(i, 1) <> Last Then 'only print array to Wb one manager at a time, we see when managers change because values in Data(i,1) will <> the next cell
If i > 1 Then 'skip header
Wb.SaveCopyAs ThisWorkbook.Path & Application.PathSeparator & _
ValidFileName(Login & " - " & Last & " - Shift Differential Validation.xlsx")
End If
With Sheets("Exempt Population")
.Rows(2 & ":" & .Rows.Count).ClearContents 'Clears previous managers data
End With
Last = Data(i, 1) 'Manager last name is in Column A
chkVal = Data(i, 8) 'Check for X or Blank in Column H
Login = Data(i, 27) 'Manager login ID is in column AA
j = 0 'Wb Column = 0
End If
a = 0 'Wb Row = 0
SaveTyping = Data(i, 8) 'Column my X's and Blanks are
If InStr(SaveTyping, "X") Then
Set FinalDest = Dest1
End If
If SaveTyping = "" Then
Set FinalDest = Dest2
End If
For k = 1 To UBound(Data, 2) 'Column 1 to Ubound of Data(columns)
FinalDest.Offset(j, a) = Data(i, k)
a = a + 1 'next Wb row
Next
j = j + 1 'next Wb column
Next
SaveCopy Wb, Login, Last '<< save the last report
End Sub

I cleaned up the code a bit, giving proper names to indexes.
In terms of a solution to your issue, I added two different row indices, one for X one for blank. Depending on whether its an X or blank, you increment either the one or the other.
Option Explicit
Sub Main()
Dim Wb As Workbook 'Workbook I'm printing each managers employee roster to and saving off a copy to a folder
Dim Data, Last, Login, chkVal 'Data = data I'm printing into template / Last = Manager name / Login = Manager Login ID
Dim row_data As Long, col_wb As Long, col_data As Long, row_wb As Long
Dim Dest1 As Range, Dest2 As Range, FinalDest As Range 'Dest1 = Sheets(1) of Wb / Dest2 = Sheets(2) of Wb
Dim row_index_x As Long, row_index_blank As Long, isX As Long
Set Wb = Workbooks("Template.xlsx") 'Sets template for each file cut
Set Dest1 = Wb.Sheets("Currently Eligible").Range("B2")
Set Dest2 = Wb.Sheets("Newly Eligible").Range("B2")
With ThisWorkbook.Sheets("Sheet1")
Data = .Range("AA2", .Range("A" & Rows.Count).End(xlUp)) 'Raw data
End With
Wb.Activate
Application.ScreenUpdating = False
' initialise row indices to 0, ignore header as Dest1 and Dest2 already at B2.
row_index_x = 0
row_index_blank = 0
For row_data = 1 To UBound(Data) 'Row 1 to Ubound of Data(rows)
' if manager name changed between this row and previous row
If Data(row_data, 1) <> Last Then 'only print array to Wb one manager at a time, we see when managers change because values in Data(row_data,1) will <> the next cell
If row_data > 1 Then 'skip header
' save wb every time manager changes
Wb.SaveCopyAs ThisWorkbook.Path & Application.PathSeparator & _
ValidFileName(Login & " - " & Last & " - Shift Differential Validation.xlsx")
End If
With Sheets("Exempt Population")
.Rows(2 & ":" & .Rows.Count).ClearContents 'Clears previous managers data
End With
Last = Data(row_data, 1) 'Manager last name is in Column A
chkVal = Data(row_data, 8) 'Check for X or Blank in Column H
Login = Data(row_data, 27) 'Manager login ID is in column AA
' reset output row every time manager name changes
row_wb = 0 'Wb Row = 0
End If
' for every data row, reset output column to zero (start a new row)
col_wb = 0 'Wb Col = 0
SaveTyping = Data(row_data, 8) 'Column my X's and Blanks are
' decide output destination
If InStr(SaveTyping, "X") Then
Set FinalDest = Dest1
row_wb = row_index_x
isX = 1 ' remember whether its X or blank
End If
If SaveTyping = "" Then
Set FinalDest = Dest2
row_wb = row_index_blank
isX = 0
End If
' Loop through all columns for one row of data
' keep output row the same, increase the output column
For col_data = 1 To UBound(Data, 2) 'Column 1 to Ubound of Data(columns)
FinalDest.Offset(row_wb, col_wb) = Data(row_data, col_data)
col_wb = col_wb + 1 'next Wb column
Next
'row_wb = row_wb + 1 'next Wb row
' decide which row index to increase
If isX = 1 Then
row_index_x = row_index_x + 1
Else
row_index_blank = row_index_blank + 1
End If
Next
SaveCopy Wb, Login, Last '<< save the last report
End Sub

Related

Why is my array returning empty? And how do I ensure it copies the data into my third selection

After countless efforts to keep the array "newvarray" within range, I am now running into a result of an empty array from a 278 line column. I believe this is also the root cause of my endgame function not executing (pasting unmatched values into the rolls sheet)?
Clarification: the actualy empty cells report on locals as "Empty", the columns with string report as " "" "
Dim oldsht As Worksheet
Dim newsht As Worksheet
Dim rollsht As Worksheet
Dim a As Integer
Dim b As Integer
Dim c As Integer
Set oldsht = ThisWorkbook.Sheets("Insert Yesterday's Report Here")
Set newsht = ThisWorkbook.Sheets("Insert Today's Report Here")
Set rollsht = ThisWorkbook.Sheets("Rolls")
Dim OldVArray(), NewVArray(), RollArray() As String
ReDim Preserve OldVArray(1 To oldsht.Range("a" & Rows.Count).End(xlUp).Row - 1, 5 To 5)
ReDim Preserve NewVArray(2 To newsht.Range("a" & Rows.Count).End(xlUp).Row, 5 To 5)
ReDim Preserve RollArray(1 To rollsht.Range("a" & Rows.Count).End(xlUp).Row - 1, 3 To 3)
For a = 2 To oldsht.Range("E" & Rows.Count).End(xlUp).Row
OldVArray(a, 5) = oldsht.Cells(a, 5)
Next a
For b = 2 To newsht.Range("E" & Rows.Count).End(xlUp).Row
NewVArray(b, 5) = newsht.Cells(b, 5)
Next b
For c = 2 To rollsht.Range("C" & Rows.Count).End(xlUp).Row
RollArray(c, 3) = rollsht.Cells(c, 3)
Next c
Dim Voyage As String
For a = 2 To UBound(OldVArray)
Voyage = OldVArray(a, 5)
For b = 2 To UBound(NewVArray)
voyage2 = NewVArray(b, 5)
If voyage2 <> Voyage Then
If voyage2 <> "" Then
For Each cell In NewVArray
voyage2 = rollsheet.Range("C:C")
Next
End If
End If
Next
Next
Here are snips of sample idea, highlighted are the rows that need to be found, and the voyage that changed is in orange. Third on Rolls would be the output of the macro.
Oldsheet:
Newsheet:
Rolls:
Untested, but this is how I'd do it. Just going from your screenshots. If your actual data looks different then you will need to make some adjustments.
Sub test()
Dim wb As Workbook, oldsht As Worksheet, newsht As Worksheet, rollsht As Worksheet
Dim c As Range, id, col, cDest As Range, copied As Boolean, m
Set wb = ThisWorkbook
Set oldsht = wb.Sheets("Insert Yesterday's Report Here")
Set newsht = wb.Sheets("Insert Today's Report Here")
Set rollsht = wb.Sheets("Rolls")
'next empty row on Rolls sheet
Set cDest = rollsht.Cells(Rows.Count, "A").End(xlUp).Offset(1)
'loop colA on new sheet
For Each c In newsht.Range("A2:A" & newsht.Cells(Rows.Count, "A").End(xlUp).row).Cells
id = c.Value 'identifier from Col A
If Len(id) > 0 Then
m = Application.Match(id, oldsht.Columns("A"), 0) 'check for exact match on old sheet
If Not IsError(m) Then
'got a match: check for updates in cols B to C
copied = False
For col = 2 To 3
If c.EntireRow.Cells(col).Value <> oldsht.Cells(m, col).Value Then
If Not copied Then 'already copied this row?
cDest.Resize(1, 3).Value = c.Resize(1, 3).Value 'copy changed row
Set cDest = cDest.Offset(1) ' next empy row
copied = True
End If
cDest.EntireRow.Cells(col).Interior.Color = vbRed 'flag updated value
End If
Next col
Else
cDest.Resize(1, 3).Value = c.Resize(1, 3).Value 'copy new row
Set cDest = cDest.Offset(1) ' next empy row
End If
End If
Next c
End Sub

Can I give an if statement by subtracting time?

Is there a way to make my VBA code work for my macro? I want my macro's if function to read the first column of each worksheet in my excel (it has as many sheets as days in the exact month i'm working on), read through each cell and if the currently read cell is equal to or larger than '15 minutes compared to the first cell, then the code would execute, otherwise go to the next cell in the first column.
This is the format of the worksheets i'm working on:
TimeStamp
Power Consumption
Power Production
Inductive Power Consumption
2021.01.01. 8:12:38 +00:00
747
575
3333
2021.01.01. 8:17:35 +00:00
7674
576
3333
... etc ,
And my code looks something like this:
Sub stackoverflow()
Dim w As Integer 'index of worksheets
Dim i As Integer 'row index that steps through the first column
Dim t As Integer 'reference row index i inspect the time to
Dim x As Integer 'row index where i want my data to be printed
Dim j As Integer 'col index
Dim Timediff As Date 'not sure if this is even needed
t = 2
j = 1
x = 1
'Timediff = ("00:15:00")
For w = 3 To ActiveWorkbook.Worksheets.Count 'for every sheet from the 3rd to the last
lRow = ActiveWorkbook.Worksheets(w).Cells(Rows.Count, 1).End(xlUp).Row 'find the last row in each worksheet
lCol = ActiveWorkbook.Worksheets(w).Cells(1, Columns.Count).End(xlToLeft).Column 'find the last column in each worksheet
For x = 2 To lRow
For i = 2 To lRow
'If the time in cell(i,j) is >= then cell(t,j) + 15 minutes,
If Cells(i, j) >= DateAdd("n", 15, Cells(t, j)) Then
ActiveWorkbook.Worksheets(w).Range(i, j).Copy ActiveWorkbook.Worksheets(2).Range(x, j)
ActiveWorkbook.Worksheets(w).Range(i, j + 1).Copy ActiveWorkbook.Worksheets(2).Range(x, j + 1)
'put the new reference point after the found 15 minute mark
t = i + 1
Else
End If
Next i
Next x
Next w
End Sub
So all in all I want my code to notice when the first column reaches a 15 minute mark, and execute some code (subtracting the values of the 15 minute mark from the reference where it started, put the value in the'2nd sheet, and then step to the next cell, and repeat the process).
I'm not entirely sure which information you are attempting to copy to the second worksheet but the following code should be able to get you there pretty easily. Additionally, I've added a function that will fix the format of your TimeStamp field so that excel will recognize it and we can then do math with it
Sub TestA()
Dim xlCellA As Range
Dim xlCellB As Range
Dim xlCellC As Range
Dim i As Integer
Dim j As Integer
Dim lRow As Long
Dim lCol As Long
Set xlCellA = ActiveWorkbook.Worksheets(2).Cells(2, 1)
For i = 3 To ActiveWorkbook.Worksheets.Count
lRow = ActiveWorkbook.Worksheets(i).Cells.SpecialCells(xlCellTypeLastCell).Row
lCol = ActiveWorkbook.Worksheets(i).Cells.SpecialCells(xlCellTypeLastCell).Column
Set xlCellB = ActiveWorkbook.Worksheets(i).Cells(2, 1)
xlCellB.Value = FixFormat(xlCellB.Value)
xlCellB.Offset(0, lCol + 1).Value = "=DATEVALUE(MID(" & xlCellB.Address & ",1,10))+TIMEVALUE(MID(" & xlCellB.Address & ",12,8))"
For j = 3 To lRow
Set xlCellC = ActiveWorkbook.Worksheets(i).Cells(j, 1)
xlCellC.Value = FixFormat(xlCellC.Value)
xlCellC.Offset(0, lCol + 1).Value = "=DATEVALUE(MID(" & xlCellC.Address & ",1,10))+TIMEVALUE(MID(" & xlCellC.Address & ",12,8))"
If xlCellC.Offset(0, lCol + 1) - xlCellB.Offset(0, lCol + 1) >= ((1 / 24) / 4) Then
With xlCellA
.Value = xlCellC.Value
.Offset(0, 1).Value = xlCellC.Offset(0, 1).Value
End With
Set xlCellA = xlCellA.Offset(1, 0)
End If
Next j
Next i
Set xlCellA = Nothing
Set xlCellB = Nothing
Set xlCellC = Nothing
End Sub
Private Function FixFormat(ByVal dStr As String) As String
Dim tmpStr As String
Dim i As Integer
For i = 1 To Len(dStr)
If Mid(dStr, i, 1) <> "." Then
tmpStr = tmpStr & Mid(dStr, i, 1)
Else
If Mid(dStr, i + 1, 1) <> " " Then tmpStr = tmpStr & "-"
End If
Next i
FixFormat = tmpStr
End Function
It's not really clear what needs to happen when the 15min threshold is met but this should get you most of the way there:
Sub stackoverflow()
Dim w As Long, Timediff As Double
Dim wb As Workbook, wsData As Worksheet, wsResults As Worksheet, col As Long
Dim baseRow As Range, dataRow As Range, rngData As Range, resultRow As Range
Timediff = 1 / 24 / 4 '(15min = 1/4 of 1/24 of a day)
Set wb = ActiveWorkbook 'or ThisWorkbook
Set wsResults = wb.Worksheets("Results")
'first row for recording results
Set resultRow = wsResults.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).EntireRow
For w = 3 To wb.Worksheets.Count 'for every sheet from the 3rd to the last
Set rngData = wb.Worksheets(w).Range("A1").CurrentRegion 'whole table
Set rngData = rngData.Offset(1, 0).Resize(rngData.Rows.Count - 1) 'exclude headers
Set baseRow = rngData.Rows(1) 'set comparison row
For Each dataRow In rngData.Rows 'loop over rows in data
If (dataRow.Cells(1).Value - baseRow.Cells(1).Value) > Timediff Then
resultRow.Cells(1).Value = dataRow.Cells(1) 'copy date
For col = 2 To dataRow.Cells.Count 'loop columns and subtract
resultRow.Cells(col).Value = _
dataRow.Cells(col).Value - baseRow.Cells(col).Value
Next col
Set resultRow = resultRow.Offset(1, 0)
Set baseRow = dataRow.Offset(1, 0) 'reset comparison row to next row
End If
Next dataRow
Next w
End Sub

Excel VBA Debugging

I'm running into a "run time error 1004". I suspect this has something to do with how much data I want my code to process. Currently I am running a 246 column by 30,000 row. What I'm trying to achieve is to consolidate my data into one row item because the current system export the data into individual row as a duplicate for certain data columns. As a result, the data has a ladder/stagger effect where there's duplicate row ID with blank cells in one and data below it.
Example:
Code:
Option Explicit
Sub consolidate()
Const SHEET_NAME = "Archer Search Report"
Const NO_OF_COLS = 101
Dim wb As Workbook, ws As Worksheet
Dim irow As Long, iLastRow As Long, c As Long, count As Long
Set wb = ThisWorkbook
Set ws = wb.Sheets(SHEET_NAME)
iLastRow = ws.Range("A" & Rows.count).End(xlUp).Row
' scan up sheet
For irow = iLastRow - 1 To 2 Step -1
' if same id below
If ws.Cells(irow + 1, 1) = ws.Cells(irow, 1) Then
' scan across
For c = 1 To NO_OF_COLS
' if blank copy from below
If Len(ws.Cells(irow, c)) = 0 Then
ws.Cells(irow, c) = ws.Cells(irow + 1, c)
End If
Next
ws.Rows(irow + 1).Delete
count = count + 1
End If
Next
MsgBox iLastRow - 1 & " rows scanned" & vbCr & _
count & " rows deleted from " & ws.Name, vbInformation
End Sub
I suspect it has to do with the massive amount of data it's running and wanted to see if that is the case. If so, is there an alternative approach? Appreciate the assistance.
Note: I got this awesome code from someone(CDP1802)here and have been using it for years with smaller data set.
Here's a slightly different approach which does not require sorting by id, includes some checking for error values, and does not overwrite any data in the output.
Sub consolidate()
Const SHEET_NAME = "Archer Search Report"
Const NO_OF_COLS = 10 'for example
Dim wb As Workbook, ws As Worksheet, dataIn, dataOut
Dim i As Long, c As Long
Dim dict As Object, id, rwOut As Long, idRow As Long, vIn, vOut, rngData As Range
Set wb = ThisWorkbook
Set ws = wb.Sheets(SHEET_NAME)
Set dict = CreateObject("scripting.dictionary")
Set rngData = ws.Range("A2:A" & ws.Cells(ws.Rows.count, 1).End(xlUp).Row).Resize(, NO_OF_COLS)
dataIn = rngData.Value 'input data as 2D array
ReDim dataOut(1 To UBound(dataIn, 1), 1 To NO_OF_COLS) 'resize "out" to match "in" array size
rwOut = 0 'row counter for "out" array
For i = 1 To UBound(dataIn, 1)
id = dataIn(i, 1) 'id for this "row"
If Not dict.exists(id) Then
'not seen this id before
rwOut = rwOut + 1
dict(id) = rwOut 'add id and row to dictionary
dataOut(rwOut, 1) = id 'add id to "out" array
End If
idRow = dict(id) 'row locator in the "out" array
For c = 2 To NO_OF_COLS
vIn = dataIn(i, c) 'incoming value
vOut = dataOut(idRow, c) 'existing value
'ignore error values, and don't overwrite any existing value in the "out" array
If Not IsError(vIn) Then
If Len(vIn) > 0 And Len(vOut) = 0 Then dataOut(idRow, c) = vIn
End If
Next c
Next i
rngData.Value = dataOut 'replace input data with output array
MsgBox "Got " & rwOut & " unique rows from " & UBound(dataIn, 1)
End Sub

How can I change the direction this script is grouping data?

I have a script that forms arrays within an overarching array based on duplicate values in column A.
manager 1 its own workbook
manager 2
manager 2 these two would be grouped into another workbook and so on.
problem is, these cells in column A are now transposed as headers in row 1.
How would I edit this script to now group this data by the row headers and take the whole column instead of how the script is originally written?
I figure it has something to do with swapping the Last = Data(1,i) or something like that.
Option Explicit
Sub Main()
Dim wb As Workbook
Dim Data, Last, JobFamily
Dim i As Long, j As Long, k As Long, a As Long
Dim Dest As Range
'Refer to the template
Set wb = Workbooks("Book2.xlsx")
'Refer to the destination cell
Set Dest = wb.Sheets("Sheet11").Range("B1")
'Read in all data
With ThisWorkbook.Sheets("Sheet1")
Data = .Range("bj2", .Range("A" & Rows.Count).End(xlUp))
End With
wb.Activate
Application.ScreenUpdating = False
'Process the data
For i = 1 To UBound(Data)
'Manager changes?
If Data(i, 1) <> Last Then
'Skip the first
If i > 1 Then
'Scroll into the view
Dest.Select
'Save a copy
wb.SaveCopyAs ThisWorkbook.Path & Application.PathSeparator & _
ValidFileName(Last & ".xlsx")
End If
'Clear the employees
Dest.Resize(, Columns.Count - Dest.Column).EntireColumn.ClearContents
'Remember this manager
Last = Data(i, 1)
'Start the next round
j = 0
End If
'Write the employee data into the template
a = 0
For k = 1 To UBound(Data, 2)
Dest.Offset(a, j) = Data(i, k)
a = a + 1
Next
'Next column
j = j + 1
Next
End Sub
You called it. All references to "Data(i,1)" must be replaced with "Data(1,i)" to transpose the first column of the range into the first row.

Add in another For Loop in order to have another worksheets data added before the file is saved

I have a script that processes a master file and creates a report per manager. In column A, all rows under mgr 1 are stored and printed to a template, and then it loops through all managers until the data ends.
Option Explicit
Sub Main()
Dim Wb As Workbook
Dim Data, Last
Dim i As Long, j As Long, k As Long, a As Long
Dim Dest As Range
'Refer to the template
Set Wb = Workbooks("SpecializedSkillsTemplate.xlsx")
'Refer to the destination cell
Set Dest = Wb.Sheets("Manager Summary").Range("B1")
'Read in all data
With ThisWorkbook.Sheets("Sheet7")
Data = .Range("Z2", .Range("A" & Rows.Count).End(xlUp))
End With
Wb.Activate
'Process the data
For i = 1 To UBound(Data)
'Manager changes?
If Data(i, 1) <> Last Then
'Skip the first
If i > 1 Then
'Scroll into the view
Dest.Select
'Save a copy
Wb.SaveCopyAs ThisWorkbook.Path & Application.PathSeparator & _
ValidFileName(Last & "_Assessment.xlsx")
End If
'Clear the employees
Dest.Resize(, Columns.Count - Dest.Column).EntireColumn.ClearContents
'Remember this manager
Last = Data(i, 1)
'Start the next round
j = 0
End If
'Write the employee data into the template
a = 0
For k = 2 To UBound(Data, 2)
Dest.Offset(a, j) = Data(i, k)
a = a + 1
Next
'Next column
j = j + 1
Next
End Sub
It takes the data from sheet 7 in the master file, but is it possible to have another For/Next loop that does this for another sheet? Say I have sheet 8 and I want it to do the same thing and take that employee data and transpose offset it by a column, so I can compare the two sets. Is this possible?
I was thinking of adding something like:
Dim Data2
With ThisWorkbook.Sheets("Sheet8")
Data2 = .Range("Z2, . Range("A" & Rows.Count).End(xlUp))
End With
and then another For/Next Loop:
For x = 1 to UBound(Data2)
If Data2(I,1) <> Last
Next
etc. Can anyone let me know if this is feasible?
Variantly Integrating For Next Loop
The Tasks
I've added 6 lines and modified one (marked with '*** in the code.
Added string constant that will hold sheet names.
Added variant where the sheet names will be put into and read from.
Added counter for looping through sheet names in variant.
Using the split function pasted data from string into variant (array).
Started For Next Loop.
Modified ThisWorkbook.Sheets().
Closed For Next Loop.
The Code
Option Explicit
Sub Main()
Const cStrSheet As String = "Sheet7,Sheet8,Sheet9" '***
Dim vntSheet As Variant ' ***
Dim iSheet As Integer ' ***
Dim Wb As Workbook
Dim Data, Last
Dim i As Long, j As Long, k As Long, a As Long
Dim Dest As Range
'Refer to the template
Set Wb = Workbooks("SpecializedSkillsTemplate.xlsx")
'Refer to the destination cell
Set Dest = Wb.Sheets("Manager Summary").Range("B1")
vntSheet = Split(cStrSheet, ",") '***
For iSheet = 0 To UBound(vntSheet) '***
'Read in all data
With ThisWorkbook.Sheets(vntSheet(iSheet)) '***
Data = .Range("Z2", .Range("A" & Rows.Count).End(xlUp))
End With
Wb.Activate
'Process the data
For i = 1 To UBound(Data)
'Manager changes?
If Data(i, 1) <> Last Then
'Skip the first
If i > 1 Then
'Scroll into the view
Dest.Select
'Save a copy
Wb.SaveCopyAs ThisWorkbook.Path & Application.PathSeparator & _
ValidFileName(Last & "_Assessment.xlsx")
End If
'Clear the employees
Dest.Resize(, Columns.Count - Dest.Column).EntireColumn.ClearContents
'Remember this manager
Last = Data(i, 1)
'Start the next round
j = 0
End If
'Write the employee data into the template
a = 0
For k = 2 To UBound(Data, 2)
Dest.Offset(a, j) = Data(i, k)
a = a + 1
Next
'Next column
j = j + 1
Next
Next ' iSheet '***
End Sub

Resources