A 回答 (8件)
- 最新から表示
- 回答順に表示
No.8
- 回答日時:
こんばんは。
#5の回答者です。
他の方の書き込みを読んでいて、私の発言には、現象面だけを比較し、深く考えなかった軽率な内容の部分がありました。それをあわせて訂正と回答を述べさせていただくと、以下のような考え方になります。
最初に、VBAのVariant 型の範囲とはプロパティ面で、ワークシートのセルに格納される型の範囲とは違いがあるということです。一般的に、VBAで使われる、統合的構造体の変数のデータ型のことをVariant 型と呼んでいるわけです。もし、あえてワークシート上でも使うなら、本来はVariant の再定義が必要になってくるような気がします。XMLのデータ型を調べている最中に気がついたのは、「未設定」のものを、単にVariant型と言っているにすぎないと言えるのではないか、と考えたのです。
私は、いつもExcel上の仕様を考える時に、このExcelの制作側のコンセプトを想像することにしていますが、Excelを制作する時とVBをApplication用として搭載する時とでは、時代的にも、また用途も違うものがあるわけです。約10年の開きがあります。ただし、私の知っている範囲では、Visual Basic と、Excel , Word の元制作者は同一人物です。その中で別の考えを持った人たちがあったかは知りません。ただ、チームとして別々に存在していたし、考え方の差異そのものは、現代まで残ったままだと思います。
2つの似ていて非なる部分があるものが、両者をインターフェースで結び合わせているということです。Variant型であるかどうかという論議を出すよりも、あえて両者のデフォルト状態をVariant型とするなら、そのコンセプト(VBAとしてはプロパティ)は、元から違うものであると言えます。
また、コンセプトの違いの中には、ワークシート側のセルに、Null値の格納と、Empty値の格納の仕様はありません。ワークシートにも、この二語の用語は使いますが、概して、内容的に意味が違っていたりするほうが多いです。
セルとVBA側で基本的に共通しているのは、データ型ではなく、その表現方法(expression)だと思います。
BLANK
BOOLEAN
ERROR
FORMULA
NUMERIC(NUMBER)
STRING
だと思います。
また言うまでもなく、VB側のVariant型は、自然発生的なものではなく、ユーザー本意の人為的に作られた変数だと思います。それに比して、ワークシート側の、データの格納場所は、二重構造になっていて、片方は、文字か文字列で準ずるデータを格納し表象する場所であり、もう一つが、それに付随し計算する空間とが隣り合わせになって出来ているような印象を与えます。そのデータを格納する場所自体は、データ型を意識していない空間というわけです。
あえていうなら、VBAのRangeオブジェクトに対する、個々のプロパティのデータ型自体が、セルのデータ格納に反映しているのではない、ということになるのではないでしょうか?
仕組みの部分で、もう少し、根拠を出せると良いのですが、元が長い英文のpdfファイルなので、それをじっくり読んでいたら、どうも間にあいそうにもありません。
この回答へのお礼
お礼日時:2015/02/26 07:39
皆様ありがとうございます。既に私の頭はパンクしてるので、1年後位に読み直してみます。とりあえずは実用面では「variantだと思っとけばいい」位に考えておきます。
No.7
- 回答日時:
#4です。
#4を読んみ返していたら、大事な事を忘れていたことに気が付いたので、
実験コードを追加します。
そういえば、エラー値や空白値などの重要な型を
書き忘れてたりもしますが、、、。
元々走り書きのプロットですし、
配列を書き換えれば追加で色々試せるようには書いたので、
あれをこちらで書き直したりするつもりはないのですが、
もし、Sub ReG8927594() を実行すること(暇)が出来たなら、
出力済のシートに対して以下の
Sub VariantArr_VariantArr_Variant_Any()
を、試してみてください。(お暇な時に、、、。)
range.Value を 配列として変数に格納した時の
各要素の【型】を、ローカルウィンドウで見てみたら
少し理解が深まるのではないかと、、、。
各要素が内部形式を伴ったVariant型であることが確認できます。
(#因みに配列としての range.Value と Variant型変数との
出し入れって、これでも結構高速だったりします。)
対して、
Sub Variant_LongArr()
の方は、
Variantの(配列ではないスカラー)変数に格納する点は同様ですが、
中身はすべてLong型です。
Variant型スカラー変数に配列を格納したからといって、
それが理由で要素すべてがVariant型になる訳ではありません。
range.Value プロパティでセル値を取得する場合、は、
Variant 型になっちゃいますよね(.Formulaでも一緒)。
というお話なんです、、、。
(Value2やn=Cells(i, j)のような形だとちょと違うようなのですが、、、)
まぁExcel VBA のVariantは難しいですよね、そこが魅力に感じる私です。
世間ではVariant 型を使うデメリットがあるとかないとか、
色々考えさせられちゃって混乱しちゃうのかも知れませんが
ご自身で色々書いて試してする中で、実感できたものから、
Excel VBA に合ったご自分のスタイルを築いて貰えたらいいな、
と思っています。
Sub VariantArr_VariantArr_Variant_Any()
Dim v As Variant ' ※ Dim v() As Variant とは違い、要素をVariant宣言している訳ではありません。
v = Range("B2", Cells(2, 2).End(xlToRight)).Value
MsgBox "[Stop ステートメント]により、" & vbLf & "デバッグ(中断)モードでVBEが開きます" _
& vbLf & vbLf & vbTab & "ローカルウィンドウを表示して""" _
& vbLf & vbTab & "変数 v の要素について【型】を確認してください" _
, vbInformation
Stop ' Variant型の(スカラー)変数である v の各要素の【型】をローカルウィンドウで、、、
End Sub
Sub Variant_LongArr()
Dim v As Variant
Dim arrN(1 To 2) As Long
arrN(1) = 99
v = arrN()
Stop ' Variant型の(スカラー)変数である v の各要素の【型】をローカルウィンドウで、、、
End Sub
No.6
- 回答日時:
そもそもExcel自信がどの開発言語で書かれているかですが、
まず間違いなくVBは使われていません。
Netで調べたかぎりでは、やはりC++が使われている様です。
すると、C++の基本型にはVariant型なんぞはありません。
( VC++には、MSDNライブラリにVariant型なるクラス定義が
ありますが、これはC++の全ての基本型をUNIONしたものです。)
さて、VBAからセルにアクセスするときは、セルはRangeオブジェクト
として取扱われています。このことから、セルはC++のRangeクラス
として定義されていることにまちがいないでしょう。
で、セルからVBAの変数に値を取り出すのには、RangeクラスのCellsやValueプロパティ
を使いますが、プロパティとは、ご存じのように、メンバデータかメンバ関数です。
したがって、VBAのIntegerやDoubleなどの変数に値を取り出すときは、
それに対応した変換関数(メンバ関数)が使われますし、Variant型はおそらく
値へのポインターとして実装されているのでしょう。
ということで、Excelのセル値の記憶形式は、VBAでのVariant型なんかではないはずです。
No.5
- 回答日時:
#3の回答者です。
この話は、もともとは開発上の問題で、開発当初(Microsoftではありません)から、この表計算ソフトは、文字と数値を両方入れられる構造にしたと読んだことがあります。それが、今のVariant型と結びつくとは言えませんが、Lotus123との違いは、表示形式の割り込みにありますね。DateやTimeのような表示には、アプリ側が割り込んでくるわけで、数値(計算)と数字(文字)の区別というものは、本来、ありませんから、計算の際にのみ、キャストされるようですね。
私が、表計算のセル上で、Variant型と考えたのは、質問者さんとは違い、ワークシート上で使用する「ユーザー定義関数」は、出力型を、Variant型にするのが、良いのだと考えました。そうしないと、エラー値が返らないからです。エラー値は、CVErr関数を用いて返るからです。
#4様の書き込みを読んでいて、私の書いた#3の内容に、修正と説明不足がありました。
あたかも、円マーク(¥)が先頭についてものは、VBAでは、Double型であるような表現をしてしまいました。
「例えば、ワークシートのセルの書式に、円マーク(¥)が先頭についたものは、Currency型になると思ったら、残念! そのまま暗黙的なDouble型(Variant/Double)でしかありませんでした。ワークシート上の数値は、すべて、Double型に収まるようです。」
正しくは、確かに、VBA側では、Variant/Currency型と認められるのですが、ワークシート上で、Currency型では計算されていないようなのです。それで、ジャストシステムの「三四郎」を持ちだしたということです。
ちなみに、"Variant" というのは、「変異、異型」という意味で、変数は"Variable"です。
両方とも、数学英語のようで、あまり使ったことがありません。
No.4
- 回答日時:
こんにちは。
> セルの値を、型宣言した変数に取り込むことはよくありますが、取り込む前のセルに入った値の型は何でしょうか?
"セルの値を、型宣言した変数に取り込むこと" 私は、殆どやらない(殆どVariant型)です。
やるとすれば、range.Value2 プロパティ(Valueではないです)から数値を取得する場合か、
n = Cells(i, j) みたいに配列を扱う場合で取得するセルのデータ型が確実に指定されている場合、
ぐらいで、あとはほぼVariant型です。
【Excel】 【Excel VBA】
数値 Variant/Double
文字列 Variant/String
日付・時刻 Variant/Date
通貨 Variant/Currency
などに分けられますが、一時的にはすべてVariant型で受けることになります。
"取り込む前のセルに入った値の型"については、下記のマクロでも試してみてください。
> セルの書式設定で標準、数値、日付等と設定出来ますが、これは型を決めているのでしょうか?
> 試しにセルにアルファベットを入力した後、書式設定で強引に「数値」を選んでもエラーも警告も出ません。
> どういう仕組なのですか?
[セルの書式設定][表示形式]
これは、セルへの入力確定時に、
優先して選択されるデータ型に関する定義、を決めている ということです。
優先して選択されるデータ型に変換できない入力値はそのままになります。
[表示形式]が何らかの数値を指定した場合
入力確定時に、数値として読むことが出来るならば
指定した[表示形式]に関連付けされたデータ型が選択される、ということです。
例えば、[表示形式]を[通貨]を指定しておけば、
数値として読めるものは【Excel】側ですべて通貨型で確定しますし、
【Excel VBA】から値を取得した場合も、
Variant/Currency (Variant型で内部形式がCurrency型)になります。
例外があるとすれば、[Ctrl + ;][Ctrl + :]等のように、
予めデータ型(表示方法)が指定されている入力方法ぐらいです。
[表示形式][標準]というのは、何となくVariant型に似た存在というか、
まぁポリバレントなのですが、これも、優先して選択されるデータ型に関する定義、
というのが複雑になってるってだけで理屈は一緒です。
例えば、[表示形式][標準]のセルに、住所録の番地の部分だけを入力する場合等で、
1-13-1
これは、他に解釈しようがない文字列なので、文字列値
1-12-1
これは、日付として読むことを優先させる決まりがあるから、日付値2001/12/1
といった具合。
もう一つは、入力確定時の文字パターンによって、
純粋にセルに表示するテキストの表示を変えるだけという例外ですが、
(これは、よく誤解されている事なのですが)
日付を伴わない[時刻値]は、時刻型?でも日付型でもなく[浮動小数点数]として
扱われます。【Excel】ワークシート上でも【Excel VBA】でセルの値を取得する時も、
注意が必要です。【Excel VBA】で取得するだけではVariant/Doubleになってしまいます。
XMLソースを見ると、ちゃんと[日付時刻型]になっているみたいなので、
場面によっては[時刻値]も[日付時刻型]として扱っているのかも知れませんけれど
今回はセルの値を取得する場合の注意点、という話にとどめます。
> 全部variantですか?
答えるの難いです。
ただ【Excel VBA】では、range.Value プロパティを取得する場合は、
どのみち少なくとも一度はVariant型を経て内部形式が決まりますから、
「セルの値=.Valueを取得・格納する時はVariant型の変数を使います」
というか、Variant型を使う方が返って型がキャストされる回数が少なく済む場合も
あるように今までずっと思っていました(出力する場合は別)。
でも、【Excel】側でセルの値が"全部variant"というようなことは
今まで考えたこと無かったです。
【Excel】は【Excel】、【Excel VBA】は【Excel VBA】なんじゃないのかな?
改めて聞かれると自信を持って答えられませんけれど。
値の取得、データ型、Variant型の扱い方、という課題だったので、
オマケのコード添えておきます。
range.Value プロパティの新しい使い方は、私もまだよく解っていません。
参考になれば、と思っているのは、
TypeName(variant)
VarType(variant)
range.Value
range.Value2
range.Formula
range.Text
とかですね。
直接の答になるか解りませんが、> 全部variantですか?
の意味合いによっては、これが答えかも?
If TypeName(variant) = "String" Then
If VarType(variant) = vbDouble Then
のような判別とか、エラー値やEmpty値の受け皿とか、
Variant型の使いこなしは【Excel VBA】ならではです。
(以下の記述では、range.NumberFormatに一切手を加えていません。
興味と余力と暇が湧いてくるようなことがあれば
range.NumberFormatを弄ってみて確認してみるのもありかな、と)
Sub ReG8927594() ' /Excel2007以降
Dim arrV, arrF, vMSP, vSp
Dim oRegExp As Object, colMp As Object, colMs As Object
Dim n As Long, i As Long
Cells.Clear
arrV = VBA.Array("xwz", 909, CLng(-2147483647), CSng(1.401298E-45), CDbl("3.141592653589793"), CCur(987), CCur(12345678901234#), Date, Time, Now, True)
arrF = VBA.Array("文字列", "整数", "長整数", "単精度浮動小数点数", "倍精度浮動小数点数", "通貨", "通貨", "日付", "時刻", "日付時刻", "論理")
n = UBound(arrV)
With Range("B2").Resize(, n + 1)
.Value = arrV
vMSP = .Value(xlRangeValueMSPersistXML)
vSp = .Value(xlRangeValueXMLSpreadsheet)
End With
Set oRegExp = CreateObject("VBScript.RegExp") ' New VBScript_RegExp_55.RegExp
With oRegExp
.Global = True
.Pattern = "<s:datatype dt:([^>]*)/"
Set colMp = .Execute(vMSP)
.Pattern = "<Data ss:Type=""([^>]*)"">"
Set colMs = .Execute(vSp)
End With
For i = 0 To n
Cells(3, i + 2) = Replace(colMp(i).SubMatches(0), """", "")
Cells(4, i + 2) = colMs(i).SubMatches(0)
Cells(5, i + 2) = TypeName(Cells(2, i + 2).Value)
Cells(6, i + 2) = VarType(Cells(2, i + 2).Value)
Cells(7, i + 2) = "=""" & Cells(2, i + 2).Value & """"
Cells(8, i + 2) = "=""" & Cells(2, i + 2).Value2 & """"
Cells(9, i + 2) = "=""" & Cells(2, i + 2).Formula & """"
Cells(10, i + 2) = "=""" & Cells(2, i + 2).Text & """"
Next i
Cells(2).Resize(, n + 1).Value = arrF
Range("A1:A10").Value = [{"入力時データ型";"セル上の値(表示値)";"ValueMSPersistXML";"ValueXMLSpreadsheet";"VBA Variant TypeName";"VBA Variant VarType";"VBA range.Value";"VBA range.Value2";"VBA range.Formula";"VBA range.Text"}]
Columns(1).Resize(, n + 2).AutoFit
Cells(5, 1).Resize(, n + 2).Interior.Color = vbYellow
End Sub
No.3
- 回答日時:
こんにちは。
>セルの中身はVariant ?
はい、セルの中身は、Variant型です。おまけに、ワークシート上の関数も、Vairant型の出力です。
>標準、数値、日付等と設定出来ますが、これは型を決めているのでしょうか?
セルの書式自体は、暗黙的な型は、システム上変換されます。しかし、「明示的な型」というのは存在しないようです。私もしばらく前まで期待して、例えば、ワークシートのセルの書式に、円マーク(¥)が先頭についたものは、Currency型になると思ったら、残念! そのまま暗黙的なDouble型(Variant/Double)でしかありませんでした。ワークシート上の数値は、すべて、Double型に収まるようです。また、Variant型だからこそ、#Valueなどのエラー値が排出できるわけです。
ちなみに、ジャストシステムの「三四郎」にはオプションで、Currency型も入れられるようです。
>試しにセルにアルファベットを入力した後、書式設定で強引に「数値」を選んでもエラーも警告も出ません。
それは、システム側に、その文字/数字が演算されることもないままになっているからですね。入れ物に入れただけで、通常は、エラーは発生しません。
逆に、数字(数値)をセル上に置いて、それを、Mid関数やLeft, Right関数で操作すると、文字扱いになります。(VBAでもありますが、どうも、私は、こういう方式は苦手です。)
しかし、ワークシート上は、常に、数値・日付(時間)・文字というものは監視しているから、日付と思われるものは、日付で変換してしまうわけです。
VBA側はVBA側で、ワークシート側はワークシート側で、自動的に内部の型に割り振られた表示に変わるように暗黙的な型は決まってきます。
これを、いわゆる「自動キャスト」(型の内部変換)機能、という現象の一つですね。
一般的には、VBAでは、a = "123" + 456 としても、a には合計が入ることで、"123" が、型の変換が怒っていることを指します。
日付や時間は、ワークシート上でも、VBA上でも、「自動キャスト」が起こります。
他にも、整数型と浮動点小数型を一緒にすると、Double型にキャストされるようですが、これは、精度の高い方に、キャストされるわけですね。
逆が、Mod や \ の演算子は、浮動小数点型に対応する整数型の丸められます。
ここは、ワークシート関数のMod や VB.Net と違うところですね。
と、こんな話で良かったかしら?
この回答へのお礼
お礼日時:2015/02/23 20:45
ありがとうございます。
Variantではあるが、内部的には型の自動変換が起きている、エクセルの内部に踏み込んだ回答をありがとうございます。
No.1
- 回答日時:
こんばんは!
あくまで私的見解ですが・・・
>セルの書式設定で標準、数値、日付等と設定出来ますが、これは型を決めているのでしょうか?
あくまで「書式設定」の中の「表示形式」の話です。
Excel的に「数値」とみなされるものはそのように表示することが可能だという意味と解釈しています。
シリアル値にしても0以上の数値を「○月○日」のように表示させているだけです。
表示形式の「時刻(時間)」は小数点以下の数値を時刻(時間)として表示させている。
>強引に「数値」を選んでもエラーも警告も出ません。
文字列はどのように転んでも文字列ですので、表示形式の変えようがないのでエラーにならないだけだと思います。
ただ、計算式に文字列が入っていると「#VALUE」のようなエラーになるはずです。
次に「変数の型」についてですが、VBAで
仮に整数型(長整数型)などに宣言した変数に文字列を格納しようとしても
「型が一致しません」というメッセージが表示されると思います。
すなわち変数の宣言を行う場合は間違いないようにする必要があります。
どの型に宣言しようか?と迷った場合は逃げ道として
どんな型でも対応できる「Valiant型」にしておけば、とりあえずはエラーは出ない。といった感じでしょうか。
(Array関数のように変数によっては必ず「Valiant型」にしなければならないものもあります)
※ 直接の回答になっていないかもしれませんし、内容に間違いがあるかもしれませんが
とりあえずはこの程度で・・・m(_ _)m
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 会計ソフト・業務用ソフト エクセル 背景色のついたセル位置を参考にして固定の数値を取得する 4 2022/07/11 08:44
- Excel(エクセル) EXCELの「接続」のSQLのコマンド文字列にて、セルから任意の数値を利用したい 2 2023/03/09 16:43
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Excel(エクセル) エクセルの書式設定の表示形式で設定した文字を文字列としてコピーしたい 1 2022/12/21 10:41
- Excel(エクセル) エクセルでシート保護のかかり方の違いとセルの非保護の設定 3 2022/08/09 10:02
- Excel(エクセル) 【!】Excel 2つの条件付き書式が反映されません。。 5 2023/07/14 16:47
- Excel(エクセル) エクセルのマクロについて教えてください。 2 2023/02/26 13:19
- Visual Basic(VBA) Excel のユーザー定義関数でソルバーが動作しない 1 2022/09/05 19:51
- Excel(エクセル) エクセルの数式で教えてください。 5 2023/02/10 15:11
- Excel(エクセル) エクセルでIF関数中にIFERROR関数を使いたいのですが???? 5 2022/04/08 13:24
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルでの計算式で求められ...
-
エクセルのセル内の余白の設定...
-
Excelで 分:秒 と表示させる...
-
エクセルの計算結果を()括弧で...
-
エクセルで数式を入れても値が...
-
EXCELで日付と時刻が入ったセル...
-
エクセルの計算式の後に、単位...
-
エクセルで日付が逆に登録され...
-
エクセルで折り返しと縮小の同...
-
エクセル 桁を増やす方法
-
【Excel】 特定セルだけに「ゼ...
-
Excelの単位で立法メイトルを表...
-
エクセルで 何時間何分と表示...
-
エクセルで西暦に変更できない
-
エクセル:日付和暦の数字だけ...
-
エクセルで、書式設定をして表...
-
Excelで数字をハイフンで区切る...
-
エクセル 条件付き書式で文字...
-
エクセルの分数表示
-
EXCELでセル内に打った文字が隠...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルでの計算式で求められ...
-
エクセルのセル内の余白の設定...
-
Excelで 分:秒 と表示させる...
-
エクセルの計算結果を()括弧で...
-
エクセルで日付が逆に登録され...
-
【Excel】 特定セルだけに「ゼ...
-
エクセルで数式を入れても値が...
-
エクセルで 何時間何分と表示...
-
エクセル 桁を増やす方法
-
エクセルで折り返しと縮小の同...
-
EXCELで日付と時刻が入ったセル...
-
エクセルで西暦に変更できない
-
エクセルの計算式の後に、単位...
-
エクセルの分数表示
-
EXCELでセル内に打った文字が隠...
-
エクセル:日付和暦の数字だけ...
-
エクセルで、書式設定をして表...
-
Excelに「隠し文字」のような機...
-
セル列のすべての文字列の頭に”...
-
エクセル A1に1と入力すると○、...
おすすめ情報