VBA open worksheet fail - vba

Sub TEST()
Workbooks.Open ("C:\Desktop\TEST\TEST\TEST2.xlsx")
Workbooks("C:\Desktop\TEST\TEST\TEST2.xlsx").Sheets("Sheet1").Range("A1").Value = 1
End Sub
it gives me subscript out of range in the 3rd line
However, if I try
Workbooks("TEST2.xlsx").Sheets("Sheet1").Range("A1").Value = 1
This works, I am sure the path is correct, the file can be opened in the second line. Any suggestion?

Use variables to scope your objects, see if this helps:
Dim wb as Workbook
Set wb = Workbooks.Open("C:\Desktop\TEST\TEST\TEST2.xlsx")
wb.Sheets("Sheet1").Range("A1").Value = 1
The problem in your original code:
Workbooks("C:\Desktop\TEST\TEST\TEST2.xlsx")
That is not the name of the Workbook. The Name of the workbook is simply "TEST2.xlsx", so as you observed, this would work (but the above method would be preferable):
Sub TEST()
Workbooks.Open ("C:\Desktop\TEST\TEST\TEST2.xlsx")
Workbooks("TEST2.xlsx").Sheets("Sheet1").Range("A1").Value = 1
End Sub

Excel refers to workbooks by the filename, not including the path. You demonstrated that with the fact that your second method works.
A consequence of that is questions like Why on earth can't Excel handle 2 files with the same name?

Related

VBA: How to address the correct workbook when giving a worksheet as an argument to a function?

I have a question regarding the correct address of Workbooks in VBA, which I am fairly new to.
Here is what I have done so far:
I have written a sub that, amongst other things, creates a worksheet with the CodeName "table10".
Then I defined a function to manipulate the contents of said sheet: this function
Text_To_Numbers(worksheet as worksheet)
expects a worksheet argument. I call the function from another sub using the following line:
Call Text_To_Numbers(table10)
Now, here is my issue:
The above works flawlessly when the only open workbook is the one I want to manipulate with my function. However, when I have multiple open workbooks, the function will try to manipulate a different workbook, resulting in an error.
I am quite certain that there must be a way to specify the workbook to be used, but I am unable to find it. That being said, there is another complication: The name of the workbook which I would like to manipulate is machine generated, so it always has a different name. This means that using an explicit reference to the same file name time and again is not an option.
Could anybody help me resolve this?
You need to fully qualify objects in VBA to avoid situations like this where it is ambiguous what the parent is.
In your situation, you want the sheet to be connected to its parent workbook, so make sure you specify that it came from a given workbook!
You cannot directly refer to worksheets in other workbooks by their CodeName, this can only be done to the ThisWorkbook object (the workbook containing the VBA code). See the question Fully reference a worksheet by codename for details on how to get the sheet by its codename from another workbook. I have included the function in the answer and how to use it in this context.
You created the sheet table10 in one of the following:
ActiveWorkbook
ThisWorkbook
WB (some workbook object)
So you can access it using that workbook object without a need for the name!
Using ThisWorkbook.table10 should give same behaviour as just table10, but here are two neater examples for calling the function.
' A neater way to call the function:
Text_To_Numbers worksheet:=ThisWorkbook.table10
' You could also call it simply using
Text_To_Numbers ThisWorkbook.table10
If your sheet is not within ThisWorkbook
' Get sheet (from the workbook object you are using, WB) and pass to your Text_To_Numbers
Text_To_Numbers GetSheetWithCodename("table10", WB)
Function GetSheetWithCodename(ByVal worksheetCodename As String, Optional wb As Workbook) As Worksheet
Dim iSheet As Long
If wb Is Nothing Then Set wb = ThisWorkbook ' mimics the default behaviour
For iSheet = 1 To wb.Worksheets.Count
If wb.Worksheets(iSheet).CodeName = worksheetCodename Then
Set GetSheetWithCodename = wb.Worksheets(iSheet)
Exit Function
End If
Next iSheet
End Function
Try assigning the workbook and sheet to a variable then calling it in this way when you need to do some work in it:
Dim WB As Workbook
Dim WS As Worksheet
'If you want to open the workbook before doing work
Set WB = Workbooks.Open("/Workbook path name goes here”)
Set WS = WB.Worksheets("Table‌​10")
Then you just need to pass a call to the WS variable from within your function to perform operations within the specified sheet.
Edit:
Apologies, didn't realise you were trying to reference the index name in the project editor when I first read your question. The code name can be referenced from an external workbook with the following example which shows how to select the workbook and sheet codename to perform a copy/paste from one workbook to another:
Sub UseCodeNameFromOutsideProject()
Dim WS As Worksheet
With Workbooks("MyWorkbook.xlsb")
Set WS = _
.Worksheets(CStr(.VBProject.VBComponents("Sheet1").Properties(7)))
WS.Range("A1").Copy
Selection.Copy
WS.Range("B1").PasteSpecial
End With
End Sub
Thanks to Enderland for the idea.

How can I use ActiveWorkbook/Workbooks(name) without getting a Runtime Error 91 in Excel 2013 VBA?

While this is not the first time I wrote macros like this, I cant seem to figure out how I get this to work. I have a snipped below that I think should work but doesn't.
My problem is that while at the beginning of my work day the snipped worked exactly once, but afterwards I always get the Runtime Error '91: object variable or with-block variable not set error message.
I have two workbooks opened, and I selected cells within the workbook I wanted to work with manually before starting the macro.
Option Explicit
Sub test()
Dim source, sheet As Worksheet
Dim sourcename As String
Dim targetname As String
Dim test As Workbook
Workbooks("Test.xlsm").Activate
test = ActiveWorkbook
Debug.Print (test.Name)
sourcename = "Tabelle1"
targetname = "Tabelle2"
Set sheet = ActiveWorkbook.Worksheets(sourcename)
Set source = ActiveWorkbook.Worksheets(targetname)
Debug.print(sheet.Name)
Debug.print(source.Name)
End Sub
The error occurs in the line containing test = ActiveWorkbook
EDIT: After the initial Seterror was fixed, the sheet and source variables are still empty, thus each is causing another error of this type.
What is the problem here and how can I fix it?
Two issues here:
1st- do not give the same name to both Variable and Sub, you have 'Test' for both
2nd- add Set before this line test = ActiveWorkbook like
Set test = ActiveWorkbook
remember- change Sub name into anything other then test

Excel Vba - Calling a sheet with a variable sheet name

I've been coding in VBA for some time, but this one has really stumped me.
I'm creating a workbook which creates technical certificates for machines. We have varying templates depending on the machine type and I am attempting to get my code to select the correct sheet from a user input and then populate the sheet. FYI these template sheets will be hidden and the user can only interact with the userforms.
Heres the code that is failing:
Machine = MachineType.Text '<-- input from userform, for example Machine = "Vertex 251"
Set wsCopy = ThisWorkbook.Sheets(Machine) '<--- select that machine's sheet
wsCopy.Copy '<--Run time Error 1004: Method copy of object_worksheet failed
I've tried numerous different types including just sheets(machine).copy or
Sheets(machine).activate
Activesheet.copy
but nothing has worked so far - I cannot tell if I am doing something fundamentally wrong.
Any help would be be appreciated.
Cheers.
You must unhide the sheet before copying it (at least to a new workbook as lturner notes) - you can then re-hide it
Dim shtTemplate as Worksheet, sheetWasHidden As Boolean
Set shtTemplate = ThisWorkbook.Sheets(Machine)
'handle the case where the sheet to be copied is Hidden
If shtTemplate.Visible = xlSheetHidden Then
shtTemplate.Visible = xlSheetVisible
sheetWasHidden = True
End If
shtTemplate.Copy
If sheetWasHidden Then shtTemplate.Visible = xlSheetHidden 're-hide if needed
When you have the worksheet object and use the Copy method, Excel seems to be making assumptions (or not) about where you want to put the new sheet. I pretty much always use the After option to define where the new sheet should go.
Option Explicit
Sub test()
Dim wsCopy As Worksheet
Set wsCopy = ActiveSheet
wsCopy.Copy After:=wsCopy
End Sub

How to fix #VALUE! when UDF references another workbook

I have defined a function in the Module1 of my workbook that looks like this:
Function Header(r As Range) As String
For i = 1 To r.Row
If r.Offset(-i, -1).Value = "" Then
Header = r.Offset(-i).Value
Exit For
End If
Next
End Function
and I call it with a reference to another workbook's cell like this:
=Header('[OtherWorkbook.xlsx]Sheet1'!C34)
and what I get is #VALUE!... until, I open the other workbook, at which point the value magically appears.
how can I force the spreadsheet to fetch the values from the other workbook, even though it isn't open?
Specifying the full path of the closed Excel workbook should do the trick.
Instead of
=Header('[OtherWorkbook.xlsx]Sheet1'!C34)
Try
=Header('C:\Users\your_username\Desktop\[OtherWorkbook.xlsx]Sheet1'!C34)
Substituting the path of the closed workbook in for the path above.
so the answer is: it can't be done. to get the values, opening the workbook is required.
there is an alternative, supplied by #omegastripes above, though is seems rather complicated:
How can I pick values from an Excel workbook and return them by function on active workbook

How to refer to with object

How can i refer to the object i use inside With if i want the object itself, not its properties / methods?
With ThisWorkbook.Sheets("MySheet")
Call MySub(ThisWorkbook.Sheets("MySheet")) ' works OK, but duplicated
Call MySub(this) ' does not works
.Range(...).Value2 = 1
...
End With
+ what is the correct terminology here? i don't even know how to compose a google query for this and get some usefull results (since with is a common word)...
UPDATE: to clarify, i was thinking in terms of a handle like with ... as handle from python syntax, not about object-oriented this keyword
How about by not using with in the first place? It makes your code much more readable, uses no more memory (as the with statement has to allocate a temporary variable anyway), and is less confusing.
Dim WS as WorkSheet
WS = ThisWorkBook.Sheets("MySheet")
Call vymaz_obrazky(WS)
WS.Range(...).Value2 = 1
In the code above, the total cost is one additional line of code (the DIM statement), and 9 less keystrokes overall. (The DIM statement is 19 keystrokes, changing to WS in the three lines is 6 keystrokes, but you've saved the with (4) and duplication (30), saving about 9 keystrokes.)
Try this
Sub Sample()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("MySheet")
With ws
MySub ws
'~~> Rest of the code
End With
End Sub
or
Sub Sample()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("MySheet")
MySub ws
With ws
'~~> Rest of the code
End With
End Sub
Edit:
do you have any info about non-existence of "this"? – deathApril 19 mins ago
this is basically a keyword from C# which refers to the current instance of the class. The equivalent of this in VB is Me.
The Me keyword provides a way to refer to the specific instance of a class or structure in which the code is currently executing. For example in a Userform you can use
Me.textBox1.Text = "Blah Blah"
In VBA, Me can also be used for thisworkbook. For example, if you paste this code in the ThisWorkbook code Area then it will give you the name of the workbook
Sub Sample()
Debug.Print Me.Name
End Sub
Similarly when you run the above code from the Sheet Code Area you will get the Sheet Name.
HTH
Use .Cells.Parent. This only works for worksheets, but there are similar things for some other objects (for a workbook you can use .Sheets.Parent)
With ThisWorkbook.Sheets("MySheet")
Call MySub(.Cells.Parent)
.Range(...).Value2 = 1
...
End With