Excelからクリップボードにコピーが行われると、クリップボード内のCSV形式のデータにはSJISでバイナリ化された文字列が入ります。
そのためSJISに無い文字は文字化けします。
文字化けしないようにするにはコピーデータをUnicodeにする必要があります。
回避方法はExcelの機能でコピーせずにVBAやVSTOでコピーを行うか、コピーされてしまったデータを修正しコピーしなおす必要があります。
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern int GetACP();
const string DATAFORMAT_BIFF5 = "Biff5"; //エクセルからのコピー判定用
const string DATAFORMAT_RESOURCEEXPROW = "ResourceExplorerRows"; //Resoruceエクスプローラーからのコピー
const string DATAFORMAT_CONVERTED = "CSV__CONVERTED"; //変換済み検出用
private void Test1()
{
var codepage = GetACP();
//if (codepage != 932)
//{//SJISじゃないなら何もしない
// return;
//}
var dOrg = Clipboard.GetDataObject();
if (dOrg != null
&& dOrg.GetDataPresent(DataFormats.CommaSeparatedValue)
&& dOrg.GetDataPresent(DataFormats.UnicodeText)
&& dOrg.GetDataPresent(DATAFORMAT_BIFF5)
&& !dOrg.GetDataPresent(DATAFORMAT_RESOURCEEXPROW)
&& !dOrg.GetDataPresent(DATAFORMAT_CONVERTED))
{
var oCSV = dOrg.GetData(DataFormats.CommaSeparatedValue);
if (dOrg.GetData(DataFormats.UnicodeText) is string unitext
&& oCSV is System.IO.MemoryStream ms) //Excelからはストリーム形式でCSV格納
{
//.NetCoreの場合はSJISを取れないのでNugetでSystem.Text.Encoding.CodePagesを入れておく
//System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
//クリップボードのCSVがSJISでエンコードされているので変換
var osEncoding = System.Text.Encoding.GetEncoding(codepage);
string csvOriginal = osEncoding.GetString(ms.ToArray());
string csvNew = csvOriginal;
//if (csvOriginal.Contains("?")) //System.Diagnostics.Debug.WriteLine("文字化けの可能性");
{
while (unitext.EndsWith("\r\n"))
{
unitext = unitext.Substring(0, unitext.Length - 2);
}
// 文字列から変換しなおす
// 文字列はTSVになってるので、てきとうにCSV文字列化
//(セル内にタブがある場合は非対応)
csvNew = string.Join(",", unitext.Split("\t").Select(_ => "\"" + _.Replace("\"", "\"\"") + "\""));
}
DataObject dNew = new DataObject();
dNew.SetData(DataFormats.Text, unitext);
dNew.SetData(DataFormats.UnicodeText, unitext);
dNew.SetData(DataFormats.CommaSeparatedValue, csvNew);
dNew.SetData(DATAFORMAT_CONVERTED, ms);//変換済みのデータとしてマーク
Clipboard.SetDataObject(dNew); //変換済みをクリップボードに
}
}
}
20250314: Repalceの文字が間違ってたのを修正(\\
-> \"
)