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. Всем Добрый день, очень странный момент. Excel 2003. Если устанавливаю значение EnableSelection через код:
    ActiveSheet.EnableSelection = xlUnlockedCells
    То при сохранении файла и повторном открытии значение данного параметра скидывается. Все ячейки доступны для выбора.

    Если же это делаю через интерфейс excel(сервис ->установить защиту) то все нормально. После закрытия/открытия всё сохраняется.

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

    ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
    ActiveSheet.EnableSelection = xlUnlockedCells

    Так же пробую именно этим кодом установить недоступность для выделения, свойство устанавливается, но после сохранение/закрытия/повторного открытия так же сбрасывается на ноль (все ячейки доступны для выделения).

    В excel 2007 таких проблем нет. Всё корректно сохраняется.
    Может быть у кого то есть мысли по данной ситуации? Благодарю за помощь.

  2. Нашел ответ, может кому пригодиться. Данный баг возникает в локализованной версии excel 2003 без сервис пака. Установка SP3 решила проблему. Нашел пользователей с подобной проблемой на другом ресурсе.

  3. Влад:

    А как можно защитить только отдельные листы из всей книги?

    • Влад, вызывайте процедуру защиты(Protect_for_User_Non_for_VBA) несколько раз, передавая в неё нужный лист по очереди. Или цикл по листам с проверкой на имя. Все зависит от ситуации и имен листов.

  4. Глеб:

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

    Private Sub Workbook_Open()
    'включаем защиту первого листа для пользователя, но не макроса
    Worksheets("Лист1").Protect Password:="123", UserInterfaceOnly:=True
    End Sub
    Помогите решить проблему за ранее спасибо!

  5. Влад:

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

    • Потому что комментарии - это объекты. И они несколько отдельный элемент защиты. При установке защиты разрешите изменение объектов и все будет работать.

  6. Мари:

    Дмитрий, дорый день, благодарю за полезную информацию, а подскажите, пож-та, возможно ли сделать так, чтобы защита работала следующим образом: формулы были скрыты, но при этом оставалась возможность не только добавления столбцов и работы с группированными данными, но и возможность удаления столбцов? или это невозможно решить в рамках VBA? не могу найти подходящий макрос в интернете(

    Option Explicit
    Private Sub Workbook_Open()
        Dim wsSh As Worksheet
        Set wsSh = Me.Sheets("рынок")
        wsSh.EnableOutlining = True 
        wsSh.Protect Password:="978", UserInterfaceOnly:=True, AllowFormattingCells:=True, AllowFormattingColumns:=True, AllowFormattingRows:=True, AllowInsertingColumns:=True, AllowInsertingRows:=True, AllowInsertingHyperlinks:=True, AllowDeletingColumns:=True, AllowDeletingRows:=True, AllowSorting:=True, AllowFiltering:=True, AllowUsingPivotTables:=True
    End Sub

    вот этот не работает так как нужно(

    Заранее благодарю за Ваш ответ, Маша

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

  7. Вероника:

    Добрый день! А подскажите такую же команду только для Word. Здесь нет данной программы и функция не работает.

    • Вероника, в Word защита совершенно иначе работает и там просто нет аналогичной возможности.

      • Вероника:

        Но как же тогда обеспечить работу макросов в защищенном режиме? Это вообще не возможно в word?

        • Вероника, во-первых непонятно, какую защиту Вы применяете в Word. От этого многое зависит. Во-вторых: можно кодом сначала снять защиту, потом поставить обратно. В Word также для документа есть методы Protect и UnProtect со своими параметрами. Их можно также просмотреть, записав макрорекордером установку защиты с нужными параметрами.

  8. saa:

    Добрый день! Дмитрий,вышеописанный Вами способ по защите от редактирования прекрасно работает. Но. Как быть если это все нужно реализовать в книге с общим доступом? Это возможно?

    • Обратите внимание на примечание в конце статьи. Там я четко написал, что при общем доступе данный метод использовать не получится.

      • saa:

        Спрошу по-другому. Существует-ли способ добиться того же результата в книге с общим доступом? Или это в принципе невозможно?

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

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


Для оформления сообщений Вы можете использовать следующие тэги:
<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 для всех   Войти