C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: DataGridView内のデータのキャストについて


(過去ログ 148 を表示中)

[トピック内 18 記事 (1 - 18 表示)]  << 0 >>

■86693 / inTopicNo.1)  DataGridView内のデータのキャストについて
  
□投稿者/ MTK (21回)-(2018/02/28(Wed) 09:59:30)

分類:[C#] 

いつもお世話になります。

DataGridViewに入っているデータをキャストしたいと考えています。
ただ、中には文字列のデータと数値のデータが混在している状態で、
その中の数値データのみ行合計を出したいです。


if ( this.DataGridView1[ i, s ].Value is long )
{
    total += (long)this.DataGridView1[ i, s ].Value;
}


このように is long 判定でやってみましたが、DataGridViewのデータがObject型なためか
数値を入れたセルもif文の中に入りません。
何か良い方法はないでしょうか?

引用返信 編集キー/
■86695 / inTopicNo.2)  Re[1]: DataGridView内のデータのキャストについて
□投稿者/ WebSurfer (1434回)-(2018/02/28(Wed) 10:21:39)
No86693 (MTK さん) に返信

> if ( this.DataGridView1[ i, s ].Value is long )
> {
> total += (long)this.DataGridView1[ i, s ].Value;
> }
>
>
> このように is long 判定でやってみましたが、DataGridViewのデータがObject型なためか
> 数値を入れたセルもif文の中に入りません。

型は long で間違いないのですか? int とか decimal ということはないですか?
引用返信 編集キー/
■86696 / inTopicNo.3)  Re[2]: DataGridView内のデータのキャストについて
□投稿者/ MTK (22回)-(2018/02/28(Wed) 11:01:38)
2018/02/28(Wed) 11:02:44 編集(投稿者)

No86695 (WebSurfer さん) に返信

回答ありがとうございます。

> 型は long で間違いないのですか? int とか decimal ということはないですか?

ウォッチで this.DataGridView1[ i, s ].Value の型を見てみると object{string} となっています。
intでもdecimalでもいいので、文字列を回避しつつ合計を出したいです。


今の状態を順に説明しますと、
@フォーム起動時にDataGridView1に規定のデータがロードされます(string型とlong型で入っています)
Aユーザがどこかのセルに数値を入れます
B行合計を計算するメソッドが呼ばれます(ここが今回の部分、 object{string} 型になっています)
引用返信 編集キー/
■86697 / inTopicNo.4)  Re[3]: DataGridView内のデータのキャストについて
□投稿者/ WebSurfer (1435回)-(2018/02/28(Wed) 11:14:51)
No86696 (MTK さん) に返信

> ウォッチで this.DataGridView1[ i, s ].Value の型を見てみると object{string} となっています。

であれば、質問者さんのコード、

> if ( this.DataGridView1[ i, s ].Value is long )

の if 文の条件が false になって合計は得られないのは当然の結果なのですが。

ちなみに、is 演算子というのは MSDN ライブラリによると "is 式は、指定した式が null 以外であり、
指定したオブジェクトを指定した型に例外がスローされることなくキャストできる場合に、true と評価
されます。" ということだそうです。

なので、上記のコードの例では ture にならない(false になる)ということです。

何かしたいのかよく分かりませんが、想像をふくらませると、"ABC", "あいう", "123" という文字列が
格納されていて、"123" だけ取り出して合計したいということではないかと思うんですが、どうでしょう?

であれば、文字列を希望の数値型(long 型?)パースできるかどうかを調べて、パース可能ならばパース
して合計するということになるはずです。
引用返信 編集キー/
■86698 / inTopicNo.5)  Re[1]: DataGridView内のデータのキャストについて
□投稿者/ 魔界の仮面弁士 (1582回)-(2018/02/28(Wed) 11:27:29)
No86693 (MTK さん) に返信
> 中には文字列のデータと数値のデータが混在している状態で、
> その中の数値データのみ行合計を出したいです。
> if ( this.DataGridView1[ i, s ].Value is long )

C#7 (VS2017) 以降なら、たとえばこんな感じ。

 if ( long.TryParse( this.DataGridView1[ i, s ].Value?.ToString(), out var longValue) )
 {
  total += longValue;
 }
引用返信 編集キー/
■86699 / inTopicNo.6)  Re[4]: DataGridView内のデータのキャストについて
□投稿者/ MTK (23回)-(2018/02/28(Wed) 11:48:36)
No86697 (WebSurfer さん) に返信

>>if ( this.DataGridView1[ i, s ].Value is long )
>
> の if 文の条件が false になって合計は得られないのは当然の結果なのですが。


はい、なので、それをどうしたら合計できるかという質問なのです・・・・


最初に記載させて頂いた通り

> 中には文字列のデータと数値のデータが混在している状態で、
> その中の数値データのみ行合計を出したいです。

というのが今回の目的です。
分かり辛く申し訳ありません。


> 何かしたいのかよく分かりませんが、想像をふくらませると、"ABC", "あいう", "123" という文字列が
> 格納されていて、"123" だけ取り出して合計したいということではないかと思うんですが、どうでしょう?

はい、仰る通りです。


> であれば、文字列を希望の数値型(long 型?)パースできるかどうかを調べて、パース可能ならばパース
> して合計するということになるはずです。

なるほど、キャストとパースでは違う判定結果になるということですかね?
同じ考え方で、long型にキャストできるかどうかを調べていた( Value is long )つもりでした。

パースを調べて実際に入力してみました。
long data;
if ( long.TryParse(this.payrollBox[ i, s ].Value, out data) )
{
  total += data;
}

しかし、「long.TryParse(this.payrollBox[ i, s ].Value」 の部分で
「引数1 は objectからstringへ変換することはできません」とエラーの表示が出てしまいます。
やり方が悪いのでしょうか?
引用返信 編集キー/
■86700 / inTopicNo.7)  Re[2]: DataGridView内のデータのキャストについて
□投稿者/ MTK (24回)-(2018/02/28(Wed) 11:54:59)
No86698 (魔界の仮面弁士 さん) に返信

いつもありがとうございます。

まさにこの方法が知りたかったです。
試してみたところ、うまく合計することができました。
ありがとうございました。
引用返信 編集キー/
■86701 / inTopicNo.8)  Re[5]: DataGridView内のデータのキャストについて
□投稿者/ WebSurfer (1436回)-(2018/02/28(Wed) 11:57:31)
No86699 (MTK さん) に返信
> 最初に記載させて頂いた通り
>
>>中にはが混在している状態で、
>>その中の数値データのみ行合計を出したいです。
>
> というのが今回の目的です。
> 分かり辛く申し訳ありません。

であれば、そこは「数値のデータ」と言わないで "123" というような文字列という方が通じやすいです。
「文字列のデータと数値のデータ」と言われると string 型と long 型などの数値型が混在しているのか
と思います。

> しかし、「long.TryParse(this.payrollBox[ i, s ].Value」 の部分で
> 「引数1 は objectからstringへ変換することはできません」とエラーの表示が出てしまいます。
> やり方が悪いのでしょうか?

エラーメッセージよ読んで理解しましょうよ。「objectからstringへ変換することはできません」
と言われてる通り this.payrollBox[ i, s ].Value は object 型で string 型ではないからです。

魔界の仮面弁士さんが No86698 で書かれたサンプルコードを見てください。ToString() で文字列型
にしているでしょ?
引用返信 編集キー/
■86702 / inTopicNo.9)  Re[3]: DataGridView内のデータのキャストについて
□投稿者/ WebSurfer (1437回)-(2018/02/28(Wed) 12:01:11)
No86700 (MTK さん) に返信
> ■No86698 (魔界の仮面弁士 さん) に返信
>
> まさにこの方法が知りたかったです。
> 試してみたところ、うまく合計することができました。

コピペするだけでなく中身を理解しているでしょうか? 特に、

this.DataGridView1[ i, s ].Value?.ToString()

の ? の意味は理解してますか?
引用返信 編集キー/
■86703 / inTopicNo.10)  Re[6]: DataGridView内のデータのキャストについて
□投稿者/ MTK (25回)-(2018/02/28(Wed) 12:04:58)
No86701 (WebSurfer さん) に返信

なるほど、ありがとうございます。
次からは記載方法に気をつけたいと思います。

ただ、その回答のされ方は結構傷つきます。
私がobject型などをきちんと理解していないのは分かります。
でもWebSurfer さんの回答には「なんでこんなことも分からないの?バカなの?」みたいなものが見えます。

ともあれ、解決することができました。
お付き合いありがとうございました。
解決済み
引用返信 編集キー/
■86704 / inTopicNo.11)  Re[7]: DataGridView内のデータのキャストについて
□投稿者/ WebSurfer (1438回)-(2018/02/28(Wed) 12:52:09)
No86703 (MTK さん) に返信

> でもWebSurfer さんの回答には「なんでこんなことも分からないの?バカなの?」みたいなものが見えます。

バカとまでは思ってませんが・・・ でも、そう思われたのであればすみません。

しかし、エディタ上で TryParse の第 1 引数の下に赤い波線でエラーであることが表示され「引数1: は
'object' から 'string' へ変換することはできません」というエラーメッセージが出ているのか確認出来
ているのだから、自分で少し調べたり考えたりすれば分かるはずことなのに、質問してくるって何なんだ
ろう・・・とは思ってます。
解決済み
引用返信 編集キー/
■86705 / inTopicNo.12)  Re[4]: DataGridView内のデータのキャストについて
□投稿者/ MTK (26回)-(2018/02/28(Wed) 13:26:25)
No86702 (WebSurfer さん) に返信


> コピペするだけでなく中身を理解しているでしょうか? 特に、
>
> this.DataGridView1[ i, s ].Value?.ToString()
>
> の ? の意味は理解してますか?

?はnullチェックだと解釈しています。
違っていたらすいません。


> しかし、エディタ上で TryParse の第 1 引数の下に赤い波線でエラーであることが表示され「引数1: は
> 'object' から 'string' へ変換することはできません」というエラーメッセージが出ているのか確認出来
> ているのだから、自分で少し調べたり考えたりすれば分かるはずことなのに、質問してくるって何なんだ
> ろう・・・とは思ってます。

今回の質問でobject型からlong型への変換ができず困っている状態でしたので、単純なキャストでいいのか?や
キャストでエラーメッセージがなくなったとして、実際の動作時に特定のデータが来た場合に問題が起きないか?
という不安もあり、そのままの状態で質問してしまいました。
今後はもう少し自分で調べる癖をつけようと思います。
解決済み
引用返信 編集キー/
■86706 / inTopicNo.13)  Re[5]: DataGridView内のデータのキャストについて
□投稿者/ WebSurfer (1439回)-(2018/02/28(Wed) 14:46:36)
No86705 (MTK さん) に返信

> ?はnullチェックだと解釈しています。

そうなのですが・・・  ? を入れたコードを提示した魔界の仮面弁士さんの配慮は伝
わっていたということでしたら余計なお世話だったようで失礼しました。

しかし、もし、伝わってないということでしたら、以下の記事の「null 条件演算子」の
セクションを見てください。

C# 6 の新機能
http://ufcpp.net/study/csharp/ap_ver6.html

単純に this.DataGridView1[ i, s ].Value.ToString() とすると、もし
this.DataGridView1[ i, s ].Value が null だった場合、例外がスローされるかと・・・
解決済み
引用返信 編集キー/
■86707 / inTopicNo.14)  Re[6]: DataGridView内のデータのキャストについて
□投稿者/ MTK (27回)-(2018/02/28(Wed) 15:05:26)
2018/02/28(Wed) 15:06:12 編集(投稿者)

No86706 (WebSurfer さん) に返信

> そうなのですが・・・  ? を入れたコードを提示した魔界の仮面弁士さんの配慮は伝
> わっていたということでしたら余計なお世話だったようで失礼しました。

はい、魔界の仮面弁士さんの配慮はきちんと伝わっています。
WebSurferさんの「コピペするだけでなく中身を理解しているか」という指摘も
始めて間もない私にとって、大変ありがたい指摘だと思っています。
記事まで用意していただき、ありがとうございました。



解決済み
引用返信 編集キー/
■86709 / inTopicNo.15)  Re[6]: DataGridView内のデータのキャストについて
□投稿者/ WebSurfer (1440回)-(2018/03/01(Thu) 12:20:51)
今さらながらですが、以下の結果を見てもう少しよく考えた方がよさそうだと思いました。

object[] values = { "ABC", null, "DEF", "100", 200, 300L, 400.0, 500m, 600.0m };

long total = 0L, num;
            
for (int i = 0; i < values.Length; i++)
{
    string ssss = values[i]?.ToString();
    if (long.TryParse(values[i]?.ToString(), out num))
    {
        total += num;
    }
}

Console.WriteLine("total: {0}", total);

// 結果は: total: 1500 (2100 ではない)
// 600.0m は ToString() で "600.0" になるのでパースできない


合計の対象とするのが string 型限定なら以下のようにした方が良いかもしれません。

for (int i = 0; i < values.Length; i++)
{
    if ((values[i] is string) && long.TryParse((string)values[i], out num))
    {
        total += num;
    }
}

Console.WriteLine("total: {0}", total);

// 結果は: total: 100

解決済み
引用返信 編集キー/
■86715 / inTopicNo.16)  Re[7]: DataGridView内のデータのキャストについて
□投稿者/ MTK (28回)-(2018/03/02(Fri) 15:09:20)
No86709 (WebSurfer さん) に返信

返信遅くなりました。


> object[] values = { "ABC", null, "DEF", "100", 200, 300L, 400.0, 500m, 600.0m };

> // 結果は: total: 1500 (2100 ではない)
> // 600.0m は ToString() で "600.0" になるのでパースできない

こういうデータがくると計算できないんですね・・・
ちょっとまだパースについて勉強不足ですので、また調べてみたいと思います。

フォームロード時に読み込まれるデータはlong型で入ってくるので
計算する時には全てstring型で計算してしまえば、教えて頂いたやり方でできそうですね。
ありがとうございます。
解決済み
引用返信 編集キー/
■86716 / inTopicNo.17)  Re[8]: DataGridView内のデータのキャストについて
□投稿者/ 魔界の仮面弁士 (1583回)-(2018/03/02(Fri) 17:10:27)
No86715 (MTK さん) に返信
>> // 600.0m は ToString() で "600.0" になるのでパースできない
> こういうデータがくると計算できないんですね・・・

long.TryParse や decimal.TryParse の引数に NumberStyles パラメーターを加えることで、
許容させる文字列書式をある程度制御できます。

object money;
//money = 1234.0m; // money.ToString() は「1234.0」、money.GetType().Name は「Decimal」
money = "1,234.0"; // money.ToString() は「1,234.0」、money.GetType().Name は「String」

// 変換できない
Console.WriteLine(long.TryParse(money.ToString(), out long a));

// 変換できる
Console.WriteLine(decimal.TryParse(money.ToString(), out decimal b));
Console.WriteLine(long.TryParse(money.ToString(), NumberStyles.Number, CultureInfo.InvariantCulture, out long c));
Console.WriteLine(decimal.TryParse(money.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out decimal d));


long.TryParse に NumberStyles を渡さなかった場合は NumberStyles.Integer 相当、
decimal.TryParse に NumberStyles を渡さなかった場合は NumberStyles.Number 相当でパースされます。
解決済み
引用返信 編集キー/
■86719 / inTopicNo.18)  Re[9]: DataGridView内のデータのキャストについて
□投稿者/ MTK (29回)-(2018/03/02(Fri) 19:44:39)
No86716 (魔界の仮面弁士 さん) に返信

引数を4つ取るタイプのTryParseもあるんですね!
調べてみた感じだと、NumberStylesの設定によって判定で許容されるものが変わるんですね。

勉強になりました。
ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -