2009-08-05 5 views
0

Я немного смущен о масштабах именованных диапазонов в Excel. У меня две версии книги excel. Иногда пользователям приходится копировать данные из старой версии книги в более новую версию. Существуют некоторые пользовательские функции VBA, используемые в большинстве вычислений ячейки. Каждая из этих функций просматривает от 4 до 12 названных диапазонов на листе. Это, казалось, хорошо работает ... Однако недавно я узнал, что, когда открываются две версии файла, ссылки VBA на все именованные диапазоны возвращают значения только из первого открытого файла (поэтому, если более новая версия форма была открыта сначала, тогда старшая версия будет действовать, как некоторые из ее данных поступают из новой версии!). Именованные диапазоны из второго файла, по-видимому, игнорируются вторым файлом, по крайней мере, в коде VBA, если оба файла остаются открытыми. Если я закрою книгу, которая была открыта первой, вторая будет правильно подсчитываться.Повторяющиеся именованные диапазоны между книгами заставляют мои пользовательские функции запутываться

Я нашел частичное исправление: вместо того, чтобы сделать это:

Blah = Range("valueXYZ").Value 

Я делаю это вместо:

Blah = ThisWorkbook.Names("namedCellXYZ").RefersToRange.Value 

Это прекрасно работает, но только на более новую версию книги. Я не могу обновить код VBA в старой версии книги. Это означает, что если клиенты открывают старую версию после того, как новая версия уже открыта, (так что оба они открыты, но старый был открыт второй), старая версия будет получать значения и именованные диапазоны от более новой версии - и таким образом, сообщают о неправильных номерах и диапазонах. Это плохо. Мне нужен хороший способ предотвратить доступ старого листа к именованным диапазонам из нового, но я могу только изменить новый. Единственное, о чем я могу думать, это переименование всех названных диапазонов и обновление большого количества кода VBA в новой версии - что-то, что подвержено ошибкам и звучит как чрезмерная работа.

Любые предложения? Например, возможно ли хотя бы показать пользователю предупреждение при открытии второго файла? Или можно использовать VBA для ограничения объема названных диапазонов? Любые другие идеи?

ответ

1

Вы можете попробовать обработать WorkbookOpen Event в окне кода «ThisWorkbook». Когда открыта новая версия рабочей книги, вы можете просмотреть все открытые книги и посмотреть, есть ли в списке старые версии. Если да, предупредите пользователя о том, что значения в старой версии электронной таблицы могут быть неверными, поскольку данные считываются с более новой версии.

+0

Хорошая идея. Тем не менее, мне не удается запустить этот обработчик событий. –

+0

Я получил его работу - мне пришлось перезапустить excel, чтобы начать работу. Благодаря!!В качестве интересной заметки, насколько я могу судить, более новая версия не нуждается в проверке уже открытых книг - первая открытая книга всегда имеет приоритет (так что если старшая версия открывается сначала, то именованные диапазоны работают правильно для него, и новая версия спроектирована правильно, так что она работает) (Таким образом, это только проблема, если старые версии открываются второй). Поэтому мне нужно только настроить функцию проверки книг, которые открываются после наиболее обновленной. –

+0

Да, это имеет смысл. Если пользователь открывает «Старый», то «Новый», «Старый» будет ссылаться на «Старый» (сначала открыт), а «Новый» будет ссылаться на «Новые» (полностью квалифицированные ссылки), поэтому проблем нет. Если пользователь открывает New, затем Old, пользователь должен быть предупрежден. Если вы хотите пойти еще дальше, вы можете показать предупреждение, а затем спросить пользователя, нормально ли закрыть и снова открыть New, чтобы решить проблему. Если в New есть несохраненные изменения, пользователю необходимо либо сохранить, не сохранить, либо отменить. – devuxer

0

[Редактировать]

Эта подпрограмма будет сообщать вам, если у вас есть повторяющиеся именованные диапазоны в любых открытых рабочих книг. Как сказал DanThMan, вы можете обратиться к нему в модуле ThisWorkbook объекта:

Sub CheckRangeDups() 
    Dim wb As Workbook 
    Dim nm As Name 
    Dim count As Integer, i As Integer 
    Dim arrNm() As String 
    Dim dup As Boolean 
    Dim rngChk As Range 

    ReDim arrNm(0) 
    'cycle through workbooks' 
    For Each wb In Workbooks 
     'cycle through names in workbook' 
     For Each nm In wb.Names 
      'check if name refers to a range' 
      On Error Resume Next 
      Set rngChk = Nothing 
      Set rngChk = nm.RefersToRange 
      On Error GoTo 0 
      If Not rngChk Is Nothing Then 
       dup = False 
       'check if name in array of names' 
       For i = 0 To UBound(arrNm) 
        If nm.Name = arrNm(i) Then 
         MsgBox "Named range " & nm.Name & " duplicated." 
         dup = True 
         Exit For 
        End If 
       Next i 
       'if not then add it' 
       If Not dup Then 
        arrNm(count) = nm.Name 
        count = count + 1 
        ReDim Preserve arrNm(count) 
       End If 
      End If 
     Next nm 
    Next wb 
End Sub 

[/ Edit]

Если я правильно Вас понял, в полной мере квалифицировать ваши ссылки на диапазоны будут решить вашу проблему. Пример: при открытии двух файлов с именами file1 и file2 имя ячейки A1 на листе 1 «arange» в обоих файлах. В file1 введите «file1» в ячейку, в файл2 введите «file2» в ячейку. Теперь запустите это:

Sub whichRange() 
    Dim f1 As Workbook, f2 As Workbook 
    Set f1 = Workbooks("file1.xls") 
    Set f2 = Workbooks("file2.xls") 
    Dim s1 As Worksheet, s2 As Worksheet 
    Set s1 = f1.Worksheets(1) 
    Set s2 = f2.Worksheets(1) 

    Dim r1 As Range, r2 As Range 
    Set r1 = s1.Range("arange") 
    Set r2 = s2.Range("arange") 

    Debug.Print "WB: "; f1.Name; " cell: "; r1.Name; " contents: "; r1 
    Debug.Print "WB: "; f2.Name; " cell: "; r2.Name; " contents: "; r2 
End Sub 

Полная квалификация позволяет Excel знать, о чем вы говорите.

+1

Полностью квалифицировать все имена, безусловно, будет хорошей идеей для всех будущих версий, но если я правильно понимаю OP, есть уже старая версия с макросами, которые нельзя изменить (они уже находятся на машине пользователя). – devuxer

+0

Я уже описал, как я по существу делаю то же самое для новой версии книги. См. Второй пример кода, который я вставил выше - мой пример кода имеет дополнительный бонус, который не зависит от знания рабочего листа, на котором находится именованный диапазон. Также, DanThMan прав - мне нужно что-то, чтобы работать на меня задним числом или, по крайней мере, предупреждать пользователей о проблеме. –

+0

Я уже могу проверить переопределенные именованные диапазоны с помощью «if Range (« nameXYZ »). Значение <> ThisWorkbook.Names (« nameXYZ »). RefersToRange.Value« в цикле for on »для каждого nm в thisworkbook.names». И еще раз, я просто не могу сделать эту работу ретроактивно, и, наконец, я повторяю, что второй пример кода в моем исходном сообщении обходит проблему в более новой версии - поэтому мне НЕ НУЖНО обнаруживать дубликаты. Другими словами, я ценю ваши усилия, но вы не решаете правильную проблему. –

Смежные вопросы