I am trying to switch between a template (hard coded) and a dynamic report which changes name weekly (ThisWorkbook). I am struggling with calling the variable x to bring focus to the workbook. I am copying the template formulas and pasting them into the dynamic report.
Sub wkbk()
Dim x As Excel.Workbook
Set x = ThisWorkbook
Dim pth As String
pth = x.FullName
Windows(pth).Activate
End Sub
Here is the VBA code I am using:
Windows("BBU_CMD_TEMPLATE.xlsx").Activate
Cells.Select
Selection.Copy
Windows(pth).Activate
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Paste
Why not just use ThisWorkbook.Activate? There's generally no need to assign a variable to represent a built-in like ThisWorkbook so the rest of those variables are unnecessary unless you're using them elsewhere in that procedure (from the snippet provided, you aren't, so you don't need them).
Sub wkbk()
ThisWorkbook.Activate
End Sub
However, what's the point of wkbk procedure? If solely to activate the workbook, that's not needed either and there are plenty of reasons to avoid Activate.
Sub CopySheetFromTemplateToThisWorkbook()
Dim tmplt As Workbook
On Error Resume Next
Set tmplt = Workbooks("BBU_CMD_TEMPLATE.xlsx")
If tmplt Is Nothing Then
MsgBox "Template file needs to be open..."
Exit Sub
End If
On Error GoTo 0
With ThisWorkbook
tmplt.ActiveSheet.Copy After:=.Sheets(.Sheets.Count)
End With
End Sub
Related
I want to copy a range from a workbook and transpose it into my current sheet.
Why would I get a "Subscript out of range" error on this line:
Workbooks("Libraries\Documents\Book1.xlsx").Worksheets("Sheet1").Range("A1:A5").Copy
Sub PasteSpecial_Examples()
'https://stackoverflow.com/questions/8852717/excel-vba-range-copy-transpose-paste
'https://www.excelcampus.com/vba/copy-paste-cells-vba-macros/
Workbooks("Libraries\Documents\Book1.xlsx").Worksheets("Sheet1").Range("A1:A5").Copy
ActiveSheet.Range("A1").PasteSpecial Transpose:=True
End Sub
Excel only permits one workbook open with a certain filename at the same time, even if those workbooks exist in different directories (which they must, or they couldn't have the same filename).
The Workbooks collection's index is just the filename, not the fully-qualified path and name.
I'm not sure whether the first point is the reason for the second point, or whether the second point is the reason for the first point, but they will be related.
So your code should be:
Sub PasteSpecial_Examples()
Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1:A5").Copy
ActiveSheet.Range("A1").PasteSpecial Transpose:=True
End Sub
Based on comments implying that you haven't yet opened Libraries\Documents\Book1.xlsx when you run your code, you could do this:
Sub PasteSpecial_Examples()
Dim wsDst As WorkSheet
Set wsDst = ActiveSheet
Workbooks.Open "Libraries\Documents\Book1.xlsx"
Workbooks("Book1.xlsx").Worksheets("Sheet1").Range("A1:A5").Copy
wsDst.Range("A1").PasteSpecial Transpose:=True
End Sub
which continues to refer to the workbook by its name.
Or, slightly better, do this:
Sub PasteSpecial_Examples()
Dim wbSrc As WorkBook
Dim wsDst As WorkSheet
Set wsDst = ActiveSheet
Set wbSrc = Workbooks.Open("Libraries\Documents\Book1.xlsx")
wbSrc.Worksheets("Sheet1").Range("A1:A5").Copy
wsDst.Range("A1").PasteSpecial Transpose:=True
End Sub
which assigns a Workbook object to refer to the newly opened workbook and then uses that object in the Copy statement.
Note: In this code "Libraries\Documents\Book1.xlsx" is a relative reference to the file, e.g. if the current directory was C:\Temp then it would look for the file C:\Temp\Libraries\Documents\Book1.xlsx. You should seriously consider using an absolute reference if possible.
I do it like this:
Dim Finfo As String
Dim FilterIndex As Long
Dim Title As String
Dim ExportFilename As Variant
Dim CopyBook As Workbook
Dim CopySheet As Worksheet
Dim MnthName As String
'Set up file filter
Finfo = "Excel Files (*.xls*),*.xls*"
'Set filter index to Excel Files by default in case more are added
FilterIndex = 1
' set Caption for dialogue box
Title = "Select a the DD Revenue Master file to Export to"
'get the Forecast Filename
ExportFilename = Application.GetOpenFilename(Finfo, FilterIndex, Title)
'Handle file Selection
If ExportFilename = False Then
'No Export File was Selected
MsgBox "No file was selected"
Else
'Check and see if this is a correct Export File
Workbooks.Open (ExportFilename)
Set CopyBook = ActiveWorkbook
Set CopySheet = CopyBook.Worksheets(1)
MsgBox "Valid File Selected."
Application.CutCopyMode = False
revenueSheet.Range("A1:BO500").Copy
CopyBook.Worksheets(1).Activate
CopyBook.Worksheets(1).Range("A1").PasteSpecial Paste:=xlPasteColumnWidths
CopyBook.Worksheets(1).Range("A1").PasteSpecial Paste:=xlPasteAllUsingSourceTheme, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False 'erase the clipboard
'close your stuff that you dont want open
End If
End Sub
Don't forget to close your workbooks when you are done. I had to trim a bunch of code because my file launches into a large case select. But often you select a workbook, open it, select some data, copy it, and paste it, close the workbook. Happens alot. Hope this helps. I believe that I found that you had to activate the newly selected workbook to perform actions on it. You can always refer to the workbook with the code in it as ThisWorkbook
To avoid confusion and since they are used in a bunch of modules I have a global variables module with the following in it but you could do this at the top of the sub if you don't have a complex project.
Option Explicit
Public thisWB As Workbook
Public functionSheet As Worksheet
Public revenueSheet As Worksheet
Public salesSheet As Worksheet
Public scratchSheet As Worksheet
Public lastRow As Double
'**********************************************************
'This sub routine will be used to intialize public variables
'**********************************************************
Private Sub SetPublicVariables()
Set thisWB = ActiveWorkbook
Set functionSheet = thisWB.Worksheets("Data Functions")
Set revenueSheet = thisWB.Worksheets("DD Monthly Revenue")
Set salesSheet = thisWB.Worksheets("Salespersons")
Set scratchSheet = thisWB.Worksheets("ScratchSheet")
End Sub
I use this method alot . . . . . .
Oh, I call the public variable set up upon workbook open (you can find that method). In order to call a private sub you must use.
Application.Run "Global_Variables.SetPublicVariables"
'that is modulename.methodname if you want to pass arguments following
'Application.Run "modulename.methodname", arg1, arg2, etc.
Cheers, Happy coding - WWC
I need to write a macro script that will copy data from one xml workbook and paste the values to another workbook. I've written the below macro that works fine, but i need to run this every week for several different documents so it means i have to replace the document name for each run.
Here's what i have so far:
Sub copying()
''''''Section 1''''''
Workbooks("Results_2561").Activate 'workbook i'm copying from
Range("B27:B41").Select
Selection.Copy
Workbooks("Overall_Results").Activate 'workbook i'm pasting to
Range("G2").PasteSpecial
''''''Section 2''''''
Workbooks("Results_2561").Activate
Range("C27:C41").Select
Selection.Copy
Workbooks("Overall_Results").Activate
Range("C2").PasteSpecial
''''''Section 3''''''
Workbooks("Results_2561").Activate
Range("I28:I40").Select
Selection.Copy
Workbooks("Overall_Results").Activate
Range("G17").PasteSpecial
''''''Section 4''''''
Workbooks("Results_2561").Activate
Range("J28:J40").Select
Selection.Copy
Workbooks("Overall_Results").Activate
Range("C17").PasteSpecial
End Sub
...
and that's only half the script. Is there a way i can declare a variable at the start and set it as the Workbooks file path so i can call that instead of typing and retyping it over and over again?
Preferably without using something like
Dim book1 as Workbook
Set book1 = Workbooks.Open("C://Results_2561.xlsm")
..as this keeps opening and closing the document when i run the script.
Thanks
since you're only interested in copying values you could use this helper Sub
Sub CopyValues(rngToCopyFrom As Range, rngToCopyTo As Range)
With rngToCopyFrom
rngToCopyTo.Resize(.Rows.COUNT, .Columns.COUNT).Value = .Value
End With
End Sub
to be exploited in your main code like follows:
Sub main()
Dim wsTo As Worksheet
Set wsTo = Workbooks("Overall_Results").ActiveSheet '<--| set the worksheet to paste values to
With Workbooks("Results_2561").ActiveSheet '<--| reference the worksheet to copy values from
CopyValues .Range("B27:B41"), wsTo.Range("G2")
CopyValues .Range("C27:C41"), wsTo.Range("C2")
CopyValues .Range("I28:I40"), wsTo.Range("G17")
CopyValues .Range("J28:J40"), wsTo.Range("C17")
End With
End Sub
should your relevant workbooks have more than one sheet, then just substitute
ActiveSheet
with
Worksheets("myRelevantShetName") '<--|change "myRelevantShetName" to the actual name of the relevant worksheet in each workbook
First of all, you don't have to Activate workbook every time when you want to copy/paste something. Just declare it in Range() property, for example:
''''''Section 1''''''
Workbooks("Results_2561").Sheets(1).Range("B27:B41").Copy
Workbooks("Overall_Results").Sheets(1).Range("G2").PasteSpecial
You can set Workbook as variable like:
Sub copying()
Dim wb1 As Workbook, wb2 As Workbook
Set wb1 = Workbooks("Results_2561")
Set wb2 = Workbooks("Overall_Results")
''''''Section 1''''''
wb1.Sheets(1).Range("B27:B41").Copy
wb2.Sheets(1).Range("G2").PasteSpecial
End Sub
Finally, as #A.S.H suggested, you can add a file dialog where you point which files you want to use. I have put it in some function (don't forget to put it in the same project as your copying macro):
Function strPath() As String
Dim intResult As Integer
Application.FileDialog(msoFileDialogFilePicker).Title = "Select file"
intResult = Application.FileDialog(msoFileDialogFilePicker).Show
If intResult <> 0 Then
strPath = Application.FileDialog(msoFileDialogFilePicker).SelectedItems(1)
End If
End Function
So your final code for Section 1 would look like:
Sub copying()
Dim wb1 As Workbook, wb2 As Workbook
MsgBox "Show file to copy form."
Set wb1 = Workbooks.Open(strPath())
MsgBox "Show file to paste in."
Set wb2 = Workbooks.Open(strPath())
''''''Section 1''''''
wb1.Sheets(1).Range("B27:B41").Copy
wb2.Sheets(1).Range("G2").PasteSpecial
End Sub
I don't know why, I just can't get this to work. I've simplified it right down to just three lines - but it's causing me problems still.
Basically I want to open a workbook and copy some data from it into a master workbook.
I have:
Sub copypaste()
Workbooks.Open("...Test.xlsx").Sheets("Sheet1").Cells(1, 1).Copy
ActiveWorkbook.Close
Sheets("Sheet1").Range("A1").PasteSpecial xlPasteValues
End Sub
I've seen runtime error 438 (object does not support this property method), I can get paste that but just hit 1004 application defined error or object defined error.
I honestly have no idea where I'm going wrong on this simple task!
Thank you in advance,
Tom
Try closing the workbook after pasting the data.
As an example you can use something like:
Sub copypaste()
Dim WBopen As Workbook, Wb As Workbook
Set Wb = ActiveWorkbook
Set WBopen = Workbooks.Open("...Test.xlsx")
WBopen.Sheets("Sheet1").Cells(1, 1).Copy
Wb.Sheets("Sheet1").Range("A1").PasteSpecial xlPasteValues
WBopen.Close
End Sub
Because you are closing the Workbook before the data is pasted it fails.
It is also preferred to not use .Copy and .Paste when it can be avoided.
See example below for a direct setting of the Values:
Sub copypaste()
Dim wbMaster As Workbook, wbData As Workbook
Set wbMaster = Workbooks("Master.xlsm")
Set wbData = Workbooks.Open("Data.xlsx")
wbMaster.Sheets("Sheet1").Range("A1").Value = wbData.Sheets("Sheet1").Range("A1").Value
wbData.Close False
End Sub
this is my first post on StackExchange! I've been using StackExchange for answers, but now i really have a question.
I am trying to add a column in excel using vba. This is procedure is part of a bigger sub function of which I created a new workbook and copy a series of sheets from a different workbook over.
Workbooks.Add
Set TTB = ActiveWorkbook
'add a bunch of sheets here
'sheetName = specific_sheet
Set ttb_sheet = TTB.Sheets(sheetName)
ttb_sheet.Columns("I:I").Insert Shift:=xlToRight
With this i get a runtime error of 1004: 'Insert method of Range class failed'
I tried following a series of questions on StackOverflow...
Select method of Range class failed via VBA
VBA error 1004 - select method of range class failed
It seems like the solution is to select the sheet first, then select the range. I have tried this and there was no luck. Anyone have any insight?
Here's my main sub code..
Sub create_TTB_workbook(TTB_name_)
'create TTB workbook
Dim wsHelper As New WorksheetHelper
Dim final_TTB As Workbook
Dim ttb_sheet As Worksheet
ttb_wb = ActiveWorkbook.name
Workbooks(ttb_wb).Activate
PCB_tab = 0
ST_COMP_tab = 0
For Each WS In Worksheets
If WS.name = "PCB_PIN_REPORT" Then
PCB_tab = 1
End If
If WS.name = "ST_PIN_REPORT" Then
ST_COMP_tab = 1
End If
Next WS
Workbooks.Add
Set TTB = ActiveWorkbook
new_ttb_wb = TTB.name
Debug.Print (new_ttb_wb)
If PCB_tab = 1 Then
wsHelper.copySheet ttb_wb, "PCB_PIN_REPORT", new_ttb_wb, "PCB_PIN_REPORT"
End If
If ST_COMP_tab = 1 Then
wsHelper.copySheet ttb_wb, "ST_PIN_REPORT", new_ttb_wb, "ST_PIN_REPORT"
End If
wsHelper.copySheet ttb_wb, TTB_name_, new_ttb_wb, TTB_name_
' TRIED A BUNCH OF METHODS here...
'Workbooks(ttb_wb).Sheets(TTB_name_).Cells.copy
'Sheets.Add.name = TTB_name_
'ActiveSheet.paste
'Sheets(TTB_name_).Activate
'Columns("I:I").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
'Worksheets(TTB_name_).Range("I1").EntireColumn.Insert
'Columns("I:I").Select
'Columns("I:I").Insert Shift:=xlToRight
Set ttb_sheet = Sheets(TTB_name_)
ttb_sheet.Columns("I:I").Insert Shift:=xlToRight
Columns("K").copy Destination:=Range("I1")
Range("I6") = "header name"
End Sub
Whenever I run into an issue like this, I always isolate the code to its simplest form. Once I get it working at that level, I add it back in to the full application and can usually figure out what I did wrong.
I've written a simple version of what you are trying to do. Note that I've included a few Debug.Print statements to help me verify what is going on. The debug messages will appear in your Immediate window. Obviously you can also step through the code and examine variables as you go.
To get this to work, create a workbook and save it as DestinationWorkbook.xlsx. Then open another workbook and insert the code below.
Sub InsertColumnInDestinationWorksheet()
Dim sourceWb As Workbook
Dim targetWb As Workbook
Dim sourceWs As Worksheet
Dim targetWs As Worksheet
Set sourceWb = ThisWorkbook
Debug.Print sourceWb.Name
Set targetWb = Workbooks("DestinationWorkbook.xlsx")
Debug.Print targetWb.Name
Set sourceWs = sourceWb.Sheets("Sheet1")
Debug.Print sourceWs.Name
Set targetWs = targetWb.Sheets("Sheet1")
Debug.Print targetWs.Name
targetWs.Range("I1").Value2 = "Moving right along..."
targetWs.Columns("I:I").Insert shift:=xlToRight
End Sub
After running the code, you can examine the target sheet. You should see the text we wrote into column I is now in column J.
This works for me when I change the variable naming to:
Sub testingg()
Dim ttb_sheet As Worksheet
Set ttb_sheet = Sheets(1)
ttb_sheet.Columns("I:I").Insert Shift:=xlToRight
End Sub
So I presume there's an issue with the way you reference the workbook when setting ttb_sheet on line 3. Note that you add a workbook but you aren't actually 'activating' it necessarily. And are you sure the 'Sheetname' actually exists in the TTB workbook?
I need to open a worksheet with a fixed name and insert the name of each tab (which will change according to the current date) at the top of the sheet.
I modified some code from a previous answer and had the code working when it did not include the code to open the workbook. Now it flicks through the tabs but doesn't insert the name into Cells(1, 1) and I have no idea why. It also bugs at the end: Run-time error 91, which is less problematic but would be good to fix.
Any tips or advice much appreciated. Below is my current code:
Sub PSOPENTAB()
ChDir "G:\directory"
Workbooks.Open Filename:="G:\directory\filename.xls"
Windows("filename.xls").Activate
ActiveWorkbook.Worksheets(1).Activate
Call nametop
End Sub
Sub nametop()
Dim i As Long
With ThisWorkbook
'exit if Activesheet is the last tab
If .ActiveSheet.Index + 1 > .Worksheets.Count Then
Exit Sub
End If
For i = .ActiveSheet.Index To .Worksheets.Count - 1
.ActiveSheet.Cells(1, 1) = .Worksheets(i).Name
ActiveSheet.Next.Select
Next i
End With
End Sub
You need to reference your objects correctly.
Your problems are:
You use Thisworkbook in your nametop routine. So it will always work on the workbook containing the code.
You can change it to ActiveWorkbook but that may lead you to other problems in the future. See this cool stuff to know more about why to avoid Activeworkbook/Activesheet and the like
Applying what's discussed there, try below code:
Sub PSOPENTAB()
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:="G:\directory\filename.xls")
nametop wb
End Sub
Sub nametop(wb As Workbook)
Dim ws As Worksheet
For Each ws In wb.Worksheets
ws.Cells(1, 1) = ws.Name
Next ws
End Sub
Above code adds the name of the sheet in Cell A1 of every sheet.
Is this what you're trying?