У меня есть книга Excel, которая должна позволить пользователю отменить несколько изменений на листе. Я искал в Интернете на каждом форуме, о котором я могу думать, и не смог найти ответ для этого. Я понимаю, что есть проблема с проблемой отмены в excel, когда выполняются макросы, и они смогли обработать это с помощью кода, полученного из here.Как разрешить несколько последовательных отменить в excel vba?
Это мой текущий процесс:
Создание глобальных переменных для хранения начального состояния книги, и изменения. Код выглядит следующим образом:
Private Type SaveRange Val As Variant Addr As String End Type Private OldWorkbook As Workbook Private OldSheet As Worksheet Private OldSelection() As SaveRange Private OldSelectionCount As Integer Private InitialState() As SaveRange Private InitialStateCount As Integer
Получить начальное состояние книги путем создания массива (InitialState), удерживающий значения всех ячеек в суб Workbook_Open. Код выглядит следующим образом:
Private Sub Workbook_Open() GetInitialCellState End Sub Private Sub GetInitialCellState() Dim i As Integer, j As Integer, count As Integer Dim cellVal As String Dim sampID As Range, cell As Range Dim e1664 As Workbook Dim rawData As Worksheet Dim table As Range Dim LastRow As Integer, LastCol As Integer LastRow = Worksheets("Raw_Data").Range("A65536").End(xlUp).Row LastCol = Worksheets("Raw_Data").UsedRange.Columns.count Set e1664 = ThisWorkbook Set rawData = e1664.Sheets("Raw_Data") Set sampID = rawData.Range("SAMPLEID").Offset(1) Set table = rawData.Range(sampID, "R" & LastRow) i = 0 j = 0 count = 0 ReDim InitialState(i) For i = 0 To (LastRow - sampID.Row) For j = 0 To LastCol ReDim Preserve InitialState(count) InitialState(count).Addr = sampID.Offset(i, j).address InitialState(count).Val = sampID.Offset(i, j).Value count = count + 1 Next j Next i InitialStateCount = count - 1 End Sub
Когда значение вводится в ячейку, сохранить значение, введенное в другой массив (OldSelection), держащего введенное значение. Это делается в подменю Workbook_Change. Важными частями здесь являются Call SaveState (OldSelectionCount, Target.Cells.address, Target.Cells.Value) и Application.OnUndo «Отменить последнее действие», «GI.OR.E1664.20150915_DRAFT.xlt! Sheet1. RevertState ", которые показаны в цифрах 4 и 5 ниже. Код выглядит следующим образом:
Private Sub Worksheet_Change(ByVal Target As Range) Dim cell As Range, InWtRange As Boolean Dim y As Integer, x As Integer, count As Integer Dim LastRow As Integer 'This saves the changed values of the cells Call SaveState(OldSelectionCount, Target.Cells.address, Target.Cells.Value) try: y = Me.Range("SampleID").Row If Target.Column > 5 And Target.Column < 8 Then If Range("A" & Target.Row).Value = Range("A" & Target.Row + 1).Value Then If Range("A" & Target.Row + 1).Value <> "" Then Range(Target.address).Offset(1).Value = Range(Target.address).Value End If End If Else 'If initial pan weight add start date If Target.Column = 8 Then If Target.Cells.Text <> "" Then If Not IsNumeric(Target.Cells.Value) Then GoTo Finally Else Application.EnableEvents = False Range("StartDate").Offset(Target.Cells.Row - y).Value = Format(Now(), "MM/DD/YY HH:NN:SS") Application.EnableEvents = True End If Else Application.EnableEvents = False Range("StartDate").Offset(Target.Cells.Row - y).Value = "" Application.EnableEvents = True End If End If End If LastRow = Worksheets("Raw_Data").Range("A65536").End(xlUp).Row For Each cell In Target.Cells 'Debug.Print Target.Cells.Address If cell.Value <> "" Then If Not IsNumeric(cell.Value) Then GoTo Finally Select Case cell.Column Case 9, 11, 13 Application.EnableEvents = False If CalcHEM(cell.Row - y, cell.Column) Then End If Application.EnableEvents = True Case Else 'Do nothing yet End Select 'Cells(Target.Row + 1, Target.Column).Select End If Next 'This will allow the changed values to be undone Application.OnUndo "Undo the last action", "GI.OR.E1664.20150915_DRAFT.xlt!Sheet1.RevertState" Finally: If Application.EnableEvents = False Then Application.EnableEvents = True Exit Sub Catch: MsgBox "An error has occurred in the code execution." & vbNewLine _ & "The message text of the error is: " & Error(Err), vbInformation, "TSSCalcs.AddQC" Resume Finally End Sub
Суб SaveState сохранит добавить в массив OldSelection, любые значения, которые изменились. Код выглядит следующим образом:
Private Sub SaveState(count As Integer, Addr As String, Val As Double) Dim i As Integer Dim cell As Range If TypeName(Selection) <> "Range" Or Selection.count > 1 Then Exit Sub ReDim Preserve OldSelection(count) Set OldWorkbook = ActiveWorkbook Set OldSheet = ActiveSheet For Each cell In Selection OldSelection(count).Addr = Addr OldSelection(count).Val = Val Next cell OldSelectionCount = OldSelectionCount + 1 End Sub
Суб RevertState будет отменить только последнее действие! Я не могу разрешить отмену последней записи. Код выглядит следующим образом:
Private Sub RevertState() Dim i As Integer, index As Integer Dim prevItem As SaveRange Dim address As String OldWorkbook.Activate OldSheet.Activate Application.EnableEvents = False address = OldSelection(OldSelectionCount - 1).Addr OldSelectionCount = OldSelectionCount - 2 If OldSelectionCount <= 0 Then ReDim OldSelection(0) For i = 0 To InitialStateCount If InitialState(i).Addr = address Then prevItem.Val = InitialState(i).Val index = i End If Next i Range(InitialState(index).Addr).Formula = prevItem.Val Else ReDim Preserve OldSelection(OldSelectionCount) For i = 0 To OldSelectionCount If OldSelection(i).Addr = address Then prevItem.Val = OldSelection(i).Val index = i End If Next i 'OldSelectionCount = OldSelectionCount + 1 Range(OldSelection(index).Addr).Formula = prevItem.Val End If OldSelectionCount = OldSelectionCount + 1 Application.EnableEvents = True End Sub
Кто-нибудь знает способ, чтобы позволить многократный откат, чтобы сделать?
Любая помощь для решения этой проблемы была бы принята с благодарностью!
Работал над аналогичной проблемой в прошлом (а не в Excel), и идея заключалась в создании своего рода структуры стека, чтобы сохранить последовательность состояний, вместо сохранения только одного состояния. –
Вы можете найти эту статью и пример, интересные вашему проекту. Создание обработчика отмены для отмены изменений, выполненных с помощью Excel VBA и примера отмены отладки –
skkakkar
Две ссылки, которые вы мне отправили, не работают, но ссылка, содержащая информацию, на которую вы ссылаетесь, должна быть [здесь] (http://www.jkp-ads.com/Articles/ UndoWithVBA00.asp). Хотя это хорошая информация, код требует большей отладки, чем того стоит. Реальная проблема связана с методом onUndo. Я хотел бы использовать Microsoft, если это возможно, но может быть проще просто написать мою собственную. Если я найду решение, я опубликую его. – DiggityCS