How to run macro from another workbook - excel

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.

Related

VBA copy and past loop

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

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.

Get error message "expected end of line" when using PasteSpecial

I am copying a range from all open workbooks with the goal of pasting the copied cells into a consolidated sheet in the master (active) workbook. I need to paste the values only but get an "end of line" error message with this code
Spent pretty much all day googling my problem to no avail
Sub Consolidate()
Dim oBook As Workbook, ws As Worksheet, wb As Workbook, bk As Workbook
Dim copyFrom As Range
'Disable Screen Updating - stop screen flickering
' And Disable Events to avoid inturupted dialogs / popups
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Delete the Consolidate_Data WorkSheet if it exists
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Sheets("Consolidate_Data").Delete
Application.DisplayAlerts = True
'Add a new WorkSheet and name as 'Consolidate_Data'
With ActiveWorkbook
Set DstSht = .Sheets.Add(After:=.Sheets(.Sheets.Count))
DstSht.Name = "Consolidate_Data"
End With
'Loop through each WorkBook in the folder and copy the data to the 'Consolidate_Data' WorkSheet in the ActiveWorkBook
Set wb = ActiveWorkbook
For Each oBook In Application.Workbooks
If Not oBook.Name = wb.Name Then
'Find the last row on the 'Consolidate_Data' sheet
DstRow = fn_LastRow(DstSht) + 1
'Determine Input data range
Set copyFrom = oBook.Worksheets(1).Range("A6:C8")
'Copy data to the 'consolidated_data' WorkSheet
copyFrom.Copy _
DstSht.Range("A" & DstRow).PasteSpecial xlPasteValues
End If
Next
IfError:
'Enable Screen Updating and Events
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
'Find the last Row of specified Sheet
Function fn_LastRow(ByVal Sht As Worksheet)
Dim lastRow As Long
lastRow = Sht.Cells.SpecialCells(xlLastCell).Row
lRow = Sht.Cells.SpecialCells(xlLastCell).Row
Do While Application.CountA(Sht.Rows(lRow)) = 0 And lRow <> 1
lRow = lRow - 1
Loop
fn_LastRow = lRow
End Function
Consolidate()
Dim oBook As Workbook, ws As Worksheet, wb As Workbook, bk As Workbook
Dim copyFrom As Range
'Disable Screen Updating - stop screen flickering
' And Disable Events to avoid inturupted dialogs / popups
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Delete the Consolidate_Data WorkSheet if it exists
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Sheets("Consolidate_Data").Delete
Application.DisplayAlerts = True
'Add a new WorkSheet and name as 'Consolidate_Data'
With ActiveWorkbook
Set DstSht = .Sheets.Add(After:=.Sheets(.Sheets.Count))
DstSht.Name = "Consolidate_Data"
End With
'Loop through each WorkBook in the folder and copy the data to the 'Consolidate_Data' WorkSheet in the ActiveWorkBook
Set wb = ActiveWorkbook
For Each oBook In Application.Workbooks
If Not oBook.Name = wb.Name Then
'Find the last row on the 'Consolidate_Data' sheet
DstRow = fn_LastRow(DstSht) + 1
'Determine Input data range
Set copyFrom = oBook.Worksheets(1).Range("A6:C8")
'Copy data to the 'consolidated_data' WorkSheet
copyFrom.Copy _
DstSht.Range("A" & DstRow).PasteSpecial xlPasteValues
End If
Next
IfError:
'Enable Screen Updating and Events
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
'Find the last Row of specified Sheet
Function fn_LastRow(ByVal Sht As Worksheet)
Dim lastRow As Long
lastRow = Sht.Cells.SpecialCells(xlLastCell).Row
lRow = Sht.Cells.SpecialCells(xlLastCell).Row
Do While Application.CountA(Sht.Rows(lRow)) = 0 And lRow <> 1
lRow = lRow - 1
Loop
fn_LastRow = lRow
End Function
Get an error message at the PasteSpecial line. Everything works fine without the paste special but, as the copied range includes formulas, I do not get the values which is what I need.
.Copy and .PasteSpecial have to be done in 2 different lines but you concatenated the lines with _
copyFrom.Copy _
DstSht.Range("A" & DstRow).PasteSpecial xlPasteValues
Change it to:
copyFrom.Copy 'no line concatenation here !
DstSht.Range("A" & DstRow).PasteSpecial xlPasteValues
For more information see the documentation:
Range.Copy method
Range.PasteSpecial method / Worksheet.PasteSpecial method

Excel VBA function to only paste what is within the print area rather than the entire sheet?

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

Excel VBA - open a workbook and pasting data

I found this excellent code however I need to adapt it for my purposes.
Firstly I need to open a data workbook that is on our network. The problem I have is that it is likely at times to be open by another user and will offer the option of "read only". How can I get it to accept the read-only option so that I can commence extracting the data.
Secondly it copies using the "=" . How can I change it to copy just the values?
First macro:
Sub test()
'to open another workbook
Application.ScreenUpdating = False
Workbooks.Open Filename:=ThisWorkbook.Path & "\Schedule.xls"
ThisWorkbook.Activate
Application.ScreenUpdating = True
End Sub
2nd Macro:
Dim Sh As Worksheet
Dim Newsh As Worksheet
Dim myCell As Range
Dim ColNum As Integer
Dim RwNum As Long
Dim Basebook As Workbook
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'Delete the sheet "Summary-Sheet" if it exist
Application.DisplayAlerts = False
On Error Resume Next
ThisWorkbook.Worksheets("Summary-Sheet").Delete
On Error GoTo 0
Application.DisplayAlerts = True
'Add a worksheet with the name "Summary-Sheet"
Set Basebook = ThisWorkbook
Set Newsh = Basebook.Worksheets.Add
Newsh.Name = "Summary-Sheet"
'The links to the first sheet will start in row 2
RwNum = 1
For Each Sh In Basebook.Worksheets
If Sh.Name <> Newsh.Name And Sh.Visible Then
ColNum = 1
RwNum = RwNum + 1
'Copy the sheet name in the A column
Newsh.Cells(RwNum, 1).Value = Sh.Name
For Each myCell In Sh.Range("A1,D5:E5,Z10") '<--Change the range
ColNum = ColNum + 1
Newsh.Cells(RwNum, ColNum).Formula = _
"='" & Sh.Name & "'!" & myCell.Address(False, False)
Next myCell
End If
Next Sh
Newsh.UsedRange.Columns.AutoFit
With Application
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
You could always open the workbook as read-only if you are only extracting data.
Instead of using .formula use .value

Resources