ところがペースト(貼り付け)先が Excel(エクセル) だと、そのままペーストすると何故か文字化けが起きてしまいます。※未確認ですが Excel2010 では発生しないという情報もありました。
ペーストする時に『形式を選択して貼り付け』で『テキスト』を選択すれば文字化けしませんが、ユーザー一人一人にお願いするのは面倒です。これをコードから行えないものかと色々と調べてみました。
文字化けの原因は Excel がペースト時にクリップボードの内容を HTML Format として解釈してしまうかららしいです。他にも、文字コードの扱いが Excel(Shift-JIS) と DataGridView(Unicode) で異なる、という情報もありましたが、こちらについての真偽は不明です。
DataGridView.GetClipboardContent().GetFormats() でクリップボードに渡されるデータの種類を調べたら Csv, HTML Format, UnicodeText, Text という4つで構成されていました。これを Text だけにしてやれば、文字化けは起きなくなるはずです。
そもそも DataGridView はどうやってコピーのタイミング(DataGridView からクリップボードにデータが渡される)を捕捉しているのでしょう。ソースが見たいです…しかし、私は Visual Studio 2005 ユーザー。
MSDN で GetClipboardContent メソッドを調べてみるとページの最後の方に
継承時の注意 カスタマイズされたクリップボード値を指定するには、このメソッドをオーバーライドします。たとえば、このメソッドをオーバーライドして、カスタムのセル型からの値のコピーをサポートできます。との事でした。
その他にも Ctrl+C をフックしたり、コンテキストメニュー(右クリックで表示)のショートカットを利用して Ctrl+C を横取りするという情報もありました。
オーバーライドは既存画面の修正が楽です。ユーザーへの分り易さを考えたらコンテキストメニューです。それぞれ一長一短がありますね。
今回は…
GetClipboardContent() メソッドをオーバーライドした、カスタムコントロールを追加作成し既存画面の DataGridView を置き換える事にしました。各画面には『Ctrl+C でコピー可能』とラベル表記するという事で。
次期メジャーバージョンアップの時はコンテキストメニューを組み合わせた方法で対応しようと思います。
■C#
namespace SampleApplication
{
public partial class DataGridViewSa : DataGridView
{
public override DataObject GetClipboardContent()
{
DataObject src = base.GetClipboardContent();
if (src == null) return null;
string t = src.GetText(TextDataFormat.Text);
DataObject res = new DataObject(DataFormats.Text, t);
return res;
}
}
}
■VB.NET
Public Class DataGridViewSa
Inherits System.Windows.Forms.DataGridView
Public Overrides Function GetClipboardContent() As System.Windows.Forms.DataObject
Dim src As DataObject = MyBase.GetClipboardContent()
If src Is Nothing Then Return Nothing;
Dim t As String = src.GetText(TextDataFormat.Text)
Dim res As DataObject = New DataObject(DataFormats.Text, t)
Return res
End Function
End Class
■環境
OS:Microsoft Windows XP Home Edition 日本語 Service Pack 3
IDE:Microsoft Visual Studio 2005 Standard Edition 日本語 Service Pack 1
Framework:Microsoft .NET Framework Version 2.0 SP2