Why the VBA UDF "Range.Formula =" don't work? - excel

I want to copy the formula from one cell/cells to another cell/cells by Range.Formula = .
But it not work as expected.
If I run the VBA step by step, the function will ended at Range.Formula = without error.
Function test1(sOURCE As Range, tARGET As Range)
tARGET.Formula = sOURCE.Formula
test1 = tARGET.Formula
End Function

You are trying to change another cell's formula with a UDF. According to the Microsoft documentation this cannot be done, but Ryan Wells has actually found a nice workaround. See: How to change another cell with a VBA function UDF. Compare also: VBA: How to change the value of another cell via a function?
We need to use Evaluate on a "helper" sub. I have slightly adjusted the first example provided by Wells to suit your needs:
Function copyFormula(copyFrom As Range, copyTo As Range)
copyFrom.Parent.Evaluate "copyOver(" & copyFrom.Address() _
& "," & copyTo.Address() & ")"
copyFormula = "Formula " & copyFrom.Address() & " -> " & copyTo.Address()
End Function
Private Sub copyOver(copyFrom As Range, copyTo As Range)
copyTo.Formula = copyFrom.Formula
End Sub
This works, but please bear in mind that (intriguingly) the formula will not automatically calculate after insertion, even with calculation set to automatic. Implementation:
Result:
One way to overcome this problem is to include a Worksheet_Change sub for the worksheet where you are using the formula. E.g. simply:
Private Sub Worksheet_Change(ByVal Target As Range)
Calculate
End Sub
But any subsequent action in the sheet seems to trigger the calculation. Also, please be aware that you won't be able to overwrite the target cell while you have a copyFormula in use with this cell. Since it will just keep overwriting it immediately with the formula (with 0 as output, if the above trick isn't applied). This might be confusing to your users.

This is a restriction by design.
Because a UDF cannot change any other cells/formulas. A UDF can only return a value to the cell the UDF was used in. Therefore tARGET.Formula = sOURCE.Formula is not possible.
Also test1 = tARGET.Formula will return the formula of tARGET as text. It will not replace the formula used in the cell nor will it evaluate the formula.

Related

Excel Macro event not working after saving data

My macro function is :
Function IsColouredCell(Range As Range, Colour As Range) As Boolean
If Range.Interior.Color = Colour.Interior.Color Then IsColouredCell = True
End Function
And event code is:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
ActiveSheet.Calculate
End Sub
Use case: To check color match of target & reference cell.
Above code is active till the time i use it just after writing code in vba for n number of entries in excel. But as soon as i save the data on a already saved macro file. my event activation doesn't work and nothing happens on changing the color of a a cell.
Please provide the solution.
You cannot declare a variable name Range in Range As Range. That is very confusing and might mess up the code. Never use reserved words as variable name. All names in VBA should at best be unique.
If this is used as UDF (user defined function) like a formula you probably need to make it volatile, because it only re-calculates on ActiveSheet.Calculate if any dependant value changed but not if a cells color changed:
So it should look something like below:
Function IsColouredCell(ByVal MyRange As Range, ByVal Colour As Range) As Boolean
Application.Volatile
If MyRange.Interior.Color = Colour.Interior.Color Then IsColouredCell = True
End Function
If you use that like =IsColouredCell(A1,B1) and it is not volatile the formula only re-calculates if the value of A1 or B1 changed. But it will not re-calculate if just their color changed, even not on ActiveSheet.Calculate.
Note that making a function volatile means that it is calculated everytime Excel needs to calculate something. So using volatile functions a lot makes your worksheet slower the more you use that function.

VBA poke a default value in a cell when called from a cell formula [duplicate]

I'm an Excel VBA newbie.
How to change the value of the specified cell via a user-defined function? What's wrong with this code:
Function Test(ByVal ACell As Range) As String
ACell.Value = "This text is set by a function"
Test := "Result"
End Function
My wish is ... when I type =Test(E6) in cell E1, Excel will display the specified text in E6.
YES, of course, it is possible.
Put this code in Module1 of VBA editor:
Function UDF_RectangleArea(A As Integer, B As Integer)
Evaluate "FireYourMacro(" & Application.Caller.Offset(0, 1).Address(False, False) & "," & A & "," & B & ")"
UDF_RectangleArea = "Hello world"
End Function
Private Sub FireYourMacro(ResultCell As Range, A As Integer, B As Integer)
ResultCell = A * B
End Sub
The result of this example UDF is returned in another, adjacent cell. The user defined function UDF_RectangleArea calculates the rectangle area based on its two parameters A and B and returns result in a cell to the right. You can easily modify this example function.
The limitation Microsoft imposed on function is bypassed by the use of VBA Evaluate function. Evaluate simply fires VBA macro from within UDF. The reference to the cell is passed by Application.Caller. Have fun!
UDF limitation documentation: https://support.microsoft.com/en-us/help/170787/description-of-limitations-of-custom-functions-in-excel
A VBA UDF can be used as an array function to return results to multiple adjacent cells.
Enter the formula into E1 and E2 and press Ctrl-Shift-Enter to create a multi-cell array formula. Your UDF would look something like this:
Public Function TestArray(rng As Range)
Dim Ansa(1 To 2, 1 To 1) As Variant
Ansa(1, 1) = "First answer"
Ansa(2, 1) = "Second answer"
TestArray = Ansa
End Function
Excel VBA will not allow a user-defined function to alter the value of another cell.
The only thing a UDF is allowed to do (with a few minor exceptions) is to return values to the cells it is called from.
Why not just typing you formula in E6 then ? That's the Excel logic: put your formula where you want the result to appear.

Autofill date by referring only one number with excel VBA

What if we could fill a date by only referring a number ? This type of feature would improve user-friendliness in some excel scenarios.
For instance : In March sheet, when I type "7" in a given dates column, the cell in which I inserted the value would return "07/03/19" (or 03/07/19).
If possible, this means I need to specify in the VBA code the month and year for this sheet, and change this variable for every single sheet (february etc.). If the sheet names are months names (Eg "March"), there could even be a way to do it with a one solution VBA code. The following formula takes advantages of it, so I guess VBA could do it to.
=MONTH(DATEVALUE(MID(CELL("filename";$A$1);FIND("]";CELL("filename";$A$1))+1;255)&" 1"))
Enter this formula in a sheet named "March" and it will return "3".
I have been looking for a simple way to do this, but there is none to my knowledge (until you bring your light :)). Data validation feature won't help as far as I know. Also, it's important that the cell in which the number is inserted autofill itself (not another cell).
Is this at least possible ? I bet yes. I've been told to look at event function, but I know too little with VBA.
This may need modified to fit your needs, but maybe a solution like this using the Worksheet_Change event.
Worksheet Change portion:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo SafeExit:
Application.EnableEvents = False
If Target.Cells.Count = 1 Then '
If Not Intersect(Target, Me.Columns("A")) Is Nothing Then 'change as needed
Target.Value = DateFromDay(Me.Name, Target.Value)
End If
End If
SafeExit:
Application.EnableEvents = True
End Sub
Main Function
Public Function DateFromDay(monthName As String, dayNum As Integer) As Date
On Error Resume Next
DateFromDay = DateValue(dayNum & " " & monthName & " " & Year(Now()))
End Function
You might consider the Workbook_SheetChange event as well to add this functionality to multiple sheets.

VBA Excel Function to Set the Calling Cell .NumberFormat Property

I created this function and it works to put the value into the cell but it doesnt work to set the .NumberFormat property.
Public Function NewYears(year As Integer)
'Determine the cell that called the function
Dim rng As range
Set rng = ThisWorkbook.Sheets("How-To").range(Application.Caller.Address)
MsgBox rng.Address
fxFormat = "[$" & holidayName & "]"
NewYears = DateSerial(year, 1, 1)
rng.NumberFormat = fxFormat
End Function
Update For more information:
I will be having functions like =NewYears() that returns a date.
I will do this for any number of holidays. I would like to format the field where it still stores the date but the .NumberFormat property has the name of the holiday
So =NewYears() would return "01/01/2014" but in the sheet it would appear as "New Years"
Use the Worksheet_Change event:
Private Sub Worksheet_Change(ByVal Target As Range)
Target.Interior.ColorIndex = 39
Target.NumberFormat = "mm/dd/yyyy"
End Sub
Put this code in the Sheets("How-To") code module. Modify to whatever color/etc that you want to format.
When you initially enter the function in the cell, it will trigger the change event and this subroutine will execute.
Per Gary's comments (below), recalculation of existing formula will not trigger this event.
Functions can only return values or manipulate Comments, they can't modify formats directly.
How many calculations are in your sheet/book?
Are the cells in a particular arranged column or everywhere or Random?
If answer is Yes to first question I wouldn't suggest a volatile function triggers, well no one should. And things you do next depends on the answer to 2nd question.
Why dont you try "conditional formatting" though it could be a bit costly. Else if the Year cell should be in an organized column or cell make sure its format is ready-made to date.... if none of these apply, you may give us a better picture if your sheet's structure/design...

How to get worksheet and cell that the current VBA function is returning to?

Is there a variable anywhere that gives the worksheet and cell that will recieve the result of a custom VBA function?
For example, if in A!B1 the formula is =MyCustomFunc() in my code:
public function MyCustomFunc()
'what can I call here to get the values "A" and "B1"?
end function
Is this what you are trying?
Option Explicit
Public Function MyCustomFunc()
'~~> Judicious use of 'Volatile' is advised.
'~~> This will be called everytime the sheet is recalculated
Application.Volatile
MsgBox Application.Caller.Parent.Name & ", " & Application.Caller.Address
End Function
You want Application.ThisCell.
This returns the cell which is currently being calculated.
ActiveSheet.Name will give you sheet name. ActiveCell.Row will give you row number and ActiveCell.Column will give you column letter. Then you can combine them to get cell address.

Resources