When Application.Quit is encountered in a subroutine,
it will only stay in memory and continue to run lines under it
and will actually quit until it encounters a «Exit Sub».
When the normal «End Sub» at the primary level is encountered,
it will then also close Excel. But say if the workbook is somehow
closed before reaching the «Exit Sub», «End» or «End Sub» line, then
Excel will not close.
Solution is to create a Public variable called ToQuitNow
with initial False value
and change it to True where you want Excel to quit.
and test right after to see if it is true, then return to previous Sub level
by «Exit Sub» or «End» to quit right away,
and do the same at every subrountine level where
it is expected to return from the deeper subroutine.
When it gets back to the primary level,
then a final «Exit Sub» will actually terminates Excel.
If you do not want Excel to ask for saving changes made,
add line «ThisWorkbook.Saved = True» right after Application.Quit,
or before the final «Exit Sub» at the Primary level
and Excel will quit without saving.
Try the following test below, just run «Test»
Public ToQuitNow As Boolean
Sub Test()
ToQuitNow = False ' initialize with False value
Call SecondSub
MsgBox ("Primary level here. Back from SecondSub")
If ToQuitNow = True Then
Exit Sub 'will actually quit Excel now if True
End If
MsgBox ("This line will not run if ToQuitNow is True")
End Sub
Sub SecondSub()
MsgBox ("SecondSub here")
Call ThirdSub
MsgBox ("SecondSub here. Back from ThirdSub")
If ToQuitNow = True Then
Exit Sub ' will return to Main level if True
End If
MsgBox ("This line from SecondSub will not run if ToQuitNow is True")
End Sub
Sub ThirdSub()
MsgBox ("ThirdSub here")
Call FourthSub
MsgBox ("ThirdSub here. Back from FourthSub")
If ToQuitNow = True Then
Exit Sub ' will return to SecondSub if True
End If
MsgBox ("This line from ThirdSub will not run if ToQuitNow is True")
End Sub
Sub FourthSub()
MsgBox ("FourthSub here")
Application.Quit
ThisWorkbook.Saved = True ' Excel will think changes already saved _
and will quit without saving
ToQuitNow = True ' activate Quit
If ToQuitNow = True Then
MsgBox ("Quit command executed in FourthSub")
Exit Sub ' will return to ThirdSub if True
'Can also put in End in above line to quit right away
End If
MsgBox ("This line from FourthSub will not run if ToQuitNow is True.")
End Sub
Эксель не закрывается с кодом Application.Quit |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
Когда Application.Quit встречается в подпрограмме, он остается только в памяти и продолжает выполнять строки под ним и фактически завершает работу до тех пор, пока не встретит «Exit Sub». Когда встречается обычный «End Sub» на основном уровне, он также закрывает Excel. Но скажем, если рабочая книга каким-то образом закрывается до достижения строки «Exit Sub», «End» или «End Sub», Excel не закроется.
Решение состоит в том, чтобы создать общедоступную переменную с именем ToQuitNow с начальным значением False и изменить ее на True там, где вы хотите закрыть Excel. и проверьте сразу после этого, чтобы убедиться, что это правда, затем вернитесь на предыдущий подуровень с помощью «Exit Sub» или «End», чтобы выйти сразу, и сделайте то же самое на каждом уровне подпрограммы, где ожидается возврат из более глубокой подпрограммы. Когда он вернется на основной уровень, последний «Exit Sub» фактически закроет Excel. Если вы не хотите, чтобы Excel запрашивал сохранение внесенных изменений, добавьте строку «ThisWorkbook.Saved = True» сразу после Application.Quit или перед последним «Exit Sub» на начальном уровне, и Excel завершит работу без сохранения.
Попробуйте следующий тест ниже, просто запустите «Тест»
Public ToQuitNow As Boolean
Sub Test()
ToQuitNow = False ' initialize with False value
Call SecondSub
MsgBox ("Primary level here. Back from SecondSub")
If ToQuitNow = True Then
Exit Sub 'will actually quit Excel now if True
End If
MsgBox ("This line will not run if ToQuitNow is True")
End Sub
Sub SecondSub()
MsgBox ("SecondSub here")
Call ThirdSub
MsgBox ("SecondSub here. Back from ThirdSub")
If ToQuitNow = True Then
Exit Sub ' will return to Main level if True
End If
MsgBox ("This line from SecondSub will not run if ToQuitNow is True")
End Sub
Sub ThirdSub()
MsgBox ("ThirdSub here")
Call FourthSub
MsgBox ("ThirdSub here. Back from FourthSub")
If ToQuitNow = True Then
Exit Sub ' will return to SecondSub if True
End If
MsgBox ("This line from ThirdSub will not run if ToQuitNow is True")
End Sub
Sub FourthSub()
MsgBox ("FourthSub here")
Application.Quit
ThisWorkbook.Saved = True ' Excel will think changes already saved _
and will quit without saving
ToQuitNow = True ' activate Quit
If ToQuitNow = True Then
MsgBox ("Quit command executed in FourthSub")
Exit Sub ' will return to ThirdSub if True
'Can also put in End in above line to quit right away
End If
MsgBox ("This line from FourthSub will not run if ToQuitNow is True.")
End Sub
Okay, this seems long winded… but here goes.
The problem you are seeing is because there can be more than one instance of the Excel Application on a machine at a given time.
When you are manually running the file, you are likely using the default behavior, which is that when you open a workbook directly it opens in your already loaded Excel Application.
This means that when you use:
Set xlApp = GetObject(, "excel.application")
It is actually returning the current Excel.Application
.
However, when you load it via the scheduled task, it generates a new Excel.Application
in order to handle your task. When it calls the code I quoted it ends up referencing the Excel.Application
you already had open (probably).
Since your scheduled workbook is running in a different instance of Excel.Application
, when you run xlApp.Quit
it only quits that other Excel and not the one actually running the code.
If you want to also close your automated Excel, you will need to add Application.Quit
to the end of your sub. Yes, I do mean use both xlApp.Quit
AND Application.Quit
.
Now technically, you could have more than one Excel Applications open when you load the new one. If you want to close all instances of Excel, the simplest way I know would be to kill all of them via a vbscript call to a program like this which terminates all processes named excel.exe. Note I did not test this on Win 7:
Dim objWMIService, objProcess, colProcess
Dim strComputer, strProcessKill, strFilePath
strComputer = "."
strProcessKill = "'excel.exe'"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\" _
& strComputer & "rootcimv2")
Set colProcess = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = " & strProcessKill)
For Each objProcess In colProcess
objProcess.Terminate
Next
WScript.Quit
Edit: I just wanted to add that you can replicate the behavior of the scheduled task manually by doing the following:
- Have Excel already open.
- Navigate through your start menu and open Excel.
- From the new instance of Excel, open your workbook.
OR
- Have Excel already open.
- Run the following
Excel.exe [path of workbook in quotes]
Edit 2:
Due to your request, I’ve written this short vbscript file that will close all open Excel Applications without upsetting auto-recover. If you also want to avoid any, «Do you want to save …» alerts uncomment the commented section.
On Error Resume Next
Dim xlApp
Set xlApp = GetObject(, "Excel.Application")
Do While Err.Number <> 429
'For each wb in xlApp.Workbooks
' wb.saved = true
'next
xlApp.Quit
Set xlApp = Nothing
Set xlApp = GetObject(, "Excel.Application")
Loop
Wscript.quit
To run it, just include the following at the end of your Excel VBA.
Shell "wscript.exe [path of .vbs file]"
Badamyan Пользователь Сообщений: 72 |
#1 21.07.2016 14:40:19
Изменено: Badamyan — 21.07.2016 15:08:59 |
||
Badamyan, И в чём, собственно, вопрос? Изменено: РОБОТ_РОБИН — 21.07.2016 14:45:58 |
|
Badamyan Пользователь Сообщений: 72 |
простите я впервые в этом форуме |
Ts.Soft Пользователь Сообщений: 576 |
#4 21.07.2016 14:56:54 Попробуйте так:
Не стреляйте в тапера — он играет как может. |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#5 21.07.2016 14:59:25
Ну а нормальное название сформулировать это разве мешает? VBA — и что? Прикрепленные файлы
|
||
Badamyan Пользователь Сообщений: 72 |
#6 21.07.2016 15:02:15 окей Юрий, спасибо
Изменено: Badamyan — 21.07.2016 15:04:53 |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#7 21.07.2016 15:08:00 Не исправили стартовое сообщение…
|
||
Badamyan Пользователь Сообщений: 72 |
Юрий так тоже не будет работать, активным считаеться тот файл в котором работает макрос, при таком коде он и будет закрываться Изменено: Badamyan — 21.07.2016 15:12:25 |
Hugo Пользователь Сообщений: 23253 |
#9 21.07.2016 15:18:55
это вообще может быть любой файл…
Тогда всегда с этим wb можно делать что угодно. |
||||
Ts.Soft Пользователь Сообщений: 576 |
#10 21.07.2016 15:19:28
Нет, активным считается именно активный файл, а тот в котором работает макрос называется ThisWorkbook Не стреляйте в тапера — он играет как может. |
||
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#11 21.07.2016 15:19:34
Проверяли? |
||
Badamyan Пользователь Сообщений: 72 |
Hugo,Огромное спасибо ) сработал |
Hugo Пользователь Сообщений: 23253 |
Тот в котором содержится макрос называется ThisWorkbook. |
Badamyan Пользователь Сообщений: 72 |
Юрий М,да, но не сработал, закрывает тот файл в котором макрос |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
У меня сработал. |
Ts.Soft Пользователь Сообщений: 576 |
#16 21.07.2016 15:34:21 Сейчас проверил код:
работает
даёт ошибку Subscript out of range. Получается, что x не является объектом Workbook? Не стреляйте в тапера — он играет как может. |
||||
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
#17 21.07.2016 15:35:38
нет. Получается что в x содержится полный путь до книги, а не только её имя, как того требует коллекция Workbooks. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
||
Ts.Soft Пользователь Сообщений: 576 |
The_Prist, спасибо. Учту на будущее. Не стреляйте в тапера — он играет как может. |
Badamyan Пользователь Сообщений: 72 |
Юрий М, получился и по вашему, наверника запустил макрос не с правильного файла |
Badamyan Пользователь Сообщений: 72 |
The_Prist,а как получить только имя ? |
Ts.Soft Пользователь Сообщений: 576 |
#21 21.07.2016 15:51:24
можно так
Проверил — работает Изменено: Ts.Soft — 21.07.2016 15:53:53 Не стреляйте в тапера — он играет как может. |
||||
Badamyan Пользователь Сообщений: 72 |
Ts.Soft,а что делает InStrRev ? находит в X ? ведь в нем несколько -ов Изменено: Badamyan — 21.07.2016 15:55:16 |
Мотя Пользователь Сообщений: 3218 |
#23 21.07.2016 15:57:17
Изменено: Мотя — 21.07.2016 16:03:02 |
||
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
#24 21.07.2016 15:57:22
но лучше использовать метод Hugo — надежнее. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
||||
Ts.Soft Пользователь Сообщений: 576 |
Badamyan, InStrRev ищет заданный символ с конца строки, но возвращает порядковый номер от начала, т.е. в данном случае находит последний «», к его номеру добавляется единица и с этой позиции до конца выделяется подстрока Не стреляйте в тапера — он играет как может. |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#26 21.07.2016 17:57:31
Вариант:
|
||||
Hugo Пользователь Сообщений: 23253 |
#27 21.07.2016 19:26:56 Зачем всё усложнять?
|
||