Some string functions

It was pointed out in a comment to this post at Daily Dose of Excel that VBA has a StrReverse function that will (logically enough) reverse a string.  That’s not awfully useful to me (except maybe for Project Euler), but it did set me thinking that I spend a fair amount of time writing lengthy formulas in Excel to extract bits of strings, which could be done with much less typing with a few simple User Defined Functions.

So here they are; download from String Functions.zip; full open source code is in the download file.

(Now updated as suggested by Dick K in the comments with a MidW() function, and an optional delimiter parameter)

Functions are:

leftw(); Return the first word(s) from a string

rightw(); Return the last word(s) from a string

Midw(); Return words(s) from the middle of a string

FINDrev(); Find from the right hand end

Leftval(); Extract a value from the left end of a string

Rightval(); Extract a value from the right end of a string

Reverse(); Reverse a string

Screenshot with more details:

Click for full size view

Click to view full size

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

Frame Analysis with Excel – 7; Shear deflections and support displacements

Continuing from: Frame Analysis with Excel – 6; Beam end releases and actions

Download Frame4.zip – the download file includes complete open source code.

Two more refinements have been added to the frame analysis spreadsheet:

  • The stiffness matrix has been revised to take account of shear deflections for members where the shear area and shear modulus are provided.
  • It is now possible to apply displacements and/or rotations to supports.  Fixed freedoms are specified with “F”, or enter the support deflection in the appropriate units, or rotation in radians.

In addition a plotting routine has been added to plot the frame, with or without scaled deflections.

Shown below are results for an example frames, with results from the same frames analysed in Strand7, and plots of the deflected shape (scaled by a factor of 20) from the spreadsheet and Strand7:

Frame4 output compared with Strand7; click to view full size.

Frame4 output compared with Strand7; click to view full size.

Spreadsheet plot of deformed shape x 20

Spreadsheet plot of deformed shape x 20

Strand7 deformed shape

Strand7 deformed shape

Truss input and output added 30 Jan 10:

Member end releases are specified by entering a 1 in the column for the freedom to be released.  A truss can be modelled by releasing the rotational freedom at both ends of each truss member (M1 and M2).  Input and results for a simple truss are shown below.  Note that all the members have zero moment at both ends, and the rotations (in radians) at each end of each beam are reported.  The end release table headings in the spreadsheets in Frame4.zip have been modified to clarify the reqired input.

Posted in Excel, Finite Element Analysis, Frame Analysis, Newton, VBA | Tagged , , , | 31 Comments

Finding square roots …

… to 100 decimal places.

Why would anyone want to do that?

To solve Project Euler Problem 80:

It is well known that if the square root of a natural number is not an integer, then it is irrational. The decimal expansion of such square roots is infinite without any repeating pattern at all.

The square root of two is 1.41421356237309504880…, and the digital sum of the first one hundred decimal digits is 475.

For the first one hundred natural numbers, find the total of the digital sums of the first one hundred decimal digits for all the irrational square roots.

Michael at Daily Dose of Excel tracked down a method of finding square roots that requires only addition and subtraction of integers:

Square Roots by Subtraction, by Frazer Jarvis

Initial step
Let a = 5n (this multiplication by 5 is the only time when an operation other
than addition and subtraction is involved!), and put b = 5.

Repeated steps
(R1) If a is greater than or equal to b, replace a with a − b, and add 10 to b.
(R2) If a is less than b, add two zeroes to the end of a, and add a zero to b just before
the final digit (which will always be ‘5’).

Conclusion
Then the digits of b approach more and more closely the digits of the square
root of n.

Implementing this very simple algorithm in VBA was complicated by the lack of a very long integer, so instead I set up two arrays a little bigger than the number of required digits, to store a and b, with one digit in each array element.  The algorithm above was then iterated until all the required decimal places had been filled, then the array was converted to a string for display in the spreadsheet (or for the Project Euler problem the sum of the digits was found with a simple loop).

A spreadsheet with the VBA code for the SqRtI() function may be downloaded from here

The screen shot below shows the function returning the first 100 digits of the square root of 3, together with a spreadsheet implementation of the algorithm (which is limited to the 15 digit precision available in Excel).

100 digits of root 3

100 digits of root 3

Posted in Arrays, Excel, Maths, Newton, UDFs, VBA | 2 Comments

Moving Average Function

The previous post presented a simple moving average user defined function (UDF).  This has been extended to provide additional functionality:

  • A weighted average may be returned; either a linear weight with a specified step value, or a using any specified weighting array.
  • The initial values may be returned either as #N/A, or with the current average values.
  • Zeroes in the data may be either treated as values or ignored.
  • Rectangular ranges may be specified to be treated as arranged in either columns or rows.

The function may be downloaded from: MovAv.zip

A screenshot is shown below:

MovAv UDF - click for full size view

MovAv UDF - click for full size view

Posted in Arrays, Excel, UDFs, VBA | Tagged , , , | 1 Comment

Moving averages and User Defined Array Functions

I have recently needed to work with moving averages on a large-ish data set (about 10,000 rows x 10 columns), and for reasons that I will describe in the next post, decided that a User Defined Function (UDF) would be useful.  Writing the UDF was simple enough, but because of the large number of data transfers between the spreadsheet and VBA it was painfully slow.  Fortunately it is easy to write a UDF as an array function, which allows all the data to be transferred in one step, the processing to be carried out within VBA, then the results to be written back to the spreadsheet in one step.  This dramatically improves the performance; to near instantaneous in the case of my 100,000 cell data set.

The procedure in outline is:

  • Declare the input datarange(s) and the function itself as variants
  • Convert the input range from a variant/range object to an array of variants with the statement: DataRange = DataRange.value2
  • Dimension an array of the required size for the results:  Dim ResA(1 to numrows, 1 to numcols) as double
  • Perform the necessary calculations and assign the results to ResA.
  • Assign the results array to the function return value:  FunctionName = ResA
  • That’s all

If you enter the function in the spreadsheet in the usual way it will only display the contents of array position (1,1).  To display the full array:

  • Enter the function in one cell in the usual way
  • Select a range large enough to hold the whole array, with the entered function in the top-left corner.
  • Press the Edit key (F2)
  • Press Ctrl-Shift-Enter
  • The array values will be transferred to the selected range

Code for a moving average array function is shown below.  This has the following advantages over using the built-in Average() function, or the “moving average wizard” in the data analysis add-in:

  • The number of values to be averaged is specified as a variable, rather than requiring the formula to be re-entered.
  • It will handle any number of columns, up to the spreadsheet limit
  • It can be easily refined to provide additional functionality, for instance weighted moving averages, as will be described in the next post

Note that this is a simplified function, with no error checking, and blank cells treated as zero.

Function MovAv1(AvData As Variant, Steps As Long) As Variant
Dim MovAvA() As Variant, NumRows As Long, NumCols As Long
Dim i As Long, j As Long, MovSum As Double
AvData = AvData.Value2
NumRows = UBound(AvData)
NumCols = UBound(AvData, 2)
ReDim MovAvA(1 To NumRows, 1 To NumCols)
For j = 1 To NumCols
MovSum = 0
For i = 1 To Steps
MovSum = MovSum + AvData(i, j)
MovAvA(i, j) = CVErr(xlErrNA)
Next i
MovAvA(i - 1, j) = MovSum / Steps
For i = Steps + 1 To NumRows
MovSum = MovSum + (AvData(i, j) - AvData(i - Steps, j))
MovAvA(i, j) = (MovSum) / Steps
Next i
Next j
MovAv1 = MovAvA
End Function

Screen shot:

Moving Average Function

Moving Average Function

Posted in Arrays, Excel, UDFs, VBA | Tagged , , , , | 8 Comments