I need help on declaring 2 workbooks globally where the workbook name is based on a cell value.
I have 3 workbooks workbook
"UPSHI" (file name does not change) workbook
"UAH DR_M04 2022"(M04 and 2022 changes monthly depending in month & year) workbook
"2022_M04_OP21_AAH"(2022, M04 & OP21 changes monthly).
UPASHI workbook will be my main file which will create all my buttons and formulas, I created formula in cell B1 for the 2nd workbook that will identify the current name of the 2nd workbook and another formula in cell B7 to identify current name of my 3rd workbook.
I used cell B1 & B7 to activate the workbooks which work fine but I cannot make it work when i want to copy a sheet from workbook 2 to my workbook 3.
I wanted to declare a global variable for each workbook that I can just call when I want to activate or select the work book, how can I make it work?.
Here is my current code:
Sub PrepFile_Click()
Workbooks(ActiveSheet.Range("b1").Value).Activate
Application.DisplayAlerts = False
Sheets("Upstream Asset Hierarchy -OLD").Delete
Application.DisplayAlerts = True
Sheets("Upstream Asset Hierarchy Viewer").Name = "Upstream Asset Hierarchy -OLD"
Workbooks("UPASHI Automation File").Activate
Workbooks(ActiveSheet.Range("b7").Value).Activate
Sheets("Upstream Asset Hierarchy Viewer").Copy before:=Workbooks(ActiveSheet.Range("b1").Value).Sheets("UPSASSET")
End Sub
Try the next way, please:
Declare four Public variables on top of a standard module (in the declarations area):
Option Explicit
Public wbUPS as Workbook, wbUAH as Workbook, wb3 As Workbook, ws As Worksheet
Create a Sub, let us say "SetWorbooks", placing the next code:
Sub SetWorbooks
Set wbUPS = ThisWorkbook
Set ws = wbUPS.Worksheets("The name of the active sheet")
Set wbUAH = Workbooks(ws.Range("b1").Value)
Set wb3 = Workbooks(ws.Range("b7").Value)
End Sub
Run the above code (once) and then just using wbUPS, wbUAH, wb3. Of course, the involved workbooks must be open...
Use the above variables in the next way:
Sub PrepFile_Click()
If wbUAH Is Nothing Then SetWorbooks 'just in case
Application.DisplayAlerts = False
wbUAH.Sheets("Upstream Asset Hierarchy -OLD").Delete
Application.DisplayAlerts = True
wbUAH.Sheets("Upstream Asset Hierarchy Viewer").Name = "Upstream Asset Hierarchy -OLD"
wb3.Sheets("Upstream Asset Hierarchy Viewer").Copy before:=wbUAH.Sheets("UPSASSET")
End Sub
Activation, selection do not bring any benefit (if you know how to avoid that), only consume Excel resources...
If something unclear, please do not hesitate to ask for clarifications. Of course, I couldn't test the above solution.
Related
I use this piece of code:
Application.Workbooks(V_WBNameOutPut).Activate
to activate a particular excel file, I notice that this method goes in error if the "File name extension" (in the View tab of the Folder Menu) is flagged.
In order to be independent of this, what modification should I do/include to the code or what alternative method should I use?
This answer is based on the comment
I interchange many times during the macro run between 2 workbooks, input and output
excel files, and I need to activate the V_WBNameOutPut, to paste and elaborate, and > this is done multiple times during the run. From the input file, I create the > V_WBNameOutPut file.
As #brax said - capture the workbook when it's opened and you don't have to worry about the extension after that.
Sub Test()
'Open the first workbook and store reference to it.
Dim wrkBk1 As Workbook
Set wrkBk1 = Workbooks.Open("H:\Darren Bartrup-Cook\Test 1.xlsx")
'Open the second workbook and store reference to it.
Dim wrkBk2 As Workbook
Set wrkBk2 = Workbooks.Open("H:\Darren Bartrup-Cook\Test 2.xlsx")
'Copy/paste from wrkbk1 to wrkbk2.
wrkBk1.Worksheets("Sheet1").Range("A1").Copy Destination:=wrkBk2.Worksheets("Sheet1").Range("A4")
'Create a new sheet in wrkbk2.
Dim NewWrkSht As Worksheet
Set NewWrkSht = wrkBk2.Worksheets.Add
NewWrkSht.Name = "My New Sheet"
'Paste copy/paste values from wrkbk1 to wrkbk2.
wrkBk1.Worksheets("Sheet1").Range("A2").Copy
NewWrkSht.Range("A5").PasteSpecial Paste:=xlPasteValues
'Make A3 in wrkbk2 equal the value in wrkbk1 A3.
wrkBk2.Worksheets("Sheet1").Range("A3") = wrkBk1.Worksheets("Sheet1").Range("A3")
'Close the two workbooks.
wrkBk2.Close SaveChanges:=True
wrkBk1.Close SaveChanges:=False
End Sub
Say I have two workbooks open with two tabs both named "Tab1". If in VBA, I want to refer to something on a tab, one would say "Tab1!" followed by what one is referring to, e.g. "Tab1!R1C1", etc.
However, how does the code know what Tab1 I am referring to in this case?
If it's worth mentioning, the code I am running is inside one of the workbooks. So will it always default back to that workbooks tab 1? If not, what does it do, and if yes, how would I make it refer to the tab 1 of the other workbook?
For context, I need to do this in the case of calling the method "ChangePivotCache" and give it a SourceData.
Without the code it's difficult to say definitively, but lets assume that you're using a range object. When you put "Tab1!R1C1" into that range object it uses the workbook of it's parent to make the determination. Most (if not all) methods that take a range argument like that will require that some parent of theirs is a workbook or worksheet.
In general if you're working with multiple workbooks best practice is to assign an object to them as you open them. That object can then be used to anchor any range calls you make. Either by calling directly from it or making children from it.
For example:
set workbook_code_is_in = Thisworkbook
set another_workbook = Application.Workbooks.Open(...)
set active_workbook = Activeworkbook
The first line will set workbook_code_is_in to the workbook that the code is located in.
The second line will set another_workbook to whatever you open.
The third line will set active_workbook to whatever workbook currently has focus. This is dangerous and prone to errors. It's very possible for a user to click a different workbook while a script is running and make the Activeworkbook an unintended one.
Referring to a Second Workbook
If you only have two workbooks open, then you refer to the workbook containing this code with ThisWorkbook and you can refer to the other workbook by using a For Each...Next loop to compare the workbooks' names.
Option Explicit
Sub ReferToSecondWorkbook()
Dim wb1 As Workbook: Set wb1 = ThisWorkbook ' workbook containing this code
If Workbooks.Count <> 2 Then
MsgBox "You need to have only two workbooks open.", vbCritical
Exit Sub
End If
Dim wb2 As Workbook
For Each wb2 In Workbooks
If StrComp(wb2.Name, wb1.Name, vbTextCompare) <> 0 Then ' different
Exit For
' Else ' it is 'wb1'
End If
Next wb2
Dim ws1 As Worksheet: Set ws1 = wb1.Worksheets("Tab1")
Dim ws2 As Worksheet: Set ws2 = wb2.Worksheets("Tab1")
Debug.Print "First: ", ws1.Name, wb1.Name
Debug.Print "Second: ", ws2.Name, wb2.Name
End Sub
So I am trying to write a Macro for Excel, that adds 2 worksheets from an excel file to a new one.
Therefore, I try this:
Sub addfile()
Dim sheet1 As Worksheet
Dim sheet2 As Worksheet
Set sheet1 = Sheets.Add(Type:="C:\Users\Helge\AppData\Roaming\Microsoft\Templates\page1.xltx")
Set sheet2 = Sheets.Add(Type:="C:\Users\Helge\AppData\Roaming\Microsoft\Templates\page2.xltx")
End Sub
When I test it, it imports the first page, but the 2nd page gives me a Runtime error 1004.
Why does this happen?
And is there another way to get 2 sheets from one excel file to another via vba?
Much to my surprise this version of your code actually worked for me.
Sub addfile()
Dim Sheet1 As Worksheet
Dim Sheet2 As Worksheet
Set Sheet1 = Sheets.Add(Type:=Environ("Userprofile") & "\OneDrive\Desktop\Template1.xltx")
Set Sheet2 = Sheets.Add(Type:=Environ("Userprofile") & "\OneDrive\Desktop\Book2.xlsx")
Debug.Print Sheet1.Name, Sheet2.Name
End Sub
The reason for my surprise is that Sheet1 and Sheet2 are the default CodeName for the first and second worksheets in any workbook. Therefore there is a conflict of naming between the Sheet1 in the workbook and the Sheet1 you declare which should come to the surface not later than Debug.Print Sheet1.Name. In fact, it may have. I didn't check which name was printed. But the code didn't crash. Since it crashes on your computer, perhaps you have an older version of Excel. Try to stay clear of variable names that Excel also uses. Or there is something wrong with the path & file name, which is hard to tell in that syntax and therefore kept me fooled for quite some time too.
In fact, I discovered the above only after finding out that my Desktop was on OneDrive and not before I had written the function below which is designed to avoid the use of Sheets.Add. It also has some extras such as being able to specify the sheet to take from the template (you could have one template with 2 or more sheets). You can specify an index number or a sheet name. And the function will give a name to the copy, too, if you specify one.
Private Function AddWorksheet(ByVal Template As String, _
TabId As Variant, _
Optional ByVal TabName As String) As Worksheet
Dim Wb As Workbook
Dim Path As String
Dim FileName As String
Set Wb = ThisWorkbook ' change to suit
' make sure the path ends on "\"
Path = "C:\Users\Helge\AppData\Roaming\Microsoft\Templates\"
With Workbooks.Open(Path & Template)
.Sheets(TabId).Copy After:=Wb.Sheets(Wb.Sheets.Count)
.Close
End With
Set AddWorksheet = ActiveSheet
If Len(TabName) Then ActiveSheet.Name = TabName
End Function
You can call the function from a sub routine like this:-
Sub AddWorksheets()
Dim Tab1 As Worksheet
Dim Tab2 As Worksheet
Application.ScreenUpdating = False
Set Tab1 = AddWorksheet("Page1.xltx", 1, "New Tab")
Set Tab2 = AddWorksheet("Page2.xltx", "Sheet1", "Another new Tab")
Application.ScreenUpdating = True
End Sub
Please observe the difference between the two function calls.
I'm trying to create a series of macros to audit some financial models.
The first macro I’m trying to create is one that names the current cell. Why? I want to name the cell, after that I’m going to record a macro to click the “Trace Precedents” and go to the cell that has the relationship.
After that I need to go back to the original cell, thats the named one. That's easy on the go function, but I need to the naming macro working
My recorded code for the naming macro is as follows:
Sub Namer ()
ActiveWorkbook.Names.Add Name:="Name1", RefersToR1C1:="=Workings!R42C6"
ActiveWorkbook.Names("Name1").Comment = ""
End Sub
I have the following problems:
I need to name the current cell on a workbook with a lot of sheets. I’m gonna be moving between sheets but my recorded code has a “fixed” sheet.
How can I fix that? Name the current cell on the current sheet
Something like this should help you ...
Public Sub CreatesNames()
Dim objSheet As Worksheet
For Each objSheet In ThisWorkbook.Worksheets
objSheet.Names.Add Name:="Name1", RefersTo:=objSheet.Range("A1")
Next
End Sub
... something to note, names can be created at the worksheet level or at the workbook level, so, if you're going to be creating the same name across worksheets then you need to use a Worksheet object, not the Workbook object.
So to use the active cell ...
Sheet Level
ActiveSheet.Names.Add Name:="Name1", RefersTo:=ActiveCell
Workbook Level
ActiveWorkbook.Names.Add Name:="Name1", RefersTo:=ActiveCell
I hope that helps.
i m new to vba and try to write some code copying some group data from a protected workbook to new Workbook.
In my source sheet is a list of grouped data with some columns like COUNTRY, REVENUE, WIN, LOSS.
The entity of country is grouped by region.
So under ever country is variable number of regions with subRevenue, subWIN, subLOSS.
What I expect: for a defined group of country entities (eg. GERMANY and JAPAN) I want to copy these data with its subdata (regions) to new Workbook.
May anyone provide me a generic example or useful functions?
Thank you in advance! (a VBA Noob)
So here something to start you off with.
First since the sheet is protected you'll need to unprotect it before being able to copy anything. The below code shows you how to do that and uses strPassword as a variable containing the password. Since the sheet is already protected in your case you'd start with unprotecting it, then doing your copying operation and then protecting it again.
In General you can use range.copy with range.pastespecial to copy data wherever you wish. To copy to a new workbook you can use Workbooks.add otherwise just specificy the filepath of the other workbook
Sub YourSub()
Dim ws As Worksheet: Set ws =Worksheets("YourSheet")
Dim strPassword As String: strPassword = "YourPassword"
Set NewBook = Workbooks.Add ' OR the workbook path
ws.Unprotect Password:= strPassword
ws.Range("A1:AA100").Copy
NewBook.Worksheets("Sheet1").Range("A1").PasteSpecial (xlPasteValues)
NewBook.SaveAs FileName:= ' Insert FilePath/ FileName here
ws.Protect Password:= strPassword
End Sub
This is some general information about how you would be going about copying ranges from a protected workbook to another workbook. To do this for certain countries you could create a table or use named ranges(using name manager or in VBA itself). Then you can adress the specific ranges either using if.. elseif.. else.. end if or the select case method, with your list of cases pointing towards a range containing all the countries to be copied.
Hope this was helpful as a quick overview