tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルVB2005で通貨型(MDB)の扱い
記事No9900
投稿日: 2010/02/24(Wed) 10:58
投稿者レモン
いつも拝見させて頂きお世話になっております。

WinXP VB2005 mdbにてシステム開発を行っております。
今回、開発しているプロジェクトをVB.NETからVB2005に移行しました。

そこでタイトルの件ですが、mdb側で通貨型(\0)をラベルテキストにセットすると"0.0000"となってしまいました。
VB.NETの時は、"0"で表示されていたのですが…

例(VB2005)
@lbll.Text=wDT.Rows(0)("aaa").Tostring (通貨型)⇒"0.0000"と表示される
Albll.Text=wDT.Rows(0)("bbb").Tostring (数値型)⇒"0"と表示される
※VB.NETでは@が0でした。

又、以下で回避できるみたいですが…
Blbll.Text=Cint(wDT.Rows(0)("aaa")).Tostring (通貨型)⇒"0"と表示される

VB2005に移行してしまった為、@のような現象がおきるのでしょうか?
よろしくお願いいたします。

[ツリー表示へ]
タイトルRe: VB2005で通貨型(MDB)の扱い
記事No9901
投稿日: 2010/02/24(Wed) 12:27
投稿者魔界の仮面弁士
> VB.NETからVB2005に移行しました。
2002 → 2005 、という事でしょうか?

> そこでタイトルの件ですが、mdb側で通貨型(\0)をラベルテキストにセットすると"0.0000"となってしまいました。
> VB.NETの時は、"0"で表示されていたのですが…
実数値を文字列に変換するときには、書式を指定するべきだと思いますよ。

この場合は、String.Format 共有メソッドや、Decimal.ToString メソッドなどの
書式を指定可能なメソッドを呼び出すようにすれば、解決できるかと思います。

# Object.ToString() の結果がどのように出力されるかは、
# 元のデータ型次第です(mdb 側の型ではなく、DataTable に取り込んだ後の型)。

[ツリー表示へ]
タイトルRe^2: VB2005で通貨型(MDB)の扱い
記事No9902
投稿日: 2010/02/24(Wed) 14:24
投稿者レモン
魔界の仮面弁士様、お世話になります。

> 2002 → 2005 、という事でしょうか?
VB.NET2003 → VB2005 です。書き方がまずく申し訳ありませんでした。

> 実数値を文字列に変換するときには、書式を指定するべきだと思いますよ。
今回の件で痛感しました。今後はしっかり周知していこうと思います。

ただやはり疑問が残るのが、今回の現象はVB2005に上げた事が原因でしょうか?
VB.NET2003では大目に見てくれていた事が、VB2005では厳密に見られてしまう?
ちょっと言葉が思いつかず、うまく表現できませんがそんな感じがしています。

> この場合は、String.Format 共有メソッドや、Decimal.ToString メソッドなどの
> 書式を指定可能なメソッドを呼び出すようにすれば、解決できるかと思います。
アドバイス恐れ入ります。(きちんと読み取れているかが不安ですが)
lbll.Text = Cdec(wDT.Rows(0)("aaa")).Tostring("##0")
このような事でしょうか?

# 実はラベルテキスト以外にも、印刷データの文字列編集など結構な箇所で同様の
# コードが存在して困りましたが、この機に統一修正しようと思っていますもので…

[ツリー表示へ]
タイトルRe^3: VB2005で通貨型(MDB)の扱い
記事No9903
投稿日: 2010/02/24(Wed) 17:30
投稿者魔界の仮面弁士
> 今回の現象はVB2005に上げた事が原因でしょうか?
幾つかの原因が予想できますが、手元に環境が無いのでこちらでは追調査できません。

先ほども書きましたが、最終的な書式は DataTable に取り込んだ後の型にも依存しますので、
気になるのであれば、実際のデータ型を確認してみてください。

データ型については、たとえば
 MsgBox(wDT.Columns("aaa").DataType.FullName)
 MsgBox(wDT.Rows(0)("aaa").GetType().FullName)
 MsgBox(TypeName(wDT.Rows(0)("aaa")))
などのようにして調べられます。

その結果、VB.NET2002 と VB2005 とで違いがあるかどうかを確認してみてください。
データ型が違うなら、そこを統一すれば同じような結果になるかも知れません。


一方で、同じ数値/同じデータ型でも、 ToString の結果が異なってしまうパターンも
存在します。たとえば Decimal 型の場合、小数点の後続のゼロも保持されているため、

 Dim a As Decimal = CDec("1.1")
 Dim b As Decimal = CDec("1.10")
 Dim c As Decimal = CDec("1.100")
 Label1.Text = a.ToString()
 Label2.Text = b.ToString()
 Label3.Text = c.ToString()

は、それぞれ同じ値(a = b AndAlso b = c)であるにも関わらず、上記は
それぞれ違う文字列が出力されることになります。

もちろん、書式を指定して、.ToString("0.0000") などとすれば同じにできますけれどね。



> lbll.Text = Cdec(wDT.Rows(0)("aaa")).Tostring("##0")
そんな感じです。

ちなみに、書式の「#」を記述しなくとも
  lbll.Text = CDec(wDT.Rows(0)("aaa")).ToString("0")
のようにすれば、小数部は出力されません。

あるいは、String.Format を使うこともできます。
  lbll.Text = String.Format("{0:0}", wDT.Rows(0)("aaa"))

String.Format の場合、上記のように CDec 等が不要となりますし、
桁数指定/右寄せ/左寄せなどの、より細かい制御も可能となります。


なお、書式化の際にはカルチャも明示した方が安全です。
(アプリケーションの仕様にもよりますが)


> 今回の件で痛感しました。今後はしっかり周知していこうと思います。
数値だけでは無く、日付もそうですね。

チェックを確実な物にするために、コントロールパネルの「地域と言語のオプション」を
 ・日付を和暦表示にした状態で動作させる。
 ・日本以外に設定した状態で動作させる。
というテストもしておく事をおすすめします。

特に前者は重要です。

たとえば和暦モードで運用しているユーザーの場合、
 TextBox1.Text = Now.ToString("yyyy/MM/dd")
の実行結果は、"2010/02/24" ではなく "22/02/24" になりますので、
地域設定のテストが不十分な場合、桁数がずれて処理されてしまうかも知れません。


一方、後者(日本以外に設定)する場面は、実運用上では可能性が低いですが、
関連する問題なので、一緒に抑えておいた方が良いでしょう。
このとき、地域設定をドイツにしておくと、日本との差異をテストし易いかと思います。


既定の【日付書式】
  日本:yyyy/MM/dd  あるいは gg yy/MM/dd
  米国:M/d/yyyy
 ドイツ:dd.MM.yyyy …日本とは、日付区切り記号も表記順も違う

既定の【数値書式】
  日本:123,456,789.012
  日本:123,456,789.012
 ドイツ:123.456.789,012 …日米とは、[小数点]と[桁区切り]の記号が逆

[ツリー表示へ]
タイトルRe^4: VB2005で通貨型(MDB)の扱い
記事No9904
投稿日: 2010/02/25(Thu) 15:06
投稿者レモン
魔界の仮面弁士様、引き続きお世話になります。

> 気になるのであれば、実際のデータ型を確認してみてください。
順に、System.Decimal、System.Decimal、Decimalという確認を得られました。


> その結果、VB.NET2002 と VB2005 とで違いがあるかどうかを確認してみてください。
教えを頂く分際で大変恐縮ですが、2003 → 2005です↓
> VB.NET2003 → VB2005 です。書き方がまずく申し訳ありませんでした。


> 一方で、同じ数値/同じデータ型でも、 ToString の結果が異なってしまうパターンも
こちらも確認しました。あらためて書式設定の徹底を周知していこうと思いました。


>   lbll.Text = CDec(wDT.Rows(0)("aaa")).ToString("0")
>   lbll.Text = String.Format("{0:0}", wDT.Rows(0)("aaa"))
双方とも"0"表示できる事を確認しました。
> String.Format の場合、上記のように CDec 等が不要となりますし、
今のアプリの仕様では必須入力でない項目もあり、Cdecする方法だと
IsDBNull(wDT.Rows(0)("aaa")) = False か?とチェックしないとエラーとなる場合もあり
余分にコードが増えてしまいそうなので、String.Formatの方が適切だと思いました。

ただ(少し余談になりますが)一時的に空文字許可のないワークテーブルの項目へ
データを書込むケースもあり、結局、判定コードは必要になりそうですが。

# ちなみにString.Formatはほとんど使った事ないですが「より細かい制御」は
# まだちょっと調べただけですが意外と複雑ですね…{0:0}をどう変えればどうなる等々
# 今回の件のついては {0:0} で十分そうですが


> 数値だけでは無く、日付もそうですね。
日付の扱いは、以前にも問題になった事がありましたので
アドバイスをもとにテストしてみたいと思います。

※関連する内容でたくさんの情報をいただき、本当に有難うございます。

[ツリー表示へ]
タイトルRe^4: VB2005で通貨型(MDB)の扱い
記事No9905
投稿日: 2010/02/25(Thu) 18:44
投稿者魔界の仮面弁士
失礼しました。VB.NET2003 (VB7.1 / .NET 1.1) でしたね。


> # ちなみにString.Formatはほとんど使った事ないですが「より細かい制御」は
> # まだちょっと調べただけですが意外と複雑ですね…{0:0}をどう変えればどうなる等々
> # 今回の件のついては {0:0} で十分そうですが

基本形は、
 s = String.Format("{0} と {2} と {1}", a, b, c)
です。{番号}の位置に引数のデータが埋め込まれます。


書式を指定する場合には、{番号:書式}とコロンで区切って指定します。
指定できる文字は元データの型によって異なりますので、ヘルプで確認してください。
 Dim num As Integer = 4321
 Dim dt As Date = Now
 s = String.Format("0埋め5桁 = {0:00000}", num)
 s = String.Format("3桁区切り= {0:#,0}", num)
 s = String.Format("小16進数 = {0:x}", num)
 s = String.Format("大16進数 = {0:X}", num)
 s = String.Format("日付 = {0:yyyy/MM/dd HH:mm:ss.fffffff}", dt)
 s = String.Format("24時間法={0:%H}時、12時間法={0:tt %h}時", dt)


そして、幅(桁数)を指定する場合には、{番号,桁数}とカンマで区切って指定します。
書式と同時に指定する場合には、{番号,桁数:書式} という記述になります。
 s = String.Format("『{0,20}』" , num) '20文字分の幅があり、数値は右寄せ
 s = String.Format("『{0,-20}』", num) '20文字分の幅があり、数値は左寄せ
 s = String.Format("『{0,20:#,0}』", num) '20文字分の幅で、桁区切り有りで右寄せ


より詳しい解説はこちら。
http://msdn.microsoft.com/ja-jp/library/txafckwd.aspx



>> なお、書式化の際にはカルチャも明示した方が安全です。
>> (アプリケーションの仕様にもよりますが)

カルチャの指定例。

 Dim fmt As String = "{0:g yyyy/M/d dddd}"
 Dim ci As System.Globalization.CultureInfo
 ci = System.Globalization.CultureInfo.InvariantCulture
 MsgBox(String.Format(ci, fmt, dt), vbInformation, "日付")
 ci = New System.Globalization.CultureInfo("de-DE")
 MsgBox(String.Format(ci, fmt, dt), vbInformation, "独逸")
 ci = New System.Globalization.CultureInfo("ko-KR")
 MsgBox(String.Format(ci, fmt, dt), vbInformation, "韓国")
 ci = New System.Globalization.CultureInfo("ja-jp")
 MsgBox(String.Format(ci, fmt, dt), vbInformation, "日本")
 ci.DateTimeFormat.Calendar = New System.Globalization.JapaneseCalendar()
 MsgBox(String.Format(ci, fmt, dt), vbInformation, "和暦")

なお、カルチャとしては利用できませんが、旧暦用のクラスもあります。
http://blogs.wankuma.com/ogiogi/archive/2006/11/07/43917.aspx

[ツリー表示へ]
タイトルRe^5: VB2005で通貨型(MDB)の扱い
記事No9906
投稿日: 2010/02/26(Fri) 09:09
投稿者レモン
魔界の仮面弁士様、本当にお世話になっております。


> 基本形は、
>  s = String.Format("{0} と {2} と {1}", a, b, c)
> です。{番号}の位置に引数のデータが埋め込まれます。
具体例とともに詳しいご説明をいただき、一気に理解が深まりました。

> より詳しい解説はこちら。
> http://msdn.microsoft.com/ja-jp/library/txafckwd.aspx
回答いただいた内容の方が「より詳しい」と思いました。(本音で)
# ヘルプ/msdnは、いつもうまく読み取れない…読解力の問題でしょうが


> カルチャの指定例。
こちらにまで詳しい具体例、ありがとうございます。
是非、参考にしてテストしてみたいと思います。


本当に何から何まで面倒見ていただき感謝です。ありがとうございました。

[ツリー表示へ]