For various reasons a user-defined function of mine needs to allow user input that is interpreted as executable code (in this case any excel expression).
The most straight forward approach would be for the function procedure to input code into a module active in the same excel session and subsequently run the code (ie call a sub to which the user-input code was written); however, there are two problems with this: A. Most importantly is a very weird problem with how excel access user- defined functions in VBA modules. If a function procedure makes ANY change to ANY module active in the same session, excel 'loses' the relationship of all the other user-defined functions in the same module. The problem is best described by doing it: 0. Open a new session of excel 1. in VBA, add a module to Book1 2. In the new module, write a inoccuous function as the 'control' of the experiment: Function innocuous() innocuous = "innocuous" End Function 3. in excel, Input =innocuous() in cells A1 and B1 of Book1 (the function returns the string 'innocuous' in each cell; this is just a control for later steps) 4. Now input the following code in module1: Function MyCodeInput(InputUserCode) Application.VBE.VBProjects("VBAProject").VBComponents("Module1").CodeModule.ReplaceLine _ Application.VBE.VBProjects("VBAProject").VBComponents("Module1"). _ CodeModule.ProcBodyLine("RunUserCode", vbext_pk_Proc) + 1, _ "RunUserCode = " & InputUserCode MyCodeInput = RunUserCode() End Function Function RunUserCode() RunUserCode = "not input yet" End Function NB: the inputs "VBAProject" and "Module1" assume you have not changed the default names for the new project and module you created in step 1 The Function MyCodeInput access the code object of VBA and overwrites the first line of code in the procedure 'RunUserCode' 5. In excel, input =MyCodeInput("2") in cell A2 During returning input into cell A2, the function writes code in RunUserCode to get it to return the user input ('2' in this case) and subsequently runs RunUserCode to get the value it is to return to cell A2 (2) !!>You will see that the functions in cell A1 and B1 immediately return #NAME? (assuming you have calc set to automatic - otherwise you will have to press {F9}) 6. Still in excel, input =MyCodeInput("3") in cell A3 The function returns 3 in cell A3 BUT !!>You will see that the entry in cell A1, B1 and A2 immediately return #NAME? 7. Go back to A2 and reinput =MyCodeInput("2") The function returns 2 in cell A2 BUT !!>You will see that the entry in cell A1, B1 and A3 immediately return #NAME? My interpretation: whenever a procedure writes code to ANY active module in an excell session, excel 'loses' its access to ALL modules (the above example doesn't prove this for all modules but further test you can think of for yourselves will bear this out). The particular occurence of a function in a cell gets recalculated upon input, but if the function writes code, then ALL other cells containing user-defined functions will revert to returning #NAME? as though the functions are not defined in any active modules. As long as the other cells are returning #NAME?, excel does not even bother to try to run the function they contain, so that subsequent recalcs fail to renew excel's access to the functions. The only way to get the function in such cells to calculate is to re-enter it in one of the cells, but then all the other cells containing user-defined functions once again rever to returning #NAME? B. Problem A is a pretty major problem with coding any function to write code during execution! However, if the user inputs text that is not syntactically correct (say s/he enteres "2/" rather than "2"), an untrappable syntax error results and the user is suddenly confronted with a line in the code pane of the VB window. This is a further problem. An alternative would be to input the text to be run as code as the formula property of a cell reserved for vb use and take the value of this cell as Func1's return value (giving nonexecutable text for the formulat property of a cell would then result in a trappable error from Excel). Of course, only code that can be interpreted as excel expressions can be 'run' this way but this fulfills my particular needs for the function in question; however, during excel calculation cells are nonaccessable so this is no option for a function. Another alternative would be to have an separate instance of excel running at all times, watching to see if a file with a certain name gets written. MyCodeInput would then not write input code to a procedure, but to a file of this name, and then wait until this file ceases to exist. The other session of excel would read the code immediately upon seeing the file exists, input the code into the formula property of a cell (this would be no problem in the other session as a function would not be in the process of being input in this session), write the result returned to that cell as a value in a file 'B' of another name, and delete the first file it read from. MyCodeInput would see the file it wrote to had ceased to exist, read the value in the file 'B' the other session had just written and return it to the user. It all seems like a truly crazy work around and I wonder whether there isn't an easier way! Note DDE functions also don't work during the input of a function so this is another no-go. -- ---------------------------------------------------------------------------------- Some important links for excel users: 1. Follow us on TWITTER for tips tricks and links : http://twitter.com/exceldailytip 2. Join our Facebook Group @ http://www.facebook.com/group.php?gid=287779555678 3. Excel tutorials at http://www.excel-macros.blogspot.com 4. Learn VBA Macros at http://www.quickvba.blogspot.com 5. Excel Tips and Tricks at http://exceldailytip.blogspot.com To post to this group, send email to excel-macros@googlegroups.com <><><><><><><><><><><><><><><><><><><><><><> HELP US GROW !! We reach over 6,800 subscribers worldwide and receive many nice notes about the learning and support from the group.Let friends and co-workers know they can subscribe to group at http://groups.google.com/group/excel-macros/subscribe