Сохранение нового документа Excel в виде книги без макросов без подсказки
Я использую Excel 2010. У меня есть макрос с поддержкой макроса Excel, который имеет подключение к текстовому файлу, которое настроено на автоматическое обновление при создании нового документа с помощью этого шаблона.
Следующий макрос находится в объекте "ThisWorkbook" для удаления подключения к данным перед сохранением нового документа:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Do While ActiveWorkbook.Connections.Count > 0
ActiveWorkbook.Connections.Item(ActiveWorkbook.Connections.Count).Delete
Loop
End Sub
Когда пользователь нажимает значок сохранения/хиты ctrl + S, вводит имя файла, а затем нажимает кнопку "Сохранить", чтобы сохранить его как книгу без макросов Excel (как и значение по умолчанию и требуемый тип файла), им будет предложено сообщение с сообщением:
Следующие функции не могут быть сохранены в книгах без макросъемки:
• Проект VB
Чтобы сохранить файл с этими функциями, нажмите "Нет", а затем выберите тип файла с поддержкой макроса в списке "Тип файла".
Чтобы продолжить сохранение в виде книги без макросов, нажмите "Да".
Возможно ли предотвратить появление этого сообщения и заставить Excel предположить, что пользователь хочет продолжить работу с книгой без макросов?
Я искал все и понимаю, что я могу добавить код к объекту книги, который удаляет себя, чтобы у Excel не было проекта VB, чтобы вызвать это сообщение, но для этого потребуется, чтобы каждый пользователь менял настройки центра доверия (доверять доступу к Объектная модель проекта VBA), которую я хочу избежать.
Я также видел предложения по использованию:
Application.DisplayAlerts = False
но не может заставить это работать. Кажется, что каждый пример этого использования находится внутри суб, который также обрабатывает сохранение документа, тогда как в моей ситуации SubSave заканчивается до того, как документ будет сохранен в стандартном, не-vba способе, который, возможно, почему он не работает?
Сбрасывает ли это свойство значение по умолчанию True после того, как sub закончил/до того, как на самом деле произойдет сохранение?
Извиняюсь за любую бессмыслицу, которую я, возможно, отказался, мой опыт работы с VBA очень ограничен.
Ответы
Ответ 1
Я не могу тестировать Excel 2010, но, по крайней мере, на 2016 год, он работает нормально:
Sub SaveAsRegularWorkbook()
Dim wb As Workbook
Dim Path As String
Set wb = ThisWorkbook
Path = "T:\he\Path\you\prefer\"
Application.DisplayAlerts = False
Application.EnableEvents = False
wb.SaveAs Filename:=Path & "Test.xlsx", FileFormat:=51
Application.DisplayAlerts = True
Application.EnableEvents = True
End Sub
Попробуйте.
Ответ 2
Разный подход... когда шаблон загружен, требуется, чтобы пользователь сохранил его (у меня есть рабочая книга/шаблон с аналогичной ситуацией...). Это должно открыть их в папке "Документы пользователя", хотя вы можете настроить ее для сохранения в любом месте.
Внутри модуля ThisWorkbook поставьте:
Option Explicit
Private Sub Workbook_Open()
Dim loc As Variant
Application.DisplayAlerts = False
loc = Application.GetSaveAsFilename(FileFilter:="Excel Files (*.xlsx), *.xlsx", Title:="Save As...", InitialFileName:="%USERPROFILE%\Documents\NAME_OF_FILE")
If loc <> False Then
ActiveWorkbook.SaveAs Filename:=loc, FileFormat:=51
Exit Sub
End If
Application.DisplayAlerts = True
End Sub
Edit1: добавление оператора if с использованием имени базового шаблона, поэтому последующие сохранения не запрашивают save-as:
Option Explicit
Private Sub Workbook_Open()
If ActiveWorkbook.Name = "_NAME_OF_FILE.xlsb" Then
Dim loc As Variant
Application.DisplayAlerts = False
loc = Application.GetSaveAsFilename(FileFilter:="Excel Files (*.xlsx), *.xlsx", Title:="Save As...", InitialFileName:="%USERPROFILE%\Documents\_NAME_OF_FILE")
If loc <> False Then
ActiveWorkbook.SaveAs Filename:=loc, FileFormat:=51
Exit Sub
End If
Application.DisplayAlerts = True
End If
End Sub
Ответ 3
Для этого ответа я предполагаю, что с помощью макроса с поддержкой макроса Excel вы имеете в виду файл xltm. Я также предполагаю, что то, что вы подразумеваете под "новым документом", это документ, который создается, когда пользователь дважды щелкает по файлу xtlm (следовательно, этот новый файл не имеет местоположения, поскольку он еще не был сохранен).
Чтобы решить вашу проблему, вы можете использовать собственное окно SaveAs (Application.GetSaveAsFilename
), чтобы иметь больше контроля над тем, как пользователь сохраняет файл при вызове макроса события Workbook_BeforeSave
.
Вот как это реализовать:
1 - Скопируйте этот код в новый модуль.
Option Explicit
Sub SaveAsCustomWindow()
Const C_PROC_NAME As String = "SaveAsCustomWindow"
Dim strFullFileName As String, strPreferedFolder As String, strDefaultName As String
Dim UserInput1 As Variant, UserInput2 As Variant
Dim isValidName As Boolean, isFileClosed As Boolean, isWorkbookClosed As Boolean
Dim strFilename As String, strFilePath As String
'To avoid Warning when overwriting
Application.DisplayAlerts = False
'Disable events (mostly for the BeforeSave event) to avoid creating infinite loop
Application.EnableEvents = False
On Error GoTo ErrHandler
'Customizable section
strDefaultName = ThisWorkbook.Name
strPreferedFolder = Environ("USERPROFILE")
Do While isWorkbookClosed = False
Do While isFileClosed = False
Do While isValidName = False
UserInput1 = Application.GetSaveAsFilename(InitialFileName:=strPreferedFolder & "\" & strDefaultName, FileFilter:="Excel Workbook (*.xlsx),*.xlsx")
If UserInput1 = False Then
GoTo ClosingStatements 'This is important to take care of the case when the user presses cancel
Else
strFullFileName = UserInput1
End If
strFilename = Right(strFullFileName, Len(strFullFileName) - InStrRev(strFullFileName, "\"))
strDefaultName = strFilename
strFilePath = Left(strFullFileName, InStrRev(strFullFileName, "\") - 1)
strPreferedFolder = strFilePath
'If the file exist, ask for overwrite permission
If Dir(strFullFileName) <> "" Then
UserInput2 = MsgBox(strFilename & " already exists." & vbNewLine & "Do you want to overwrite?", vbYesNoCancel Or vbExclamation)
If UserInput2 = vbNo Then
isValidName = False
ElseIf UserInput2 = vbYes Then
isValidName = True
ElseIf UserInput2 = vbCancel Then
GoTo ClosingStatements
Else
GoTo ClosingStatements
End If
Else
isValidName = True
End If
Loop
'Check if file is actually open
If isFileOpen(strFullFileName) Then
MsgBox "The workbook you want to overwrite is currently open. Choose a different name, or close the workbook before saving.", vbExclamation
isValidName = False
isFileClosed = False
Else
isFileClosed = True
End If
Loop
'Check if an opened workbook has the same name
If isWorkbookOpen(strFilename) Then
MsgBox "You cannot save this workbook with the same name as another open workbook or add-in. Choose a different name, or close the other workbook or add-in before saving.", vbExclamation
isValidName = False
isFileClosed = False
isWorkbookClosed = False
Else
isWorkbookClosed = True
End If
Loop
ThisWorkbook.SaveAs Filename:=strFullFileName, FileFormat:=xlOpenXMLWorkbook
ClosingStatements:
Application.EnableEvents = True
Application.DisplayAlerts = True
Exit Sub
ErrHandler:
Call MsgBox("Run-time error '" & Err.Number & "': " & Err.Description & vbNewLine & _
"While running: " & C_PROC_NAME & IIf(Erl <> 0, vbNewLine & "Error Line: " & Erl, "")
GoTo ClosingStatements
End Sub
Function isFileOpen(ByVal Filename As String) As Boolean
Dim ff As Long, ErrNo As Long
On Error Resume Next
ff = FreeFile()
Open Filename For Input Lock Read As #ff
Close ff
ErrNo = Err
On Error GoTo 0
Select Case ErrNo
Case 0: isFileOpen = False
Case 70: isFileOpen = True
End Select
End Function
Function isWorkbookOpen(ByVal Filename As String) As Boolean
Dim wb As Workbook, ErrNo As Long
On Error Resume Next
Set wb = Workbooks(Filename)
ErrNo = Err
On Error GoTo 0
Select Case ErrNo
Case 0: isWorkbookOpen = True
Case Else: isWorkbookOpen = False
End Select
End Function
Объяснение части 1: все это может показаться чересчур избыточным, но здесь важна вся обработка ошибок, чтобы учесть потенциальные ошибки и убедиться, что параметр для Application.EnableEvents
возвращается к TRUE
даже если произошла ошибка. В противном случае все макросы событий будут отключены в приложении Excel.
2. Вызовите процедуру SaveAsCustomWindow
внутри процедуры Workbook_BeforeSave, например:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'Your code
If ThisWorkbook.Path = "" Then
SaveAsCustomWindow
Cancel = True
End If
End Sub
Обратите внимание, что нам нужно установить переменную Cancel = True, чтобы предотвратить появление окна SaveAs по умолчанию. Кроме того, оператор if должен убедиться, что пользовательское окно SaveAs будет использоваться, только если файл не был сохранен.
Ответ 4
Чтобы ответить на ваши вопросы:
Возможно ли предотвратить появление этого сообщения?
Да, используя свойство Application.DisplayAlerts
Возможно ли, чтобы Excel предполагал, что пользователь хочет продолжить работу с книгой без макросов?
Нет, вам нужно написать процедуру, чтобы сохранить книгу и обойти событие SaveAs
excel и сохранить книгу с использованием пользовательского ввода (Path
& Filename
) с требуемым форматом.
Следующая процедура использует FileDialog для захвата Пути и имени файла от пользователя, а затем сохраняет файл без отображения предупреждающего сообщения. Однако я добавил несколько пояснительных комментариев, дайте мне знать о любых вопросах, которые могут возникнуть у вас.
Скопируйте эти процедуры в модуль ThisWorkbook
:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Cancel = True 'Prevents repetitive Save
Call Workbook_BeforeSave_ApplySettings_And_Save
End Sub
Private Sub Workbook_BeforeSave_ApplySettings_And_Save()
Dim fd As FileDialog, sFilename As String
Rem Sets FileDialog to capture user input
Set fd = Application.FileDialog(msoFileDialogSaveAs)
With fd
.InitialView = msoFileDialogViewDetails
.Title = vbNullString 'Resets default value in case it was changed
.ButtonName = vbNullString 'Resets default value in case it was changed
.AllowMultiSelect = False
If .Show = 0 Then Exit Sub 'User pressed the Cancel Button
sFilename = .SelectedItems(1)
End With
With ThisWorkbook
Do While .Connections.Count > 0
.Connections.Item(.Connections.Count).Delete
Loop
Application.EnableEvents = False 'Prevents repetition of the Workbook_BeforeSave event
Application.DisplayAlerts = False 'Prevents Display of the warning message
On Error Resume Next 'Prevents Events and Display staying disable in case of error
.SaveAs Filename:=sFilename, FileFormat:=xlOpenXMLWorkbook 'Saves Template as standard excel using user input
If Err.Number <> 0 Then
MsgBox "Run-time error " & Err.Number & String(2, vbLf) _
& Err.Description & String(2, vbLf) _
& vbTab & "Process will be cancelled.", _
vbOKOnly, "Microsoft Visual Basic"
End If
On Error GoTo 0
Application.DisplayAlerts = True
Application.EnableEvents = True
End With
End Sub