All men will be sailors then, until the sea shall free them

The YouTube video of A Sailor’s Life by the Fairport Convention contains the image shown below:

I have just discovered that the words are taken from the Leornard Cohen song Suzanne, but of the origin of the image I have no idea. If anyone recognises it, please leave a comment.

Here’s the original, from 1970 or threabouts:

And a live version from 2008:

Suzanne takes you down to her place near the river
You can hear the boats go by
You can spend the night beside her
And you know that she’s half crazy
But that’s why you want to be there
And she feeds you tea and oranges
That come all the way from China
And just when you mean to tell her
That you have no love to give her
Then she gets you on her wavelength
And she lets the river answer
That you’ve always been her lover
And you want to travel with her
And you want to travel blind
And you know that she will trust you
For you’ve touched her perfect body with your mind.
And Jesus was a sailor
When he walked upon the water
And he spent a long time watching
From his lonely wooden tower
And when he knew for certain
Only drowning men could see him
He said “All men will be sailors then
Until the sea shall free them”
But he himself was broken
Long before the sky would open
Forsaken, almost human
He sank beneath your wisdom like a stone
And you want to travel with him
And you want to travel blind
And you think maybe you’ll trust him
For he’s touched your perfect body with his mind.

Now Suzanne takes your hand
And she leads you to the river
She is wearing rags and feathers
From Salvation Army counters
And the sun pours down like honey
On our lady of the harbour
And she shows you where to look
Among the garbage and the flowers
There are heroes in the seaweed
There are children in the morning
They are leaning out for love
And they will lean that way forever
While Suzanne holds the mirror
And you want to travel with her
And you want to travel blind
And you know that you can trust her
For she’s touched your perfect body with her mind.

 

Update 23 April 2012: I have just found a new version of this song recently uploaded on Youtube by Coffeescup:

 

Update 27 March 2012: Debra Dalgleish (from the Contextures Blog) sent me an e-mail identifying the source of the image. It comes from Jason Kinney and can be seen here: http://www.coolhunting.com/style/pauper-voile-sc.php

After realizing scarves by covetable designers such as Alexander McQueen or Hermes were out of reach, Portland-based photographer Jason Kinney decided to apply his medium to silk. Pauper Voile is the upshot, with Kinney explaining that his interest in scarves made him “curious about how to put an image on fabric.” Starting out with wood-block prints before teaching himself how to screen print, he refined his skill to an obsessive degree for a line of scarves that exude Gothic sophistication.

… “The Sail” design is composed of elements from Victorian paintings and an old photograph of a sailor in profile.

Posted in Bach | Tagged , , , , , | 1 Comment

Writing Arrays to the worksheet – VBA function

Previous posts have looked at the VBA code for efficiently writing a VBA array to the spreadsheet as quickly as possible, most recently here.

I have now put this code in a function that can be conveniently called from any other VBA routine, with several optional features:

  • Optional “NumRows” and “NumCols” parameters, allowing part of the array to be written to the spreadsheet (default is write the whole array)
  • Optional “ClearRange” parameter, allowing the data in the named range to be cleared before writing the new data.  This may be useful if the range to be written is smaller than the old range, and you wish to keep the old data outside the limits of the new array.  Default is True, i.e. the old data will be cleared.
  • Optional Rowoff and Coloff parameters, allowing the data to be offset from the top-left corner of the specified range.  Default offset values are zero.

Another new feature is that the array to be written may be a worksheet range, providing a quick and convenient way of copying the data in any range as values to another location.

The code is shown below:

Function CopyToRange(VBAArray As Variant, RangeName As String, Optional NumRows As Long = 0, _
                    Optional NumCols As Long = 0, Optional ClearRange As Boolean = True, _
                    Optional RowOff As Long = 0, Optional ColOff As Long = 0) As Long
Dim DataRange As Range

    On Error GoTo RtnError
    If TypeName(VBAArray) = "Range" Then VBAArray = VBAArray.Value2
    If NumRows = 0 Then NumRows = UBound(VBAArray)
    If NumCols = 0 Then NumCols = UBound(VBAArray, 2)
    Set DataRange = Range(RangeName)
    If ClearRange = True Then DataRange.Offset(RowOff, ColOff).ClearContents
    DataRange.Resize(NumRows, NumCols).Name = RangeName
    Range(RangeName).Offset(RowOff, ColOff).Value = VBAArray
    Set DataRange = Nothing
    CopyToRange = 0
    Exit Function

RtnError:
    CopyToRange = 1
End Function

It may also be downloaded from CopyToRange.zip, which includes the code plus a short sample code that generates a 4×4 array, writes it to the spreadsheet, then copies that range to another named range on the spreadsheet, producing the output below:

CopyToRange Function

Note that this function must be called from a VBA subroutine, since functions called from the spreadsheet, as a User Defined Function, cannot write to other parts of the spreadsheet.

Finally, another short but useful function is included in the download file, which clears a named range. After clearing the named range is re-sized to 1 row, or optionally to any specified number of rows:

Function ClearRange(RangeName As String, Optional NumRows As Long = 0, _
        Optional RowOff As Long = 0, Optional ColOff As Long = 0) As Long
Dim DataRange As Range, NumCols As Long

    On Error GoTo RtnError

    Set DataRange = Range(RangeName)
    If NumRows = 0 Then NumRows = 1
    NumCols = DataRange.Columns.Count

    DataRange.Offset(RowOff, ColOff).ClearContents
    DataRange.Resize(NumRows, NumCols).Name = RangeName
    Set DataRange = Nothing
    ClearRange = 0
    Exit Function

RtnError:
    ClearRange = 1
End Function
Posted in Arrays, Excel, VBA | Tagged , , , , | 17 Comments

More from the Former Love …

… with video directed by Kerinne Jenkins

(Click on Vimeo to visit site, or click play, then full screen button:

Dancing in Silence – The Former Love from Kerinne Jenkins on Vimeo.

Posted in Bach, Films | Tagged , , , | 1 Comment

Getting the address of a selected range

The Excel Indirect() function allows other functions to use the text in a worksheet cell to define a range, rather than selecting the range, or entering it directly into the function. For instance, if cell A1 contained the text B1:B10, then the function =Sum(Indirect(A1)) would return the sum of the values in B1:B10.

It would be convenient if there was a built in Excel function that returned the address of a selected range, but there isn’t. It is possible to create the address using a combination of functions and text strings, but in my opinion a much simpler method is available through a very short piece of VBA:

Function RngAddress(Rng As Range) As String
RngAddress = Rng.Address
End Function

Pasting those three lines into a code module in the VB Editor will create a RngAddress function that will return a text string with the address of a selected range.

But having done that, wouldn’t it be nice if we could also just select the top left hand corner, and enter the number of rows and columns we wanted. Also being able to (optionally) return the worksheet name would be useful. Another few lines will do what we want:

Function RngAddress(Rng As Range, Optional NumRows As Long, Optional NumCols As Long, Optional SheetName As Boolean) As String

' If you want this function to update with every worksheet change, then un-comment the line below
' Application.Volatile

If NumRows = 0 And NumCols = 0 Then
RngAddress = Rng.Address
    Else
If NumRows = 0 Then NumRows = Rng.Rows.Count
If NumCols = 0 Then NumCols = Rng.Columns.Count
RngAddress = Rng.Cells(1, 1).Address & ":" & Rng.Cells(NumRows, NumCols).Address
    End If

If SheetName = True Then RngAddress = "'" & Rng.Worksheet.Name & "'" & "!" & RngAddress

End Function

The entire code for this function, together with some examples can be downloaded from: RngAddress.xlsb

And this is what it looks like:

RngAddress

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

Newton Excel Shakespeare

Another excellent link from Al Vachris:

Bruce McPherson’s Site

This site is all about how to free your Excel data from your desktop and take advantage of web capabilities such as Docs, Maps, Earth , Gadgets, Visualizations and a whole bunch of other services . Along the way, you’ll see a few techniques, tips and tricks as well as fully functional sample applications in Vba and javaScript. All examples are downloadable here, and the code is unprotected and free for non commercial re-use.

Click to open site in new window

A random example from the site is the code below, which will let your computer quote Hamlet to you:

Public Sub say()
Dim TextA As Variant, i As Long
Dim sTerm As String, spv As Object

TextA = Selection.Value
Set spv = CreateObject("SAPI.SpVoice")

If IsArray(TextA) = True Then
For i = 1 To UBound(TextA)
sTerm = TextA(i, 1)
            spv.Speak sTerm
Next i
    Else
        spv.Speak TextA
    End If

Set spv = Nothing

End Sub

See http://ramblings.mcpher.com/Home/excelquirks/snippets/speak for more details, and download the sample spreadsheet below from Text2Speech.xlsb

Text2Speech.xlsb, download from the link above

Posted in Computing - general, Excel, Javascript, VBA | Tagged , , , , , | 2 Comments