11

I'm building a VSTO Excel add-in that manipulates the values of multiple cells. I would like to allow the user to undo and redo the changes created by the add-in via the standard Excel features. I prefer to avoid using VBA.

Is this possible? If so, how?

Another question: is it possible to examine the existing undo/redo stack?

4 Answers 4

5
+25

You failed to mention which version of Excel/.NET/VSTO runtime you wish to use, but it does not really matter :]
Custom Undo just cannot be done without injecting VBA, where you would need to set an undo method for rolling back your actions, by using compensation (i.e. reverse operations) or by restoring a saved state.

4

I know you want to avoid VBA but as others have mentioned, this is not really possible to get the Undo.

Here is a VBA example that preserves the existing selection as custom data type so that it can be undone later.

Option Explicit
'Stores info about current selection'
Public OldWorkbook As Workbook
Public OldSheet As Worksheet
Public OldSelection() As SaveRange

'Custom data type for undoing'
Type SaveRange
    Value As Variant
    Address As String
End Type

Public Sub YourSubRoutine()
    'A simple subroutine that acts on a Range selection'
    Dim UserRange As Range

    Set UserRange = Selection


    If UserRange Is Nothing Then
        Exit Sub
    End If

'## The next block of statements '
'## Save the current values for undoing '
    Set OldWorkbook = ActiveWorkbook
    Set OldSheet = ActiveSheet

    Application.ScreenUpdating = False

    '## Code to manipulate the Selection range '
    '## Code to manipulate the Selection range '
    '## Code to manipulate the Selection range '

    '## Specify the Undo Sub '
    Application.OnUndo "Undo the YourSubRoutine macro", "UndoYourSubRoutine"

End Sub
Public Sub UndoYourSubRoutine()

Dim i As Integer

'   Undoes the effect of the YourSubRoutine '

'   Tell user if a problem occurs '
    On Error GoTo Problem

    Application.ScreenUpdating = False

'##  Make sure the correct workbook and sheet are active '
    OldWorkbook.Activate
    OldSheet.Activate

'## Restore the saved information '
    For i = 1 To UBound(OldSelection)
        Range(OldSelection(i).Address).Value = OldSelection(i).Value
    Next i
    Exit Sub

'   Error handler'
Problem:
    MsgBox "Can't undo"

End Sub
4
  • Could I generate and inject VBA from C# with some sort of unique ID, store the ID in my app as mapped to a state transform, and have the sub itself just be a callback to C# that when invoked, reverses the transform? Commented Apr 26, 2013 at 2:44
  • er, can't edit my comment...something like combining this stackoverflow.com/questions/15196534/… with this msdn.microsoft.com/en-us/library/vstudio/… maybe? Commented Apr 26, 2013 at 2:54
  • kind of out of my element here, but skimming those it seems possible to combine those methods. Ultimately, you will need to either reverse the procedures, or store a copy of the affected data in memory, and revert to that state on the Undo call. Seems like either could be done in C# -- but tying them in to Excel's standard interface (e.g., Ctrl+Zhotkey for Undo, etc) would require some code injection -- even if it is simply a VBA soubroutine to call an external Object (C#) to perform the "undo". Commented Apr 26, 2013 at 3:17
  • 6
    An alternative to VBA for the OnUndo routine might be to have your C# macro in an Excel-DNA add-in. Excel-DNA registers functions and procedures with the native Excel C API, so you don't have the VSTO limitations.
    – Govert
    Commented Apr 26, 2013 at 13:56
0

You can add operations to the stack by using:

Application.OnUndo text, procedureName

Where Text is the text that appears with the Undo command (Edit menu) and procedureName is a name of one of your subs. You can also programatically undo operations by using:

Application.Undo

I don't think it's possible to access existing undo operations; at least I've never heard of any. There may be a library that you can access online that will allow this.

Hope this helps.

1
  • ...meaning I would need to use VBA? Commented Apr 17, 2013 at 0:52
-1

The solution I actually went with was the following:

  • Save a copy of the clipboard state
  • Clear the clipboard
  • Generate the data I want in a tab/newline delimited format, push it to the clipboard
  • Simulate a Ctrl+V operation to Excel
  • Clear the clipboard
  • Restore the original clipboard state

Obviously this is localized to cell manipulations, so you can't push arbitrary operations/callbacks to the undo stack. Also, I'm clearly violating principles around clipboard use in Windows, but if Microsoft exposed a better API for such things (hint), I wouldn't have to.

Additionally, I didn't go with the solution I described in the first comment on David Zemens' answer because I hit some security violations in our environment (i.e., injecting VBA code into a workbook is a no-no).

Anyways, thanks everybody!

1
  • Hijacking the clipboard is not feasible because you could potentially overwrite user's contents and they will be really mad if you do that.
    – Leo G.
    Commented Sep 14, 2016 at 17:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.