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

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

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

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

Q&A

解決済

4回答

1905閲覧

VBA Fuction 戻り値

yakumo02

総合スコア103

VBA

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

0グッド

0クリップ

投稿2020/09/11 07:16

以下はtarget変数に文字列が入っており、別のシートにその文字列が存在するか判定するプログラムです。
hikaku2プロシージャを複数呼び出して何回か処理しているのですが、別シートに存在するはずなのにFuction関数の戻り値がFalseになってしまいます。
Debug.printで結果がTrueになっていることも確認していますがhikaku2ではElseで処理されてしまいます。
以下のコードの中は問題ないのでしょうか
ちなみに以下のコードとほぼ同じものが、もう一つ存在します。複数回使えないものなどあるのでしょうか?

Sub hikaku2() e = 2 Set this = ThisWorkbook.Worksheets("イベント") Do While e = 2 target = this.Cells(2, 7).Value Application.ScreenUpdating = False If target Like "初期表示" Then '初期表示という文字列なら Call IsContained2(target) If kekka2 = True Then this.Cells(e, 9).Value = "一致" Else '全てこっちで処理されてしますう this.Cells(e, 9).Value = "不一致" End If End If If Not target Like "初期表示" Then '初期表示という文字列以外なら Call tes2(target) If answer2 = True Then this.Cells(e, 9).Value = "一致" Else '全てこっちで処理されてしまう this.Cells(e, 9).Value = "不一致" End If End If e = e + 1 Loop End Sub Function IsContained2(target) As Boolean On Error Resume Next num2 = Application.WorksheetFunction.Match(target, ThisWorkbook.Worksheets("Sheet3").Range("A1:A1000").Offset(0, nn), 0) ' ここで別シートにtargetがあるか判定 nnは別で更新しています On Error GoTo 0 If num2 = 0 Then kekka2 = False Else 'こっちになるときもある kekka2 = True End If End Function Function tes2(target) As Boolean On Error Resume Next num2 = Application.WorksheetFunction.Match(target, ThisWorkbook.Worksheets("Sheet3").Range("A1:A800").Offset(0, nn), 0) On Error GoTo 0 If num2 = 0 Then answer2 = False Else 'こっちになるときもある answer2 = True End If End Function

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

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

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

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

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

guest

回答4

0

解決済みですが、
Functionの機能を理解されていないようなので、補足説明します。

おそらくkekka2、answer2 をグローバル変数として宣言して(標準モジュールの先頭で宣言)解決したのだと思いますが、せっかくのFunctionの機能がまったく生かされていない使い方なのでもったいないです。
また、グローバル変数はコードの可読性が下がるし、バグの原因になりやすいので避けるべきだとされています。

下記のようにFunctionの戻り値を利用すればグローバル変数を使う必要はありません。
また、nnもグローバル変数としているようですが、引数で渡すように変更しましょう。
(詳細が不明なので、下のコードではグローバル変数のままにしてますが。)

vba

1Option Explicit '変数宣言強制 バグを防ぐために必須 2 3Dim nn As Long 4 5Sub hikaku2() 6 Dim this As Worksheet 7 Set this = ThisWorkbook.Worksheets("イベント") 8 9 Dim e As Long 10 e = 2 11 12 Application.ScreenUpdating = False 13 14 Do While e = 2 'このDo While は必要ですか?現状だと常に一回しか実行れません。 15 Dim target 16 target = this.Cells(2, 7).Value 17 18 If target Like "初期表示" Then '"初期表示"という文字列なら 19 20 If IsContained2(target) = True Then 'Functionの戻り値で判別 21 this.Cells(e, 9).Value = "一致" 22 Else 23 this.Cells(e, 9).Value = "不一致" 24 End If 25 26 Else '"初期表示"という文字列以外なら 27 28 If tes2(target) = True Then 'Functionの戻り値で判別 29 this.Cells(e, 9).Value = "一致" 30 Else 31 this.Cells(e, 9).Value = "不一致" 32 End If 33 34 End If 35 36 e = e + 1 37 38 Loop 39 40 Application.ScreenUpdating = True '画面更新許可に戻しておく 41 42End Sub 43 44Function IsContained2(target) As Boolean 45 46 On Error Resume Next 47 48 Dim num2 As Long 49 num2 = Application.WorksheetFunction.Match( _ 50 target, _ 51 ThisWorkbook.Worksheets("Sheet3").Range("A1:A1000").Offset(0, nn), _ 52 0) 53 'ここで別シートにtargetがあるか判定 54 'このnnはどこで取得しているか不明なのでそのままにしているが、 55 'グローバル変数とするのではなく引数で渡すようにすべき 56 On Error GoTo 0 57 58 If num2 = 0 Then 59 IsContained2 = False '結果を関数名に代入することで戻り値して利用できる。 60 Else 61 IsContained2 = True '結果を関数名に代入することで戻り値して利用できる。 62 End If 63 64 '上記の4行は下記のように1行で記述することもできる。 65 IsContained2 = (num2 = 0) 66 67End Function 68 69Function tes2(target) As Boolean 70 71 On Error Resume Next 72 73 Dim num2 As Long 74 num2 = Application.WorksheetFunction.Match( _ 75 target, _ 76 ThisWorkbook.Worksheets("Sheet3").Range("A1:A800").Offset(0, nn), _ 77 0) 78 'ここで別シートにtargetがあるか判定 79 'このnnはどこで取得しているか不明なのでそのままにしているが、 80 'グローバル変数とするのではなく引数で渡すようにすべき 81 82 On Error GoTo 0 83 84 If num2 = 0 Then 85 tes2 = False 86 Else 87 tes2 = True 88 End If 89 90 '上記の4行は下記のように1行で記述することもできる。 91 tes2 = (num2 = 0) 92 93End Function

投稿2020/09/11 08:08

hatena19

総合スコア34075

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

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

sousuke

2020/09/11 08:56

めんどくさくて書かなかったことをやってもらって申し訳ない気分だぁ…ありがとうございます!m(__)m
yakumo02

2020/09/11 13:51

ご指摘ありがとうございます!
guest

0

解決してしまっていますが、一言二言。

今回の原因を再発させないためにも、コード内冒頭でOption Explicitを定義することをお勧めします。
これを定義しておくと未定義の変数はエラーになります。

またコード内に全角スペースが3ヵ所をありました(コメント内を除く)
基本的にプログラムのコードに全角スペースは論外です。
VBAは割とルーズなので許されているようですが、他の言語ではほぼエラーになります。
今はVBAだからいいじゃん、という考えもありますが、半角か全角かは意識して使うようにしたほうがよいでしょう。

投稿2020/09/11 08:12

ttyp03

総合スコア17000

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

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

yakumo02

2020/09/11 13:51

ご指摘ありがとうございます!
guest

0

私の認識ではVBAのFunctionの戻り値というのは
「そのFunction内でFunction名に対して代入して呼び出し元に値を返す」
ことを言います。

提示のコードを直すと以下のようになります。

vba

1Function IsContained2(target) As Boolean 2 3On Error Resume Next 4 5num2 = Application.WorksheetFunction.Match(target, ThisWorkbook.Worksheets("Sheet3").Range("A1:A1000").Offset(0, nn), 0) ' ここで別シートにtargetがあるか判定 nnは別で更新しています 6 7On Error GoTo 0 8 9If num2 = 0 Then 10 ' kekka2 = False 11 IsContained2 = False ' Booleanを返す 12Else 'こっちになるときもある 13 ' kekka2 = True 14 IsContained2 = True 15End If 16 17End Function

で呼び出し元で「Functionの戻り値」を受け取ります。

vba

1 Dim kekka2 As Boolean ' 変数は宣言しましょ 2'~~~ 略 3 4 'Call IsContained2(target) 5 kekka2 = IsContained2(target) ' Functionの戻り値を変数に代入する 6 7 if kekka2 = True Then

投稿2020/09/11 07:34

sousuke

総合スコア3830

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

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

0

ベストアンサー

kekka2もanswer2もどこでも宣言されていないので
各プロシージャ内だけの変数になっています。
そのため見た目は同じ変数でもhikaku2の中では
変数に何も入っておらずFalseになります。

投稿2020/09/11 07:25

radames1000

総合スコア1925

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

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

yakumo02

2020/09/11 07:32

ありがとうございます 宣言していませんでした
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問