- ベストアンサー
クラスの宣言について教えてください。(エクセル)
ヘルプを読むと、印刷設定のPageSetupで、Orientationには、XlPageOrientation クラスの定数が返されるとあります。私が持っている本で、宣言を調べたら、バイト型、ブール型、整数型、・・・・とありクラス型ってのがありません。どれを選べばいいのですか?(すみません、今まで宣言を行なわずにいました)ちょー、基本的なことですみません。宜しくお願い致します。
- みんなの回答 (15)
- 専門家の回答
質問者が選んだベストアンサー
こんばんは。 onlyrom さんへ >ということは他に何かある??? 私は、別に文句をつけたわけではありませんので、気に障りましたら、お許しください。 たぶん、 >「a=60 * 60 * 24」は回答にもありますように「使い方自体を間違っています」 というのは、私の書いた内容自体が、Variant型の宣言の是非には当たらないとおっしゃるのでしょうけれども、それは、今回、リテラルで書いたのですから、ご指摘のとおりです。適当な例ではありませんでした。 変数 a を Long型に書いたところで、それはエラーを変えようがないわけです。本来は、リテラルで書くこと自体が問題といえば、それまでですが、ただ、これは、オーバーフローになっている理由は、それが、Interger 型の範囲(32767)を越えているので、エラーが出ています。演算する場合、変数に入れない限り型のキャストが利きません。 Variant 型というのは、VB/VBAの自動キャスト(型の内部変換)機能を使っているわけで、Variant型という大きな入れ物で値をやり取りするというのは、あまり入門レベルの人以外は、関心できません。その理由は、Variant型は複合的な型であり、値の内部処理をします。メモリは22バイトであり、それに文字列の場合は、さらに加わります。それだけ、メモリ負担が大きくなります。また、変数の暗黙的型のキャストを避け、必ず変数の型を把握しながら明示的にコードを書くべきだと思っています。そのほうが、コーディングが分りやすいし、エラーが少ないのです。 例えば、以下のような例の場合は、b が、数値に変ってしまいます。 Sub TestA() Dim a, b, c a = 1 b = "60" c = a + b '61 End Sub これは、変数の中で、自動的にキャストされて計算しています。本来は、b に文字列が入ることは弾くべきですね。 次に、以下のような場合、a は、Double型に変りますが、本来、その必要性がない場合は、Single型などでよいわけで、そうすることによって、演算スピードを上げることが出来ます。 Sub TestB() Dim a a = 1.1 End Sub 他にも、時間計算で演算をする場合は、Variant型では正確な数字が出てこないことがあります。 以下は、また、別な例です。引数の宣言を明示的に行わないと、エラーになります。 Sub Test() Dim a Dim b As Variant a = "abc" b = TestFunction(a) End Sub Function TestFunction(myStr As String) TestFunction = myStr + Str(Len(myStr)) End Function a は、String 型に自動キャストされているはずですが、TestFunction の引数では、受けられませんね。では、Function側の引数の型を変えるべきでしょうか?それは、メモリ負担だけではなく、関数の引数の型を限定することによって、正しい値を返すことが目的です。Variant型で引数を設定するようなユーザー定義関数の作り方は、よほど初心者でない限りは、一般的ではありません。 精密な計算をする場合、浮動小数点丸めを嫌う演算には、当然ですが、キャストは利きません。明示的にDecimal 型や、Currency型が必要です。(ただし、Decimal 型の変数宣言はありませんので、CDecで変数の型を変えてあげる必要があります。)また、この他、暗号システムで使う、一般的には、多倍長整数型と言われている大きな数を用いる時などは、当然、Variant 型は使えません。 他にも、Win32 API関数は、明示的な変数の型の宣言をしないと、Applicationエラーになることがあります。 今、思いつくところでは、こんなところが挙げられます。
その他の回答 (14)
- KenKen_SP
- ベストアンサー率62% (785/1258)
本スレッドの趣旨に関連すると思いますので回答します。 > dが0にならないのは誤差のためであり、それはdがDouble型の値を >「賄っている」いるとの証だと思うのですが。 その通りです。でも、それは意図した結果を返しましたか? #11 の例だと変数 d は Variant 型で宣言されていますが、コードの 実行時の内部処理では Variant / Double 型、つまり Double 型とし て計算されています。 したがって、 #11 の例では端数の丸め誤差が発生し、計算結果が 0 になりません。また、エラーにもなりません。まあ、この例ではコー ディングミスとも言えますが、VB / VBA は変数を宣言しないと、ディ フォルトで Variant 型になるため、入門者の方のコードではよくある ミスです。 Variant 型や Object 型は何でも代入できる、、、これは、VB / VBA がコードの実行時に内部的に適切な型にキャストしてから処理する仕 組みをとっているに過ぎません。これが曲者です。 必ずしも期待どおりにキャストしてくれる保証がありません。特に ユーザーから代入値を受け取るような場合は、なおさらですね。 もちろん、 d = CCur(0.5 - 0.4 - 0.1) のように、コーディングでカバーすることはできますが、このように するのであれば、初めから変数 d を Currency 型で宣言しておくべき でしょう。 > dがDouble型の値を「賄っている」いる... というのは単純に「代入できる」という話であって、「意図したとお り処理される保証を保てるか?」についても考慮しなければなりません。 #11 のように丸め誤差を許さない場合、つまり、Double 型へキャスト されては困る場合は、Variant 型は「代入はできるけど、使えない」 のです。 「Variant型は無闇に使うものではない」と言われる最大の理由は、 「何でも代入できる」がゆえに、意図したとおり動作する保証が得られ ない、、というところにあります。
- onlyrom
- ベストアンサー率59% (228/384)
おはようございます。 vba_minaraiさん、ここを借りてすみません。 to KenKen_SPさん Dim a As Double Dim b As Single Dim c As Currency Dim d As Variant a = 0.5 - 0.4 - 0.1 b = 0.5 - 0.4 - 0.1 c = 0.5 - 0.4 - 0.1 d = 0.5 - 0.4 - 0.1 この例を挙げられて「計算結果はどれも 0 となるはずです」とのことですが、結果0と「Variantは全てを賄う」との関係がいまいち理解できません。 dが0にならないのは誤差のためであり、それはdがDouble型の値を「賄っている」いるとの証だと思うのですが。 読解力、知識不足のため、たぶんKenKen_SPさんの意図されるところを汲み取ってないのだと思いますが。 ---------------------------------------------- to Wendy02さん 「Variant型は無闇に使うものではない」、これは仰るとおりだと思います。初心者にとってメモリ、スピードよりも可読性の面で特にそう感じます。 それを踏まえまして。。。 Sub TestA() Dim a, b, c a = 1 b = "60" c = a + b '61 End Sub この例のように文字列の数字が恰も数値として計算されるのは、bがVariant型でなくてもstring型で宣言してあっても同じだと思います。 にも拘わらずこの例を挙げられて「本来は、b に文字列が入ることは弾くべきですね。」と仰っておられます。 そのことが「Variantは全てを賄う」云々とどういう関係があるのかがよく分かりません。 また、2番目の例ですがそれも計算スピードの問題で「Variantは全てを賄う」云々とは別な問題かなと思ったりしています。 それから、 Sub Test() Dim a Dim b As Variant a = "abc" b = TestFunction(a) End Sub Function TestFunction(myStr As String) TestFunction = myStr + Str(Len(myStr)) End Function この使い方ですが、いくらVariantに文字列を入れたといっても、それをFunctionの方で新たにString型で宣言するということは少し乱暴なやりかたではないでしょうか。 例えば、 --------- Dim A as Long A=100 call TestFunc(A) ------- Function TestFunc(A as Integer) ------- このように一度宣言した変数の型を再度別の型で宣言することと同じことになるのではないでしょうか。 もしそのようなことをしたいのであれば、参照渡しではなく値渡しにするのが本当なのでは、と思います。 何れにしろ、この例と「Valiantは全てを賄う」云々の関係がいまいちよく理解できないでいます。 たぶん、それもこれも初心者ゆえの知識、経験、読解力不足のためだろうと思います。これから経験を積むに従い意図されていることが理解できるようになってくるのでないかとと思っていますので、今回の便乗質問はこれで締めさせていただきたいと思います。 今回も貴重なお時間を割いていただき、また惜しげもなく知識、考え方等与えてくださり感謝しています。 これからもKenKen_SPさん、Wendy02さんには迷惑をお掛けると思いますが、今回同様宜しくご指導をお願いいたします。 ありがとうございました。 また言葉使いの面で気に障る部分がありましたらお許しください。
- onlyrom
- ベストアンサー率59% (228/384)
KenKen_SPさん、Wendy02さん、こんばんは。 便乗質問にも拘わらず、長文かつ丁寧な回答ありがとうございます。 貴重な時間を割いていただき回答していただいたものですから、内容は後でじっくり読ませていただきます。 まずはお礼まで。 それから、Wendy02さん、 >私は、別に文句をつけたわけではありませんので、気に障りましたら 気に障るなどとんでもありません。 >>ということは他に何かある??? この書き方が拙かったのかなと反省しています。 「他に何かあるのかなぁ~」そんな気持ちで書いたものです。 変な気を使わせてしまい、こちらこそ申し訳分けなくなく思います。すみませんでした。
- KenKen_SP
- ベストアンサー率62% (785/1258)
横レスで申し訳ありませんが、vba_minarai さんにも参考になると思 いますので、、、 onlyrom さんへ >「賄えない」のはどんな場合でしょうか。 以下のコードを試してみて下さい。一例です。 '浮動小数点演算テスト Sub TESTMACRO() Dim a As Double Dim b As Single Dim c As Currency Dim d As Variant '計算結果はどれも 0 となるはずです a = 0.5 - 0.4 - 0.1 b = 0.5 - 0.4 - 0.1 c = 0.5 - 0.4 - 0.1 d = 0.5 - 0.4 - 0.1 MsgBox "Double型の結果:" & CStr(a) MsgBox "Single型の結果:" & CStr(b) MsgBox "Currency型の結果:" & CStr(c) MsgBox "Variant型の結果:" & CStr(d) End Sub
- onlyrom
- ベストアンサー率59% (228/384)
vba_minaraiさん、すみません。 >この宣言方法は、オブジェクト型なのですか? オブジェクト型と書いてみたものの何となくおかしいと思い、ちょっと調べてみたらLong型でした。 生半可な知識での回答、申し訳ありません。 以後気をつけます。
- KenKen_SP
- ベストアンサー率62% (785/1258)
> この宣言方法は、オブジェクト型なのですか? オブジェクトブラウザで確認できますが、Excel の PageSetup クラ ス内のメンバ Orientation プロパティーは XlPageOrientation とし て宣言されています。 Property Orientation As XlPageOrientation この場合の XlPageOrientation は列挙型といいます。Excel で既に 定義されているので改めて書く必要は無いのですが、敢えてコードを 書くと以下の様になります。 Public Enum XlPageOrientation xlPortrait = 1 xlLandscape = 2 End Enum この列挙型とは、要は「入力されるべき候補が限定される Long 型」 なのです。Enum キーワードで定義した「ある特定の値」を代入する ことを目的に、プログラマが任意につくることができるカスタムデー タ型ですね。ですから、#5 のように Dim TEST As XlPageOrientation と宣言することが可能なのです。 ここで、Enum キーワードをヘルプで調べると分かりますが、Enum の メンバ(ここでは xlPortrait など)は Long 型 として評価される とあります。 したがって、他の方の回答やヘルプにあるとおり、Long 型の変数で 受ける、、というのが「プログラマとして正解」なのですが、メンバ に設定された値が許容範囲内であれば、他の型の変数で受けることも 可能ではあります。今回の 列挙型 XlPageOrientation のメンバは 1 または 2 ですから Integer 型などでも OK ですね。 ( もちろん Long 型がベスト) ただ、列挙型を使う最大のメリットは、 ・VBE で自動メンバ表示機能が働く ・取りうる値が明確である ・コードの可読性が向上する ことにあります。ですから、結論としては、Long 型で正解、列挙型 なら 実質 Long 型なのだが、上記のようなメリットもある、、 ということになります。 サンプルコードを書いてみます。新しいモジュールに以下を貼り付け て、税込金額(curVALUE, 現税率) で第2引数で自動メンバ表示機能が 働くことを確認して見て下さい。 Public Enum enmTAXRATE 旧税率 = 3 現税率 = 5 End Enum Function 税込金額(金額 As Currency, 消費税率 As enmTAXRATE) As Currency 税込金額 = Int(金額 * (1 + 消費税率 / 100)) End Function Sub TESTMACRO() Dim curVALUE As Currency curVALUE = 20000 MsgBox 税込金額(curVALUE, 現税率) End Sub
- onlyrom
- ベストアンサー率59% (228/384)
また便乗質問です。 Wendy02さんの回答はとても参考になるので必ず見るようにしています。 で、また質問させてください。 No.7の回答に、「全てが、Variant 型でまかなえるわけではありません」と書かれていますが、「賄えない」のはどんな場合でしょうか。 回答の中の「a=60 * 60 * 24」は回答にもありますように「使い方自体を間違っています」ので、これをもって「全てを賄えない」とはならないですよね。 ということは他に何かある??? 「Variant型」は「固定長の文字列型データ」と「ユーザー定義型」を除くあらゆる種類のデータを格納できる、と理解していましたので気になり質問させていただきました。 宜しくお願いいたします なお、意図されていることを勘違いしていましたらVBA初心者ということでお許しください。 それから、便乗質問だけでは悪いのでkenken_spさんへのお礼での質問、 >この宣言方法は、オブジェクト型なのですか? オブジェクトブラウザを覗いてみれば分かるとおもいますが、覗かなくてもヘルプにもXlPageOrientationはクラスとありますので「オブジェクト型」です。 オブジェクトブラウザを覗く癖をつけておくとより多くのことが学べると思います。
- Wendy02
- ベストアンサー率57% (3570/6232)
vba_minarai様 Wendy02です。 >Rangeオブジェクトの話で、そのようなことを自分の専門分野で感じたことを思い出しました。Rangeオブジェクトに複数形がないあたりに、エクセルVBAにおけるオブジェクト指向の基本がありそうな気がしています。 とても、するどいです。Rangeオブジェクトには、なぜ複数形がないっていう話は、本で読んだことがあります。Ranges がないのは、Rangeには、基本的に領域であって個数が存在しないからだと思います。 >そのxlLandscapeの値を代入する変数の宣言は、何の型で行なえばいいのでしょうか?ってことです。 私などが、気になる時に、良くチェックする方法は、 Sub Test a = Me.PageSetup.Orientation End Sub として、ローカルウィルンドウで、その返ってきた値aの型をチェックしますね。 Variant / Long と出ているはずです。 32 bit で、一般数値ですから、Long型になると考えてもよいのですが、気になる場合、念のために確かめるに越したことはありません。それと、基礎的なことなのですが、演算子を使うときに、うっかり、型を間違えることがありますね。 ご質問には直接関係がありませんが、例えば、\ 演算子は、返ってきたものが、Byte, Integer, Long 型になっていたりしますから、時間計算の時に、Double型が、その下の低精度に丸められてしまいますから、基本的には時間計算には使えない、ということになります。 また、逆に、時間計算の秒を表す場合の 60 * 60 * 24 は、リテラルに使って、仮にVariant 型の変数 aで受けようとしても、そのままでは、オーバーフローのエラーが出ますね。 a =60 * 60 * 24 その場合、「60& * 60 * 24」として、Long型に変更してあげないといけません。全てが、Variant 型でまかなえるわけではありません。 これらは、ここの掲示板で回答してきた中で印象的だったものです。
- onlyrom
- ベストアンサー率59% (228/384)
再度のこんにちは。 エクセルのバージョン、最初に聞いておくべきでした。 当方のは、xl2000のヘルプです。 いまxl2003のヘルプを覗いてみましたら仰るように型は書いてありませんね。 が、しかし2000と2003で変わったということは耳にしていませんから、Long型でOKだと思います。 もし、それでも不安でしたら、Variantで宣言すればすむことですね。
補足
Long型って書いてあるとの記載に、何度もヘルプを見たのですが、結果が分かって一安心でした。何度も何度も同じ質問にお付き合い頂き大変感謝しております。今後とも宜しくお願い致します。ありがとう御座いました。
- KenKen_SP
- ベストアンサー率62% (785/1258)
こんにちは。KenKen_SP です。 Dim TEST As XlPageOrientation '変数へ代入 TEST = ActiveSheet.PageSetup.Orientation 'セルへ変数の内容を転記 ActiveSheet.Range("A1").Value = TEST こういうことですか?
お礼
すみません。追加で、更にお手を煩わせますが、この宣言方法は、オブジェクト型なのですか?それとも、何型になるかは、定数による(定数に最適なものが自動的に選ばれる)ってことでしょうか? 実用的には、何型であっても、メモリーが有効に使えれば問題ないと思いますが、入門書に記載が無いので、気になってしょうがない感じがします。 すみません。つまらないことで、お手を煩わせて!!宜しくお願いいたします。
補足
いつもいつもありがとう御座います。 ご指導の内容のような定義の方法があるのならば、まさしくその通りです。って思い宣言エリアにASまで入力して候補選択をずーーーーと下まで見ると載ってました。XlPageOrientationが! 与えられている情報を全く活用していないことを痛感しています。Wedny02さんから教えて頂いた、F2とあわせれば自分で解決できるべき内容でした。VBAを知らないのではなくてVBAEを知らないことを知りました。 ありがとう御座いました。今後とも宜しくお願いいたします。
- 1
- 2
補足
話も落ち着いたようなので、申し訳ありませんが、閉めさて頂きます。皆様有難う御座いました。 ご指導、ご討議頂いた内容は、じっくり噛み砕いて今後に役立てたいと思います。いつの日か?皆様と対等に討論できるまで、自己研鑽に励みたいと思います。(そのためには、今後とも皆様のご指導が必要ですが・・!。勝手言ってすみません) 有難う御座いました。