C#とWPFでポンチな業務アプリ作ってるんですが,「Excelで送られてきたデータを行でコピーしてセル毎に個別のテキストボックスに格納する」みたいな事をしています。
Excelで複数セルをコピーするとセル毎にタブ区切りされたテキストになるので、C#側で「str.Split('\t')」して一旦リストに格納するなりの処理をしているのですが、セル内で改行があったりすると当該セルの値だけダブルクォーテーションで括られっちゃうんですよね。
なので以下のような文字列としてクリップボードに格納されています。
(「↵」は改行、「→×」はタブとご理解ください)。
セル1→×セル2→×"改行されてる↵
セル3"……
それでまあタブ区切りの前に「str.Replace(""", "")」でダブルクォーテーションを全部除去してからタブ区切りしていたんです。
これで数年何の問題もなく上手く行ってたのが、昨日になって「突然テキストボックスに格納される値がズレる」って事象が発生して、何事かとデータを調べたらエクセルのセルにタブが混じってる……
"セル1→×"→×セル2→×"改行されてる↵
セル3"……
上記のように先頭セルの末尾にタブ文字がくっついてました。Excelでタブキー押下したら普通セル移動やろがい!どうやってタブ文字突っ込んでんねん!(メモ帳からのコピペとかでうっかり出来ます)と元データ作った奴に怒りを覚えましたが、元データはいろんな人が作成しているのでそりゃまあおバカちゃんもおるやろ、と思い直してこっち側で対策することにしたのですが、これがなかなか難儀したので、今回の解決策を共有しておこうと思いました。
まあ糞コードなんですが……
当初は正規表現で「"」で括られてる間に含まれるタブ文字を見つけて除去すりゃいいだろうと高をくくったのですが、上記データの通り複数セルに改行やタブなどの制御文字が含まれている場合だと、セル1の終わりの「"」とセル3の始まりの「"」の間もヒットしちゃってセル間の区切りのタブも除去されちゃって駄目だったので、泥臭いコードを書いて解決しました。
//修正した文字列を格納する変数
string fixStr = "";
//「"」の数を数えるカウンタ
int counter = 0;
//半自動入力文字列を1文字ずつ分解したArrayをforeachする
foreach (char c in SemiAutoText_textBox.Text.ToCharArray())
{
//cが「"」の場合、カウンタの値を+1する
if (c == '"')
{
counter++;
}
//「"」が奇数番目の場合(始まりの「"」か、「"」で括られた「中」と評価する)
if (counter % 2 != 0)
{
//三項演算子:cがタブの場合はfixStrの末尾に空文字を追加、タブ以外の場合はcを追加
fixStr += c == '\t' ? "" : c.ToString();
}
//上記以外=最初の「"」の前か、「"」が偶数番目の場合(終わりの「"」か、「"」で括られた「外」と評価する)
else
{
//cをfixStrの末尾に追加
fixStr += c.ToString();
}
}
//ダブルクォーテーションを除去
fixStr = fixStr.Replace("\"", "");
//タブで区切ってListに変換する
List<string> excelCell = fixStr.Split('\t').ToList();
「"」の数を数えてカウンタに格納し、カウンタの値が奇数なら括りの頭の「"」か括りの内側だし、カウンタの値が偶数になってたら括りの終わりの「"」か括りの外側って評価してるのがアイデアと言えばアイデアかな……