Setting up UDF Applications

Following a recent comment, this post looks at setting up a user defined function (UDF) on a blank worksheet, using the ConBeamU function as an example.

To use a UDF, the VBA code for the function must either be included in the active workbook, or another open file.  In most cases the VBA code can be copied from the master file to a new workbook, but in the case of the ConbeamU function the units related code refers to a database of units data in the master file.  The easiest way to set up a new file for this case is to save the master file with a new name, and delete all the unwanted sheets.  I have added a ConbeamU-template file to the ConbeamU zip file, that has all the required code and units data, two sheets with notes and instructions, and a single blank sheet.  The new zip file can be downloaded from:

ConbeamU.zip

The screen shots below illustrate how to set up a new application of the ConbeamU function, starting from a blank worksheet.

First copy details of the function arguments from the Functions sheet, and enter or copy and paste the input data.  Each data range may be placed in any convenient position.  For the ConbeamU function the required data ranges are:

  • Segments: details of each beam segment with different section properties, with distance of the segment end from the start (left hand end) of the beam, flexural stiffness (EI), and optionally shear stiffness (GA).
  • Outpoints: a single column with either the number of output sections for each span, or a list of output point positions (see below for more details).
  • Supports: position of each support, with optionally translational stiffness, rotational stiffness, and displacement.
  • Dloads: extent and magnitude of distributed transverse loads.
  • PLoads: location and magnitude of point transverse loads and moments.
  • OutUnits: single row with units for output results: position, shear force, bending moment, slope (leave blank), and deflection.
  • Out: output index, optional, default = 1 (output as listed above).
  • ListOutPoints, optional, default = False, output at specified number of sections/span.  See below for details of True option.

Note that for the ConBeamU function (and other unit aware functions) all data ranges with values that have a unit must be headed by a valid unit symbol:

After entering all required input data, enter the function in the top-left cell of the output range.  The easiest way to ensure that all arguments are provided, in the right order, is to enter the function name, including the opening bracket, then click the “insert function” button, just to the left of the edit bar, as shown below

As each function argument is selected the contents of the cell or range are shown to the right of the data box.  When all the required arguments are selected the function results appear under the data boxes.  In this example the default values are what we want for the two optional arguments, so we can leave them blank.  Click OK or press enter to enter the function:

At this stage only the first value of the results array is visible:

The standard Excel way to display all the contents of an array function is:

  • Select the required output range, with the array function in the top-left corner.
  • Press F2 (edit).
  • Press Ctrl-Shift-Enter

However the ConbeamU spreadsheet has a macro that will do this automatically, so with the cell containing the entered function still selected, just press Ctrl-Shift-S.

The default output option is to specify the number of output sections for each span.  An alternative is to list the position of each section where output is required.  In the example below two points are entered at each internal support, and each point with a point load or moment.  To display the output set the final “ListOutPoints” argument to True, and select the list of locations range as the “OutPoints” argument.  Having edited the function, press Ctrl-Shift-Enter to enter:

As before, to re-set the output range to display only the cells with valid output values, press Ctrl-Alt-S:

Note that the list of output point locations does not need to be adjacent to the output range, it can be anywhere in the workbook, or even in another workbook.

The procedures described above are applicable to any Excel function or UDF that returns an array function, except that resetting the output range to display the whole array by pressing Ctrl-Shift-S only works in those workbooks where the required macro has been added.

Advertisements
Posted in Arrays, Beam Bending, Excel, Finite Element Analysis, Newton, UDFs, VBA | Tagged , , , , | 1 Comment

UDF to replace cell references with values

I recently posted an update to the Eval2 spreadsheet with a subroutine to display a cell formula as a text string, with the cell references replaced by the associated values.

I have now added three user defined functions (UDFs) to do the same job:

  • Addr2Val1 takes a text string as input and returns the formula with all cell references or range names converted to the value in the referenced cell.  Cell references may be anywhere on any spreadsheet.
  • The Eval function has been modified to work with cell references and range names, as well as optional lists of parameter symbols, and their associated values.
  • Addr2Val2 works the same as Addr2Val1, except the input is an active cell formula, rather than a text string.

The new file may be downloaded from:

Eval2.zip

Examples of each function are shown in the screenshot below, followed by source code for the Addr2Val2 function.  Full open-source code for the other functions is included in the download file.

Updated 3 Sep 2017: There seem to be issues with the WordPress system removing line breaks in some places, and inserting them in others. I have corrected the code below, but if you want to copy the code I recommend doing so from the download spreadsheet, rather than from the listing below, which probably still has some errors.

Function Addr2Val2(FuncRng As Range, Optional CommaDec As Boolean = False) As Variant
 Dim NumChar As Long, ParamDict As Scripting.Dictionary, i As Long, CheckC As String, AscCheckC As Long, CheckP As String, NewFunc As String, iErr As Long
 Dim ParamRng As Range, NumParam As Long, PVal As Variant, IsRng As Boolean, CheckRng As String, Func As String

    ' Evaluate a cell formula (Func), replacing cell addresses or range names with the values in the referenced cells.

    'Func is a single cell containing the formula to be evaluated
    
    ' CommaDec = True to convert commas to decimal point and semi-colons to commas
    ' CommaDec = False (default) for no convertion.
    
    Func = Trim(FuncRng.Formula)
    Func = Replace(Func, "$", "")
    
    If CommaDec = True Then
    ' Replace all , with . and ; with ,
        Func = Replace(Func, ",", ".")
        Func = Replace(Func, ";", ",")
    End If
    
    NumChar = Len(Func)
    i = 1
    Do While i <= NumChar
        CheckP = "" 
            Do 
                CheckC = Mid(Func, i, 1) 
                AscCheckC = Asc(CheckC) 
                If (AscCheckC > 64 And AscCheckC < 91) Or (AscCheckC > 96 _               And AscCheckC < 123) Or AscCheckC = 95 Or AscCheckC = 33 Then
                CheckP = CheckP & CheckC
                i = i + 1

       ElseIf CheckP <> "" And Asc(CheckC) > 47 And Asc(CheckC) < 58 Then 
                CheckP = CheckP & CheckC
                i = i + 1
            Else
                ' Check if CheckP is a cell address or range name
                On Error Resume Next
                CheckRng = ""
                IsRng = False
                CheckRng = TypeName(Range(CheckP))
                If CheckRng = "Range" Then IsRng = True
                If IsRng Then
                    NewFunc = NewFunc & Range(CheckP).Value2 & CheckC
                                
                ' else leave it unchanged
                Else
                    NewFunc = NewFunc & CheckP & CheckC
                End If
                i = i + 1
                Exit Do
            End If
        Loop

    Loop

    Addr2Val2 = NewFunc
End Function

Posted in Excel, UDFs, VBA | Tagged , , , , | Leave a comment

Jansch and Renbourn live

Three recently uploaded You Tube recordings of live performances by guitarists Bert Jansch and John Renbourn.  As further evidence that the quality of a You Tube video is inversely proportional to the number of views, none of the three have over 1000 views, and the first has just 6.

Bett’s Dance; Bert Jansch live at the 12 bar:

Bert Jansch and John Renbourn; un-named instrumental, live from Massachusetts, 1990

From the same concert, John Renbourn plays So Early in the Spring:

 

Posted in Bach | Tagged , , | Leave a comment

Scottish Fiddlers

Yesterday I saw “Scotland the Brave” at the Sydney Opera House, featuring the Willoughby Symphony Orchestra and Choir, and fiddler extraordinaire Marcus Holden:

whose playing of Scottish fiddle music reminded me of Robin Williamson and the Incredible String Band:

and lead to the discovery that Marcus Holden also plays in a string band, The Jugalug String Band:

Posted in Bach | Tagged , , , , , | Leave a comment

Evaluating text and calling Python functions from Excel with xlwings

The Alglib spreadsheet presented here includes functions to evaluate formulas entered as text on the spreadsheet, or to call specified Python functions.  I have now added a user defined function (UDF) that will perform either of these operations (xl_CallFuncD), and added a number of examples of use in different situations.  The updated spreadsheet (including full open-source code) can be downloaded from:

xlAlglib.zip

As before the following software is required:

  • Python, including Numpy and Scipy
  • xlwings ver 0.11.04 or later
  • Alglib Python version 3.11 or later

The Anaconda Python package includes Numpy, Scipy and xlwings (now updated to ver 0.11.04).  Alglib must be installed separately, and comes in free and commercial versions.

To deal with the need to pass any number of arguments, the function arguments are listed in a two (or three) column range; column 1 lists argument names, and column 2 either single values, or range addresses, entered as a text string.  This data is read into a VBA variant array, then converted to a Python dictionary.  Examples of the usage of xl_CallFuncD are shown in the screen-shots below:

A formula entered as text on the spreadsheet, with any number of listed variables.  Note that exponents may be entered using either VBA notation (^) or Python/Fortran notation (**):

Function results may be used as input values for another formula:

On-sheet formulas may include any built-in Python function, or functions from the imported Numpy, Scipy or Alglib modules:

Both on-sheet formulas and external function calls may have array arguments.  In this case the argument range must have three columns, with the third column specifying the number of dimensions for the array (1 or 2).  The range address may be entered as text, but to ensure that the address is updated if the range is moved the UDF RngAddress should be used:

xlCallFunc will call user defined Python functions from the xlAlgLib module without any dedicated VBA interface function:

… or user defined functions from another module:

… or functions from other Python libraries.  If the called function returns 2 or more array results the Out argument must be used to select the array to be returned.  The Python dictionary of arguments passes arrays as tuples, which will cause problems with some functions.  In this case enter True in the Convert argument, which will convert all passed tuples to lists, or lists of lists.

Note that argument names must be entered exactly, including correct case.  To list all arguments for any function, use the get_argnames UDF:

 

Posted in AlgLib, Excel, Link to Python, Maths, Newton, NumPy and SciPy, UDFs, VBA, xlwings | Tagged , , , , , , , , , | 1 Comment

Converting a formula to values

Excel has a built-in function (FormulaText) to display a formula as cell references, rather than the result value.  It would be useful to be able to display the value of each cell reference as well, but there is no built-in function to do that.

It turns out it’s not easy to do with VBA either.  I have added a macro to do the job to the Eval2 spreadsheet:

Sub Addr2Val()
Dim PrecCells As Variant, CellRng As Range, NumP As Long, i As Long, Form As String
Dim CellAddr() As String, CellVal() As Double, xCell As Range, OutCols As Long

    Set CellRng = Application.ActiveCell
    Form = CellRng.Formula
    Form = Replace(Form, "$", "")
    Set PrecCells = CellRng.Precedents
    NumP = PrecCells.Count
    ReDim CellAddr(1 To NumP, 1 To 1)
    ReDim CellVal(1 To NumP, 1 To 1)
    i = 1
    For Each xCell In PrecCells
        CellAddr(i, 1) = xCell.Address
        CellAddr(i, 1) = Replace(CellAddr(i, 1), "$", "")
        CellVal(i, 1) = xCell.Value
        i = i + 1
    Next
    Form = Eval(Form, CellAddr, CellVal, 0)
    OutCols = Selection.Columns.Count
    If OutCols > 1 Then OutCols = OutCols - 1
    CellRng.Offset(0, OutCols).Value = " " & Form
    Set CellRng = Nothing
    Set PrecCells = Nothing
End Sub

The macro uses the Range.Precedents method to return the address and value of each cell reference in the formula, then calls the Eval user defined function (UDF) to convert the cell addresses in the formula to their numerical values.  It would be convenient to put this in a function, which could be called from the spreadsheet, but when entered in a UDF the .Precedents method does not return information on the cell precedents, it returns the information for the cell itself.  If anyone has any suggestions for converting the macro to a working UDF, please leave a comment.

The macro has been set up to return the results in the cell to the right of the selected cell, or if three or more columns are selected, in the top right cell of the selected range.  Note that the macro will write over  any contents in the results cell.

An example of the macro in use (with instructions) is shown in the screen-shot below:

The updated spreadsheet, including full open-source code and the example above, can be downloaded from:

Eval2.ZIP

Posted in Excel, UDFs, VBA | Tagged , , , | 2 Comments

Excel to Alglib via xlwings

The Alglib library provides many valuable numerical analysis routines, but the VBA version is no longer actively maintained.  The latest versions are available in C++, C#, and Python, of which the Python version (in conjunction with xlwings) provides the easiest interface with Excel.

An Alglib/Python based spreadsheet has previously been presented here.  I have now updated this to the latest versions of xlwings and Alglib, added additional solver and linear algebra functions, and updated the Python code to make better use of the xlwings auto-import functionality, which generates the necessary VBA code at the touch of a button.  The new spreadsheet can be downloaded from:

xlAlglib.zip

As usual, the download files include full open source code.

To install the necessary files:

  1. Install Python, either version 2 or 3.  The Anaconda Python package will also install xlwings, but see below.
  2. Install or update to the latest version of xlwings (0.11.04 at the time of writing).  If the automatic install delivers an earlier version, see here.
  3. Install Alglib.
  4. Copy the contents of the xlAlglib zip file to any convenient location.
  5. Any problems, please let me know.

The screenshots below show the functions available in the new version.  Future posts will look in more detail at specific examples, and procedures for modifying the Python code.

List of functions:

Spline Functions:

Parametric Splines:

Rational Interpolation Function:

2D and 3D Interpolation:

Fit a spline to scattered data:

Polynomial fitting:

Non-Linear Fitting:

Fit Polynomial to scattered data:

Radial Basis Function Interpolation:

Levenberg-Marquardt optimisation:

Integration of Cubic Splines:

Differentiation of Cubic Splines:

Matrix algebra:

Posted in AlgLib, Curve fitting, Excel, Link to Python, Maths, Newton, Numerical integration, UDFs, VBA, xlwings | Tagged , , , , , , , , , | 3 Comments