DataGridのコピー機能が、日本語限定でバグってる(壱)

 もう長い間開発を続けていたアプリケーションが、新たなユーザーにリリースされた。利用する部署が格段に増えたので、当然ながら問合せも増える。その中の一つに不可解な不具合報告があった。
リスト(DataGrid)からデータをコピーして、Excelに貼り付けたらなんかおかしい
なんかおかしいって…と思いつつ、確認作業をしてみたら、確かになんかおかしい。
 最後まで貼り付けしてくれない感じで、例えば、7行コピーしてExcelに貼り付けても、6行ちょっとしか貼り付けない。しかし、テキストファイルに貼り付ける分には、特に異常がない。なんぞこれは。というので調査することになった。しかし、貼り付け機能はともかく、コピー機能なんてWPF標準の機能として存在するので、それに任せっきりだったなぁ。
 で、調査した結果、コピーする範囲に日本語を含んでいる時におかしくなるようだった。DataGridのソースコードまで探しだして調査する羽目になった。

 (1)DataGridのセルに対して、コピーコマンドが実行される。
  その際、ApplicationCommands.Copyとして登録されているCommandBindingが呼び出される。
 (2)開発側がこれ(ApplicationCommands.Copy)に独自のコマンドを設定していないなら、DataGrid内部のメソッド(OnExecutedCopy)が実行される。
 (3)クリップボードにセルの内容を設定する。その際、設定するのは、以下の4つに対して行われる。
  HTML形式:DataFormats.Html,
  テキスト形式:DataFormats.Text,
  Unicodeテキスト:DataFormats.UnicodeText,
  カンマ区切りテキスト:DataFormats.CommaSeparatedValue
  Excelに貼り付けた時、Excelはこの中からHtml形式を優先して取得して、セルに貼り付けようとする。
 (4)セルの内容をHtml形式にする際、セルの内容(文字列)の前後にHTMLのタグ等、必要な文字列を付ける処理が行われる。
  HTML Clipboard Format
  このうち、終了位置を示す、EndFragment及びEndHTMLに、内容にともなった数値を設定する必要がある。

   EndFragment: bytecount from the beginning of the clipboard to the end of the fragment.
   EndHTML: bytecount from the beginning of the clipboard to the end of the context, or -1 if no context

bytecount=バイト数。片や、DataGridのソースコード(ver4.0)には、こうあった。
internal static void GetClipboardContentForHtml(StringBuilder content) {
content.Insert(0, "<TABLE>");
content.Append("</TABLE>");

// Marshal.SystemDefaultCharSize is 2 on WinXP Pro -
// so the offsets seem to be in character counts instead of bytes.
int bytecountEndOfFragment = 135 + content.Length;
int bytecountEndOfHtml = bytecountEndOfFragment + 36;
//...以下続く
135や36のマジックナンバーは、差し込む文字列の合計バイト数。定数で宣言されており、ここでは割愛する。
 StringBuilderのLengthプロパティは文字数(正確には、 オブジェクトの長さ)を返す。半角英数字なら確かに、バイト数=文字数となるので問題ない。対して、全角文字(日本語)は文字数=バイト数とはなるとは限らない。「あいうえお」は、文字数=5に対してバイト数=10になる。

ああ!だから日本語だと尻切れトンボみたいになるのか!そっかー、じゃあ仕方ないなー…ってなるわけないだろ!ヽ(`Д´#)ノ
ああもう、結局、コピー機能も実装する羽目になるのか。Orz
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m