
No.2ベストアンサー
- 回答日時:
こんにちは。
>ちなみにこのモジュールに渡される配列の型は一次元、二次元ともにありますので、どちらにも対応できるようにするにはどうすればよいでしょう?
うーん、ご質問のレベルは、そのユーザー定義関数のコードのレベルよりワンランク上というよりも、一般的には、こういう場合、あくまでも、Excel VBAの範疇では、Excelでは、ワークシートを使いますね。もちろん、VBAでも技術的にも可能ですが、最初から行・列を想定しているなら、マトリックスになったワークシートに置き換えたほうが考え方が楽です。
元の質問と、「お礼」側とは、内容が変わりますが、そのユーザー定義関数を、1次元・2次元も両方できるように変えてみました。
以下のマクロは、最初から、1次元を2次元に切り替えてしまいます。本来、1次元と2次元の違いが検出できるのだから、別々に検索すればよいわけですが、紙面の関係上というのか、ここでは、2次元に切り替えてしまいました。
また、単に、各次元の上限の添え字を取るなら、Ubound で、エラーが出るまで、次元を増やせばよいのですが、その先に、文字列を探すということだと、あえて、ここでは、2次元までとして、それ以上は打ち切りました。
だから、解は、配列で返します。1次元でも、Ary(10) の3 に目的のものがあるとしても、「3,0」とします。関数内部では、引数が、1次元か2次元かは、If m = Empty Then で、取れていますから、もし、第一次引数Ar が、1次元だから、解も1次元にするというなら、分岐して、解の出力側で変えてあげれば済みます。どちらがよいかは、今考えておりません。
この関数のエラー値は、2次元以上の多次元は、解は「0」で、また、配列でない、第一次引数Ar も、解は「0」を返します。本来、関数の戻り値をVariant 型にしていますから、 CVErrで、エラー値を返してもよいのですが、処理が増えますから、一応、便宜的に数値にしました。
-----------------------------------------------------------------
Function FindArrayR(ByRef Ar, ByVal arg As String) As Variant
Dim ub As Integer
Dim Ar2 As Variant
Dim n As Variant
Dim m As Variant
Dim i As Long
Dim j As Long
Dim flg As Boolean
flg = False
If Not IsArray(Ar) Then FindArrayR = 0: Exit Function
On Error Resume Next
Do
i = i + 1
ub = UBound(Ar, i)
If Err.Number = 0 Then
If i = 1 Then
n = ub
ElseIf i = 2 Then
m = ub
ElseIf i > 2 Then
FindArrayR = 0: Exit Function
End If
Else
Exit Do
End If
Loop
On Error GoTo 0
'1次元配列を、2次元配列に切り替え
If m = Empty Then
ReDim Ar2(n, 0)
For j = 0 To n
Ar2(j, 0) = Ar(j)
Next j
m = 0
Else
Ar2 = Ar
End If
For j = 0 To m
For i = 0 To n
If StrComp(Ar2(i, j), arg) = 0 And flg = False Then
flg = True
Exit For
End If
Next i
If flg Then Exit For
Next j
FindArrayR = Array(i, j)
End Function
なお、今回使った、テスト用のマクロ
Sub TestMacro()
Dim i As Integer
Dim ret As Variant
Dim Ar(10, 10) As Variant
For i = 0 To 10
Ar(8, i) = Chr(65 + i)
Next
ret = FindArrayR(Ar, "E")
End Sub
------------------------------------------------------------------
なお、val$ という書き方はしないでね。Val は、VBA関数ですから、非常に見にくい状態になります。
回答ありがとうございます。
DoLoopでUbound で、エラーが出るまで次元を増やせばよいという考えが思いつきませんでした。このコードを元に1次元は1次元で返すように変更してやってみようと思います。
重ねて質問なんですが、
>>本来、1次元と2次元の違いが検出できるのだから
とありますがそれはどういうことでしょうか?
No.4
- 回答日時:
ご大家の後で、素人の小生が言うのも気が引けるのですが、質問者は
http://msdn2.microsoft.com/ja-jp/library/95b8f22 …
で言っているようなことを聞いているのではないでしょうか。
http://dobon.net/vb/bbs/log3-1/511.html
にASPの例の質問があり、上記にいたりました。
上記WEB記事で言っているのは
Sub test02()
Dim a(100, 200)
MsgBox UBound(a, 2)
End Sub
で200と表示されますが、こんなのでよければ参考にしてください。
ーー
Array関数を使った場合は、今まで私の経験する程度の易しい範囲内では、Ubound+1でデータ数(使用要素数)が取れましたが
一般的にDim A(100) と宣言した場合
Sub test01()
Dim a(100)
MsgBox UBound(a)
End Sub
は100と表示されますが、実際何個使われているかは1発では判らないのでは。
配列要素内容を使うごとに1つづつRedim、ResizeでもしないとVariantのArrayと同じようには捉えられないのでは。
http://www.atmarkit.co.jp/fdotnet/dotnettips/444 …
ーー
Wendy02さんのご回答に既に出ている内容なら、Wendy02さんお許しください。
解答ありがとうございます。
Wendy02さんの解答で既に解決していました。
今までUBOUND(ary)という使い方しかしたことがなく、UBOUND(ary,Rank)というようにRankを指定すれば任意の次元の添字の最大値が求められるということを知らなかったんです。
お手数かけてすいません。
No.3
- 回答日時:
こんにちは。
>>>本来、1次元と2次元の違いが検出できるのだから
>とありますがそれはどういうことでしょうか?
だから、
>引数が、1次元か2次元かは、If m = Empty Then で、取れていますから、
ということです。それ以上の多次元の話と、1・2次元の話とは、意味合いが違います。ある程度の予想はあるけれども、3次元以上の多次元で検索することは、今のところ考慮には入れていません。また、それ3次元以上の検索というのは、あまり現実的ではありません。もちろん、3次元検索自体は、Excel Cube に存在している検索ではあるのですが、実際には、やったことがないからです。
>引数が、1次元か2次元かは、If m = Empty Then
そういうことですよね。てっきり配列の次元を調べる関数があるのかなと勘違いしてしまいました。
そもそも、なんでこうなるかと言いますと、表のに行タイトル(B5:M9)の上部(D1:M4)に項目名が記載されていて、項目名を配列Arに読込データベースの項目名(先程のval$)とArを比べArのインデックス(そのままセルアドレスになります)を取得し、その場所から相対的に値を代入する表を作りたいいう事が目的で、将来作成者がいなくても上部の項目名の並びや削除をするだけで、表が作れるということをしたかったんですよね。
いままでは上部の項目名(B1:M1)でタイトル(B2:M3)というような感じで一次元でよかったんですが、要求された表が多次元だったもので質問しました。
ですので、2次元までで十分ですので、先程のコードを活用させていただきます。ありがとうございました
No.1
- 回答日時:
こんにちは。
Sub Test()
Dim ar(4, 13) As Variant
Dim one As Integer
Dim two As Integer
one = UBound(ar, 1)
two = UBound(ar, 2)
End Sub
array は、関数名ですから、変数には使わないほうがよいです。
p.s.別件で、ふだん、こういうことはローカルルールに反するので書いてはいけないので、もし問題があれば、削除されてもかまいませんが、
前回の「エクセルファイルの自動起動と内容更新」の質問の、20点側の回答の「起動時に全てのファイルを開く」に設定する方法は、非常にトラブルの多い設定で、万が一失敗すると、Excelのセーフモードでしか開けられなくなります。
C:\Documents and Settings\[ユーザー名]\Application Data\Microsoft\Excel\XLSTART\
フォルダに入れるのが一般的です。よけいなことかもしれませんが、ちょっと気になりました。
先日の質問まで補足していただき、ありがとうございます。
私の質問が足りなかったせいで、Wendy02にはご迷惑をかけます。
Function FindArray(ByRef ary() As String, ByVal val$) As Long
For idx = LBound(ary) To UBound(ary)
If ary(idx) = val Then
FindArray = idx
Exit Function
End If
Next
End Function
というやりかたで一次元配列内の中身とval$を比較して、そのインデックス番号を取得するというコードがあるのですが、これを二次元配列に対応できるようにしたいんです。
ちなみにこのモジュールに渡される配列の型は一次元、二次元ともにありますので、どちらにも対応できるようにするにはどうすればよいでしょう?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- PHP PHPでCSVを出力するさいに、ループの中で前の行の値を変更したい 3 2022/10/27 17:44
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- PHP ファイルの書き込みについて教えて下さい。 1 2023/03/20 12:01
- PHP PHPでCSVを出力するさいに、ループの中で前の行の値を変更したい 1 2022/10/27 14:21
- PHP PHPの構文で間違えが分からない 5 2022/07/11 16:38
- PHP SQLとPHPの連結方法がわからないのでアドバイスお願い致します 1 2022/07/12 12:16
- Java Java 南京錠 2 2023/02/04 11:46
- Perl perlで2次元配列をサブルーチンに値渡しで渡す 5 2022/12/17 18:49
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列数式の解除
-
2つ以上の変数を比較して最大数...
-
配列変数の添字が範囲外ですと...
-
配列を任意の数値で埋める方法
-
VB6 配列を初期化したい
-
配列に同じ値を入れる方法
-
OutlookVBAでサブフォルダ一括作成
-
VBA 1次元配列を2次元に追加する
-
subの配列引数をoptionalで使う...
-
モンテカルロ法を用いた積分計...
-
2次元動的配列の第一引数のみを...
-
Dim は何の略ですか?
-
特定のセル範囲で4文字以上入力...
-
ListViewで、非表示列って作れ...
-
Array配列の末尾に追加したい。
-
エクセルマクロで配列の値から...
-
VBAで近似曲線の係数取得
-
エクセルで特定の列が0表示の場...
-
教えて下さい
-
特定のPCだけ動作しないVBAマク...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
配列数式の解除
-
2つ以上の変数を比較して最大数...
-
VBA 1次元配列を2次元に追加する
-
特定のセル範囲で4文字以上入力...
-
subの配列引数をoptionalで使う...
-
VB6 配列を初期化したい
-
配列変数の添字が範囲外ですと...
-
2次元動的配列の第一引数のみを...
-
ListViewで、非表示列って作れ...
-
Excel-VBAの配列「Public Const...
-
for each の現在の配列ポインタ...
-
AES暗号にて、AES_set_encrypt_...
-
Dim は何の略ですか?
-
VBのFunctionで、配列を引数...
-
配列を任意の数値で埋める方法
-
verilogで配列の任意の8bitを取...
-
エクセルで最小値から0を除く方法
-
《エクセル2000》A列・B列の商...
-
配列内の内容を全て表示する方法
-
配列に同じ値を入れる方法
おすすめ情報