Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Закрыть без сохранения

5.5K
24 июня 2004 года
Sergan
26 / / 11.06.2004
1) Хотелось бы узнать, как сделать так, чтобы при закрытии файла Excel программа не спрашивала пользователя "Сохранить изменения?", а сразу закрывала файл без сохранения?

2) Ещё было бы хорошо, чтобы пользователь при сохранении текущего файла не мог сохранить его под этим именем, а только под другим.

Суть в том, что есть файл Excel с макросами, содержание которого (файла) сохранять не нужно. Изменения могут производиться только в процессе работы с этим файлом, а сохранять их нельзя.
5.2K
24 июня 2004 года
Dimitry
26 / / 11.06.2004
[QUOTE]Originally posted by Sergan
1) Хотелось бы узнать, как сделать так, чтобы при закрытии файла Excel программа не спрашивала пользователя "Сохранить изменения?", а сразу закрывала файл без сохранения?

ActiveWorkbook.Close savechanges:=False
5.5K
24 июня 2004 года
Sergan
26 / / 11.06.2004
Цитата:
Originally posted by Dimitry
ActiveWorkbook.Close savechanges:=False


Я поместил команду ActiveWorkbook.Close savechanges:=False в процедуру Workbook_BeforeClose. Теперь при закрытии файла программа не спрашивает "Сохранить изменения?" и закрывает без сохранения.
А как быть со вторым вопросом?

5.2K
24 июня 2004 года
Dimitry
26 / / 11.06.2004
Цитата:
Originally posted by Sergan

Я поместил команду ActiveWorkbook.Close savechanges:=False в процедуру Workbook_BeforeClose. Теперь при закрытии файла программа не спрашивает "Сохранить изменения?" и закрывает без сохранения.
А как быть со вторым вопросом?



попробуй вот так....может получится

ActiveWorkbook.SaveAs Filename:="Имя.xls"
ActiveWorkbook.Close savechanges:=True

5.5K
24 июня 2004 года
Sergan
26 / / 11.06.2004
Цитата:
Originally posted by Dimitry

попробуй вот так....может получится

ActiveWorkbook.SaveAs Filename:="Имя.xls"
ActiveWorkbook.Close savechanges:=True



Дмитрий,по-моему,эти команды можно применить при выполнении какого-то макроса. Я же хочу, чтобы при нажатии пользователем кнопки или меню "Сохранить", программа предлагала сохранить этот файл под другим именем, а под этим не разрешала вообще.
Как это сделать?

5.2K
24 июня 2004 года
Dimitry
26 / / 11.06.2004
Цитата:
Originally posted by Sergan


Дмитрий,по-моему,эти команды можно применить при выполнении какого-то макроса. Я же хочу, чтобы при нажатии пользователем кнопки или меню "Сохранить", программа предлагала сохранить этот файл под другим именем, а под этим не разрешала вообще.
Как это сделать?



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

258
24 июня 2004 года
SergeySV
1.5K / / 19.03.2003
Цитата:
Originally posted by Sergan


Дмитрий,по-моему,эти команды можно применить при выполнении какого-то макроса. Я же хочу, чтобы при нажатии пользователем кнопки или меню "Сохранить", программа предлагала сохранить этот файл под другим именем, а под этим не разрешала вообще.
Как это сделать?



У тебя какая-то нетривиальная задачка, ты хочешь отобрать у пользователя возможность сохранения файла под тем же названием?

Тогда надо залезть в обработчик события Workbook_BeforeSave этой книги:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

SaveAsUi - True if the Save As dialog box will be displayed - наверное то что тебе нужно.


End Sub

5.5K
24 июня 2004 года
Sergan
26 / / 11.06.2004
Цитата:
Originally posted by SergeySV


У тебя какая-то нетривиальная задачка, ты хочешь отобрать у пользователя возможность сохранения файла под тем же названием?

Тогда надо залезть в обработчик события Workbook_BeforeSave этой книги:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

SaveAsUi - True if the Save As dialog box will be displayed - наверное то что тебе нужно.

End Sub


Да, Сергей, Вы правы: хочу отобрать у пользователя эту возможность. Но использование параметра SaveAsUi ничего не дало. Для того, чтобы пользователь не смог сохранить файл нужно сделать так

Cancel = True

тогда файл не сохраняется.

Самое смешное, что написав в обработчике событий выше приведенную команду я и сам теперь этот файл не могу сохранить, то есть не могу сохранить этот код ( Cancel=True )
Поэтому ничего не получается. Как быть?

5.2K
24 июня 2004 года
Dimitry
26 / / 11.06.2004
Цитата:
Originally posted by Sergan



Самое смешное, что написав в обработчике событий выше приведенную команду я и сам теперь этот файл не могу сохранить, то есть не могу сохранить этот код ( Cancel=True )
Поэтому ничего не получается. Как быть?



Попробуй открыть эту книгу ... отключить макросы...изменить нужную процедуру....и сохранить...должно получиться..... а вообще ситуация веселая :)

258
24 июня 2004 года
SergeySV
1.5K / / 19.03.2003
Смешно получилось, вот так дашь совет :)

Ну пока можно в конце Cancel=False приписать, который все разрешит. Ну пока код не отработан, можно его еще тестить, а сохранять уже в самом конце.

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

Думаю логика должна быть такая (сходу, не проверяя, убегать уже пора :) )

1. Показываем диалог выбора сохранения файла (простой диалог, который возвращает токо имя и ничего больше не делает): Application.GetSaveAsFilename

2. Проверяем путь, если совпадает с текущим файлом - ругаемся на пользователя, куда-нибудь его посылаем или тихо игнорируем и ставим Cancel=True. Если путь не совпадает, то Cancel=False.
5.5K
25 июня 2004 года
Sergan
26 / / 11.06.2004
Цитата:
Originally posted by SergeySV
...
Думаю логика должна быть такая

1. Показываем диалог выбора сохранения файла (простой диалог, который возвращает токо имя и ничего больше не делает): Application.GetSaveAsFilename

2. Проверяем путь, если совпадает с текущим файлом - ругаемся на пользователя, куда-нибудь его посылаем или тихо игнорируем и ставим Cancel=True. Если путь не совпадает, то Cancel=False.


Вообщем сделал я следующее:
[COLOR=blue]
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim name, fName As String
name = "имя_файла.xls"
MsgBox "Рекомендуется сохранить файл под именем " + name, , "Внимание!"
ChDir ActiveWorkbook.Path
fName = Application.GetSaveAsFilename(InitialFileName:=name)
[color=green]'Если выбранное имя совпадает с именем текущего файла[/color]
If fName = ActiveWorkbook.FullName Then
[color=green]'Ругаемя на пользователя[/color]
MsgBox "Сохранение файла под текущим именем ЗАПРЕЩЕНО! Сохраниет файл под другим именем!", , "Внимание!"
Cancel = True [color=green]'отключаем сохранение[/color]
Else
[color=green]'иначе сохранение возможно[/color]
Cancel = False
[color=black]ПОСЛЕ ЭТОГО ФАЙЛ СОХРАНЯЕТСЯ ПОД ТЕКУЩИМ ИМЕНЕМ, А НЕ ПОД ТЕМ, КОТОРЫЙ ВЫБРАЛ ПОЛЬЗОВАТЕЛЬ!!! ВО КАК!!! ЧТО НУЖНО СДЕЛАТЬ, КАКОМУ ПАРАМЕТРУ ПРИСВОИТЬ ВЫБРАННОЕ ПОЛЬЗОВАТЕЛЕМ ИМЯ, ЧТОБЫ СОХРАНЕНИЕ ПРОИЗОШЛО КАК НАДО ???[/color]
End If
End Sub
[/COLOR]
Ещё обнаружил, что при вызове команды "Сохранить как" открывается стандартное окно сохранения, даже
[COLOR=blue]SaveAsUI = False[/COLOR]
не помогает. Вот блин, никак не могу как следует извратиться. Можно конечно просто запретить любое сохранение и всё.
Что посоветуете?

258
25 июня 2004 года
SergeySV
1.5K / / 19.03.2003
Хм, прикольная получилась задачка, я раз десять подвесил свой Excel, прежде чем во всем разобрался и отладил код :)

Сразу поясню насчет параметра SaveAsUI, чтоб он больше нам не мешал - эта переменная в событии _BeforeSave всего лишь показывает как пользователь пытается сохранить файл: серез СОХРАНИТЬ или через СОХРАНИТЬ КАК, и все. Это для информации, соотв. присвоение этой переменной какого своего значение внутри события _BeforeSave не имеет никакого смысла. Тебе Excel эту переменную передал в качестве информации, по ByVal к тому же и то что ей что то еще пытаешься присвоить, на это Excel уже никакого внимание обращать не будет.

Теперь на счет твоих проблем с SaveAs внутри события _BeforeSave.
Тут складывается действительно забавная ситуация. Дело в том, что вызывая метод в SaveAs в этом событии мы порождаем опять же это событие, поэтому очень важно предусмотреть возможность выхода из него, не допустив зацикливания.
Происходит все следующим образом:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

строка1
ThisWorkbook.SaveAs "c:\3.xls" ' строка2
строка3
End Sub

Мы нажимаем кнопку Сохранить в Excel'е.
попадаем в событие _BeforeSave на строчку1.
Переходим к строчке2 - ThisWorkbook.SaveAs "c:\3.xls", которая порождает ВТОРОЕ событие _BeforeSave.
Поэтому со строчки2 мы вновь попадаем на строчку1.
Визуально это можно представить себе так, как если разместить рядом два одниковых куска кода процедуры Private Sub Workbook_BeforeSave и нарисовать стрелку перехода со строчки2 первого куска на второй кусок Private Sub Workbook_BeforeSave.

Эта аналогия будет полной еще в том смысле, что Excel отработает весь второй кусок и потом, ВНИМАНИЕ: вернуться в первый кусок на след. строчку после той, с которой его грубо прервали вызвав SaveAs (т.е. в нашем примере на строчку3)

Т.е. выполнение кода по строчка будет следующее:
строчка1 (_BeforeSave1)
строчка2 (тут мы вызываем еще одно _BeforeSave)
строчка1 (_BeforeSave2)
'строчка2(_BeforeSave2)
строчка3 (_BeforeSave2)
строчка3 (вернeлись в первый _BeforeSave)


Хорошо видно что если не поставить какое-нибудь доп. условие на строчку2 (.SaveAs), то оно будет каждый раз порождает очередные _BeforeSave и мы так зациклимся.

Поэтому если внутри события _BeforeSave надо сохранить файл под другим названием, то бцдет например такой:
Код:
Dim lEvent As Long
Dim bolEx As Boolean

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

 If lEvent = 0 Then
    lEvent = 1
    ThisWorkbook.SaveAs "c:\3.xls"
 ElseIf lEvent = 1 Then
    lEvent = 0
    bolEx = True
 End If

 If lEvent = 0 And bolEx Then
   bolEx = False
   Cancel = False
 Else
   Cancel = True
 End If

End Sub


Чтобы посмотреть как работает этот код можешь открыть приложенный файл поставить breakpoint на If lEvent = 0 Then в событии _BeforeSave и нажать кнопку сохранить и двигаясь по шагам (через F8 ) увидишь как для второго события устанавливается Cancel=False, а при возвращаении к первому Cancel становится равным =True (если этого не сделать, то получим зависание Excel'я, он будет пытаться сохранить файл, который мы уже сохранили под другим именем, у Excel крышу тогда снесет)
5.5K
28 июня 2004 года
Sergan
26 / / 11.06.2004
Цитата:
Originally posted by SergeySV
Хм, прикольная получилась задачка, я раз десять подвесил свой Excel, прежде чем во всем разобрался и отладил код :)

...вызывая метод в SaveAs в этом событии мы порождаем опять же это событие, поэтому очень важно предусмотреть возможность выхода из него, не допустив зацикливания.


Что происходит зацикливание, я сообразил, у меня тоже несколько раз подвисал Excel. Просто не знал как это обойти.
Большое спасибо тебе, Сергей. Я использую этот код, подредактирую и всё будет очень здорово! :)

А что значит на каждом листе такое начало:

[COLOR=blue]Option Explicit[/COLOR]

Это объявление глобальных переменных, которые будут видны во всех листах этой рабочей книги?
На самом деле я пытался просто объявить переменные в листе, чтобы из любой процедуры я мог иметь к ним доступ, но что-то у меня не вышло. Имя переменной доступно, а её значение оставалось нулевым или пустым.

258
28 июня 2004 года
SergeySV
1.5K / / 19.03.2003
Цитата:
Originally posted by Sergan

Что происходит зацикливание, я сообразил, у меня тоже несколько раз подвисал Excel. Просто не знал как это обойти.
Большое спасибо тебе, Сергей. Я использую этот код, подредактирую и всё будет очень здорово! :)

А что значит на каждом листе такое начало:

[COLOR=blue]Option Explicit[/COLOR]

Это объявление глобальных переменных, которые будут видны во всех листах этой рабочей книги?
На самом деле я пытался просто объявить переменные в листе, чтобы из любой процедуры я мог иметь к ним доступ, но что-то у меня не вышло. Имя переменной доступно, а её значение оставалось нулевым или пустым.



А вот именно потому Option Explicit и нужно, чтобы не создавалось впечатления будто переменная доступна, но только нулевая.

Поясню:
Option Explicit - это директива в начале модуля с кодом означает - что все переменные требуют ОБЯЗАТЕЛЬНОГО объявления. Если переменная не была объявлена, но используется в коде, то возникнеи ошибка в процессе компиляции (т.е. еще до запуска программы)

Когда такой директивы Option Explicit нет, то компилятор Visual Basic работает в режиме, назовем его режимом "чайника-холявщика". Это когда компилятор встречая непознаную переменную просто объявляет ее в тихоря вместо тебя (на коде это не отражается, это происходит только в момент компиляции)

Типичный случай чем это плохо и почему надо всегда писать Option Explicit это твой пример.

Ты хотел объявить глобальную переменную, чтобы она была доступна везде внутри проекта. Для этого переменную нужно объявлять - обязательно в модуле (в обычном модуле) и Public.
Ты этого не знал и допустил ошибку, объявив свою переменную как Public НО внутри модуля листа. При этом твоя переменная НЕ СТАЛА доступной за пределами этого листа. При этом когда ты стал в блаженном неведении писать имя этой переменной в других модулях (в которых не стояло Option Explicit) компилятор не стал ругаться и спокойно тебе разрешил это сделать, он просто в тихоря создал еще одну локальную переменную в этом модуле. Именно поэтому она и была нулевой, потому что у тебя получилось две разные переменные, но с одинаковыми именами.

Если бы ты использовал бы Option Explicit, то компилятор бы сразу стал бы ругаться и эта ошибка не прошла бы у тебя незамеченной.


Чтобы не писать в начале каждого модуля - Option Explicit, достаточно поставить галку в Tools/Options - Require Variable Declaration (Требовать обязательного объявления) и в каждом новом модуле автоматом будет появляется эта строка.

5.5K
28 июня 2004 года
Sergan
26 / / 11.06.2004
Большое тебе спасибо, Сергей.

Проверь свои входящие сообщения. ;) :roll: 8)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог