Lost your password?


Хитрости »
Основные понятия (27)
Сводные таблицы и анализ данных (10)
Графики и диаграммы (5)
Работа с VB проектом (12)
Power BI и Power Query (23)
Условное форматирование (5)
Списки и диапазоны (5)
Макросы(VBA процедуры) (68)
Разное (43)
Баги и глюки Excel (5)

Как защитить лист от пользователя, но не от макроса?

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

Sub Write_in_ProtectSheet()
    'снимаем защиту с листа
    Worksheets("Лист1").Unprotect
    'если лист защищен с паролем 1234: Worksheets("Лист1").Unprotect "1234"
    'действия на листе.Например,изменение значения ячейки А1
    Cells("A1").Value = "www.excel-vba.ru"
    'устанавливаем защиту на лист
    Worksheets("Лист1").Protect
    'если лист был защищен с паролем 1234: Worksheets("Лист1").Protect "1234"
End Sub

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

Sub Protect_for_User_Non_for_VBA()
    ActiveSheet.Protect Password:="1111", UserInterfaceOnly:=True
End Sub

Основную роль здесь играет параметр UserInterfaceOnly. Если его установить в True, то это говорит Excel-ю, что коды VBA могут выполнять действия по изменению ячеек, не снимая защиты методом Unprotect. Однако сама защита листа при этом не снимается и вручную изменить данные ячеек, не сняв защиту с листа, невозможно.
Код выше устанавливает такую защиту только на активный лист книги. Но можно указать лист явно(например установить защиту на лист с именем Лист1 в активной книге и лист, идущий вторым по порядку в книге(Sheets(2))):

Sub Protect_for_User_Non_for_VBA()
    Sheets(2).Protect Password:="1111", UserInterfaceOnly:=True
    Sheets("Лист1").Protect Password:="1111", UserInterfaceOnly:=True
End Sub

Так же приведенный код можно еще чуть модернизировать и разрешить пользователю помимо изменения ячеек еще и использовать автофильтр:

Sub Protect_for_User_Non_for_VBA()
    Sheets(2).Protect Password:="1111", UserInterfaceOnly:=True
    'на лист "Лист1" поставим защиту и разрешим пользоваться фильтром
    Sheets("Лист1").Protect Password:="1111", AllowFiltering:=True, UserInterfaceOnly:=True
End Sub

Можно разрешить и другие действия(выделение незащищенных ячеек, выделение защищенных ячеек, форматирование ячеек, вставку строк, вставку столбцов и т.д. Чуть подробнее про доступные параметры можно узнать в статье Защита листов и ячеек в MS Excel). А как будет выглядеть строка кода с разрешенными параметрами можно узнать, записав макрорекордером установку защиты листа с нужными параметрами:

После этого получится строка вроде такой:

ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
        , AllowInsertingColumns:=True, AllowInsertingRows:=True, AllowFiltering:=True

здесь я разрешил использовать автофильтр(AllowFiltering:=True), вставлять строки(AllowInsertingRows:=True) и столбцы(AllowInsertingColumns:=True).Чтобы добавить возможность изменять данные ячеек только через код VBA, останется добавить параметр UserInterfaceOnly:=True:

ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
        , AllowInsertingColumns:=True, AllowInsertingRows:=True, AllowFiltering:=True, UserInterfaceOnly:=True

и так же неплохо бы добавить и пароль для снятия защиты, т.к. запись макрорекордером не записывает пароль:

ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
        , AllowInsertingColumns:=True, AllowInsertingRows:=True, AllowFiltering:=True, UserInterfaceOnly:=True, Password:="1111"

Этот метод всем хорош, все отлично, но. Параметр UserInterfaceOnly сбрасывается сразу после закрытия книги. Т.е. если установить таким образом защиту на лист и закрыть книгу, то при следующем открытии защиты этой уже не будет - останется лишь стандартная защита. Поэтому, если необходимо такую защиту видеть постоянно, то данный макрос лучше всего прописывать на событие открытия книги(модуль ЭтаКнига(ThisWorkbook)).
Сделать это можно таким кодом:

Private Sub Workbook_Open()
    Sheets("Лист1").Protect Password:="1111", UserInterfaceOnly:=True
End Sub

Этот код сработает только после того, как книга будет открыта. А это значит, чтобы увидеть результат необходимо после записи этого кода в ЭтаКнига сохранить книгу, закрыть её и открыть заново. Тогда в сам момент открытия книги код сработает и установит на "Лист1" правильную защиту.

Часто так же бывает необходимо устанавливать одинаковую защиту на все листы книги. Сделать это можно таким кодом, который так же должен быть размещен в модуле ЭтаКнига(ThisWorkbook):

Private Sub Workbook_Open()
    Dim wsSh As Object
    For Each wsSh In Me.Sheets
        Protect_for_User_Non_for_VBA wsSh
    Next wsSh
End Sub
Sub Protect_for_User_Non_for_VBA(wsSh As Worksheet)
    wsSh.Protect Password:="1111", UserInterfaceOnly:=True
End Sub

Плюс во избежание ошибок лучше перед установкой защиты снимать ранее установленную(если она была):

Sub Protect_for_User_Non_for_VBA(wsSh As Worksheet)
    wsSh.Unrotect "1111"
    wsSh.Protect Password:="1111", UserInterfaceOnly:=True
End Sub

Ну и если надо такую защиту установить только на конкретные листы, то убираем цикл и вызываем процедуру только для нужных листов. Если известны их имена, то можно прибегнуть к использованию массивов:

Private Sub Workbook_Open()
    Dim arr, sSh
    arr = Array("Отчет", "База", "Бланк")
    For Each sSh in arr
        Protect_for_User_Non_for_VBA Me.Sheets(sSh)
    Next
End Sub
Sub Protect_for_User_Non_for_VBA(wsSh As Worksheet)
    wsSh.Protect Password:="1111", AllowFiltering:=True, UserInterfaceOnly:=True
End Sub

Для применения в своих задачах в данном коде необходимо лишь изменить(добавить, удалить, вписать другие имена) имена листов в этой строке: Array("Отчет", "База", "Бланк")

Примечание: Метод защиты через UsefInterface всем хорош, но есть одно ограничение: метод невозможно использовать в книге с общим доступом(Рецензирование -Доступ к книге), т.к. при общем доступе существуют ограничения, среди которых и такое, которое запрещает изменять параметры защиты для книги в общем доступе.

Также см.:
Как разрешить изменять только выбранные ячейки?
Защита листов/снятие защиты
Как оставить возможность работать со структурой на защищенном листе?


Статья помогла? Поделись ссылкой с друзьями!
  Плейлист   Видеоуроки

Поиск по меткам

Access apple watch Multex Power Query и Power BI VBA управление кодами Бесплатные надстройки Дата и время Записки ИП Надстройки Печать Политика Конфиденциальности Почта Программы Работа с приложениями Разработка приложений Росстат Тренинги и вебинары Финансовые Форматирование Функции Excel акции MulTEx ссылки статистика
Обсуждение: 63 комментария
  1. sr. Pomidor:

    Коллеги.

    С листами все понятно, очень помогло, но возможно ли сделать так, что бы пользователь файла не мог попасть в VBA и испортить макрос или вскрыть скрытые листы???

    Заранее спасибо.

  2. Алексей:

    @sr. Pomidor
    Добрый день.
    Защита на VBA ставится: Alt+F11 -> Tools -> Properties -> Protection.
    И обязательно ставьте галку на Lock project for viewing.
    +чтобы нельзя было вскрыть скрытые листы, я дополнительно использую защиту книги.
    Хотя, все пишут, что от грамотных рук эта защита не работает.
    Но против обычных юзеров сгодится. )))

    • Кирилл:

      Алексей, прям то что нужно. Только половина макросов перестает работать. Из-за чего так происходит? Подскажите

  3. Goody:

    Хранить пароль в теле макроса не есть хорошая идея... Открыть книгу в OpenOffice и посмотреть макрос на предмет паролей самое первое что пришло в голову.
    А вот как не через макрос, а с помощью интерфеса MS Excel защитить лист но сразу с параметром UserInterfaceOnly:=True ?

  4. Александр:

    Можно ли защитить какую нибудь информацию зависящую от даты на следующем листе (например после 03 февраля 2014г. данные за январь будут защищены)?

  5. Виктор:

    Добрый День! Спасибо Вам за статью!
    Установил защиту как Вы описывали, всё работало. А теперь, после доработки таблицы-добавлял макрос-кнопку и т.п. и теперь после сохранения и вновь открытия файла макросы не выполняются-так как стоит защита листа...хотя раньше работали(когда только прописал защиту как Вы описали). Помогите, на что обратить внимание? из-за чего защита после закрытия файла не снимается, а остается? и мешает выполнять макросы...

    • Виктор, после закрытия файла защита и не должна сниматься. По крайней мере в статье этого нет. Тут именно установка защиты с параметром UserinterfaceOnly.
      А причина может быть одна - код прописан не в модуле книги, а где-то в другом месте.

      • viktor595:

        Дмитрий! Пожалуйста! поможете посмотреть мой файл, почему-то при повторном открытии макросы не работают-пишет защищенный лист! https://yadi.sk/d/UI760JmRcUWAK

        • Я посмотрел. Но у меня нет времени разбираться в Вашем проекте и искать где не работает. Напишите что необходимо сделать и на каком листе, чтобы добиться ошибки.
          Проставление галок у меня работает. И после первого запуска файла и после повторного.

          • viktor595:

            на появляющемся UserForm1 кнопка "очистить всю таблицу", так же при выборе другого значения на листе ком-ка в выпадающем списке ячейка Z8

  6. Виктор, надо же и логически подходить к построению кодов.
    У Вас сначала показ формы, а затем установка защиты предложенным в статье кодом. Поэтому и ошибка при очистке. Поменяйте местами:

    Private Sub Workbook_Open()
        Dim wsSh As Object
        For Each wsSh In Me.Sheets
            Protect_for_User_Non_for_VBA wsSh
        Next wsSh
        UserForm1.Show
    End Sub

    А вып.списки не имеют отношения к макросам и поэтому значение изменить не получится в защищенной ячейке. Для этой ячейки просто установите свойство "Защищаемая ячейка" в ЛОЖЬ(снять галку в соответствующем пункте в Формате ячеек-вкладка Защита)

  7. viktor595:

    Дмитрий! Спасибо Вам большое! Я уже всю голову сломал!

  8. Михаил:

    Уважаемый Дмитрий, подскажите, пожалуйста, а можно ли проверить наличие защиты листа? Листов в книге много, некоторые нуждаются в защите, некоторые нет, хотелось бы при запуске проверять защиту и, если необходимо, устанавливать её.

  9. Михаил:

    Извините, Дмитрий, не разобрался как оформлять код VBA, поэтому привожу свои процедуры как они есть.
    Может кому-нибудь пригодятся. Это проверка наличия защиты и выключение её по паролю (включение без пароля):

    Private Sub CB_R2_Click()
    ' Проверка включения защиты
    Dim S_Psw As String
    If ActiveSheet.ProtectContents Then
    ' Ввод пароля
       S_Psw = InputBox("Пожалуйста, введите пароль:", "Подверждение доступа")
       If S_Psw  Sheets("DATA").Cells(1, 15) Then
    ' Пароль не верен, выход из процедуры
          MsgBox "Извините, пароль не верен!", , "О Ш И Б К А"
          Exit Sub
       End If
    End If
    ' Запуск процедуры включения/выключения защиты
    Switch_Protect
    End Sub
     
    'И, собственно, процедура Switch_Protect:
     
    Public Sub Switch_Protect()
    ' Включение/выключение защиты
    Dim N_Cnt As Integer
    If ActiveSheet.ProtectContents Then
    ' Выключение защиты листов
       For N_Cnt = 1 To ThisWorkbook.Sheets.Count
           With Sheets(N_Cnt)
                .Unprotect ("123")
           End With
       Next
       MsgBox "Защита снята!"
    Else
    ' Включение защиты листов
       For N_Cnt = 1 To ThisWorkbook.Sheets.Count
           With Sheets(N_Cnt)
                .Unprotect ("123")
                .Protect Password:="123", UserInterfaceOnly:=True
           End With
       Next
       MsgBox "Защита установлена!"
    End If
    End Sub
  10. ИГОРЬ:

    Есть ли для openoffice.org аналог метода "ActiveSheet.Protect Password:="1111", UserInterfaceOnly:=True"

Поделитесь своим мнением

Комментарии, не имеющие отношения к комментируемой статье, могут быть удалены без уведомления и объяснения причин. Если есть вопрос по личной проблеме - добро пожаловать на Форум


Для оформления сообщений Вы можете использовать следующие тэги:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Тренинги

Заказать
Юридическая информация

Использование материалов сайта

Политика Конфиденциальности

ИП Щербаков Дмитрий Валентинович
ОГРНИП: 318502700083307
ИНН: 504013350772

Наши партнеры

Перейти

Счетчики

Рейтинг@Mail.ru Яндекс.Метрика
© 2024 Excel для всех   Войти