保存用シートにセルをコピペしておいて、もとに戻す処理でそこから元のシートにコピペという、かなり強引な力技での危険な疑似アンドゥ・リドゥ
マクロや
VBAで処理したことに対してエクセルの元に戻す(Ctrl+z)ややり直しは使えない
事前に保存していなくて間違って実行したら手動で戻すしか無い
一歩間違えると自動実行が強制手動実行になってしまう、めんどくさい!
なので
複数回のアンドゥとリドゥ(戻すとやり直し)をするマクロを書いてみた
元に戻せる回数を3回にした時の動作
起動すると保存用シートを3枚と一時保存シートを1枚作成する
終了時にはこれらのシートは削除される
元に戻すややり直しボタンの右の数値はそれぞれの実行できる回数
マクロや
VBAで処理する前に対象となるセル範囲を保存用シートに
コピペと同時にコピペした場所も記憶してから
実行している
アンドゥ・リドゥ(元に戻す時ややり直し)の時は保存用シートからコピペしている
なのでアンドゥ・リドゥできるのはセルに対するマクロや
VBAだけ
できないのはセル、シート、ブックなどの削除や追加するもの…グラフや図形もだな
ここまで書いて思ったのは
シートまるごとコピペしたほうが早かったかな…
使い道としては1枚のシートに対するマクロ用
セルの値や書式を変更するようなマクロ
そのセル範囲がわかっているもので
実行した直後に間違いに気づいた時
限定的だな
できあがった時はなかなかいいものができたなあって思ったんだけど
これ書いていたらイマイチな気がしてきたw
さらにエラーの処理も書いていないからちょっと変なことをするとエラーになる
今回も作るときにどんなふうになればいいのかエクセルを使って考えた
順番に操作を行った時にどの値がどのに保存されればいいのとか
アンドゥ・リドゥでどういう状態になればいいのか
難しかったのは保存先の決定の辺り
元に戻せる回数の指定は
Const wsCount As Long = 3 '保存用シートの枚数(元に戻せる回数)
UserForm1の最初の方に書いてある↑の数値が元に戻せる回数の指定なので
3回じゃ足りない時は増やせばいい、多くても100までくらいにした方がいい?
標準モジュール
'ユーザーフォームをModelessで表示する
'セルやシートを変更、クリックできる状態で表示する
Sub ufshow()
UserForm1.Show vbModeless
End Sub
UserForm1のデザイン画面
4つのボタンと2つのラベルのそれぞれの名前
UserForm1に書いたマクロ
Dim TempSheet As Worksheet
Dim HOZONSheet() As Worksheet
Const wsCount As Long = 3
Dim undoCount As Long
Dim redoCount As Long
Dim saveCount As Long
Dim ima As mySousa
Dim mae As mySousa
Enum mySousa
nasi = 0
Sitei = 1
iUndo = 2
iRedo = 3
End Enum
Dim SAddress() As String, SSheetName() As String, SBookName() As String
Private Sub UserForm_Initialize()
mae = nasi
undoCount = 0
redoCount = 0
Call urLabelラベル表示更新
ReDim SAddress(wsCount - 1)
ReDim SSheetName(wsCount - 1)
ReDim SBookName(wsCount - 1)
ReDim HOZONSheet(wsCount - 1)
saveCount = 0
Dim nWS As Worksheet
Application.ScreenUpdating = False
For i = 0 To wsCount - 1
Set nWS = ThisWorkbook.Sheets.Add(Count:=1)
nWS.Name = "保存" & i
Set HOZONSheet(i) = nWS
Next
Set TempSheet = ThisWorkbook.Sheets.Add(Count:=1)
TempSheet.Name = "一時保存"
Application.ScreenUpdating = True
ThisWorkbook.Worksheets("Sheet1").Activate
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
With Application
.ScreenUpdating = False
.DisplayAlerts = False
For i = 0 To wsCount - 1
HOZONSheet(i).Delete
Next
TempSheet.Delete
.DisplayAlerts = True
.ScreenUpdating = True
End With
End Sub
Private Sub CommandButton1_Click()
Call myBefore前処理
Dim r As Range
Randomize
For Each r In Selection
r.Value = Int((10 - 0 + 1) * Rnd(10) - 0)
Next
Call myAfter後処理
End Sub
Private Sub CommandButton4_Click()
Call myBefore前処理
Dim r As Range
For Each r In Selection
If r.Value >= 5 Then
r.Interior.Color = RGB(255, 100, 100)
Else
r.Interior.Color = xlNone
End If
Next
Call myAfter後処理
End Sub
Private Sub CommandButton2_Click()
Call myUndoアンドゥ
End Sub
Private Sub CommandButton3_Click()
Call myRedoリドゥ
End Sub
Sub saveAddressアドレスの記録()
SAddress(saveCount) = Selection.Address
SSheetName(saveCount) = ActiveSheet.Name
SBookName(saveCount) = ActiveWorkbook.Name
End Sub
Sub toSaveSheet保存シートにコピペ()
Dim r As Range
Set r = HOZONSheet(saveCount).Range(SAddress(saveCount))
Selection.Copy r
Application.CutCopyMode = False
End Sub
Sub uAndrアンドゥリドゥの処理()
Dim hozonR As Range, tempR As Range
Set hozonR = Workbooks(SBookName(saveCount)).Sheets(SSheetName(saveCount)).Range(SAddress(saveCount))
Set tempR = TempSheet.Range(SAddress(saveCount))
hozonR.Copy tempR
HOZONSheet(saveCount).Range(SAddress(saveCount)).Copy hozonR
tempR.Copy HOZONSheet(saveCount).Range(SAddress(saveCount))
tempR.Clear
Application.CutCopyMode = False
End Sub
Sub myセーブ場所選択()
If ima = iUndo And mae = iUndo Then
If saveCount = 0 Then
saveCount = wsCount - 1
Else
saveCount = saveCount - 1
End If
ElseIf ima = iUndo Or mae = iUndo Then
ElseIf mae = nasi Then
saveCount = 0
ElseIf saveCount < wsCount - 1 Then
saveCount = saveCount + 1
ElseIf saveCount >= wsCount - 1 Then
saveCount = 0
End If
End Sub
Sub urLabelラベル表示更新()
Me.LabelRedo.Caption = redoCount
Me.LabelUndo.Caption = undoCount
End Sub
Public Sub myBefore前処理()
ima = Sitei
Call myセーブ場所選択
Call saveAddressアドレスの記録
Call toSaveSheet保存シートにコピペ
End Sub
Public Sub myAfter後処理()
If undoCount < wsCount Then
undoCount = undoCount + 1
End If
redoCount = 0
Call urLabelラベル表示更新
mae = Sitei
End Sub
Public Sub myUndoアンドゥ()
If undoCount = 0 Then Exit Sub
ima = iUndo
Call myセーブ場所選択
Call uAndrアンドゥリドゥの処理
undoCount = undoCount - 1
redoCount = redoCount + 1
Call urLabelラベル表示更新
mae = iUndo
End Sub
Public Sub myRedoリドゥ()
If redoCount = 0 Then Exit Sub
ima = iRedo
Call myセーブ場所選択
Call uAndrアンドゥリドゥの処理
undoCount = undoCount + 1
redoCount = redoCount - 1
Call urLabelラベル表示更新
mae = iRedo
End Sub
Call myBefore前処理
ここにアンドゥ・リドゥをしたい処理を書く
Call myAfter後処理
ダウンロード先
ファイル名:マクロで行った処理をマクロでアンドゥ・リドゥ.xlsm
この記事のつづきは
エクセルVBAでの処理をエクセルVBAで複数回のアンドゥ・リドゥ(元に戻すとやり直し)を書いてみた、その2 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
セル範囲じゃなくてシートごとコピペするようにした