Страницы: 1
RSS
Как выполнить отмену(Undo) макросом?
 
Доброго времени суток.

Подскажите, пожалуйста, как будет выглядеть код который будет эмитировать "Ctrl+Z"
Заранее спасибо.
 
Код
application.undo
 
вот такая ошибка:
Run Time Error '1004'
Method 'Undo' of object '_appliacation' failed
 
А у меня (в моем коде) нет такой ошибки)
 
Вот всего -то кода:
Код
Private Sub CommandButton1_Click()
   Application.Undo
End Sub

А может из-за Excel 2003 быть? (Хотя у меня в хелпе VBA описывается точно так же)
Изменено: Artmasterpro - 09.05.2016 01:06:44
 
1. Код следует оформлять соответствующим тегом. Исправьте, пожалуйста.
2. А чего в Вашем коде отменять? Нет никакого действия по нажатию кнопки.
А теперь скопируйте мой код в модуль листа и попробуйте что-нибудь ввести в ячейку А1 - undo сработает
Код
Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("A1")) Is Nothing Then
        Application.EnableEvents = False
        Application.Undo
    End If
    Application.EnableEvents = True
End Sub


 
Спасибо огромное за подсказку!!!
я забыл про EnebleEvents
теперь все работает!!
 
Да отключение событий тут никакой роли (в Вашем коде) не играет. Отменяется ведь последнее действие пользователя. А у Вас последнее действие - нажатие кнопки )
Попробуйте, например, закрасить ячейку и выполнить
Код
Sub Macro1()
    Application.Undo
End Sub



 
Цитата
Юрий М написал:
отключение событий тут никакой роли (в Вашем коде) не играет. Отменяется ведь последнее действие пользователя
Нет, Юра, может играть роль. Т.к. зависит от того, что делал до этого пользователь - если изменял значение ячейки, то Undo вызовет событие Worksheet_Change, что повлечет опять Undo и т.д. пока либо стек памяти не переполнится, либо(что вероятнее) - отменять будет просто нечего(по идее на втором проходе уже должно выбить в ошибку).
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Дим, да я и не спорю, что может ) Я про приведённый пример говорил: никаких действий, а автору помогло ))
В моём примере я ведь как раз и делаю отключение событий.
 
В изначальном коде согласен. Просто было у меня подозрение, что это Undo у автора изначально выполнялось при наступлении события Change листа :) Поэтому решил уж развернуто написать.
Изменено: The_Prist - 09.05.2016 13:36:49
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Доброго времени суток! Говорю сразу: я новичок в VBA.
Мне необходимо придумать макрос на отмену всех действий пользователя перед сохранением книги.
Подразумевается не отмена действия макросов, а откат обычных заполнений ячеек пользователем введенных вручную,
то есть пользователь мог бы и сам все отменить командой "Ctrl+Z", но мне надо это сделать макросом)

к примеру, пользователь после открытия и до сохранения успел заполнить 5 разных ячеек - пишу такой "топорный" код)
в результате:
- стирает последнюю ячейку (то что и нужно)
- возвращает последнюю ячейку (а нужно чтоб стёр предпоследнюю)
- стирает последнюю ячейку
- возвращает последнюю ячейку
- стирает последнюю ячейку
Код
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Application.Undo
    Application.Undo
    Application.Undo
    Application.Undo
    Application.Undo
End Sub


Вообще пользователь может и 100 ячеек скорректировать и даже на разных листах, а потом нажал сохранить (а надо сначала откатить все изменения с начала открытия, а потом сохраниться) - может посоветуете какой то цикл к отмене?

В итоге мы получаем две кнопки отмены при выходе)

ПС: Описал максимально подробно, чтоб помогли именно с этой конкретной задачей, а не предлагали другие варианты решения.
Там не так все просто, после сохранения предусмотрен откат действий (надеюсь каким то циклом который упрется в то что уже откатывать нечего и закончит работу цикла), но потом допишет время сохранения файла.
В итоге: пользователь нажав сохранить ничего не изменит, только добавит дату сохранения)
Дату умею добавлять )
Заранее спасибо!
Изменено: RoMuLX - 16.06.2017 23:04:07
 
Цитата
RoMuLX написал: каким то циклом который упрется в то что уже откатывать нечего и закончит работу цикла
Цитата
RoMuLX написал: не предлагали другие варианты решения.

Думаю, что тем способом который Вы допускаете как единственный, это сделать невозможно.
Хотя могу ошибаться.
Согласие есть продукт при полном непротивлении сторон
 
Sanja,
Цитата
RoMuLX написал:
ПС: Описал максимально подробно, чтоб помогли именно с этой конкретной задачей, а не предлагали другие варианты решения.
часто тут читал, что вместо конкретной задачи предлагают совсем не то...(
Я не хотел читать комменты типа "а зачем тебе откатывать? можно же просто выйти без сохранения"  и т.д. ....

Я видел темы по откатам макросов, значит можно реализовать нужный мне макрос по откатам простых действий и код будет проще (надеюсь).
Про цикл я не утверждаю)
Изменено: RoMuLX - 16.06.2017 21:46:24
 
Проще выйти без сохранения. По памяти:
Код
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
me.saved=-1
me.close 0
End Sub
Изменено: kuklp - 16.06.2017 21:46:11
Я сам - дурнее всякого примера! ...
 
RoMuLX, я так понял, что Вы хотите при помощи Undo отменить НЕСКОЛЬКО подряд выполненных действий. Но дело в том, что Application.Undo отменяет ПОСЛЕДНЕЕ действие.  
 
Цитата
RoMuLX написал:
часто тут читал, что вместо конкретной задачи предлагают совсем не то
Да, есть такое. Только это не вредностью продиктовано как правило, а тем, что человек напридумывает всяких себе проблем, а решать их предлагает другим, да еще на своих условиях :) А условия-то порой невыполнимы или пожелания сделать именно так просто избыточны.
Вот даже сейчас: можете кратко пояснить - почему надо именно откатами(Undo) делать, а не просто вернуть книгу в то состояние, которое было до...До какого момента, кстати? Как понять, когда закончить откатывать? Ведь количество откатов может быть разным на разных ПК. У кого-то вообще может быть только 5 установлено. Что делать-то?
Да и событие-то какое: перед сохранением. В этом случае проще вообще запретить всякое сохранение книги. Тогда и откатывать ничего не надо. В общем я бы сначала выслушал ЗАЧЕМ это, а потом уже подумал, что реально можно с этим сделать.
Ну а если не хотите пояснять, дело личное. Через Undo это сделать нереально.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Юрий М, я думал, что Application.Undo полностью заменяет Ctrl+Z, т.к. если заполнить к примеру 5 ячеек и потом нажать 5 раз Ctrl+Z, то сотрутся все 5 ячеек в порядке убывания ввода.
Мне бы макрос на это. Но, блин, макрорекордер не пишет командуCtrl+Z))

kuklp, Ваш код я ввел и после нажатия сохранения зависает файл. Может это и то что мне нужно, но потом надо придумать "стоп-кран" от зависания.
и можно потом будет добавить после "стоп-крана" дописать еще мою часть кода?
Цитата
Worksheets("лог").Cells(2, 2) = Now
ActiveWorkbook.Save

Не знаю как вы вставляете код так красиво, чтоб с подсветкой синтаксиса.
Если что у меня Excel 13.  
Изменено: RoMuLX - 19.06.2017 10:17:14
 
Цитата
RoMuLX написал:
если заполнить к примеру 5 ячеек и потом нажать 5 раз Ctrl+Z, то сотрутся все 5 ячеек в порядке убывания ввода.
Нет )) Пять раз Undo - пять раз будет меняться пятая ячейка.
По поводу кода: ищите такую кнопку и заодно отформатируйте с её помощью своё стартовое сообщение.
 
Цитата
RoMuLX написал:
после "стоп-крана" дописать
Если уж надо зафиксировать попытку изменения книги и время попытки, то используйте событие изменения листа книги:
Workbook_SheetChange
P.S. а оформить код просто - кнопка <...> на панели редактирования. :)
Я сам - дурнее всякого примера! ...
 
The_Prist, хорошо, расскажу полную ситуацию) внимание: много букв))
У меня есть инженерный расчетный файл. Он считает таблицы без макросов.
А макрос как раз на отслеживание входа из этой темы: http://www.planetaexcel.ru/techniques/5/196/
Но тут проблема, что окошко при выходе не вылезает, да и всегда идет сохранение файла (значит можно что-то по ошибке испортить и выйти).

И что бы правильно работало добавил форму при выходе: http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=1&TID=71378&...

В итоге у меня форма fmQueryClose на "сохранить"  "не сохранять"  "отмена".

1. Если жмем "сохранить" - то в реестр добавляется пользователь+дата, потом скрывает все листы, потом идет сейв, потом выход.
2. Если жмем "не сохранять" - то откатывает все изменения, потом скрывает все листы, потом идет сейв, потом выход.
3. Если жмем "отмена" - то просто закрывается форма и ничего больше.

Во всех этих вариантах стандартного диалога при выходе не будет.


и такой код у меня склепался из вышеперечисленных источников:
Код
Private Sub Workbook_Open() 

For Each sh In ActiveWorkbook.Worksheets 'отображаем все листы 
   sh.Visible = True 
Next sh 
Worksheets("Предупреждение").Visible = xlSheetVeryHidden  'скрываем лист ПРЕДУПРЕЖДЕНИЕ 

Worksheets("Реестр изменений").Rows("2:2").Insert Shift:=xlDown 'вставляем между строками 1 и 2 новую строку 
Worksheets("Реестр изменений").Rows("1001:1001").Delete Shift:=xlUp 'удаляем строку 1001 (реестр на 1000 строк) 
Worksheets("Реестр изменений").Cells(2, 1) = Environ("USERNAME") 'запись в первую ячейку второй строки 
Worksheets("Реестр изменений").Cells(2, 2) = Now 'запись во вторую ячейку второй строки 
ActiveWorkbook.Save 

End Sub 

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

Worksheets("Реестр изменений").Rows("2:2").Insert Shift:=xlDown 'вставляем между строками 1 и 2 новую строку 
Worksheets("Реестр изменений").Rows("1001:1001").Delete Shift:=xlUp 'удаляем строку 1001 (реестр на 1000 строк) 
Worksheets("Реестр изменений").Cells(2, 1) = Environ("USERNAME") 'запись в первую ячейку второй строки 
Worksheets("Реестр изменений").Cells(2, 3) = Now 'запись в третью ячейку второй строки 
  
End Sub 

Private Sub Workbook_BeforeClose(Cancel As Boolean) 
    
   If Not Me.Saved Then 

       fmQueryClose.Show 

       Select Case fmQueryClose.DialogResult 
           Case VbMsgBoxResult.vbYes: Me.Save 
               Worksheets("Предупреждение").Visible = True 'скрываем все листы, кроме листа ПРЕДУПРЕЖДЕНИЕ 
               For Each sh In ActiveWorkbook.Worksheets 
                   If sh.Name = "Предупреждение" Then 
                       sh.Visible = True 
                   Else 
                       sh.Visible = xlSheetVeryHidden 
                   End If 
               Next sh 
               ActiveWorkbook.Save 
           Case VbMsgBoxResult.vbNo: Me.Saved = True 
                
>>>> Тут как раз и нужен код на откат всех изменений <<<< 

               Worksheets("Предупреждение").Visible = True 'скрываем все листы, кроме листа ПРЕДУПРЕЖДЕНИЕ 
               For Each sh In ActiveWorkbook.Worksheets 
                   If sh.Name = "Предупреждение" Then 
                       sh.Visible = True 
                   Else 
                       sh.Visible = xlSheetVeryHidden 
                   End If 
               Next sh 
               ActiveWorkbook.Save 

           Case VbMsgBoxResult.vbCancel: Cancel = True 
            
       End Select 
       Unload fmQueryClose 
   End If 
End Sub 

При выходе без сохранения я подумал именно про откаты(Undo), т.к. вручную-то я могу после открытия откатить все, что исправил в ячейках, зажатием Ctrl+Z.
Получаем только открытый открытый файл, но после отката нужно скрыть все страницы.

Цитата
До какого момента, кстати?
Откат до открытия файла
Цитата
Как понять, когда закончить откатывать?
Закончить откат, когда уже нечего отменять (кнопка Undo будет неактивна)
Цитата
Ведь количество откатов может быть разным на разных ПК.
Да, кто-то может 1 ячейку косякнуть и выйти, а кто-то и 40.
в файле в принципе не более 100 ячеек для ввода данных (остальное ВПРом подцепляется в зависимости от того что ввели в исходных + математические формулы )
Цитата
Да и событие-то какое: перед сохранением.
Да, уже подумал что лучше перед выходом + форма (то о чем я писал выше. Надеюсь из кода понятно что я хочу)
Цитата
Через Undo это сделать нереально.
Спасибо, я не знал. Надеюсь, сейчас подскажите, как сделать то, что мне нужно)

Ну если что, буду использовать методы для отмены действий макросов (по идее должно помочь)
Изменено: RoMuLX - 17.06.2017 13:18:13
 
Цитата
kuklp написал:
P.S. а оформить код просто - кнопка   на панели редактирования.
Цитата
Юрий М написал:
По поводу кода: ищите такую кнопку и заодно отформатируйте с её помощью своё стартовое сообщение.
Спасибо!
я первый раз так нажал и код вставился весть в 1 строчку,  а щас почему-то сработало как надо)))
 
Цитата
RoMuLX написал:
я первый раз так нажал и код вставился весть в 1 строчку
У меня тоже так. Нажимаю F5 - обновляется, и всё в порядке )
 
В вашем случае оптимально делать просто копию листа на временном листе книги(скрытом). И в нужный момент просто копировать оттуда все ячейки на рабочий лист. И никаких откатов не надо отслеживать.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
The_Prist написал:
В вашем случае оптимально делать просто копию листа на временном листе книги(скрытом). И в нужный момент просто копировать оттуда все ячейки на рабочий лист. И никаких откатов не надо отслеживать.
Спасибо! буду искать нужную тему и пробовать)

Надеюсь у меня получится: у меня в файле 6 вкладок расчетов и в каждой только от 5 до 100 ячеек для заполнения в разных местах листа, остальные ячейки с формулами и защищены паролем от изменений. и еще 6 вкладок сводящих результаты с предыдущих листов.
Страницы: 1
Наверх