I have the below VBA Macro to go through a dropdown list of names and then copy and paste the values and formatting for each into a new workbook and then save based on the name. It works well except for the fact that at the end of the process it seems to be hardcoding all of the data in the original workbook as well.
Is there something I can change to prevent this from happening? Below is what I currently have.
Sub CreateWorkbooks()
Dim wb As Workbook
Dim ws As Worksheet
Dim nwb As Workbook
Dim nws As Worksheet
Dim rng As Range
Dim path As String
Dim myDate As String
Dim x As Integer
x = ActiveSheet.Range("C77").Value
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Summary")
Set rng = ws.Range("B2")
path = "X:\Private\Forecast\Forecasts by name\"
myDate = Format(Now(), "MM-DD-YYYY")
For i = 77 To x
rng = ws.Range("A" & i)
ws.Copy
Set nwb = ActiveWorkbook
Set nws = nwb.Worksheets("Summary")
With nws
Cells.Copy
Cells.PasteSpecial (xlPasteValues)
End With
Application.DisplayAlerts = False
nwb.SaveAs Filename:=path & rng & " " & myDate & ".xlsx", FileFormat:=xlWorkbookDefault
nwb.Close
Application.DisplayAlerts = True
Next i
End Sub
The Main Issue
At some point in the code, your source workbook becomes the active workbook overwriting the formulas with values. To prevent this from happening, you could check if the source workbook is the active workbook:
Set nwb = ActiveWorkbook
If nwb Is wb Then
MsgBox "The source workbook became the active workbook on iteration " & i & "!", _
vbExclamation
Else
Set nws = nwb.Worksheets("Summary")
' ... code between
Application.DisplayAlerts = True
End If
This would also prove the following.
Sometimes there is an issue with Set nwb = ActiveWorkbook
after copying a sheet to a single-sheet workbook. I don't know why, just following the 'reasonably-looking' recommendation:
Set nwb = Workbooks(Workbooks.Count)
referencing the workbook most recently added to the Workbooks Collection.
Other Issues
Use Option Explicit
at the top of each module so you don't forget to declare all variables i.e. Dim i As Long
.
Use the Long datatype for all integers unless required not to (e.g. e.g. Windows APIs).
Turn off screen updating to prevent screen flickering.
Use the smallest possible range to process. ws.Cells
has many cells (1048576*16384
), ws.UsedRange.Cells
has mostly fewer.
Avoid Range.PasteSpecial
whenever possible because it's slow. When copying values, the most efficient way is to copy values by assignment:
rgDest.Value = rgSource.Value
where rgSource
and rgDest
are two same-sized single-area ranges.
Use variables to avoid long (unreadable) lines e.g. nFilePath
.
Option Explicit
Sub CreateSummariesByName()
Const FOLDER_PATH As String = "X:\Private\Forecast\Forecasts by name\"
Const SRC_FIRST_ROW As Long = 77
Const DATE_FORMAT As String = "mm-dd-yyyy"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim sws As Worksheet: Set sws = wb.Sheets("Summary")
Dim scell As Range: Set scell = sws.Range("B2")
Dim sLastRow As Long: sLastRow = sws.Cells(SRC_FIRST_ROW, "C").Value
Dim TodayString As String: TodayString = Format(Date, DATE_FORMAT)
Application.ScreenUpdating = False
' Declare additional variables (to be used in the upcoming 'For...Loop').
Dim nwb As Workbook, nws As Worksheet
Dim n As Long
Dim nName As String, nFilePath As String
' Loop...
For n = SRC_FIRST_ROW To sLastRow
nName = sws.Cells(n, "A").Value
scell.Value = nName
' Create a copy of the source (summary) sheet in a new workbook.
sws.Copy
' Reference this new workbook...
Set nwb = Workbooks(Workbooks.Count)
' and the one and only sheet in it.
Set nws = nwb.Sheets(1)
' Convert formulas to values (efficiently).
With nws.UsedRange
.Value = .Value
End With
' Build the new file path (based on 'nName').
nFilePath = FOLDER_PATH & nName & " " & TodayString & ".xlsx"
' Save and close the new workbook.
Application.DisplayAlerts = False
nwb.SaveAs Filename:=nFilePath, FileFormat:=xlWorkbookDefault
nwb.Close SaveChanges:=False
Application.DisplayAlerts = True
Next n
Application.ScreenUpdating = True
' Inform.
MsgBox "Summaries by name created.", vbInformation
End Sub