Question

ふぅみん.えがち on Thu, 24 Aug 2017 07:57:00


CustomXMLParts への変更を、Undo エントリに追加することはできないのでしょうか?

CustomXmlParts.Add() の前に Application.StartNewUndoEntry() を呼び出しても、Undoエントリが追加されません。

確認に使用したのは、PowerPoint 2016 & VisualStudio 2017 です。

よろしくお願いいたします。


Sponsored



Replies

gekka on Thu, 24 Aug 2017 11:31:57


そのような機能はないですね。
あくまでユーザー操作に対してのUndoRedoなのでコードでしか行えないことは記録しないのでしょう。

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Office.Tools.Ribbon;

namespace PowerPointAddIn1
{
    public partial class Ribbon1
    {
        Microsoft.Office.Core.CommandBarComboBox undoCombo;

        System.Windows.Forms.Timer timer;
        List<string> list = new List<string>();
        Dictionary<string, UndoRedoItem> undoredo = new Dictionary<string, UndoRedoItem>();

        private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
        {
            //元に戻すボタンを探す
            undoCombo = Globals.ThisAddIn.Application.CommandBars.FindControl(Type.Missing, 128) as Microsoft.Office.Core.CommandBarComboBox;

            timer = new System.Windows.Forms.Timer();
            timer.Tick += timer_Tick;
            timer.Interval = 1;
            timer.Start();
        }

        private void button1_Click(object sender, RibbonControlEventArgs e)
        {
            string xml = "<sample>あああ</sample>";
            var app = Globals.ThisAddIn.Application;

            UndoRedoItem item = new UndoRedoItem(app.ActivePresentation, xml);
            undoredo.Add(item.part.Id, item);

            app.StartNewUndoEntry();
            app.ActivePresentation.SetUndoText(item.part.Id);//Undoに名前を付ける
        }


        void timer_Tick(object sender, EventArgs e)
        {
            List<string> newlist = new List<string>();
            int count = 0;
            try
            {
                count = undoCombo.ListCount;
            }
            catch
            {
            }

            for (int i = 1; i <= count; i++)
            {
                //元に戻せるリストの名前を取得する
                newlist.Add(undoCombo.List[i]);
            }

            foreach (string guid in undoredo.Keys.ToArray())
            {         
                //名前を比較して対象の操作がリストから消えたかどうかを調べてみる
                if (list.Contains(guid) && !newlist.Contains(guid))
                {
                    //Undoされたか、Undoで戻れなくなった
                    //新旧リストを比較すればUndoと確定できるかもしれない
                    if (list.Count > newlist.Count) //条件追記
                    {
                        UndoRedoItem item = undoredo[guid];
                        item.Undo();
                    }
                    undoredo.Remove(guid);

                    //戻してもRedoで再度リストに登録されるわけではないので意味がない...
                }
            }
            this.list = newlist;
        }



        class UndoRedoItem
        {
            public Microsoft.Office.Core.CustomXMLPart part { get; private set; }
            public Microsoft.Office.Interop.PowerPoint.Presentation pre { get; private set; }

            string xml;

            public UndoRedoItem(Microsoft.Office.Interop.PowerPoint.Presentation pre, string xml)
            {
                this.pre = pre;
                this.xml = xml;
                Redo();
            }
            public void Redo()
            {
                if (part != null) { throw new InvalidOperationException(); }
                this.part = this.pre.CustomXMLParts.Add(this.xml);
            }
            public void Undo()
            {
                if (part != null)
                {
                    this.part.Delete();
                }
            }
        }

    }
}


個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

ふぅみん.えがち on Thu, 07 Sep 2017 03:21:29


gekka様

ありがとうございます。

Undo, Redoに関しては、当座諦めます。