How to fix #VALUE! when UDF references another workbook - vba

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

Related

VBA open worksheet fail

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?

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.

Worksheets.Add in UDF Not Working

I have a UDF that can be called from within a cell in my excel workbook. I need it to add a worksheet at the end of the workbook. I have used sheets.add multiple times in my VBA script, but never in a function called from inside a cell and this is apparently causing some issue.
The function accepts an optional parameter for file path of the workbook in which to add the sheet, and if the user leaves this blank I want to default to the active workbook.
Below is the relevant code... What am I doing wrong?
Public Function onesheet(Optional filepath As String)
Dim wb As Workbook
Dim ws As Worksheet
If filepath = "" Then
Set wb = ActiveWorkbook
Set target_ws = wb.Sheets.Add(after:=wb.Sheets(wb.Sheets.Count))
End If
The function is being called from the cell with
=onesheet()
A function (UDF) has one role: compute a value and return that value to the cell (or formula/expression) that called it.
This is a function:
Public Function Foo(ByVal bar As String) As String
Foo = "Hello, " & bar
End Function
You can use it in a worksheet cell like this:
=Foo("dsdavidson")
And every time Excel recalculates that cell's value, it calls the UDF, making the cell's value read Hello, dsdavidson.
Functions don't have side-effects. Functions don't modify other cells. Functions take input, process it, and output a result.
What you're doing wrong, is using a UDF as if it were a macro.
Change your Function for a Sub, and don't call it from within a cell. Make a button to call it instead. Or whatever rocks your boat. But you can't have a cell formula that adds a worksheet to the workbook every time it recalculates.
Macros need to be Public and parameterless. So you'll want to take your optional parameter value from a specific cell, or display a form that lets the user pick from a list of available opened workbooks - and then call your procedure and pass the user's selection as a parameter.
Quite possibly the macro code could end up looking something like this (YMMV):
Public Sub AddWorksheet()
With New PromptForm
.Show
If .Cancelled Then Exit Sub
OneSheet .SelectedBook
End With
End Sub
You cannot add sheets through user defined function.
Here are the limitations of User Defined Functions.
A user-defined function called by a formula in a worksheet cell cannot change the environment of Microsoft Excel. This means that such a function cannot do any of the following:
1) Insert, delete, or format cells on the spreadsheet.
2) Change another cell's value.
3) Move, rename, delete, or add sheets to a workbook.
4) Change any of the environment options, such as calculation mode or screen views.
5) Add names to a workbook.
6) Set properties or execute most methods.
For more details visit this site...
https://support.microsoft.com/en-in/help/170787/description-of-limitations-of-custom-functions-in-excel

Using the contents of cell's as part of a file location in a macro

This is what I have:
Option Explicit
Sub EditWorksheet()
Workbooks.Open "Y:\Laurence\contents(J2)"
Sheets("contents(N2)").Select
End Sub
So what I want to do is have VBA call on the values of cells J2 and N2 in order to decide which workbook and worksheet to open. For your information J2 could contain for example "Forecast2016.xlsx" and N2 may contain "MASTER". Just to be clear, for every possible content these cells can have, I do indeed have a spreadsheet in the relevant file location (Y:\Laurence).
Thanks in advance!
The problem is you are not passing a string, but a range with that code. This causes the run time error 13. Instead of
Workbooks.Open "Y:\Laurence\contents(J2)"
Sheets("contents(N2)").Select
try
Workbooks.Open "Y:\Laurence\" & Sheets("Contents").Range("N2").Value
Sheets(Sheets("Contents").Range("N2").Value).Select
This forces the value of the cell to be passed, not a reference to the range. Also notice I qualified your worksheet that you were referencing as well. As you had it before, it would have pulled Range("N2") from whatever sheet happened to be open at that moment.

Excel worksheet name

I want to make a macro that copies data from one sheet to another.
No problem, but I named the sheet with an emoji.
How can I tell VBA which sheet he has to use if the name of the sheet is for example: 🏠
Thanks in advance
You can use the AscW function to find the appropriate unicode value for the item and use that to find the correct sheet
To find the name of any given worksheet, activate the worksheet, open the VBA Editor (Alt+F11), open the Immediate Window (Ctrl+G) and type the following:
? ActiveSheet.Name
If the name for some reason is nonsensical, and only consists of a single character, run ? Asc(ActiveSheet.Name) to get the ASCII value.
Referencing an ASCII value in VBA can be done by calling Chr(putValueHere), for example like this:
Worksheets(1).Name = Chr(50)
If you have a plethora of sheets, you can print all of them by running this code:
Sub SheetNamePrinter
For i = 1 To Worksheets.Count
Debug.Print Worksheets(i).Name
Next i
End Sub