Mantalog

~ blog of the Mantarou, by the Mantarou, for the Mantarou ~

Visual Studioでコピーした文字列を、文字色を保持してExcelに貼り付けるアドインを作ってみた

Visual Studioでコピーしたソースコードを、文字色を保持してExcelに貼り付けたい場面があると思います。ですが、標準の機能ではできません。テキストだけ貼り付けられてしまいます。ということでExcelアドインを作りました。

RichTextPaste for Excel


ネットで調べると「Productivity Power Tools extension」というVisual Studio拡張機能の「HTMLコピー」を使えばいいらしいのですが、Express Editionでは使えないので今回は作ることにしました。
さらに、Visual Studio 2010 Expressあたりで、コピーした文字列をWordに貼り付けると文字化けするという不具合があったので、それも修正した状態で貼り付けるようになってます。
なお、セルではなくオートシェイプに貼り付けた場合は文字色が保持されるようです。

機能概要

Excelアドインをインストールするだけで機能が有効になります。
Visual Studioソースコードをコピーして、Excelに貼り付ければ勝手に文字色が保持されて貼り付けられます。
f:id:mantarou-tarou:20140226234220p:plain

f:id:mantarou-tarou:20140226234216p:plain

インストール方法

  1. 下記のリンクから「RichTextPaste_***.zip」をダウンロードします。
  2. ダウンロードしたファイルを解凍します。
  3. 全てのファイルに対して「ブロックの解除」を行います。
    やり方は、ファイルを右クリックしてプロパティを開き、「ブロックの解除」をクリックして「OK」をクリックします。面倒ですが1ファイルずつ行ってください。まとめて行うソフトもあるようなので、それを使っても大丈夫です。
    f:id:mantarou-tarou:20140227003459p:plain
  4. 「setup.exe」を実行します。

動作原理

Visual Studioでコピーすると、クリップボードに複数の形式でコピーされます。その形式に「Rich Text」はありますが「HTML」はありません。Excelは、貼り付け時に「HTML」形式のテキストがあれば文字色を保持して貼り付けますが、その形式が無い場合はテキストのみ貼り付けます。(動作を見てみての推測。)
ということで、アドインの動作は、Excelがアクティブになった時にクリップボードをチェックして、「Rich Text」形式があって「HTML」形式が無い場合、「Rich Text」からコンバードして生成した「HTML」形式の情報をクリップボードに追加します。

動作メモ

Excelのアクティブの検知

Excelのアクティブの検知は、以下のようにSetWinEventHookで行っています。
この関数だと、C#でもフックができるようです。

    public class ExcelWindow : IDisposable
    {
        delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

        [DllImport("user32.dll")]
        static extern bool UnhookWinEvent(IntPtr hWinEventHook);

        private Excel.Application m_excel;
        private WinEventDelegate  m_eventProc;
        private IntPtr            m_WinEventHook;

        public event EventHandler Activate;

        public ExcelWindow(Excel.Application excel)
        {
            const uint EVENT_SYSTEM_FOREGROUND = 3;

            m_excel        = excel;
            m_eventProc    = new WinEventDelegate(winEventProc); // メンバ変数にコピーしないとガベコレに解放されてエラー
            m_WinEventHook = SetWinEventHook((uint) EVENT_SYSTEM_FOREGROUND,
                                             (uint) EVENT_SYSTEM_FOREGROUND,
                                             (IntPtr) 0,
                                             m_eventProc,
                                             (uint) 0,
                                             (uint) 0,
                                             (uint) 0);
        }

        void winEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            if (hwnd.ToInt32() == m_excel.Hwnd)
            {
                if (Activate != null)
                {
                    Activate(this, new EventArgs());
                }
            }
        }

        #region IDisposable

        public void Dispose()
        {
            m_excel = null;
            UnhookWinEvent(m_WinEventHook);
        }

        #endregion
    }

HTMLテキストをクリップボード用テキストに変換

Copying an HTML-fragment to the Clipboard
http://blog.tcx.be/2005/08/copying-html-fragment-to-clipboard.html

Visual Studio 2010の不具合での文字化け問題

Visual Studio 2010 からソースコードPowerPoint にコピーすると文字化けする
http://ufcpp.wordpress.com/2010/05/11/

Click Once用の証明書の作成

makecert -r -pe -n "CN=mantarou" -sv RichTextPaste.pvk RichTextPaste.cer
pvk2pfx -pvk RichTextPaste.pvk -spc RichTextPaste.cer -pfx RichTextPaste.pfx -po "*********"

ClickOnceマニフェストに署名するためのテスト用の証明書を作成する
http://quickprogram.blogspot.jp/2010/03/vc-clickonce.html

クリップボードの状態の確認

デバッグクリップボードの中身を見たくなったので使いました。

Free Clipboard Viewer
http://www.freeclipboardviewer.com/