3

I have a workbook, UserFileBook, that contains the Name 'Version' which simply refers to a number (it does not refer to any range, in the Name Manager it just 'Refers to =5'). I am trying to compare this number with the version number of a different workbook. When I had UserFileBook's 'Version' as an actual named range (it referred to cell C1 which had the value of 5 in it) everything worked fine. But IdiotUser can edit that value or delete it right on the sheet, so I made it just refer to a number so it can only be edited through the manager. Is there a way for me to obtain the value of that Name and alter it from another WB now? Currently I'm trying this:

Sub CheckVersionNumber(Vers As Long)

'Checks to see if this version is compatible with the UW version
Dim wb As Workbook
Set wb = UserFileBook

Dim UWVers As Long
UWVers = wb.Names("Version").Value 'Breaks here

'Version information is in the range "Version" on UW
If UWVers < Vers Then
    GoTo LowerVersion
    
Else
    If wb.Names("Version") > Vers Then  'tried this originally and also breaks, also if .Value is added
        GoTo UpperVersion
    End If
End If

Exit Sub

I also tried comparing to wb.Range("Version"), and even wb.Worksheets("Sheet 1").Range("Version) but those didnt work either. How can I reference (and alter) the value of "Version" in the USerFileBook if it doesn't refer to a range?

J_Nyiri
  • 61
  • 6
  • Is it not just `wb.Range("Version").Value`? Also ou never define `LowerVersion` or `UpperVersion`. – BruceWayne May 12 '22 at 02:05
  • Those are defined later. All of it worked when it was an actual range, and wb.Range("Version") returned the value in the named cell, but trying it usng Range when it only refers to a number also breaks :/ For example, putting in UWVers = wb.Range("Version").Value says object doesn't support the property/method – J_Nyiri May 12 '22 at 02:18

2 Answers2

4

You cannot use .Range because Version is not a range. It's a named formula.

But you can evaluate it:

UWVers = wb.Worksheets(1).Evaluate("Version")

To update the named formula with a different value, say 999:

wb.Names.Add "Version", 999

To make the named formula invisible in the Name Manager:

wb.Names.Add "Version", 999, True

As an aside... since you are having difficulties with users changing your solution settings you may wish to explore utilizing CustomXMLParts.Add to store your Version. There is no user interface to CustomXMLParts, but they are stored in the workbook. The only way to access them is through code. A normal user will NEVER see your version number stored this way. In fact most advanced developers would never find it either.

Excel Hero
  • 14,253
  • 4
  • 33
  • 40
  • That worked! But why do I need to include a worksheet in the reference if the name (formula) isn't assigned to any range and has wb scope? I can't use UWVers =wb.Evaluate("Version"). Would it matter what worksheet I used or could I use any (i.e. just use (1) like you have since who cares what worksheet it is?) Thanks! I looked at the Microsoft documentation for evaluate and it seemed like it only returned strings. – J_Nyiri May 12 '22 at 03:34
  • Also, I still need to update the value of "Version"...how would I do that after comparing it? – J_Nyiri May 12 '22 at 03:35
  • The string is "Version" which is the argument passed to Evaluate. You can choose ANY worksheet from the target workbook. Evaluate() is a method on the worksheet object. That's why you must reference a worksheet. Every workbook must have at least one worksheet and so `wb.Worksheets(1)` is a sensible and generic approach. – Excel Hero May 12 '22 at 03:37
  • I updated the answer to include code for updating the value of `Version`. It may seem confusing to use the `.Add` method when `Version` already exists, but this is correct. What happens when the name already exists and you use `.Add` is that the old name's definition is replaced with the new one. – Excel Hero May 12 '22 at 03:44
  • I updated the answer with a suggestion worth looking into! – Excel Hero May 12 '22 at 03:58
  • Thanks! I wasn't sure if I could .Add a named formula already defined. I actually used .Value like this: Dim strngset As String strngset = "=" & Version 'this is the version# the "Version" formula was compared too wb.Names("Version").Value = strngset – J_Nyiri May 12 '22 at 03:59
  • I will dig into the XML Parts reference you gave, thanks! Still definitely very new to all this – J_Nyiri May 12 '22 at 04:00
  • You are welcome. I've been at it since Excel was first released. ;) – Excel Hero May 12 '22 at 04:03
-1

You can use wb.Names("Version").Value but it returns a string >> =999. Therefore you have to omit the equal-sign before assigning to a long value.

If you want to hide the name from the normal user, you can set the visibility of the name - when adding it the first time - to false. Then the name doesn't show up in the name manager.

I would create a function and a sub.


'---> get current version
Public Function getVersion(wb As Workbook, Optional throwError As Boolean = False) As Long
    
    On Error Resume Next    'in case version does not exist function will return 0
        
    'remove =-sign as from returned value to return a long value
    getVersion = Replace(wb.Names("Version").Value, "=", vbNullString)
    
    'if useful you could throw an error here
    If Err <> 0 And throwError = True Then
        Err.Clear: On Error GoTo 0
        Err.Raise vbObjectError, , "Version hasn't been set for this workbook"
    End If
    
    On Error GoTo 0
End Function


'--->> set version
Public Sub setVersion(wb As Workbook, newVersion As Long)

    On Error Resume Next    'in case version doesn't yet exists
    wb.Names("Version").Value = newVersion
    
    If Error > 0 Then
        Err.Clear: On Error GoTo 0
        'Version name does not yet exist --> add as invisible name
        wb.Names.Add "Version", "=" & newVersion, Visible:=False
    Else
        On Error GoTo 0
    End If

End Sub

This is how you use them:

Sub testVersionAsNameConstant()

    Debug.Print getVersion(ThisWorkbook, False)
    
    'comment this out if you don't want to see the error
    Debug.Print getVersion(ThisWorkbook, True)

    setVersion ThisWorkbook, 1
    Debug.Print getVersion(ThisWorkbook), "should be 1"
    
    setVersion ThisWorkbook, 2
    
    Dim checkValue As Long
    checkValue = 1
    Debug.Print getVersion(ThisWorkbook) > checkValue, "should be true"
    Debug.Print getVersion(ThisWorkbook) = checkValue, "should be false"
    
End Sub

Ike
  • 9,580
  • 4
  • 13
  • 29
  • I didn't know I could set the name to not be visible in the name manager either! Thanks for that tip (I'm assuming my dear Idiot.User cant even find the Name Manager but that would be a nice extra layer of security! – J_Nyiri May 12 '22 at 18:10