how does excel decide a suggested name to a range?

D

dwake

I have a routine that takes a range and names it by the contents of
it's first cell (much as Excel does when you use the define name
window).

But I have noticed that Excel alters the name with the following
observed rules:
/ = _
[space] = _

if the cell begins with a number, the name gets preceeded by a "_"


Is there a source where I can find all of the rules it uses? Or
perhaps even a routine I can call to make that conversion
programmatically ( I am refreshing the contents of the range from a
database, and the database finds the right location on the spreadsheet
through it's key field (a string field), so I would need to make that
conversion then.
 
J

John

I guess you could run a check on the string value that you get for your
range name and use the Replace function if it finds an underscore as the
first character. Something like:

strRngName = Replace(strRngName, "_", "", 1, 1)

I'm afraid I don't know of a source for rules though.

Best regards

John
 
F

Fredrik Wahlgren

dwake said:
I have a routine that takes a range and names it by the contents of
it's first cell (much as Excel does when you use the define name
window).

But I have noticed that Excel alters the name with the following
observed rules:
/ = _
[space] = _

if the cell begins with a number, the name gets preceeded by a "_"


Is there a source where I can find all of the rules it uses? Or
perhaps even a routine I can call to make that conversion
programmatically ( I am refreshing the contents of the range from a
database, and the database finds the right location on the spreadsheet
through it's key field (a string field), so I would need to make that
conversion then.

I guess excel does this when it feels there's a chance that the name would
be ambiguous unless renamed. I'm not aware of any documentation for this.

/Fredrik
 
T

Tushar Mehta

That is XL's way of creating legitimate names. In addition to
characters that are invalid in a name (such as / and space), certain
names such as a one indistinguishable from a cell reference (B1 or D12,
for example) are also invalid.

I thought there was some documentation that indicated the rules for
valid names. But a 10 minute search of help and msdn.microsoft.com
proved futile. What you can do is develop your own rule for creating
names. I use the following:

Names I create programmatically *start* with _TM{add-in id}
_TM to identify a name created by a program I wrote
{add-in id} identifies which program

If the name is being created from some user-specified source (file name
for example), I remove all characters other than letters and numbers.

If the name concatenates two tokens (chart name and series name for
example), I remove all characters other than letters and numbers and
then use underscore between the two tokens to get something like
_TMAddInID_chart1_series1

Does this guarantee that the user doesn't have the same name in the
workbook? No. But, it reduces the likelihood.

--
Regards,

Tushar Mehta
www.tushar-mehta.com
Excel, PowerPoint, and VBA add-ins, tutorials
Custom MS Office productivity solutions
 
T

Tushar Mehta

Maybe, I'm missing something but I saw nothing related to the
definition of names.

--
Regards,

Tushar Mehta
www.tushar-mehta.com
Excel, PowerPoint, and VBA add-ins, tutorials
Custom MS Office productivity solutions
 
K

keepITcool

ok.. here goes..


Const sINV1 = "[.0-9¤^~T?¯?·?[?]*"
Const sINVn =
"*[!0-9A-z.\_f¦¼´¨½¸¾ªµºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïð
ñòóôõöøùúûüýþÿ¤^~T?¯?·?[?]*"

Function NameIsInvalid(ByVal sFull As String) As Boolean

Dim sText$, bRes As Boolean

If InStrB(sFull, "!") Then
sText = fnSplice(sFull)(1)
Else
sText = sFull
End If
If Not sText Like sINV1 Then
If Not sText Like sINVn Then
bRes = True
End If
End If
If bRes Then
If Not UCase$(sText) Like "*[!0-9RC" & _
application.international(xlUpperCaseRowLetter) & _
application.international(xlUpperCaseColumnLetter) & "]*" Then
If CStr(Application.ConvertFormula(sText, xlR1C1, , xlRelative))
<> sText Then
bRes = False
GoTo theExit
End If
End If

If sText Like "[A-z]*#" Then
If IsNumeric(MidB$(sText, 3)) Or IsNumeric(MidB$(sText, 5)) Then
If IsObject(Evaluate(sText)) Then
bRes = False
GoTo theExit
End If
End If
End If
End If
theExit:
NameIsInvalid = Not bRes
End Function


Function fnSplice(sName As String) As String()
Dim s(0 To 1) As String, i%

i = InStrRev(sName, "!")
If i = 0 Then
s(1) = sName
Else
s(0) = Left$(sName, i - 1)
s(1) = Mid$(sName, i + 1)
End If

fnSplice = s
End Function

--
keepITcool
| www.XLsupport.com | keepITcool chello nl | amsterdam


Tushar Mehta wrote :
 
T

Tushar Mehta

OK, test it with TM_C1. It's a valid name that the function claims is
invalid.

Just keep in mind that it was the 2nd token I tested after looking at
the code. {g}

The only way to develop a function that can be trusted is if the
specification it is meant to implement were available. As I've already
pointed out, I could not find any in XL 2003 help or in
msdn.microsoft.com (though I know it used to be available with an older
version of XL -- 97? 95? 5?).

In any case, we were discussing valid names. The page you referred to
does not have any information that *I* could find on what XL considers
a valid name. Ah, well. The search continues. ;-)

--
Regards,

Tushar Mehta
www.tushar-mehta.com
Excel, PowerPoint, and VBA add-ins, tutorials
Custom MS Office productivity solutions

ok.. here goes..


Const sINV1 = "[.0-9¤^~T?¯?·?[?]*"
Const sINVn =
"*[!0-9A-z.\_f¦¼´¨½¸¾ªµºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïð
ñòóôõöøùúûüýþ=3F¤^~T?¯?·?[?]*"

Function NameIsInvalid(ByVal sFull As String) As Boolean

Dim sText$, bRes As Boolean

If InStrB(sFull, "!") Then
sText = fnSplice(sFull)(1)
Else
sText = sFull
End If
If Not sText Like sINV1 Then
If Not sText Like sINVn Then
bRes = True
End If
End If
If bRes Then
If Not UCase$(sText) Like "*[!0-9RC" & _
application.international(xlUpperCaseRowLetter) & _
application.international(xlUpperCaseColumnLetter) & "]*" Then
If CStr(Application.ConvertFormula(sText, xlR1C1, , xlRelative))
<> sText Then
bRes = False
GoTo theExit
End If
End If

If sText Like "[A-z]*#" Then
If IsNumeric(MidB$(sText, 3)) Or IsNumeric(MidB$(sText, 5)) Then
If IsObject(Evaluate(sText)) Then
bRes = False
GoTo theExit
End If
End If
End If
End If
theExit:
NameIsInvalid = Not bRes
End Function


Function fnSplice(sName As String) As String()
Dim s(0 To 1) As String, i%

i = InStrRev(sName, "!")
If i = 0 Then
s(1) = sName
Else
s(0) = Left$(sName, i - 1)
s(1) = Mid$(sName, i + 1)
End If

fnSplice = s
End Function

--
keepITcool
| www.XLsupport.com | keepITcool chello nl | amsterdam


Tushar Mehta wrote :
Maybe, I'm missing something but I saw nothing related to the
definition of names.
 
T

Tom Ogilvy

Here is a cleaned up version:

Const sINV1 = "[.0-9¤^~T?¯?·?[?]*"
Const sINVn = "*[!0-9A-z.\_f¦¼´¨½¸¾ªµ" & _
"ºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕ" & _
"ÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíî" & _
"ïðñòóôõöøùúûüýþÿ¤^~T?¯?·?[?]*"

Function NameIsInvalid(ByVal _
sFull As String) As Boolean

Dim sText$, bRes As Boolean

If InStrB(sFull, "!") Then
sText = fnSplice(sFull)(1)
Else
sText = sFull
End If
If Not sText Like sINV1 Then
If Not sText Like sINVn Then
bRes = True
End If
End If
If bRes Then
If Not UCase$(sText) Like "*[!0-9RC" & _
Application.International( _
xlUpperCaseRowLetter) & _
Application.International( _
xlUpperCaseColumnLetter) & "]*" Then
If CStr(Application.ConvertFormula(sText, _
xlR1C1, , xlRelative)) <> sText Then
bRes = False
GoTo theExit
End If
End If

If sText Like "[A-z]*#" Then
If IsNumeric(MidB$(sText, 3)) Or _
IsNumeric(MidB$(sText, 5)) Then
If IsObject(Evaluate(sText)) Then
bRes = False
GoTo theExit
End If
End If
End If
End If
theExit:
NameIsInvalid = Not bRes
End Function


Function fnSplice(sName As String) As String()
Dim s(0 To 1) As String, i%

i = InStrRev(sName, "!")
If i = 0 Then
s(1) = sName
Else
s(0) = Left$(sName, i - 1)
s(1) = Mid$(sName, i + 1)
End If

fnSplice = s
End Function

--
Regards,
Tom Ogilvy


keepITcool said:
ok.. here goes..


Const sINV1 = "[.0-9¤^~T?¯?·?[?]*"
Const sINVn =
"*[!0-9A-z.\_f¦¼´¨½¸¾ªµºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïð
ñòóôõöøùúûüýþÿ¤^~T?¯?·?[?]*"

Function NameIsInvalid(ByVal sFull As String) As Boolean

Dim sText$, bRes As Boolean

If InStrB(sFull, "!") Then
sText = fnSplice(sFull)(1)
Else
sText = sFull
End If
If Not sText Like sINV1 Then
If Not sText Like sINVn Then
bRes = True
End If
End If
If bRes Then
If Not UCase$(sText) Like "*[!0-9RC" & _
application.international(xlUpperCaseRowLetter) & _
application.international(xlUpperCaseColumnLetter) & "]*" Then
If CStr(Application.ConvertFormula(sText, xlR1C1, , xlRelative))
<> sText Then
bRes = False
GoTo theExit
End If
End If

If sText Like "[A-z]*#" Then
If IsNumeric(MidB$(sText, 3)) Or IsNumeric(MidB$(sText, 5)) Then
If IsObject(Evaluate(sText)) Then
bRes = False
GoTo theExit
End If
End If
End If
End If
theExit:
NameIsInvalid = Not bRes
End Function


Function fnSplice(sName As String) As String()
Dim s(0 To 1) As String, i%

i = InStrRev(sName, "!")
If i = 0 Then
s(1) = sName
Else
s(0) = Left$(sName, i - 1)
s(1) = Mid$(sName, i + 1)
End If

fnSplice = s
End Function

--
keepITcool
| www.XLsupport.com | keepITcool chello nl | amsterdam


Tushar Mehta wrote :
Maybe, I'm missing something but I saw nothing related to the
definition of names.
 
K

keepITcool

hmm..

ofcourse AN important part is the contant of the constants.

alas, the mailman got his hands on the translation,
and they appear to be different from what's in my VBA orignal.

I'll try to figure a way to post it.
let you know later tonite.


--
keepITcool
| www.XLsupport.com | keepITcool chello nl | amsterdam


Tom Ogilvy wrote :
 
T

Tushar Mehta

Persistence pays off... {grin}

Using XL97 it took about 5 seconds to find 'Guidelines for naming
cells, formulas, and constants in Microsoft Excel'. Knowing that MS
uses the keyword 'guideline', I found the same information in XL2003
except it is no longer a standalone topic but instead embedded in
'About labels and names in formulas '

Guidelines for names
What characters are allowed? The first character of a name must be a
letter or an underscore character. Remaining characters in the name can
be letters, numbers, periods, and underscore characters.

Can names be cell references? Names cannot be the same as a cell
reference, such as Z$100 or R1C1.

Can more than one word be used? Yes, but spaces are not allowed.
Underscore characters and periods may be used as word separators=3F for
example, Sales_Tax or First.Quarter.

How many characters can be used? A name can contain up to 255
characters.

Note If a name defined for a range contains more than 253 characters,
you cannot select it from the Name box.

Are names case sensitive? Names can contain uppercase and lowercase
letters. Microsoft Excel does not distinguish between uppercase and
lowercase characters in names. For example, if you have created the
name Sales and then create another name called SALES in the same
workbook, the second name will replace the first one.


--
Regards,

Tushar Mehta
www.tushar-mehta.com
Excel, PowerPoint, and VBA add-ins, tutorials
Custom MS Office productivity solutions
 
T

Tushar Mehta

FWIW...

As usual, the only documentation is of intent and limitations. In this
case, that is substantial. The actual code is miniscule {bg}

Option Explicit
'Need a reference to MS VBScript Regular Expressions 5.5
Private Sub InitRE(ByRef aRE As RegExp)
If aRE Is Nothing Then Set aRE = New RegExp
aRE.Global = True
aRE.IgnoreCase = True
End Sub
Function ValidCellReference(aStr As String, ByRef aRE As RegExp)
'This function is limited in its capability; it only _
distinguishes between an XL name and a possible cell reference _
that has already met the test for a sytantically valid name. _
Hence, aStr is presumed to have no $ or [ or ] or -
'Also see comment for FoundName function
Const ValidCellRCPattern As String = "^(R\d+)?(C\d+)?$"
'should actually use a variable and use the _
international codes for R and C
Const ValidCellA1Pattern = "^([a-h][a-z]*|i[a-v]|[i-z])\d*"
'Note this pattern only works as long as MS doesn't increase _
# columns.
'A 'trick' that seems to work is to convert the string from _
xlR1C1 to xlA1. _
If it is not a valid reference, the result is the string itself. _
If the string is a valid A1 reference, the result is the string _
itself but *in* single quotes. _
Otherwise XL converts it into a valid A1 reference. _
Now, all one needs to do is check for the first condition

'WARNING: This method / trick has only been confirmed empirically _
======= and that too only on XL2003

ValidCellReference = Not ( _
Application.ConvertFormula(aStr, xlR1C1, xlA1) = aStr)
'hopefully, ConvertFormula is aware of international _
conventions
End Function
Function FoundName(aStr As String)
'See XL help for the definition of a valid name; it basically _
starts with a _ or a letter and includes any combination of _
_ or letter or digit or period. _
However, it cannot be a cell reference in either A1 or R1C1 _
reference style. The first part is easy (see the _
ValidNameSyntaxPattern constant. The 2nd part, at first, appears _
more difficult because even after we parse the string into its _
components we need to check if a number, if present at the _
expected position(s) is between 1 and, as appropriate, the max. _
number of rows/columns allowed. However, a trick allows great _
simplification; see the comment in ValidCellReference

Static aRE As RegExp
Const ValidNameSyntaxPattern As String = _
"^[_a-zA-Z][_a-zA-Z0-9.]*$"
InitRE aRE
aRE.Pattern = ValidNameSyntaxPattern
If aRE.Test(aStr) Then
FoundName = Not ValidCellReference(aStr, aRE)
Else
FoundName = False
End If
End Function
Sub testit()
MsgBox FoundName("__9aN.909ame")
MsgBox FoundName("090abc")
MsgBox FoundName("r[-1]c") & "," & FoundName("r1c1") _
& "," & FoundName("r65536c1") & "," & FoundName("r65537c1")
MsgBox FoundName("rc") & "," & FoundName("iv65536") _
& "," & FoundName("iv65537")
End Sub


--
Regards,

Tushar Mehta
www.tushar-mehta.com
Excel, PowerPoint, and VBA add-ins, tutorials
Custom MS Office productivity solutions

Here is a cleaned up version:

Const sINV1 = "[.0-9=3F^~T?¯?·?[?]*"
Const sINVn = "*[!0-9A-z.\_f=3F=3F=3F=3F=3F=3F=3Fªµ" & _
"ºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕ" & _
"ÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíî" & _
"ïðñòóôõöøùúûüýþ=3F=3F^~T?¯?·?[?]*"

Function NameIsInvalid(ByVal _
sFull As String) As Boolean

Dim sText$, bRes As Boolean

If InStrB(sFull, "!") Then
sText = fnSplice(sFull)(1)
Else
sText = sFull
End If
If Not sText Like sINV1 Then
If Not sText Like sINVn Then
bRes = True
End If
End If
If bRes Then
If Not UCase$(sText) Like "*[!0-9RC" & _
Application.International( _
xlUpperCaseRowLetter) & _
Application.International( _
xlUpperCaseColumnLetter) & "]*" Then
If CStr(Application.ConvertFormula(sText, _
xlR1C1, , xlRelative)) <> sText Then
bRes = False
GoTo theExit
End If
End If

If sText Like "[A-z]*#" Then
If IsNumeric(MidB$(sText, 3)) Or _
IsNumeric(MidB$(sText, 5)) Then
If IsObject(Evaluate(sText)) Then
bRes = False
GoTo theExit
End If
End If
End If
End If
theExit:
NameIsInvalid = Not bRes
End Function


Function fnSplice(sName As String) As String()
Dim s(0 To 1) As String, i%

i = InStrRev(sName, "!")
If i = 0 Then
s(1) = sName
Else
s(0) = Left$(sName, i - 1)
s(1) = Mid$(sName, i + 1)
End If

fnSplice = s
End Function
 
K

keepITcool

Tushar

while you're at it :)

Another limit is length:

... total names length (including optional sheet prefix ) cannot exceed
256 chars.

ok:
ActiveWorkbook.Names.Add String(256, "a"), "1"
ok:
ActiveSheet.Names.Add String(256 - Len(ActiveSheet.Name), "b"), "1"
FAIL:
ActiveSheet.Names.Add String(256 + 1 - Len(ActiveSheet.Name), "c"), "1"

Also note that vbscript RegEX pattern [A-Za-z] will exclude extended
characters (ü é etc), which are acceptable in names.
using \w wont help either ([Equivalent to "[A-Za-z0-9_]]




--
keepITcool
| www.XLsupport.com | keepITcool chello nl | amsterdam


Tushar Mehta wrote :
FWIW...

As usual, the only documentation is of intent and limitations. In
this case, that is substantial. The actual code is miniscule {bg}

Option Explicit
'Need a reference to MS VBScript Regular Expressions 5.5
Private Sub InitRE(ByRef aRE As RegExp)
If aRE Is Nothing Then Set aRE = New RegExp
aRE.Global = True
aRE.IgnoreCase = True
End Sub
Function ValidCellReference(aStr As String, ByRef aRE As RegExp)
'This function is limited in its capability; it only _
distinguishes between an XL name and a possible cell reference _
that has already met the test for a sytantically valid name. _
Hence, aStr is presumed to have no $ or [ or ] or -
'Also see comment for FoundName function
Const ValidCellRCPattern As String = "^(R\d+)?(C\d+)?$"
'should actually use a variable and use the _
international codes for R and C
Const ValidCellA1Pattern = "^([a-h][a-z]*|i[a-v]|[i-z])\d*"
'Note this pattern only works as long as MS doesn't increase _
# columns.
'A 'trick' that seems to work is to convert the string from _
xlR1C1 to xlA1. _
If it is not a valid reference, the result is the string itself.
_ If the string is a valid A1 reference, the result is the
string _ itself but in single quotes. _
Otherwise XL converts it into a valid A1 reference. _
Now, all one needs to do is check for the first condition

'WARNING: This method / trick has only been confirmed empirically
_ ======= and that too only on XL2003

ValidCellReference = Not ( _
Application.ConvertFormula(aStr, xlR1C1, xlA1) = aStr)
'hopefully, ConvertFormula is aware of international _
conventions
End Function
Function FoundName(aStr As String)
'See XL help for the definition of a valid name; it basically _
starts with a _ or a letter and includes any combination of _
_ or letter or digit or period. _
However, it cannot be a cell reference in either A1 or R1C1 _
reference style. The first part is easy (see the _
ValidNameSyntaxPattern constant. The 2nd part, at first, appears _
more difficult because even after we parse the string into its _
components we need to check if a number, if present at the _
expected position(s) is between 1 and, as appropriate, the max. _
number of rows/columns allowed. However, a trick allows great _
simplification; see the comment in ValidCellReference

Static aRE As RegExp
Const ValidNameSyntaxPattern As String = _
"^[_a-zA-Z][_a-zA-Z0-9.]*$"
InitRE aRE
aRE.Pattern = ValidNameSyntaxPattern
If aRE.Test(aStr) Then
FoundName = Not ValidCellReference(aStr, aRE)
Else
FoundName = False
End If
End Function
Sub testit()
MsgBox FoundName("__9aN.909ame")
MsgBox FoundName("090abc")
MsgBox FoundName("r[-1]c") & "," & FoundName("r1c1") _
& "," & FoundName("r65536c1") & "," & FoundName("r65537c1")
MsgBox FoundName("rc") & "," & FoundName("iv65536") _
& "," & FoundName("iv65537")
End Sub
 
I

iainshaw

Firstly can I say what an amazing forum. This is the first time I've
looked for an Excel forum but this is amazing :)

This thread has helped me out enormously, but I was wondering if anyone
could help me out with the issue that this thread started with.

I need a routine that cycles through columns of a workbook, selects the
range that is the length of the column and gives it a name using the
contents of the first cell in the range - this is very similar to where
the first poster started. Can anyone help me on this, thanks
Iain
 
N

Nigel

You might try this to name ranges on the current worksheet, if the first row
name appears more than once then the last instance will define the range.

Sub Namer()
Dim xlc As Integer, xlr As Long
For xlc = 1 To 255
xlr = Cells(Rows.Count, xlc).End(xlUp).Row
If xlr > 1 Then ActiveWorkbook.Names.Add Name:=Cells(1, xlc), _
RefersTo:=Range(Cells(1, xlc), Cells(xlr, xlc))
Next xlc
End Sub
 
I

iainshaw

That's deeply cool, does exactly what I want and there will never be a
duplicate reference in the first row. I can only repeat, what a great
forum :)
 
I

iainshaw

I've noticed that if you redefine an existing range and give it a new
name, Excel seems to stack the names up rather than deleting the old
name. Can anyone show me how I might ammend the code above to delete
all names on an active worksheet,
thanks
 
S

STEVE BELL

Here is some general code to delete specific workbook names

Dim nme



For Each nme In ActiveWorkbook.Names

If nme.Name Like "*TABLE*" Then

nme.Delete

End If

Next


to do it on a worksheet - it might look like:

Dim nme



For Each nme In ActiveSheet.Names

If nme.Name Like "*TABLE*" Then

nme.Delete

End If

Next


to delete all names, try:

Dim nme



For Each nme In ActiveSheet.Names

nme.Delete

Next
 
I

iainshaw

Been playing around and only just got to this.

this seems to work - I'm such a dimwit, sorry


Code
-------------------

Sub CleanDown()

For Each RName In ActiveSheet.Names
RName.Delete
Next RName

End Su
 
I

iainshaw

The delete names macro above has just stopped working.....worked fine
yesterday. is there anything peculiar about names that casues them to
persist or have I screwed the code up somehow?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top