User Defined Functions NOT recalculating - excel

I recently took a large, stable XLSM file, and split it apart into an XLAM and XLSX. Thousands of cells in the XLSX call (udfs) functions in the XLAM, and each such udf begins with the statement "Application.Volatile" (overkill, to force recalc).
The XLSX will NOT recalc with F9 thru Ctrl-Alt-Shift F9, nor with Cell.Calculate thru Application.CalculateFull. The XLSX cells are simply "dead" ... but ... I can reawaken them one by one if I hit F2 to edit the formula and then hit ENTER. Cells reawakened this way seem to stay awake, and recalc normally thereafter.
Has anyone encountered this strange behavior and are there any additional ways to force Excel to reconstruct the calc graph from scratch that I should try ?
One additional note in case it matters: I opened the XLAM and the XLSX via File Open, and have not installed the XLAM using the File ... Options ... Addins route - because in the past when I have done so, the minute you "uncheck" and installed XLAM then all the UDF references get replaced by full pathname links - pretty ugly. Alternatively if someone can outline a workaround for installing XLAM addins that doesn't create broken links everywhere I'll go with that.

This works:
Sub Force_Recalc()
Cells.Replace What:="=", Replacement:="=", LookAt:=xlPart, SearchOrder _
:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
End Sub

Figured it out - not sure why Microsoft has this "feature":
The condition arises when a virgin XLSX that uses an XLAM function is opened / created prior to opening the XLAM. In this case no amount of cajoling will cause the XLSX formulas to bind to and execute those XLAM functions, UNLESS you go into each cell & touch the formula bar & hit ENTER (or, as I discovered, do so en masse via a global replace - in my case all the funcs began w a "k", so globally replacing "k" with "k" fixed the error). The problem does not occur if the XLAM is opened first.

For UDFs who can access to Application instance could use:
Application.CalculateFull()
MSDN source here

You can force recalculation in this situation by search and replace on the = which is at the start of all formulae. You can also make this into a macro and map it to a key combination.
Edited to add
See the macro Greg Glynn has in his answer.

One possible solution: Set calculation mode to manual, then back to automatic
Application.Calculation = xlCalculationManual
Application.Calculation = xlCalculationAutomatic

Press CTRL+ALT+SHIFT+F9
This may recalc more than wanted, but it updated my UDF.
(Source)

Here is what I found. I haven't tested it but I believe there may be a work-around.
This is a direct quote:
"Excel depends on analysis of the input arguments of a Function to determine when a Function needs to be evaluated by a recalculation. "
from http://www.decisionmodels.com/calcsecretsj.htm
Here's what I'm going to try later today.
I am going to generate a specific address of a table, dynamically within my function.
Based on why we're here, I should not get an update should the value at the calculated address change.
By including the whole table as a parameter, even without using the parameter, the function should update if anything in the table changes.
In this way, your function hits the dependency tree regardless if you actually process the whole table.

My screen shot:
I had the same problem. Find and Replace works, but not very nice. My solution is:
go to Data tab > Edit links > Click Open Source will resolve this

Excel will monitor the range mentioned in the formula for any change, I faced this today and I was thinking and realized that. So to fix it, make a dummy argument in your function which takes the range you want to monitor or create a dummy function. In my case I called it monitorRange which returns nothing
Function monitorRange(rng As Range)
End Function
and I mentioned it in my formula example
=myfunction(a,b) & monitorRange(RANGE_TO_MONITOR)
This worked very well and it should work with any other function

Ice ages after the original question, but ran into a similar problem just today where I had created a UDF to determine which values of a pivot table filter were selected. The UDF would work fine in when running in macro editor as well as when directly updating the field where the UDF was used, but would throw a "#VALUE!" when updating the sheet or pivot table.
It was killing me until I incrementally added content from my original UDF to Ali's simple monitorRange function. I then found that my UDF had a pivot table refresh statement that when removed eliminated the "#VALUE!" error. Below is the specific offending lines from my UDF, but I the general rule is that the UDF cannot have any code in its call chain that updates other workbook content. That is, the UDF must only GET values, NOT SET values.
I verified this with the following two scenarios, which both cause this error:
Refresh a pivot, e.g.: pt.PivotCache.Refresh
Change a value of another cell, e.g.: Range("AA1").Value = "Test"
Strangely, I tested and found that it is absolutely okay (kinda cool, actually) that the UDF can include a MsgBox call to display a dialog without problem. This would allow a UDF to monitor a range, then popup a msgbox dialog for any condition you wish to include in the UDF. I will keep that in mind for other situations.
Hope this helps others running afoul of this nasty litter issue.

I've tried the above solutions.
The problem is, calculating all the formulae in the file takes too long when you have thousands of formula.
I tried the following solution, and it works.
In VBA Editor, set the object to Workbook, and procedure to SheetChange, and paste the following.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Target.Calculate
End Sub

I was having the same issue...I found (in another post) that adding Application.Volatile to the function code made it calculate with the spreadsheet (f9)

Related

Custom Excel-Function throws error when workbook is refreshed

I have a custom Excel-Function
Public Function getDate(interval, no)
getDate = Format(DateAdd(interval, no, Date), "dd.mm.yyyy")
End Function
When I enter this function in a cell it works as expected.
However, when I open a file, which does already have the function used, it produces an #Value! Error.
Example input of a cell: =">" &getDate("ww";-1) normally the result is:
>30.07.2015
I do also use the Bloomberg Excel-Addin and have Bloombergfunctions used in cells. But these work without any problems.
Does anyone have an idea how to fix it?
best regards
This is either a partial answer or a full answer. Your function contains Date -- which suggests that you want the function to be Volatile but UDFs are non-volatile by default. If you put
Application.Volatile
as the first line in getDate then it will update automatically as the date changes.
Perhaps the problem is that when you open a file at a later date Excel somehow detects a dependency on the date but is unable to recalculate it. I can't reproduce your bug and I don't have this Bloomberg Addin, so I don't know if this is the bug, but it does seem like a bug.
Another thought -- to use add-ins you don't need to save as a macro-enabled workbook but to use UDFs you need to. I don't think this is the problem, but you should double-check that it is saved as a macro-enabled workbook and that is opened with security settings which enable it.
If these suggestions don't solve it -- see if you still get the error without that add-in installed.

automatically run excel macro upon creation from template

I want to create an excel template that will includes formulas for dating the columns. However, since those formulas will be based on TODAY(), I need to convert them to static strings (so the dates don't change everytime someone opens it). Is there a way to add a macro that will run automatically when someone creates a new spreadsheet based on the template? (Similarly to Auto_Open(), only on Create, rather than Open). If so, I could just create a macro that will replace the formulas with their results upon document creation. Can this be done?
[Note: I'm not married to this solution; it just seemed like the simplest way to protect my spreadsheet. If someone can suggest an alternative approach, I'd be obliged.]
I have a couple thoughts...
If you run a copy/paste values macro every time it really won't matter, right?
You could check if the file exists yet (has been saved), and if not
then this must be the template opened as a new workbook, maybe?
Code:
Private Sub Workbook_Open()
If Dir(ActiveWorkbook.Name) = "" Then
'run the macro?
MsgBox "I'm gonna run this macro"
End If
End Sub
You could have a cell on one of the sheets, that will never be used,
or is hidden, that will store whether or not to run the macro, and
change that when the file is opened or when the macro is ran. Then
have a macro run on open that checks that cell. (Or custom/document property)
You could populate the cells that have the today() formula only on
open and if they are already populated then don't run the macro?
I realized that there is no need for a Workbook_Create() function, as that behavior can be emulated by simply deleting the macro after it has run once (which happens when it is first created). Deleting macros is done automatically when the file is saved with a .xlsx extension. In addition, you need to prevent the macro from running when you open the template itself (while editing the it). You can hold the SHIFT key when opening it to prevent auto-run macros, but since that method isn't foolproof, I added this code at the top:
Private Sub Workbook_Open()
'If we're opening the template, don't run the macro
If Application.ActiveWorkbook.FileFormat = xlOpenXMLTemplateMacroEnabled Then
Exit Sub
End If
...
'add code here to SaveAs .xlsx, thus removing the macros, so it won't run every time.
End Sub
(Note: I didn't show my SaveAs code as it is rather messy: I wanted to suppress the default warning about losing macros, but wanted to also protect the user from inadvertantly overwriting previous file. If anyone is interested, I could post it)

#NAME? error in Excel for VBA Function

I am making my first VBA program and trying to run the following function. The function checks a specific named range for the first row which does not have a value greater than it's leading value, but less than 1.
Public Function findPurchase()
Dim CRT As Range
Set CRT = Range("CostRateTable")
Dim existsBetter As Boolean
existsBetter = True
Dim r As Integer
r = 2
Dim c As Integer
c = 4
While existsBetter
Dim Found As Boolean
FoundBetter = False
While Not FoundBetter And c <= CRT.Columns.Count
If CRT(r, c) > CRT(r, 2) And CRT(r, c) < 1 Then
FoundBetter = True
Else
c = c + 1
End If
Wend
existsBetter = FoundBetter
If existsBetter Then
r = r + 1
End If
Wend
findPurchase = CRT(r, 3)
'MsgBox(findPurchase)
End Function
I know the function does what it is supposed to because I have both manually checked the table of values, removed the comment ' from the MsgBox, and used the debug tools to step in and out of each of the functions steps as it went through the table. However, when I reference the function in Excel with =findPurchase() I'm given a #NAME? error. The function even shows up in the function auto-complete box when I begin to type its name. When I write other functions, both with and without parameters, I can reference them just fine, for example:
Function addtwo()
addtwo = 1 + 2
End Function
What am I doing wrong with my function which causes it not to work?
You are getting that error because you have a module with the same name as the function.
Change that name to say find_Purchase and everything will be fine :) See the image below...
I had the same issue myself. It turned out that I "Saved As..." another file and macros were not enabled for that file. No banner on the top appeared, but a #NAME? error was generated.
I reopened the file, enabled macros, and the problem was resolved.
Make sure you have placed the function in a Standard Module. The error message means Excel can't find the function.
When Excel opens an unkown workbook containing VBA-Code, it usually asks for macros to be enabled by the user (depending on the application settings).
If the user then enables the macros, all event-driven procedures will be started, such as auto_open or others.
Custom VBA Functions however require for a full recalculation of the workbook. Otherwise the functions return-value still is #NAME, as the calculation is only done directly after opening the workbook.
In order to work directly at the first time opening, one has to add the following line to the workbook_open event
'
' Workbook open event
Private Sub Workbook_Open()
Application.CalculateFullRebuild
End Sub
Check "Trust access to the VBA project object model" in Macro settings from Macros security
One reason for this problem is security restrictions.. I had this problem and I activate "Enable all macros" from security center, and the problem solved
I had a similar persistent problem with one of my functions when everything else seemed fine.
Open the worksheet & go to the Developer Tab. Open VBA, and back on the Developer ribbon select "View Code". See if it opens any similar Code (apart from your Module) specific to that worksheet (eg. Sheet2 (Code). I found that I had duplicated the code on the worksheet in addition to the Module. Delete the "worksheet" code. (You may need to save the workbook & re-open at this stage). When I deleted the worksheet code, the module function then worked.
In addition to checking some of the above mentioned items, you might need to specify the filename where the custom function is actually defined, e.g. cell content
=XLstart.xlsm!myCustomFunc(Arg1,Arg2)
where myCustomFunc is defined in the startup file XLstart.xlsm.
Following the Excel help for "Correct a #NAME? error":
In the formula bar, select the [suspect] function name.
In the Name Box (to the left of the formula bar), click the arrow and then select a [user-defined] function from the list that Excel suggests.
This will add the filename per the above format.
MS 2010, Windows 10.
Here's why I got that error. This answer is not provided so far.
If you have two or more workbooks (spreadsheets) open, then you may have your module under the other workbook - not the only you want to do the calculation on. This may seem impossible but ... as soon as you open the Developer/VBA code editor Excel wants to show you the structure (objects, modules, etc) of every open workbook. It's not what I expect as a developer, but there it is. So like me, you may have pressed 'Add module' and dropped the code in another workbook and worksheet.
If this is your issue, nothing mention above will work. Move your VBA module and code to the correct spreadsheet visible through this VBA code editor.
True,
I had the same (in Excel 2010) and when I migrated to Excel 2016 , the function prototype was shown, but when I completed the function, the #NAME error was shown with a pop-up... so the code was never triggered.
It turned out I had a Macro of the same name as a Sub or UDF function !
I renamed the Macro, and then it worked
Cheers
Another cause I found for the #NAME? error is that the macro workbook with the custom function has a range name the same as the function name. I changed the function name and solved the problem.
This solution applies to users with an Excel installed in another language than "United States English":
I had a similar problem when making a copy of the active workbook to duplicate it and immediately opened the copy afterwards:
Non-working code:
ThisWorkbook.SaveCopyAs NewFileName
Set wb = Workbooks.Open(FileName:=NewFileName)
This always showed me several cells with Error 2029 / "#NAME?". If I opened the Workbook "the official way" via the File-Menu it worked as expected.
I solved the issue by adding the parameter "local:=true" to the open statement:
Working code:
ThisWorkbook.SaveCopyAs NewFileName
Set wb = Workbooks.Open(FileName:=NewFileName, Local:=True)
as VBA expected english function names in my German workbook. With this parameter VBA is told directly to use the local names.
I hope that helps someone not to loose several hours, as I did...
Short answer - if the function was working before, RESTART YOUR COMPUTER.
Long answer - I had this same thing happen to me. The problem is that the function I had created had been working for months. Then one day it just started showing a #NAME error instead of working like it was before. I had tried closing all other excel workbooks and even closing excel all-together and re-opening the sheet. Nothing seemed to work. Then for kicks, I edited the code to where I knew VBA would complain that there is a compile error. Surprisingly, it didn't complain. OK... I saved and closed excel anyways and then restarted my computer.
Once rebooted, I re-opened the excel workbook. Then VBA finally gave me a compile error. So I changed my function back to the original code I had before and now the sheet is running the function like it is supposed to. No more #NAME error.
Not sure all of those steps are necessary, but simply restarting the computer seems to have fixed my issue.

sheet_name.calculate doesn't update formulae but shift+f9 does update?

I am automating a sheet and within vba I call:
sheet_name.calculate
The problem is this doesn't appear to be updating some of my cells which depend on API calls to financial addins. They all still contain #VALUE! However, if I press "shift + f9" on the same sheet then all the cells containing #VALUE! suddenly refresh and contain correct numerical values.
Why isn't .calculate doing this?
(My calculation update settings are set to "manual" - this has been decided as I don't want automatic updates, only when my code calls .calculate)
Try
Application.CalculateFull
http://msdn.microsoft.com/en-us/library/office/ff194064.aspx
If that doesn't work maybe this will help - it ensures all dependencies are rebuilt
Application.CalculateFullRebuild
http://msdn.microsoft.com/en-us/library/office/ff822609.aspx
I have not personally discovered any difference between worksheets("SheetName").Calculate and shift-f9 - but it may be worth trying this:
Worksheets("SheetName").EnableCalculation=False
Worksheets("SheetName").EnableCalculation=True
Worksheets("SheetName").Calculate
This forces a full calculation of the worksheet as opposed to a recalculate.

Excel VBA can't open Workbook

First: I'm using Excel 2007, but the code has to work for Excel 2003 as well.
My problem is the following: I need to access cells in a different workbook, which may be closed. The following code can be found all around the web:
Function Foo()
Dim cell As Range
Dim wbk As Workbook
Set wbk = Workbooks.Open("correct absolute path")
' wbk is Nothing here so the next statement fails.
Set cell = wbk.Worksheets("Sheet1").Range("A1")
Foo = cell.Value
wbk.Close
End Function
sadly, wbk is Nothing after the open statement (I'd love to give a better error message, but no idea how I'd do that; what I'd give for a real IDE and an useful language :/). The absolute path is correct and points to a valid excel xlsx file.
Also I assume the best way to do this, is to "cache" the workbook and not open/close it every time the function is called? Any possible problems with that (apart from having to handle the situation when the workbook is already open obviously)?
Image while stepping through:
I can reproduce this problem. It only happens to me when I attempt to paste this code into a user-defined function.
I believe this is by design (the quote is for XL 2003, but the same thing happens to me on XL 2010)
Using VBA keywords in custom functions
The number of VBA keywords you can use in custom functions is smaller than the number you can use in macros. Custom functions are not allowed to do anything other than return a value to a formula in a worksheet or to an expression used in another VBA macro or function. For example, custom functions cannot resize windows, edit a formula in a cell, or change the font, color, or pattern options for the text in a cell. If you include "action" code of this kind in a function procedure, the function returns the #VALUE! error.
http://office.microsoft.com/en-us/excel-help/creating-custom-functions-HA001111701.aspx
The only workaround I've found is to call this kind of code via a normal macro. Something like selecting the cells to apply it to, then looping over Selection or the like.
You can use this (similar to what Bruno Leite proposed, but much simpler to write):
Dim excelApp As New Excel.Application
excelApp.Visible = False
Set WB = excelApp.Workbooks.Open(FileName, xlUpdateLinksNever, True)
As UDFs are called repeatedly, you should make sure to do an excelApp.Quit before exiting the function (and a WB.close(False) before) to avoid having countless Excel instances running on your box.
I spent some thoughts on it and came to the conclusion that you cannot mess around with the workbooks of the current instance of excel while executing a UDF. On the other hand, opening a second instance of excel will do the job without interference.
To get data from Workbook without is open, you can use this, with ADO connection.
To use in Excel 2007 change this
Microsoft.Jet.OLEDB.4.0
to
Provider=Microsoft.ACE.OLEDB.12.0
and
Extended Properties=\"Excel 8.0;HDR=Yes;\
to
Extended Properties=\"Excel 12.0;HDR=Yes;\
[]'s
The workaround of putting my routine into a separate macro in the workbook module, and calling that macro from the Workbook_BeforeSave code, seems to have done the trick.
I've had a similar issue, but in my case it's a "Workbooks.Open(filename)" command at the start of a small routine embedded in Workbook_BeforeSave. VBA just skips right over the line of code as if it weren't there, it doesn't even report an Err.Code or Err.Description.
The only clue for me was that it's part of the Workbook_BeforeSave routine, and the limits with Functions above seem to indicate that could be a possible cause. So I dug around further to find more details.
It seems that Workbook_BeforeSave disables Excel from opening more files, and I guess there's a good reason for doing that, since the File > Open option is still visible in the File menu, but it can't be clicked. Strangely, the Open toolbar icon/button still works, and so whilst I can manually open the file from there, I wonder if it's because it's impossible to call this action from VBA code and that's why they allowed it?
You don't have to "Set" a cell, It's part of the workbook class (as far as I know). Just use the following...
foo = wbk.Worksheets("Sheet1").Range("A1").Value
I would suggest that you open you the new workbook upon opening the calling workbook, in the worbook_open event.
You then store the new workbook reference in a global variable.
Then the function called by your cell uses the said global variable instead of trying to open a new workbook. This way you go around the limitations.
PS : Of course global variable are to be avoided, some sort of container would be better than a direct global variable.
You can check the error in a proper way by using the following code:
filelocation = c:\whatever\file.xlsx
On Error GoTo Handler 'this is key as if the next row returns an error while opening the file it will jump to the Handler down there.
Set wkb2 = Workbooks.Open(filelocation, ReadOnly)
Handler:
MsgBox "File " & filelocation & " does not exist or cannot be reached, please review and try again"
I know that this does not answer the question (that's why I also landed in this thread, as I cannot open the file and can't understand why is that so)
Cheers,
RV

Resources