How to create a non-dynamic copy of a sheet? - excel

I need to copy a sheet and rename based on cell value.
How do I create a non-dynamic copy? I need it to be more of a screenshot so all values stay the same. The idea being I can make many still copies and edit the main sheet.
The code I have makes a dynamic copy that changes when the main does.
How would I edit this code so it is gives still image copies?
Private Sub CommandButton3_Click()
Dim ws As Worksheet
Set wh = Worksheets(ActiveSheet.Name)
ActiveSheet.Copy After:=Worksheets(Sheets.Count)
If wh.Range("W13").Value <> "" Then
ActiveSheet.Name = wh.Range("W13").Value
End If
wh.Activate
End Sub

Two people have suggested copy and pasting special values. This adds an operation of moving the data to your clipboard, which is an external buffer outside of Excel. This has the side effect of clearing the users clipboard. If they had copied something it would now be lost.
This is faster and doesn't destroy the clipboard:
Private Sub CommandButton3_Click()
Dim oldSheet As Worksheet
Set oldSheet = ActiveSheet
oldSheet.Copy After:=Worksheets(Sheets.Count)
Dim newSheet As Worksheet
Set newSheet = ActiveSheet
If oldSheet.Range("W13").Value <> "" Then
newSheet.Name = oldSheet.Range("W13").Value
End If
With newSheet.UsedRange
.Value = .Value
End With
End Sub

Addition of these lines will help:
With ActiveSheet
.UsedRange.Copy
.UsedRange.PasteSpecial xlPasteValues
End With
You can make use of the Range.Pastespecial property of Range Class
Full Code:
Private Sub CommandButton3_Click()
Dim ws As Worksheet
Set ws = Worksheets(ActiveSheet.Name)
ws.Copy After:=Worksheets(Sheets.Count)
With ActiveSheet
.UsedRange.Copy
.UsedRange.PasteSpecial xlPasteValues
End With
If ws.Range("W13").Value <> "" Then
ActiveSheet.Name = ws.Range("W13").Value
End If
ws.Activate
End Sub

All you are missing is to copy data and paste them as values
Private Sub CommandButton3_Click()
Dim ws As Worksheet
Set wh = Worksheets(ActiveSheet.Name)
ActiveSheet.Copy After:=Worksheets(Sheets.Count)
If wh.Range("W13").Value <> "" Then
ActiveSheet.Name = wh.Range("W13").Value
End If
With ActiveSheet.Cells
.Copy
.PasteSpecial xlPasteValues
Application.CutCopyMode = False
.Range("A1").Select
End With
wh.Activate
End Sub

Related

XLPaste Code applying differently to separate sheets

I asked a question about this piece of code yesterday but this is part two. Once the identified sheets have detached from the original workbook, they maintain all of their formulas (xlPasteValuesAndNumberFormats). There are two sheets in particular, "REQUESTOR" and "Copy", that am only needing the values for but the other 3 sheets need to bring their formulas along during the detachment. The reason is because those 2 sheets contain external referencing formulas while the other 3 do not. How do I get all of the sheets to detach into a new work book and make the 2 identified sheets be values only while the other 3 carry all of their formulas into the new workbook?
Private Sub CommandButton1_Click()
' Plain_Copy Macro
Sheets("PROCUREMENT").Visible = True
Sheets("Request").Visible = True
Sheets("LISTS").Visible = True
Sheets("Copy").Visible = True
Dim TheActiveWindow As Window
Dim TempWindow As Window
Dim ws As Worksheet
With ActiveWorkbook
.Sheets(Array("REQUESTOR", "PROCUREMENT", "Request", "LISTS", "Copy")).Copy
Application.ScreenUpdating = False
For Each ws In ActiveWorkbook.Worksheets
With ws.UsedRange
.Copy
.PasteSpecial xlPasteValuesAndNumberFormats
End With
TempWindow.Close
Next ws
Application.CutCopyMode = False
Application.ScreenUpdating = True
End With
Avoid any potential problems with nesting With ActiveWorkbook for both the original and the copy by assigning them to variables and then it is clear which is being processed.
Option Explicit
Private Sub CommandButton1_Click()
' Plain_Copy Macro
Dim wb As Workbook, wbCopy As Workbook
Dim ws As Worksheet, ar, v
ar = Array("REQUESTOR", "PROCUREMENT", "Request", "LISTS", "Copy")
Application.ScreenUpdating = False
Set wb = ActiveWorkbook
With wb
For Each v In ar
.Sheets(v).Visible = True
Next
.Sheets(ar).Copy
Set wbCopy = ActiveWorkbook
End With
For Each ws In wbCopy.Worksheets
If ws.name = "REQUESTOR" Or ws.name = "Copy" Then
With ws.UsedRange
' replace formula with values
.Value2 = .Value2
End With
End If
Next
Application.ScreenUpdating = True
MsgBox "Copy is " & wbCopy.name
End Sub

Excel Macro Loop Through Range

I am using the macro below by clicking a button each time I want to run it. This works ok but is quite time consuming.
In the Summary sheet (range H2:H21) of the workbook I have a list of ID numbers which I have been manually pasting into E3 before running the macro.
Instead of doing this I would like to amend the macro so it loops through all the IDs when I click the button.
The workbook is quite big and takes a while to calculate each time a new ID is pasted in so this needs to be factored in.
Can anyone show me have to do these things?
Sub CreateNewSheet()
Application.ScreenUpdating = False
Application.Calculation = xlManual
With Workbooks("Batsmen.xlsx").Worksheets.Add()
.Name = ThisWorkbook.Worksheets("Summary").Range("E3").Value
End With
With ThisWorkbook.Worksheets("Summary").Range("A22:J63").Copy
Workbooks("Batsmen.xlsx").Sheets(1).Range("A1").PasteSpecial Paste:=xlPasteValues
Workbooks("Batsmen.xlsx").Sheets(1).Range("A1").PasteSpecial Paste:=xlPasteFormats
Workbooks("Batsmen.xlsx").Sheets(1).Range("A1").PasteSpecial Paste:=xlPasteColumnWidths
Workbooks("Batsmen.xlsx").Sheets(1).Range("A:J").Font.Size = 10
End With
With ThisWorkbook.Worksheets("Summary").Range("A22:J27").Copy
With Workbooks("Batsmen.xlsx").Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Offset(2)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
.PasteSpecial Paste:=xlPasteColumnWidths
.Font.Size = 10
End With
End With
Application.Calculation = xlAutomatic
Application.ScreenUpdating = True
End Sub
This can be optimized, but should get you started.
Check the code's comments and adjust it to fit your needs.
You can put the cursos inside the Process procedure, press F8 key and see what the code does.
EDIT: Added summarySheet.Range("E3").value = cell.value to the loop
Option Explicit
Public Sub Process()
Dim targetWorkbook As Workbook
Dim summarySheet As Worksheet
Dim sourceRange As Range
Dim cell As Range
' Customize this settings
Set targetWorkbook = Workbooks("Batsmen.xlsx")
Set summarySheet = ThisWorkbook.Worksheets("Summary")
Set sourceRange = summarySheet.Range("H2:H21")
Application.ScreenUpdating = False
Application.Calculation = xlManual
' Loop through each cell in source range
For Each cell In sourceRange.Cells
' Validate that cell has a value
If cell.Value <> vbNullString Then
' Fill E3 with cell value from range in column H
summarySheet.Range("E3").value = cell.value
' Execute procedure to create new sheet
CreateNewSheet targetWorkbook, cell.Value, summarySheet
End If
Next cell
Application.Calculation = xlAutomatic
Application.ScreenUpdating = True
End Sub
Private Sub CreateNewSheet(ByVal targetWorkbook As Workbook, ByVal newSheetName As String, ByVal summarySheet As Worksheet)
Dim targetSheet As Worksheet
Set targetSheet = targetWorkbook.Worksheets.Add
targetSheet.Name = newSheetName
summarySheet.Range("A22:J63").Copy
With targetSheet
.Range("A1").PasteSpecial Paste:=xlPasteValues
.Range("A1").PasteSpecial Paste:=xlPasteFormats
.Range("A1").PasteSpecial Paste:=xlPasteColumnWidths
.Range("A:J").Font.Size = 10
End With
summarySheet.Range("A22:J27").Copy
With targetSheet.Range("A" & Rows.Count).End(xlUp).Offset(2)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
.PasteSpecial Paste:=xlPasteColumnWidths
.Font.Size = 10
End With
End Sub
Let me know if it works
The code below should answer your question because it does create the sheets you want.
Sub CreateNewSheet()
Dim Wb As Workbook
Dim WbBat As Workbook
Dim WsSum As Worksheet
Dim NamesRange As Range
Dim i As Integer
Dim TabName As String
With Application
.ScreenUpdating = False
.Calculation = xlManual
End With
Set Wb = ThisWorkbook
Set WbBat = Workbooks("Batsmen.xlsx")
Set WsSum = Wb.Worksheets("Summary")
Set NamesRange = WsSum.Range("H2:H21")
For i = 1 To NamesRange.Cells.Count
TabName = Trim(NamesRange.Cells(i).Value)
If Len(TabName) Then ' skip if name is blank
With WbBat.Worksheets.Add()
.Name = TabName
WsSum.Range("A22:J63").Copy Destination:=.Cells(1, "A")
WsSum.Range("A22:J27").Copy Destination:=.Cells(.Rows.Count, "A").End(xlUp).Offset(2)
.Range("A:J").Columns.AutoFit
.Range("A1:J" & .Cells(.Rows.Count, "A").End(xlUp).Row).Font.Size = 10
End With
End If
Next i
With Application
.Calculation = xlAutomatic
.ScreenUpdating = True
End With
End Sub
Regrettably, it doesn't provide you usable code because it pastes the same data to all sheets. I presume that you have a plan how to vary the data. Unfortunately, I failed to understand such a plan from your question. However, I suspect that you will be able to modify the code to make it useful.

Copying range of cells generates object defined error

I'm trying to copy paste from an assigned variable worksheet to another.
I've been able to make do by recording but I would like to know how to do it manually.
This is the code I made:
Sub Parse_Reportable()
Dim ws As Worksheet
Sheets.Add.Name = "Copy to Reportable or TAK"
Set ws = Sheets("Copy to Reportable or TAK")
Sheets("sheet1").Select
Range("H3", Cells.Columns(8).End(x1Down)).Copy
ws.Cells(2, 2).Paste
End Sub
Running it creates the worksheet but gives me an
object defined error
in the copy code.
Cells.Columns(8).End(x1Down) will give you the error. It also has a typo. x1Down
Instead of using xlDown, use xlUp to find the last row using THIS and then construct your range to copy.
Is this what you are trying? (Untested)
Option Explicit
Sub Parse_Reportable()
Dim rngToCopy
Dim ws As Worksheet
Dim lRow As Long
Sheets.Add.Name = "Copy to Reportable or TAK"
Set ws = Sheets("Copy to Reportable or TAK")
With Sheets("sheet1")
lRow = .Range("H" & .Rows.Count).End(xlUp).Row
Set rngToCopy = .Range("H3:H" & lRow)
End With
rngToCopy.Copy ws.Cells(2, 2)
End Sub
Note: You may also want to delete the sheet "Copy to Reportable or TAK" if it already exists before naming the new sheet with that name else you will again get an error.
On Error Resume Next
Application.DisplayAlerts = False
Sheets("Copy to Reportable or TAK").Delete
Application.DisplayAlerts = True
On Error GoTo 0
Sheets.Add.Name = "Copy to Reportable or TAK"

Copy data from current workbook and paste it to another open workbook with userform list

I am wanting to have a button open a userform with a list of all open Workbooks. The user selects the workbook they want and the code copies data from a fixed range in the current workbook and pastes it into a fixed range in the user selected workbook.
While searching around I found this code, that works similarly but copies from the selected workbook and pastes into the current one.
Option Explicit
Const PSWD = "atari"
Private Sub CancelButton_Click()
Unload Me
End Sub
Private Sub CopyPasteButton_Click()
ActiveSheet.Unprotect Password:=PSWD
'This code will be executed when the "Copy" button is clicked on the userform.
Dim wsData As Worksheet
Dim rCopy As Range
Dim CopyRw As Long
Set wsData = ThisWorkbook.Sheets("SALES Details")
With Application
.DisplayAlerts = False
.ScreenUpdating = True
With wsData
.Unprotect PSWD
CopyRw = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
End With
On Error GoTo exit_err
With Workbooks(Me.ListBox1.Value).Sheets("Master Sheet")
Set rCopy = .Cells(10, 1).CurrentRegion
Set rCopy = rCopy.Offset(1, 0).Resize(rCopy.Rows.Count - 1, 40)
rCopy.Copy ThisWorkbook.Sheets("SALES Details").Cells(CopyRw, 1)
End With
Unload Me
exit_err:
wsData.Protect Password:=PSWD
.DisplayAlerts = True
.ScreenUpdating = True
.CutCopyMode = False
End With
End Sub
Private Sub UserForm_Activate()
'Populate list box with names of open workbooks, excluding main workbook.
Dim wb As Workbook
For Each wb In Workbooks
If wb.Name <> ThisWorkbook.Name Then ListBox1.AddItem wb.Name
Next wb
End Sub
This code works great, for what it does. I have been trying to edit it without luck. How can I edit this to reverse the direction and have it copy from a fixed range in the current sheet (A50:J57) to a fixed range on the user selected sheet (A4:J11)?
I think this should work. Of course you have to adapt the sheet names in code.
Private Sub CopyPasteButton_Click()
Dim mySheet As Worksheet, otherSheet As Worksheet
On Error GoTo exit_err
Application.DisplayAlerts = False
Set mySheet = ThisWorkbook.Sheets("SheetXYZ")
Set otherSheet = Workbooks(Me.ListBox1.Value).Sheets("SheetABC")
mySheet.Range("A50:J57").Copy Destination:=otherSheet.Range("A4:J11")
exit_err:
Application.DisplayAlerts = True
End Sub
UPDATE
For copying the values and not the formulas of the range use this code instead of the Copy function:
mySheet.Range("A50:J57").Copy
otherSheet.Range("A4:J11").PasteSpecial xlPasteValuesAndNumberFormats
For further options of the PasteSpecial function see the documentation.

Linking data between 2 sheets based on non uniform data ranges

I am trying to take a non uniform range of data on one sheet and link it up(cells will have "=Sheet1!A1", instead of hard coded values) to another worksheet within the same workbook.
I cant use just .UsedRange because I get a lot of empty cells in my selection which I don't want to link to another worksheet
Here is my code so far, but I get an error saying you can't use .copy with this kind of selection. Could someone please suggest a way around this. Thank you.
Sub test()
Application.ScreenUpdating = False
ActiveSheet.UsedRange.SpecialCells(xlCellTypeConstants).Copy
With Sheets("Sheet2")
.Activate
.Range("A1").Select
ActiveSheet.Paste Link:=True
End With
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
You can iterate over the SpecialCells ranges cell by cell, and write the links based on the source cell address, like this
Sub test()
Dim cl As Range
Dim sh As Worksheet
Dim ShName As String
Dim OldCalc As XlCalculation
Application.ScreenUpdating = False
OldCalc = Application.Calculation
Application.Calculation = xlCalculationManual
Set sh = Worksheets("Sheet2")
sh.Cells.Clear '<-- Optional
ShName = "='" & ActiveSheet.Name & "'!"
For Each cl In ActiveSheet.UsedRange.SpecialCells(xlCellTypeConstants)
sh.Range(cl.Address).Formula = ShName & cl.Address
Next
Application.ScreenUpdating = True
Application.Calculation = OldCalc
End Sub
While looping over a range is not ideal (due to speed) it may be adequate in this case.
This Sub will error if the active sheet is empty: you may want to add an error handler for this case

Resources