11
votes

Given a Row and Column (As Long), how can you determine the spreadsheet notation using VBA in Excel (2007):

e.g.:

(R, C) = (1, 1) -> "A1"
(R, C) = (2, 1) -> "A2"
(R, C) = (2, 2) -> "B2"

Thus if you had a function:

Function CellRef(R As Long, C As Long) As String

which provided that functionality, you could do something like:

Worksheet.Range(CellRef(R1, C1) + ":" + CellRef(R2, C2)).Copy

A little background, in case this is the wrong approach to be taking: The purpose of this is that I have a master sheet which describes other worksheets in a table:

WorksheetName, Range etc....

This master sheet controls transformations on the sheet, but the Range value is obviously in Excel notation for convenient later use in referencing the range. However a routine to manage this table, report exceptions and ensure consistency really gets things from other sheets in row and column, so for instance it gets a row and column where it knows something is starting and ending.

Here's the function I ended up with:

Private Function CellRef(R As Long, C As Long) As String
    CellRef = vbNullString
    On Error GoTo HandleError:
    CellRef = Replace(Mid(Application.ConvertFormula("=R" & R & "C" & C, XlReferenceStyle.xlR1C1, XlReferenceStyle.xlA1), 2), "$", "")
    Exit Function
HandleError:
End Function
5

5 Answers

4
votes

Maybe this is what you are looking for?

1
votes

http://support.microsoft.com/kb/833402 is a Microsoft solution for the problem of converting numbers to letters (the tricky part of the conversion from 1,1 to A1). This actually has the beuaty of working in other applications than Excel as it relies on basic VBA.

Then you add:

' Converts row and column index to Excel notation, ie (3, 2) to B3.
Private Function generateExcelNotation(row As Integer, column As Integer) As String
    ' error handling of your choice, I go for returning an empty string
    If (row < 1 Or column < 1) Then
        generateExcelNotation = ""
        Exit Function
    End If
    generateExcelNotation = ConvertToLetter(column) & row
End Function
0
votes

The expression 'rngTemp.Address(False, False, , , .Cells(1, 1))' will display the address of the range rngTemp in A1 notation which does not contain $s to signify an absolute address. To get an absolute address, replace 'False, False' with ','.

0
votes

Here are two solutions. One with elegant generality, another simple and direct aimed at the present implementation of Excel. The first is limited only by the precision of the Integer or Long data type. The second will fail if the maximum number of columns were to increase beyond 18278, the point when column references go from three letters to four letters. Both are pure VBA with no reliance on a feature peculiar to an MS Office application.

The column references are viewed as consecutive sets of base 26 numbers of a given number of digits with the alphabet serving as digits A=0,B=1,.. etc. First there are 26 single letter columns. Then 26^2 = 676 double letter columns, Then 26^3 = 17576 triple letter columns for a total of 18278 of which only 16384 are used by Excel.

A1,B1,...,Z1 (1-26, 26 columns)

AA1,....,ZZ1,(27 to 702, 26^2 = 676 columns)

AAA1,...,XFD1 (703 to 16384, 15682 columns of 26^3 = 17576 possible with three letters)

This is the first solution. Currently the maximum column number is 16384 so code will work with Integer (upper limit 32767) in place of Long. If you like you can error check that column parameter C is not out of range.

    '
    ' A "pure" implementation limited only by precision of the Long integer data type    
    '     
    '
    ' The first step is to find how many letters are needed.
    ' the second is to translate the column index into 0..(26^n) - 1  range
    ' Finally render that value as a base 26 number using alphabet for digits
    '


       Public Function CoordToA1Cell(ByVal R As Long, ByVal C As Long) As String
        Dim colRef As String
        Dim cwork As Long
        Dim n As Integer
        '
        Static e(0 To 6) As Long ' powers of 26
        Static s(0 To 6) As Long ' index ranges for number of letters needed

    If C <= 0 OR R <= 0 Then Exit Function

        ' initialize on first call
           If e(0) = 0 Then ' first call
              s(0) = 1
              e(0) = 1
              For n = 1 To UBound(s)
                e(n) = 26 * e(n - 1)
                s(n) = s(n - 1) + e(n)
              Next n
           End If

           cwork = C
           colRef = ""
        '
        ' step one: discover how many letters are needed
        '
           n = 1
           Do
              If C < s(n) Then
                 n = n - 1
                 Exit Do
              End If
              n = n + 1
           Loop
        ' step two: translate into 0..(26^n) - 1 interval
           cwork = cwork - s(n)
        '
        ' Step three: represent column index in base 26 using alphabet for digits
        '
           Do While n > 0
             colRef = colRef & Chr(65 + cwork \ e(n))
             cwork = cwork Mod e(n)
             n = n - 1
           Loop
        ' the final (or only) digit
           colRef = colRef & Chr(65 + cwork)

        CoordToA1Cell = colRef & R

        End Function

This second is simple ("Quick and Dirty") and will work with current Excel. It will require serious modification if the maximum number of columns exceeds 18278 when the column reference goes from 3 to 4 letters. '

Public Function CoordToA1CellQAD(ByVal R As Long, ByVal C As Long) As String
Dim colRef As String
Dim cwork As Long

If C <= 0 OR R <= 0 Then Exit Function

cwork = C

If cwork <= 26 Then
   colRef = Chr(64 + cwork)
ElseIf cwork <= 26 * 26 + 26 Then
   cwork = cwork - (26 + 1)
   colRef = Chr(65 + (cwork \ 26)) & Chr(65 + (cwork Mod 26))
'ElseIf cwork <= 26 * 26 * 26 + 26 * 26 + 26 Then  ' theoretical limit for three letters, 17576
ElseIf cwork <= 16384 Then                         ' actual Excel limit for columns
   cwork = cwork - (26 * 26 + 26 + 1)
   colRef = Chr(65 + (cwork \ 676))
   cwork = cwork Mod 676
   colRef = colRef & Chr(65 + (cwork \ 26)) & Chr(65 + (cwork Mod 26))
Else ' overflow
   Exit Function
End If

CoordToA1CellQAD = colRef & R

End Function