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.
Related
I have a macro in the workbook1 (code below).
I want to run this macro on another workbook, but it keeps opening the workbook1 and create the sheet in workbook1. It works fine if I copy the code into another workbook, but I want to run macro in another workbook from workbook1. The macro will create a sheet in workbook1 using another workbook data. How to make it create the sheet in an active workbook or another workbook.
Sub Pneumatic_Diagram()
Dim FileToOpen As Variant
Dim OpenBook As Workbook
Dim Machine As String
Dim iPnuematic As Integer
Dim iProject As Integer
Dim Lastrow As Long
Machine = Sheets("Project plan").Range("E4")
FileToOpen = "O:\060 Designs\06 All Pneumatic\Pneumatic_Tools\Pneumatic-Database2.xlsx"
With Application
.ScreenUpdating = False
.EnableEvents = False
.Calculation = xlCalculationManual
End With
'*** Delete define sheet name ***
For Each Sheet In ActiveWorkbook.Worksheets
If Sheet.Name = "Pnumatic_Diagram" Then
Sheet.Delete
End If
Next Sheet
'**** Copy GN. from Projectplan****
Sheets("Project plan").Range("B:B").Copy
Sheets.Add(After:=Sheets("Follow up")).Name = "Pnumatic_Diagram"
Sheets("Pnumatic_Diagram").Range("L1").PasteSpecial xlPasteValues
Range("L:L").SpecialCells(xlCellTypeConstants, 2).EntireRow.Delete
Range("L:L").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
'**** Get data from data base****
If FileToOpen <> False Then
Set OpenBook = Application.Workbooks.Open(FileToOpen)
OpenBook.Sheets(Machine).Range("A:F").Copy
With ThisWorkbook.Worksheets("Pnumatic_Diagram").Range("A1")
.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
.PasteSpecial Paste:=xlPasteColumnWidths
.PasteSpecial Paste:=xlPasteFormats
End With
OpenBook.Close
End If
'**** Check data***
Cells(1, 7) = 1
For iPnuematic = 1 To Cells(Rows.Count, 2).End(xlUp).Row
For iProject = 1 To Cells(Rows.Count, 12).End(xlUp).Row
If Cells(iPnuematic, 1) = Cells(iProject, 12) Then
Cells(iPnuematic, 7) = 1
End If
Next iProject
Next iPnuematic
'*** Delete GN. project plan ***
Columns(12).EntireColumn.Delete
'*** Clear Data ***
For iPnuematic = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1
If Cells(iPnuematic, 7) <> 1 Then
Rows(iPnuematic).EntireRow.Delete
End If
Next iPnuematic
'*** Delete mark 1 ***
Columns(7).EntireColumn.Delete
With Application
.EnableEvents = True
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
Please, try replacing this code part
'*** Delete define sheet name ***
For Each Sheet In ActiveWorkbook.Worksheets
If Sheet.Name = "Pnumatic_Diagram" Then
Sheet.Delete
End If
Next Sheet
with
'your existing code...
'*** Delete define sheet name ***
'create a workbook variable to be set as ActiveWorkbook
Dim wbAct As Workbook: set wbAct = ActiveWorkbook
For Each Sheet In wbAct.Worksheets
If Sheet.Name = "Pnumatic_Diagram" Then
Sheet.Delete
End If
Next Sheet
'your existing code
Then replace ThisWorkbook with wbAct...
Like a general piece of advice, it is good to fully qualify all the used ranges. For instance Sheets("Project plan").Range("B:B").Copy works on the active workbook. To be sure that your code will not open another workbook, which will become the active one, you should use wbAct.Sheets("Project plan").Range("B:B").Copy.
And do the same for all cases where the code works on the active workbook, which may become problematic when the code becomes more complex: Range("L:L"), Cells(1, 7), Cells(iPnuematic, 1) etc.
I am trying to write a macro that goes into an infinite amount of sheets and copies and pastes a data range from A10:E10, A11:E11 and so on until it hits a blank cell until pastes it into a new tab until it has gone through each sheet and grabbed the data. I have tried to use the code below, but it will only let me paste one cell and if I change the range to more than one it pastes over and leaves out data. Any Help would be greatly appreciated.
Dim sh As Worksheet
Dim wb As Workbook
Dim DestSh As Worksheet
Dim i As Integer
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set wb = ThisWorkbook
Set DestSh = wb.Sheets("Combined")
' Loop through worksheets that start with the name "20"
i = 4
For Each sh In ActiveWorkbook.Worksheets
If sh.Name = "Data" Then Exit Sub
sh.Range("E10").Copy
With DestSh.Range("AF" & i)
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
i = i + 1
Next
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
I am creating a copy/paste vba code to transfer my financial model to a pasted version in a separate excel model and cannot figure out how to only paste what is shown within the print area. Currently it is working just fine but it pastes all data outside of the print range and shows all data that is hidden in rows/columns and not displayed.
I cannot seem to find a function or simple function to add to the already working code that would do this. I am new to VBA and unsure of the best method to add this functionality.
Sub Test()
Dim wb As Workbook, wbPaste As Workbook, wsExhibit1 As Worksheet, wsPaste As Worksheet, wsInputs As Worksheet, _
wsExhibit2 As Worksheet
With Application
.ScreenUpdating = False
.Calculation = xlCalculationAutomatic
.EnableEvents = False
End With
Set wb = ThisWorkbook
Set wbPaste = Workbooks("Copy_PasteWorkbook.xlsx")
With wb
Set wsExhibit1 = .Sheets("Value_Summary")
Set wsInputs = .Sheets("Inputs")
Set wsExhibit2 = .Sheets("Calculations")
End With
With wbPaste
Set wsPaste = .Sheets.Add(after:=.Sheets(.Sheets.Count))
End With
With wsPaste
wsExhibitA1.UsedRange.Copy
.Range("A1").PasteSpecial xlPasteValues
.Range("A1").PasteSpecial xlPasteFormats
.Range("A1").PasteSpecial xlPasteColumnWidths
.Name = .Cells(1, 3)
End With
wsInputs.Range("Selected_Calculation").Value = 1
Do Until wsInputs.Range("Selected_Calculation").Value > wsInputs.Range("Total_Calculations").Value
Application.Calculate
With wbPaste
Set wsTemp = .Sheets.Add(after:=.Sheets(.Sheets.Count))
End With
With wsTemp
wsExhibit2.UsedRange.Copy
.Range("A1").PasteSpecial xlPasteValues
.Range("A1").PasteSpecial xlPasteFormats
.Range("A1").PasteSpecial xlPasteColumnWidths
.Name = .Cells(1, 3)
End With
wsInputs.Range("Selected_Calculation").Value = wsInputs.Range("Selected_Calculation").Value + 1
DoEvents
Loop
wsInputs.Range("Selected_Calculation").Value = 1
With Application
.ScreenUpdating = False
.Calculation = xlCalculationAutomatic
.EnableEvents = False
.CutCopyMode = False
End With
End Sub
I am hoping to only paste what is within the print area set within the workbook on the respective pages. Not pasting down hidden data or data outside of the range.
Print_Area is a named range.
Sheets(“SheetName”).Range(“Print_Area”).Copy
To avoid hidden cells:
Sheets(“SheetName”).Range(“Print_Area”).SpecialCells(xlCellTypeVisible).Copy
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