質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

2回答

2288閲覧

Excel VBAについて質問させていただきます。初心者です。

G-apple-tmp

総合スコア11

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

1クリップ

投稿2014/12/31 22:36

初めまして。お世話になります。初めてこちらのサイトで質問させていただくので、何か不備があった場合は先にこの場でお詫び申し上げます。

私はExcel VBAで、セル内の空白で区切られた単語を反転させるプログラムを再帰的に書いています。
例えば、

山田 田中 鈴木 本田

という単語の列があった場合、これを

本田 鈴木 田中 山田

という風に反転させたいのです。

実は、某所でも質問したのですが、その時は自分でも何がわかっていて何がわかっていないのかさっぱりだったので、プログラマーの方がいらっしゃるというこのサイトで、改めて質問させていただくことにいたしました。

現在、私が書いたプログラムは以下の通りです。

lang

1Function ReverseWord(str As String) As String 2 3Dim Num As Integer, N As Integer 4Dim R1 As String, R2 As String, R3 As String 5 6 If N = 0 Then 7 Num = InStr(str, " ") 8 R1 = Mid(str, 1, Num) 9 R2 = Mid(str, Num) 10 R3 = R1 + R3 11 12 N = N + Num 13 ReverseWord (R2) & " " & R3 14 End If 15 16 If Len(str) > N > 0 Then 17 Num = InStr(str, " ") 18 19 R1 = Mid(R2, 1, Num) 20 R2 = Mid(R2, Num) 21 R3 = R1 + R3 22 ReverseWord (R2) & " " & R3 23 N = N + Num 24 End If 25 26 If InStr(R2, " ") = 0 Then 27 R3 = " " + R2 + R3 28 End If 29 30 ReverseWord = R3 31 32End Function

このプログラムについて質問です。

始めのIf文(N=0の部分)で、再帰呼び出しを書いたのですが(ReverseWord(R2))、If文(N=0)のところでループしてしまい、ここから長い期間わからないまま止まっております。おそらくこの始めのIf文がいけないのだと思いますが、何がいけないのか、教えていただけないでしょうか。

再帰呼び出しについて自分がよくわかっていないということもあるのだと思いますが、ここを理解しないと次に進めず困っております。ループ文ではなく、あくまで再帰的に書きたいということを強調させていただきます。

どなたか回答いただけると幸いでございます。

※完成したので一応載せておきます。正直、この再帰呼び出しは非常にわかりづらいと思いますが、非常に参考になる回答をいただいたので、あえて、ということで、あしからず。

lang

1Option Explicit 2Public N As Integer 3Public R1 As String, R2 As String, R3 As String 4 5Sub TestRM() 6Dim Tt2 As String 7 Tt2 = Sheet1.Cells(10, 2) 8 9 MsgBox ReverseWord(Tt2) 10 11 If InStr(R2, " ") = 0 Then 12 R1 = "" 13 R2 = "" 14 R3 = "" 15 End If 16End Sub 17 18Function ReverseWord(str As String) As String 19 20Dim Num As Integer 21 22 If N = 0 Then 23 Num = InStr(str, " ") 24 R1 = Mid(str, 1, Num) 25 R2 = Mid(str, Num + 1) 26 R3 = R1 + R3 27 N = Num 28 ReverseWord (R2) 29 End If 30 31 If (Len(str) > N) And (N > 0) Then 32 Num = InStr(R2, " ") 33 R1 = Mid(R2, 1, Num) 34 R2 = Mid(R2, Num + 1) 35 R3 = R1 + R3 36 N = N + Num 37 ReverseWord (R2) 38 End If 39 40 If InStr(R2, " ") = 0 Then 41 R3 = R2 + " " + R3 42 End If 43 44 If R2 = "" Or InStr(R2, " ") = 0 Then 45 N = 0 46 R1 = "" 47 R2 = "" 48 End If 49 50 ReverseWord = R3 51 52End Function

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

解決済みのようですが、ちょっと気になったので・・・。
やりたいことは再起もループも必要ありません。
split関数で配列化して逆順に文字列連結でOKです
こんな感じです。

Function ReverseWord(strSrc As String) As String
Dim i As Integer
Dim strTmp As String
Dim names

names = Split(strSrc) For i = UBound(names) To 0 Step -1 strTmp = strTmp & " " & names(i) Next i ReverseWord = Trim(strTmp)

End Function

アドバイスさせてもらうと、プログラミングはコツはどれだけロジックを簡単に整理できるかということです。
難しい事は、より単純なモデルに当てはめていくことでバグの少ないものが作れるようになります。

投稿2015/02/23 02:22

Guu

総合スコア142

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

お邪魔します。

とりあえずプログラム全体はおいておいて、ご質問の件に関してのみ回答します。

(このプログラムのやりたいことからして、再帰にこだわる理由は全くないと思います。
ループと再帰は相互に変換可能なのですが、再帰でやるほうが見通しのよいものと、ループで書いたほうが見通しのよいものがあり、このプログラムに関しては、再帰を使用することでかえって見通しが悪くなっていると思うので。。。)

再帰呼び出しにする場合、呼び出されたプロシージャ内の変数、例えば以下のものは

lang

1Dim Num As Integer, N As Integer 2Dim R1 As String, R2 As String, R3 As String

新たに領域が確保されます。
それなので、呼び出した側のNの値の変更が呼び出された側のNに伝わることはなく、Nは常に初期化時の0のままです。
このことが原因で無限ループが発生しています。

lang

1Static N As Integer 2Dim Num As Integer 3Dim R1 As String, R2 As String, R3 As String

とするか、Nを関数の外に宣言し、共通変数としてください。

これだけでプログラムが正常動作するかはちゃんと見ていないのでわかりませんが、とりあえず第一関門突破、ということで次のデバッグに入ってください。健闘を祈ります。

以上、参考まで。


追記です。

①Static宣言したが2回目の実行でおかしくなる。

1回目の実行が終わったら初期化してやらないとずっとカウントアップされたままなのかもしれませんね。
終了したタイミングか、最初に実行するタイミングでNを0に初期化する手段を考えたほうがよいです。
そう考えると、Static宣言よりプロシージャ外に宣言して共通変数とするほうがよいのかもしれません。

②If Len(str) > N > 0 Thenに入らない

lang

1If(Len(str) > N) And (N > 0) Then

としてみてください。
Len(str) > N > 0 では Len(str) > N = True が暗黙の型変換で-1にキャストされ、
-1 > 0 として評価されるのですが結果はFalseとなります。
(VBの黒いところです。イミディエイトウィンドウなどでint(True)やint(False)を実行してみてください)
この動きは望んだものではありませんよね。

以上です。

投稿2015/01/01 05:43

ShinpeiYamamoto

総合スコア540

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問