Visual Studioでコピーした文字列を、文字色を保持してExcelに貼り付けるアドインを作ってみた
Visual Studioでコピーしたソースコードを、文字色を保持してExcelに貼り付けたい場面があると思います。ですが、標準の機能ではできません。テキストだけ貼り付けられてしまいます。ということでExcelアドインを作りました。
ネットで調べると「Productivity Power Tools extension」というVisual Studio拡張機能の「HTMLコピー」を使えばいいらしいのですが、Express Editionでは使えないので今回は作ることにしました。
さらに、Visual Studio 2010 Expressあたりで、コピーした文字列をWordに貼り付けると文字化けするという不具合があったので、それも修正した状態で貼り付けるようになってます。
なお、セルではなくオートシェイプに貼り付けた場合は文字色が保持されるようです。
インストール方法
- 下記のリンクから「RichTextPaste_***.zip」をダウンロードします。
- ダウンロードしたファイルを解凍します。
- 全てのファイルに対して「ブロックの解除」を行います。
やり方は、ファイルを右クリックしてプロパティを開き、「ブロックの解除」をクリックして「OK」をクリックします。面倒ですが1ファイルずつ行ってください。まとめて行うソフトもあるようなので、それを使っても大丈夫です。 - 「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 }
Rich Text→HTMLの変換
RTF Converter
http://www.codeproject.com/Articles/27431/Writing-Your-Own-RTF-Converter
C#でクリップボードにデータを追加 (新規セットではなく追加)
クリップボードにHTMLデータを貼り付ける
http://azumaya.s101.xrea.com/wiki/index.php?%B3%D0%BD%F1%2FC%A2%F4%2F%A5%AF%A5%EA%A5%C3%A5%D7%A5%DC%A1%BC%A5%C9%A4%CBHTML%A5%C7%A1%BC%A5%BF%A4%F2%C5%BD%A4%EA%C9%D5%A4%B1%A4%EB
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/
ローカル環境のHTML開発で「/」を指定しても「index.html」を開くchrome拡張機能を作ってみた
ローカル環境でHTML開発をしている場合、「/」を指定しているリンクはフォルダを開いちゃって面倒です。ですが「index.html」を開く方法をネットで探しても、Webサーバを立てるという解決策が多く、これはちょっと面倒くさい。ということでファイル名を省略していても「index.html」を補完して開くchrome拡張機能を作ってみました。
機能概要
・リンク先のhtmlファイルがローカル環境で、(※1)
フォルダ指定している場合、(※2)
「index.html」のファイルの存在をチェックして、(※3)
ファイルがある場合は補完してリンク先を開きます。
ファイルが無い場合は、元のリンク先を開きます。
※1:リンク先が「file://」で始まると判断した場合をローカル環境としています
※2:リンク先が「*.htm」or「*.html」で終わらない場合、フォルダ指定とみなします。
※3:ファイルの存在は、「index.html」→「index.htm」→「default.html」→「default.htm」の順番でチェックします。
インストール方法
- 以下からredirectIndex.crxをダウンロードします。
ダウンロードはここ - redirectIndex.crxを拡張機能画面にドラッグアンドドロップして追加します。
インストール方法の詳細は、ここのHPがわかりやすかったです。
Chromeにcrxファイルのインストール - ねとめもー - 「ファイルの URL へのアクセスを許可する」をチェックします。
実装メモ
参考HP1
chrome拡張機能の作り方の基本は、ここで勉強しました。
本当に必要なポイントのみを書いているので、シンプルでわかりやすいです。
http://www.casleyconsulting.co.jp/blog-engineer/chrome/chrome%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%81%AE%E4%BD%9C%E6%88%90%E6%96%B9%E6%B3%95-2/
参考HP2
chrome拡張機能でjQueryを使用する場合の"contents_scripts"の"js"の書き方は、ここを参考にしました。
http://d.hatena.ne.jp/ksk_kbys/20111109/1320849314
参考HP3
相対パスから絶対パスを求める方法は、ここを参考にしました。
ローカル環境でも問題なく使えました。
http://www.kaasan.info/archives/1856
参考HP4
ファイルの有無のチェックは、ここを参考にしました。
ローカル環境でも問題なく使えました。
http://stackoverflow.com/questions/5163690/check-if-htm-file-exists-on-local-disk-using-javascript
リンク先の書き換え
リンク先の書き換えは、jQueryを使って以下のようにしました。
$(function() { $("a").click(function(){ $(this).attr('href', 新しいリンク先); }); });
リボンからマクロを実行するPowerPointアドインを作成する
「PowerPointで使用しているフォントを集計するマクロを作ってみた」で作ったマクロの解説の続きです。
前回はマクロの内部の説明を行いましたが、今回はリボンから実行できるようにする方法です。
参考HP
このHPを参考にさせていただきました。
http://homepage2.nifty.com/suyamsoft/Ribbon/Excel2010/RibbonEditor/
Office Ribbon Editorのダウンロード
Office Ribbon Editorを使用することで、簡単にリボンをカスタマイズするファイルを作成できます。
ということで、下記のサイトからダウンロードしてインストールします。
http://www.leafcreations.org/
インストールはダウンロードした*.exeを実行して、[Next]を選択していけばOKです。
リボンの設定
Office Ribbon Editorを使って、PowerPoint上に表示するリボンの詳細と、ボタンを押したときに実行するマクロを設定します。
- Office Ribbon Editorの起動します。
- Office Ribbon Editorで、マクロを作ったPowerPointファイルを開きます。
- 画面右の[Document Explorer]からファイル名を右クリックして[Add CustomUI]→[Office 2007]を選択します。
- [RibbonX12]をダブルクリックします。
- 画面中央の[Code]タブにリボンの情報を書き込みます。
今回は、ボタンを押してマクロを実行する簡単なものなので、画面左の[Toolbox]の[Samples]タブから[Office 2007]→[Custom Ribbon]を選択して、サンプルを入力します。 - 入力されたサンプルを参考に、必要な部分を編集します。
id:ユニークであれば何でもいいはずです。
label:画面に表示するテキストです。
buttonのonAction:後で作成するマクロの関数名にします。
buttonのimageMso:リボンに表示する画像です。ここやこれを参照して、表示したい画像の名前を設定します。 - 保存します。
これで、Office Ribbon Editorでの作業は終了です。[Callbacks]にマクロを書きたいところですが、なぜか保存できないので、これ以降はPowerPointで作業します。
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"> <ribbon startFromScratch="false"> <tabs> <tab id="aggregateTab" label="Aggregate"> <group id="aggregateGroup" label="Aggregate Font in Use"> <button id="aggregateButton" label="Aggregate" imageMso="ExportExcel" size="large" onAction="AggregateFontInUse" /> </group> </tab> </tabs> </ribbon> </customUI>
ボタンを押したときに実行する関数の作成
- リボンの設定を行ったPowerPointのファイルを開きます。
- [Alt + F11]でVBEを開きます。
- リボンのボタンを押したときに実行する関数を作成します。
関数名はxmlの"onAction"で設定した名前にします。
引数は"IRibbonControl"型にします。
Public Sub AggregateFontInUse(control As IRibbonControl) Call aggregateFontInUseSub End Sub
アドインとして保存
- "名前を付けて保存"でファイルの種類を"PowerPoint アドイン (*.ppam)"とすれば完成です。
PowerPointの使用中フォント集計マクロの解説
「PowerPointで使用しているフォントを集計するマクロを作ってみた」で作ったマクロの解説です。
PowerPointマクロの作り方
- 「新しいプレゼンテーション」でファイルを新規作成します。
まあ実際はなんでもいいのですが。 - [Alt + F11]を押してVBE(Visual Basic Editor)を開きます。
- [VBAProject (プレゼンテーション1)」を右クリック→「挿入」→「標準モジュール」をクリックします。
- エディタ部分にマクロを書きます。
- 実行したいマクロにカーソルを合わせて[F5]で実行します。
マクロの解説
全てのスライドのすべてのオブジェクトを走査する
Private Sub checkAllSlides() Dim sld As Slide For Each sld In ActivePresentation.Slides Dim sh As Shape For Each sh In sld.Shapes ' shにオブジェクトが入ってくるので、それを使う Next Next End Sub
テキストを持っているオブジェクトからテキストを取得する
プレイスホルダやオートシェイプなどのテキストを持っているオブジェクトからのテキストの取得方法です。
Shape::HasTextFrameでテキストの有無をチェックしてから、TextFrame.TextRange.Textで取得します。
If sh.HasTextFrame Then Debug.Print sh.TextFrame.TextRange.Text End If
グラフからテキストを取得する
グラフの各場所のテキストの取得方法です。
Shape::TypeがmsoChartの場合、またはShape::HasChartがTrueの場合がグラフのはずなので、その場合にタイトル、凡例、軸のタイトル、軸のテキストを取得します。
If sh.Type = msoChart Or sh.HasChart Then Dim txt ' タイトル If sh.Chart.HasTitle Then Debug.Print sh.Chart.ChartTitle.Text End If ' 凡例 If sh.Chart.HasLegend Then For Each txt In sh.Chart.SeriesCollection Debug.Print txt.Name Next End If ' X軸Y軸 Dim ax For Each ax In sh.Chart.Axes ' 軸のタイトル If ax.HasTitle Then Debug.Print ax.AxisTitle.Text End If '------------- ' 軸のテキスト '------------- ' 項目軸 or 系列軸(3Dグラフのみ) If ax.Type = XlAxisType.xlCategory Or _ ax.Type = XlAxisType.xlSeriesAxis Then For Each txt In ax.CategoryNames Debug.Print txt Next ' 数値軸 ElseIf ax.Type = XlAxisType.xlValue Then Dim num As Double For num = ax.MinimumScale To ax.MaximumScale Step ax.MajorUnit Debug.Print num Next End If Next End If
表からテキストを取得する
表のテキストの取得方法です。
Shape::TypeがmsoTableの場合、またはShape::HasTableがTrueの場合が表のはずなので、その場合に各セルのテキストを取得します。
If sh.Type = msoTable Or sh.HasTable Then Dim col As Column Dim c As Cell For Each col In sh.Table.Columns For Each c In col.Cells Debug.Print c.Shape.TextFrame.TextRange.Text Next Next End If
スマートアートからテキストを取得する
スマートアートからのテキストの取得方法です。
Shape::TypeがmsoSmartArtの場合、またはShape::HasSmartArtがTrueの場合がスマートアートのはずなので、その場合に各ノードのテキストを取得します。
ただし、PowerPoint2010以降にしかHasSmartArtメソッドが無いため、バージョン確認後に詳細をチェックします。
' こっちがチェックしてテキストを取得する処理 If checkHasSmartArt(sh) Then Dim n As SmartArtNode For Each n In sh.SmartArt.Nodes Debug.Print n.TextFrame2.TextRange.Text Next End If ' こっちがチェックするための関数 ' shの型をShapeに固定するとPowerPoint2010以前でエラーになるので型指定しない Private Function checkHasSmartArt(sh) As Boolean checkHasSmartArt = False ' PowerPoint 2010以降のみ If Application.Version >= 15 Then If sh.Type = msoSmartArt Or sh.HasSmartArt Then checkHasSmartArt = True End If End If End Function
グループ化されているオブジェクトからテキストを取得する
グループ化されている場合は、グループ内の各オブジェクトに対して再帰的にテキストを取得します。Shape::TypeがmsoGroupの場合がグループです。
If sh.Type = msoGroup Then Dim groupSh As Shape For Each groupSh In sh.GroupItems ' groupShに対して、再度テキスト取得処理を行う。 Next End If
PowerPointからExcelを操作する
CreateObjectでExcel.Applicationを生成すれば、あとは自由自在です。
' Excelの生成 Dim xlApp Set xlApp = CreateObject("Excel.Application") ' 画面に表示 xlApp.Visible = True ' 新規ワークブック生成 xlApp.Workbooks.Add ' セルを変更 xlApp.Workbooks(1).Worksheets(1).Cells(1, 1) = "Test" ' Excelを解放 Set xlApp = Nothing
PowerPointで使用しているフォントを集計するマクロを作ってみた
PowerPointの資料で、複数フォントが混在していると格好悪い。
ということで、フォントの混在を発見するために、使用しているフォントを集計して一覧出力するマクロを作成しました。
作り方に関しては、以下を参照してください。
PowerPointの使用中フォント集計マクロの解説 - Mantalog
リボンからマクロを実行するPowerPointアドインを作成する - Mantalog
使い方
- 集計したいPowerPointファイルを開きます。
- リボンから「Aggregate」をクリックします。
- 集計結果がExcelファイルに出力されます。
インストール方法
「bugspots」のWindows版を作ってみた
もう2年も前ですが、googleのバグ予測アルゴリズムを実装した「bugspots」というツールが発表されました。
本家のWebサイト
https://github.com/igrigorik/bugspots
http://google-engtools.blogspot.jp/2011/12/bug-prediction-at-google.html
SVN版を作ってくれた方
http://szk-takanori.hatenablog.com/entry/20120109/p1
気にはなっていたのですが、いままでバグ予測をしたい場面が無かったので放置してました。ですが、ちょっと最近これを使用したくなりましたので、自分用にカスタマイズした
bugspots.net
を作ってみました。
オリジナルからの変更点は以下の通りです。
- Windowsで動作する (.net framework 4.0が必要)
- リポジトリはSVN限定
- RedmineやTracでチケット管理していても使えるように
正規表現と外出しリストファイルで解析対象を指定 - グラフィカルな表示
- などなど
2年経っても誰も作ってなかったので需要は無いかもしれませんが、現場のQA担当の方など試してみてください。
簡単な使い方
- 「URL」に解析したいリポジトリを入力
- 「Execute」ボタンを押下
- しばし待つ
- 「Maximum」や「Total」が大きいところが怪しいので、
そのあたりのファイルを調査
使い方
- URL
リポジトリのURLを入力します。
例えば、http://server/svn/trunk/ - Username、Password
リポジトリにアクセスするユーザ名とパスワードを入力します。 - View file list
後述する「Filter regex」を指定すると、ファイル一覧には解析対象のみが表示されます。全ファイルを表示したい場合、この設定を変更します。
処理が重くなるため、Disable推奨です。
- Disable:解析対象のみを表示します
- All files:解析対象以外の全ファイルを表示します。ただし外部参照は表示しません。
- All files (including externals):解析対象以外の全ファイルを表示します。外部参照も表示します。 - Start revision、End revision
解析対象の開始リビジョン・終了リビジョンを入力します。
推奨は空欄で、その場合は全てのリビジョンが対象になります。
ただし「Limit」での制限はかかります。 - Limit
解析対象のログの数を入力します。
空欄の場合は全てのログが対象になります。
推奨は500です。(本家と同じ) - Filter regex
「Filter check file」が空の場合、入力した正規表現がコミットログにマッチすると解析対象になります。例えば不具合のコミットログには「fixes」or「fixed」が入力されている場合、この「Filter regex」に「fixes|fixed」と入力します。 - Filter check file
文字列を改行で区切ったファイルを指定します。
「Filter regex」で抽出した文字列が、このファイルに書かれている場合に解析対象とします。
例えばRedmineで管理している場合、「Filter check file」には不具合チケットを改行で並べたファイルを指定します。そして「Filter regex」には「refs #([\d]+)」と入力します。これにより正規表現でコミットログからチケット番号を取得し、そのチケットがファイルに存在する場合に解析対象になります。 - Testボタン
正規表現のテストダイアログを表示します。 - Executeボタン
bugspotsの解析を行います。 - Export CSVボタン
解析結果をcsv出力します。
実装に関するメモ
勉強のためWPFを使用しています。
C#からSVNにアクセスしています。これには「SharpSVN」というライブラリを使用しています。最近のVisual StudioではNuGetで取得できるようです。
TreeなGridには「WPF TreeListView Control」というライブラリを使用してます。Gridの縦線・横線を表示するのに苦戦しましたが、非常に使いやすく便利です。