I have a UDF that I'm using throughout a Workbook, when I save and reopen the Workbook and then try to recalculate a single cell, Excel will update that cell but it will also recalculate every other cell containing that formula in the Workbook.
Here's a simple formula that demonstrates this issue:
Public Function MyFormula(a As Integer, b As Integer) As Integer
Debug.Print "calculating: " & Application.Caller.Address
MyFormula = a * b
End Function
I would expect that after recalculating a single cell to see a single log statement, but I'm actually seeing 4 (I have 4 cells with this UDF in the Workbook).
I'm guessing that when I save & reopen the Workbook, Excel is marking the cells as "Dirty" and in need of recalculation, but that doesn't make sense. According to the docs (https://learn.microsoft.com/en-us/office/client-developer/excel/excel-recalculation#dependence-dirty-cells-and-recalculated-cells) dirty cells are defined as those who's dependancies have changed:
When new data or new formulas are entered, Excel marks all the cells that depend on that new data as needing recalculation. Cells that are marked in this way are known as dirty.
My UDF isn't volatile and I haven't altered any dependancies, so why is Excel recalculating the all cells and how can I stop it from doing so?
(By the way, I'm aware that Manual calculation mode exists. I'd like to be able to use Automatic mode and allow automatic cell updates, but just only when dependancies have changed)
I've since found that this issue is only present on Excel for Mac (tested on the 2016 version).
Related
I´m using an Excel workbook with a custom formula for taking a value from the previous worksheet. I use this formula like INDIRECT(SHEETNAME(SHEET(A1)-1)&"!A1"), so SHEET(A1) returns the current sheet number, and SHEETNAME(SHEET(A1)-1) returns the name of the previous sheet, then I use INDIRECT to take the value A1 from that previous sheet.
Here is the code for the custom sheetname formula:
Function SHEETNAME(number As Long) As String
SHEETNAME = Sheets(number).Name
End Function
The problem is that when I use other workbook at the same time, the mentioned command returns #VALUE!.
Thanks for the help! :)
You should always fully qualify.
So instead of Sheets(number).Name, try ThisWorkbook.Sheets(number).Name
Not doing so can lead to bugs that are difficult to diagnose.
I would always suggest avoiding "ActiveWorkbook" unless you specifically need it.
My situation:
I have a piece of code that copies data from a database into Excel sheet, let's take this code
RangeExcelData(objWorkbook.Worksheets.Item("DATA").Range("D71"), rptLotNo)
To cut it short, RangeExcelData is a user-defined function in my VB.NET application that lets me copy the variable data into a range in Excel
I have lots of this in my code, having to copy an entire data from the database into a sheet.
I also have a formatted Excel worksheet where I put the data from the database. What I want to know is can I copy the format from the formatted Excel worksheet, into a space inside the worksheet?
Here is a little illustration of what I want, this is the formatted excel for example:
If the data exceeds the Excel, I want VB.NET to copy the format to the space next to it. Including the formulas that it may have:
Assuming your original values start at B2 and end at D7, you can do something like this:
Dim xlSheet As Excel.Worksheet = objWorkbook.Worksheets("DATA")
With xlSheet
.Range("B2:D7").Copy()
.Range("E2:G7").PasteSpecial(Excel.XlPasteType.xlPasteFormats)
.Range("E2:G7").PasteSpecial(Excel.XlPasteType.xlPasteFormulasAndNumberFormats)
' Start adding the new values.
.Range("E3:E6").Value = 4
.Range("F3:F6").Value = 5
.Range("G3:G6").Value = 6
End With
Note: Since you're copying the formulas as well (not just the formats), any fixed values (if any) will be copied too, but that shouldn't matter since you'll be overwriting them with the new values.
Result:
If you don't want the fixed values to be copied, you might check the answers in this question. It's about VBA, but you can do the same thing in VB.NET.
I use popular custom function which I found on the internet on one of vba blogs. It reads text cell as if it be formula (i.e. "=A2+B2" or "=ABS(A2+B2)", I created them by using CONCATENATE function, in workbook they are without quotation marks). The code goes:
Function Eval(Ref As String)
Application.Volatile
Eval = Evaluate(Ref)
End Function
In my workbook I have multiple sheets which are exact same copies except 2 columns of data, which calculate some descriptive statistics (i.e. sum, average, standard deviation etc.), the formulas are in my source sheet, copied sheet have formula like: Eval(sourceSheet!A1) and A1 contains text of formula like above. The problem is that to apply macro after loading it, I need to pres F9 to refresh (sometimes several times). It makes refreshing ALL my copied worksheets with the data I have in worksheet I am refreshing. So for example: if i refresh in worksheet 3 and sum of data was 5 it changes sum to 5 in all other sheets. I guess somehow my code makes the function applied to entire workbook instead of single worksheets like every other excel function.
So I have 2 questions:
Is there any way to change the code so my custom function will only apply to worksheet I put it in?
Can you post me a macro code for refreshing entire workbook with every single click of left mouse button?
Thank you in advance
Thats a rather buggy UDF: Evaluate always takes unqualified references as referring to the active sheet.
You really need to use Worksheet.Evaluate. Try something like this that assumes that any unqualified references in Ref are to the sheet that Ref is on
Function Eval(Ref As range)
Application.Volatile
Eval = ref.parent.Evaluate(Ref.value)
End Function
Or if you want it to refer to the sheet that the UDF is being called from try this
Function Eval(Ref As variant)
Application.Volatile
Eval = Application.Caller.Parent.Evaluate(Ref)
End Function
There are also a number of strange things/Quirks/bugs with evaluate you should be aware of: see my blog post
https://fastexcel.wordpress.com/2011/11/02/evaluate-functions-and-formulas-fun-how-to-make-excels-evaluate-method-twice-as-fast/
I have two ideas that could lead to more or less the same result.
I am trying to have similar cells or tables update themselves to whatever the most recent entry was in the linked system. For example, cell A1 is linked to cell B2 (in this system that I am trying to create). I would enter something like "1" or "Text" or whatever in A1 and the system would update cell B2 to whatever I entered in cell A1. However the opposite must work in the same manner. If I changed whatever in cell B2 to, say, "5", cell A1 would also display "5". Also, note that I have Excel 2013.
I need this to work with a cell or a table. So, getting to the possible solutions...
A subroutine in VBA that automatically updates all the linked cells or tables.
Some sort of mechanic unknown to me that uses VBA or another Excel aspect to do this, like a function or tool.
In your answer or solution, please be mindful to my inexperience with VBA. Thanks in advance.
You can try a worksheet change function:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Range("A1").Address then
ActiveSheet.Range("B1").Value = ActiveSheet.Range("A1").Value
ElseIf Target.Address = Range("B1").Address then
ActiveSheet.Range("A1").Value = ActiveSheet.Range("B1").Value
End If
End Sub
Although this seems like it might create an infinite loop (the update from the change causes another change) it DOES work for me in Excel 2010..
There are other Worksheet functions you can try as well (e.g. Worksheet_SelectionChange)
This macro needs to be placed/entered as a WORKSHEET macro on the sheet where you desire to use it..it will not work in a Module.
To install:
1) Save your workbook as a macro-enabled file.
2) Close Excel, reopen file, and enable macro security
3) Type Alt-F11
4) In the project explorer view on the left, look for your sheet name. Double click it
5) In the code entry area on right (big window) paste the example code above
6) Return to your worksheet and try it.
I have a named range called "cellabove" in my workbook that always references the cell above the cell it is used in. The RefersToR1C1 property of the name is "=!R[-1]C". This allows it to be applied on any worksheet in the workbook.
When I run a macro that deletes some rows then some cells containing cellabove in their formulas are not recalculating, even though I end the macro with application.calculatefullrebuild. However when I then manually force a full rebuild by pressing CTRL+SHIFT+ALT+F9 the cells do recalculate.
Any idea of how I can force the relative referenced named range to refresh?
Using refersto that start with ! in Defined Name formulas is IMHO not advisable as there are long-standing bugs.
You could use =INDIRECT("R[-1]C",FALSE) instead
Try adding one of these calculation options into your code to see if they have an effect.
Sub Calculate_It()
ActiveSheet.Calculate
''// Equivalent to Shift+F9 Recalculates the active worksheet
Application.Calculate
''// Equivalent to F9 Recalculates all worksheets in all open workbooks
Application.CalculateFull
''// Equivalent to Ctrl+Alt+F9 Recalculates all worksheets in all open workbooks (Full recalculation)
Application.CalculateFullRebuild
''// Equivalent to Shift+Ctrl+Alt+F9 Rebuilds the dependency tree and does a full recalculation
End Sub