電子書籍の厳選無料作品が豊富!

過去の質問で色々と助言を受け、以下のプログラムを作成しました。エラーはでないのですが
最後のMsgBoxで何も出てきません。

詳しい方教えていただけないでしょうか。




'1号機の品名を重複分もすべて格納する
Dim No1_M_number(100) As Variant


'1号機の品名で重複分を除いた配列
Dim M_number() As Variant

※色々ループ文で処理をしてNo1_M_number(0)~No1_M_number(67)
まで品名が格納されている。


'関数に配列を渡し、重複分除去



M_number = deleteDuplicateItem(No1_M_number())

Dim s As String
s = ""

s = Join(M_number, vbCrLf)

MsgBox s  ←ポップアップに何も表示されない



Function deleteDuplicateItem(ary() As Variant) As Variant()
'#####################################################################
'配列から重複している要素を削除する
'Dictionaryを使用するので、Microsoft Scripting Runtimeの参照設定が必要
'---------------------------------------------------------------------
'引数 :ary 重複を削除したい配列
'#####################################################################

 Dim Dic As Dictionary
 Set Dic = New Dictionary
 
 Dim i As Long
 
 For i = 0 To UBound(ary)
  If Dic.Exists(ary(i)) = False Then
   Dic.Add ary(i), ary(i)
  End If
 Next i
  
 deleteDuplicateItem = Dic.Keys()
 
 Set Dic = Nothing
 
End Function

A 回答 (12件中1~10件)

//デバッグで、イミディエイトウィンドウを使う場合と、ブレークポイントを使用することの違い。



・イミディエイトウィンドウを利用する
Debug.Print の命令を書き込むことが必要でする

値を単独で取る場合など、命令で値を拾うことが目的になることが多いのです。
いくつか、私の使っている例を挙げておきます。

//マウスの選択の[幅、高さ、トップ、左] で、位置を調べる
With Selection
 w = .Width
 h = .Height
 t = .Top
 l = .Left
Debug.Print "wd:" & w; " ht:" & h; " tp:" & t; " lft:" & l
End With
//
長い名前でテキストで記録が必要な場合
Debug.Print Application.DefaultFilePath 'デフォルトのファイルの置き場所
Debug.Print Application.UserLibraryPath 'ユーザーのアドインの置き場所

*これで分かる通り、記録が必要な場合は、このように、イミディエイトウィンドウを利用します。
 これを多用する時は、イミディエイトウィンドウの内容が煩雑になりすぎますので、その内容を消しゴムのアイコン(MZ-Tools)で内容を削除します。これをブレークポイントど同じようにする場合は、一旦変数にとって、それを変数をCtrl+C コピーで取り出しますが、メモ帳などを立ち上げなくてはならないし、面倒かもしれません。

=======================

・ ブレークポイントを利用する
それに対して、ブレークポイントは、
No.9の画像の通り、左端のフレーム部分をクリック
または、ツールバーですと、デバッグツールバーのの「手(ハンド)」のアイコンをクリック

FNo = FreeFile()
Open Fname For Input As #FNo
● Do While Not EOF(FNo) '**
'命令
Loop '**
Close #FNo

このように延々と続くループや刻々と値が変化する場合に、その経過を調べる時に利用します。
●の場所の実行直前でマクロが一時的に止まります。その後をステップモードの、F8を押して一つずつ飛ばします。上記の「命令」の部分が、Call 別プロシージャ などが入っている場合には、
Shift + 8(ステップオーバー) で、その内容を飛ばして、次に進むことが可能です。
この時、ローカルウィンドウで、値がどう変化しているか見ることが可能です。

ローカルウィンドウを利用する変則的な用法例
Sub Test1()
  a = 1.1
  b = 2
  c = a + b 'どっちが強いか?
  d = c Mod 5 'どっちが強いか?
  e = c + 5.3@ 'どっちが強いか?
End Sub

変数 cの暗黙のデータ型は、何か? ローカルウィンドウで、Double 型になるのが分かります。
変数 dの暗黙のデータ型は、何か? (VB6/VBA)
変数 e の暗黙のデータ型は、何か?
後で変数の型を付け加えることが可能です。

答えは、
a As Double, b As Integer, c As Double, d As Long, e as Currency
ただし、b は、Integer 型ですと、入れ物として小さいかもしれません。

今回の場合、
//
Dim s As String
s = ""
● s = Join(M_number, vbCrLf)
MsgBox s ←ポップアップに何も表示されない
//
このような、確認の命令コードの必要がありません。
ブレークポイントで、M_number の変数を確ローカルウィンドウで調べれば、表示されない理由は、M_Number で格納されていないか、次のステップで、s の変数がどのようになっているか、みることが可能です。

なお、試験そのものはあまり意味がないかもしれませんが、VBAエキスパート試験では、「Excel VBAスタンダード」に出題される問題で、イミディエイトウィンドウもブレークポイントも両方とも必須だと思って間違いないと思います。
他に、ウォッチウィンドウというものもありますが、コードで、一旦、数式でTrueを立てないと、内容が見れないので、長いコードの場合に、利用しますが、私はあまり利用していません。

以上で、再度まとめを書かせていただきました。
    • good
    • 0

No.9 の添付画像


訂正:ブレークポイントは「ワンクリック」でした。ダブルクリックではありませんでした。

No.10に対して
>勉強のためにその手間が多いと言う具体的な理由を知りたいと願います。

ブレークポイントは、VBAの基礎の基礎ではなかったのではないでしょうか。
理由もなにも、使ってみれば分かるはずですが。手間という言葉が気に入らなければ、手数ということです。このレベルになると、さすがに回答者どうしが、教え合うというものではないように思うのです。ブレークポイントをお使いになっていないようですね。

ブレークボイントは、そのポイントの後は、ステップモードで、変数などの流れを見るということをするわけで、途中で、条件付きではあっても書き換えが可能です。これがないと、どうしても開発できない場合があります。

また、いくつでもおけるし、それを残し忘れても、一度に消すことができるし、再度立ち上げた時には、それは消えているわけです。また、Debug.Print のように出力しつづけていることはないわけです。

>ローカルウィンドウに配列変数の中身をあるだけ吐き出して、そこから何を知るのでしょう。
ローカルウィンドウは、展開はあっても吐き出しません。展開したものは、また、折りたたんで戻すことも可能です。Debug.Print の使用を否定するわけではありませんが、記録として残す必要がある場合に使います。

インストラクターのネタ帳
・『ブレークポイントを使ってみてください』
https://www.relief.jp/docs/why-do-not-you-use-br …
    • good
    • 0

No.8です。


回答ではなく申し訳ないです。

私はイミディエイトをよく使うのですが、勉強のためにその手間が多いと言う具体的な理由を知りたいと願います。
デバッグ処理はともかくローカルウィンドウに配列変数の中身をあるだけ吐き出して、そこから何を知るのでしょう。

今回の質問が配列変数の値が一部予期せぬ物であったなら、その原因を突き詰める為インデックスを調べると言うのならわかります。
けど既にと言うか元から不明点はそこにはないのでは?
ならば配列変数のインデックスで部分的に表示させる、要素数を調べるなどが必要と思いましたのですけど。

確かに他言語を幾つも扱われているからこその御意見とは思いますので、是非とも知りたいところではあります。
    • good
    • 0

No.2の回答者です。



デバッグはマクロの基本中の基本ですから、ぜひ覚えてください。
イミディエイトウィンドウでは、手間が多いです。
MsgBox も手間が多いです。

デバッグというメニューがありますから、そこで、ブレークポイントが付きます。
F9でも、左端のダブルクリックでも可能です。
ブレークポイントは、左端に●が付きます。

なお、少し気になる、コーディングの中に出てくる変数ですが、マクロがよく理解できていない状態では、変数の宣言は一番上にしたほうがよいと思います。変数の宣言をすると、内容がご破産になるからです。

図は少し複雑にはなっていますが、単にブレークポイントを入れるだけの仕組みです。
「VBA 配列で重複した単語が格納されてい」の回答画像9
    • good
    • 0

No.7です。



ついでですが、ReDimも使い方をミスるとデータを消しちゃうかも。
私はあまり好きではないので使いませんけど。
    • good
    • 0

個人的な意見ですが。



全くの新規ブックでMicrosoft Scripting Runtimeの参照設定をしてみて、

Sub Sample()
Dim Dic As Dictionary
Set Dic = New Dictionary

Dic.Add "あいうえお", "abc"
Dic.Add "かきくけこ", "def"

MsgBox Join(Dic.Keys(), vbCrLf)

Set Dic = Nothing
End Sub

を実行してみるとか?
ここで何も表示されないって事なら、参照設定しているDllがおかしいのかも知れないし。(最近バージョン変更をしたなど)

ちゃんと表示されるのなら、見えない部分でNo1_M_numberを初期化しているかプログラムを中断(Exit Sub)しているのかも。
特に中断の場合だとIf文の判定が正常に行われてないなどの可能性もある。
    • good
    • 0
この回答へのお礼

新規のブックで実行したところ、ちゃんとポップアップで表示されました。
プログラムのほうを疑ってみます。

お礼日時:2019/11/14 08:57

そうですね、元のプログラムにも適当な個所にメッセージボックスを置いてどこまで進んでいるか確かめるといいかもです。

    • good
    • 0

確認方法ですが「deleteDuplicateItem」関数に以下のようにメッセージボックスを追加してどこまでデータが有るか確認してみたらいかがでしょうか?


「配列の要素数は0です」と出たら配列にデータがセットされていないという事です。

Function deleteDuplicateItem(ary() As Variant) As Variant()
'#####################################################################
'配列から重複している要素を削除する
'Dictionaryを使用するので、Microsoft Scripting Runtimeの参照設定が必要
'---------------------------------------------------------------------
'引数 :ary 重複を削除したい配列
'#####################################################################

 Dim Dic As Dictionary
 Set Dic = New Dictionary

 Dim i As Long
 MsgBox ("配列の要素数は" & UBound(ary) & "です")
 For i = 0 To UBound(ary)
  If Dic.Exists(ary(i)) = False Then
   Dic.Add ary(i), ary(i)
  End If
 Next i
 MsgBox ("辞書の要素数は" & Dic.Count & "です")
 deleteDuplicateItem = Dic.Keys()

 Set Dic = Nothing

End Function
    • good
    • 0
この回答へのお礼

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

MsgBox2か所追加しましたが、何もポップアップが出ずに終わってしまいました。
これは関数が使用されていないということなのでしょうか・・・

お礼日時:2019/11/13 20:23

No.3のお礼に対して。



ユーザー定義に

 Next i
 Debug.Print "Dic = " & Dic.Count '★追加 
 deleteDuplicateItem = Dic.Keys()

としてみるとか。
そしてイミディエイトウインドウにどのように出るか?
    • good
    • 0

簡単にやるなら



MagBox M_number(0) & "_" & M_number(UBound(M_number)) '最初と最後の値を表示
MsgBox UBound(M_number) '要素数を調べる

などを調べるのも手では?
    • good
    • 0
この回答へのお礼

MsgBox M_number(0) & "_" & M_number(UBound(M_number)) '最初と最後の値を表示 ←エラー
MsgBox UBound(M_number) '要素数を調べる

を入れてみたら実行時エラー:'9'
インデックスが有効範囲内にありませんと出力されました。

このエラーが出るのはどういうときなのか調べてみますね。

お礼日時:2019/11/13 18:58

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!