Вопрос:
У меня есть электронная таблица, которая будет распространена среди сотрудников; Я хочу сделать его максимально удобным для пользователя, поэтому для запуска макросов у меня есть простая кнопка, которая автоматизирует все для них. Но я не хочу, чтобы у них был доступ к запуску любого из макросов самостоятельно.
Мне это удалось, используя
Option Private Module Public Sub Run_Batch_Report() ‘The actual script that works is here, cutting it to skip to the portion that won’t work’ Call Misc_Doc MsgBox («Report finished.») End Sub
Все, что Public Sub Misc_Doc() делает, это импорт данных из другой электронной таблицы и форматирование.
А затем с помощью кнопки Command, вызывающей модуль через application.run
Private Sub CommandButton1_Click() Application.Run «Batching_Module.Run_Batch_Report» End Sub
Выполнение подобных работ; так как в нем, похоже, работает подпрограмма Run_Batch_Report просто отлично, но этот юг также вызывает другие субтитры в одном модуле для завершения задания. Эти субмастеры не будут работать БЕЗ РАЗГРУЗКИ VB в настройках разработчиков для просмотра и редактирования. Возможно ли, чтобы подпрограммой полностью (включая вызов других подсайтов внутри одного модуля), или мне пришлось бы реструктурировать мой юг, чтобы включить в него все остальные подписи, которые он вызывает?
Извините, если я сформулировал это случайно – я на самом деле посреди встречи и жонглирования этим, слушая боссов.
Изменение: Чтобы уточнить, я заблокировал VB от просмотра. Когда я запускаю скрипт, пока он все еще заблокирован, он не позволит субпользователю вызывать другие части модуля. Когда мой пароль введен для разблокировки VB для просмотра, он работает.
Лучший ответ:
Предполагая, что “но я не хочу, чтобы у них был доступ к запуску каких-либо макросов самостоятельно” означает “Я не хочу, чтобы макросы были перечислены в окне” Макросы “, у вас уже есть это.
Я не могу воспроизвести ваш “макрос не запускается, если проект не разблокирован”, с использованием или без Application.Run Запустите участие, не уверен, что это значит. В любом случае, похоже, вы испытываете ложное впечатление о том, что защита паролем вашего проекта дает ему какую-либо защиту. Это не так.
Код VBA не безопасен. Защита паролем проекта VBA – это буквально шутка, это только раздражает dev (вы!) И предотвращает незнакомых пользователей, которые в любом случае не знали, что делать с VBE, от просмотра исходного кода, который они все равно не понимают – и если кто-то хочет видеть код, поверьте мне, они будут – в считанные секунды.
Если кто-то может открыть документ хоста, он может получить код VBA.
Либо пользователь может запустить макрос, либо не может. Если пользователь может нажать кнопку, чтобы вызвать код VBA, тогда у них есть разрешение на вызов этого кода VBA из любого места.
Имейте “скрытые” макросы в стандартном модуле (.bas) с дополнительным Option Private Module:
Option Private Module Option Explicit Public Sub SomeHiddenMacro() MsgBox «Hi» End Sub
И тогда вы все равно можете присвоить этот макрос какой-либо форме, набрав имя макроса (оно не будет указано в списке, поскольку Option Private Module):
Нажмите кнопку, чтобы увидеть, как она работает:
Формы можно отформатировать, чтобы выглядеть намного красивее, чем любая кнопка ActiveX:
Это не должно быть более сложным, чем это.
Отличное решение
Вы начинаете с VBA, поэтому я предполагаю, что вы не много играли с модульными модулями. Одна из приятных вещей в модулях классов заключается в том, что их публичные члены не могут быть вызваны как макросы, поскольку во время выполнения модули классов не существуют – это типы, а не модули. Для типа, означающего что-либо, его нужно создать, а макро-бегун этого не делает.
Поэтому поставьте “рабочий” код в модуле класса, скажем BatchReport:
Option Explicit Public Sub Run() ‘TODO: do your thing End Sub
Теперь в макросе, прикрепленном к кнопке (или в кнопке ActiveX Click handler), все, что вы делаете, это создать экземпляр этого объекта с ключевым словом New и вызвать его метод Run:
Option Private Module Option Explicit Public Sub RunBatchReport() With New BatchReport .Run End With End Sub
Здесь у меня есть привязка With блокировкой объекта. В качестве альтернативы вы могли бы объявить объектную переменную и Set ее ссылку на New экземпляр класса BatchReport:
Option Private Module Option Explicit Public Sub RunBatchReport() Dim report As BatchReport Set report = New BatchReport report.Run End Sub