[[20200310170529]] 『配列が空かどうかを判定するには』(自宅待機) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『配列が空かどうかを判定するには』(自宅待機)

開いているブックのうち、条件に合うブックだけを配列に納める関数をつくりましたが
その条件に合うブックがあるときは良いのですが、条件に合うブックがないときにエラーが起きてしまいます。

 Option Explicit

 Sub Sample0()
    Dim WorkB() As Workbook
    WorkB() = Sample1
    Call Sample2(WorkB)
 End Sub

 Function Sample1() As Workbook()
    Dim wb As Workbook
    Dim temp() As Workbook
    Dim i As Long
    For Each wb In Workbooks
        On Error GoTo Ignore
        If wb.Worksheets("Sheet1").Range("A1").Value = "Hello" Then
            ReDim Preserve temp(i)
            Set temp(i) = wb
            i = i + 1
        End If
 Ignore:
        On Error GoTo 0
    Next wb
    Sample1 = temp
 End Function

 Sub Sample2(wb() As Workbook)
    Dim i As Long
    For i = LBound(wb) To UBound(wb)
        wb(i).Worksheets("Sheet1").Range("A2").Value = "World"
    Next i
 End Sub

該当するブックがあったときには良いのですが、該当なしのときにSample2でエラーが発生してしまいます。
(なぜかステップ実行で試行錯誤しているとエラーなく進む場合もありますが確実ではないので困っています。)
Sample1で該当者があったときもなかった時もエラーなく進むようにするにはどうすれば良いでしょうか?
よろしくお願いします。

< 使用 Excel:Excel2016、使用 OS:Windows10 >


 パッと見ですが、
 i
 のカウントで判断してはいかがでしょう?
(OK) 2020/03/10(火) 17:10

 なお、複数プロシージャ間で変数を共有する場合は、
 変数の型の宣言をプロシージャ外で行い、
 プロシージャ内の変数の型の宣言の部分を削除してください。
(OK) 2020/03/10(火) 17:12

アドバイスありがとうございます。
 なお、複数プロシージャ間で変数を共有する場合は、
 変数の型の宣言をプロシージャ外で行い、
 プロシージャ内の変数の型の宣言の部分を削除してください。

この文章を見て頭の上に?がいっぱい出てきてしまったところなのですが、
もしよかったら簡単なサンプルを示していただけませんか?
(自宅待機) 2020/03/10(火) 17:38


 こんな感じです。※コード全体はよく見てませんので
 間違いがありましたらすみません。

 Option Explicit

 Dim cnt As Integer

 Sub Sample0()
    Dim WorkB() As Workbook
    WorkB() = Sample1

    If cnt <> 0 Then 'この部分を追加

       Call Sample2(WorkB)

    End If 'この部分を追加

 End Sub

 Function Sample1() As Workbook()
    Dim wb As Workbook
    Dim temp() As Workbook
    Dim i As Long

    cnt = 0 'この部分を追加

    For Each wb In Workbooks
        On Error GoTo Ignore
        If wb.Worksheets("Sheet1").Range("A1").Value = "Hello" Then

            cnt = cnt + 1

            ReDim Preserve temp(i)
            Set temp(i) = wb
            i = i + 1
        End If
 Ignore:
        On Error GoTo 0
    Next wb
    Sample1 = temp
 End Function

 Sub Sample2(wb() As Workbook)
    Dim i As Long
    For i = LBound(wb) To UBound(wb)
        wb(i).Worksheets("Sheet1").Range("A2").Value = "World"
    Next i
 End Sub
(OK) 2020/03/10(火) 17:57

 これまたパッと見ですが、

 > If wb.Worksheets("Sheet1").Range("A1").Value = "Hello" Then

 これを

 If wb.Worksheets("Sheet1").Range("A1").Value = "Hello" Then wb.Worksheets("Sheet1").Range("A2").Value = "World"

 にするだけのような気がします。

 こうすると、
 Sample2は不要になりますし、配列も不要になります。

(OK) 2020/03/10(火) 18:29


 あと、配列に格納するのは、ブック名にしたほうが
 安全なような気がします。
(OK) 2020/03/10(火) 18:34

 ↑の
 2020/03/10(火) 18:34
 の私のレスは勘違いでした。スルー願います。

(OK) 2020/03/10(火) 18:35


 実験してみると、IsArray(配列変数) で検査すると、
 ファクタ無し配列はそれがトリガーになって、
 ( 0 to -1 )に次元がセットされるようです。

 なので、

 If IsArray(配列変数) then ’次元を強制セット
     If Ubound(配列変数) = -1 Then 'ファクタなし

 でどんなもんですかねぇ・・

(半平太) 2020/03/10(火) 20:47


こんなのでも

If Not Not 配列変数 Then

Excel VBA 動的配列が空かどうかの確認方法
2012年6月23日 投稿者: t_nary
(kazuo) 2020/03/10(火) 22:34


みなさん回答ありがとうございます。

OKさん
変数の書き方のサンプル等いろいろありがとうございます。
冒頭で書きましたサンプルコードでは割愛してしまいましたが、Sample1で抽出した結果をもとに
人の目で確認(MSGBOX)をしてからSample2の動きをしたいと思っているので
2020/03/10(火) 18:29で教えてくださったコードにはできません。すみません。

半平太さん
こちらで試行錯誤していたところでもisarrayでエラーが出なくなるのを見ていましたが、
結果がTrueになってしまうのと配列の添え字が負の数になるという
気持ちの悪い(※)結果が出てしまうので使えないと思っていました。
※どこかで予期しないエラーが発生するのではないかと心配になりました。

しかし、調べると「負の数の添字を指定できるのは、空の配列を宣言するために範囲の上限として -1 を使用する場合のみ」とあり
空の配列のときに-1になるのは仕様だということがわかりました。
https://docs.microsoft.com/ja-jp/dotnet/visual-basic/misc/bc30611

この方法で試行したいと思います。どうもありがとうございました。

kazuoさん
望みの結果にならず、教えていただいた式は役に立ちませんでした。
教えていただいたのにすみません。
(校内全文検索でもこの質問しかヒットせず元の質問を見ることができませんでした。)
(自宅待機) 2020/03/11(水) 08:58


 こんにちは    

    'サンプル1  WBSをVariantで受ける

    Sub sample1()
        Dim wb As Workbook
        Dim WBs As Variant
        WBs = WbArray()

        For i = LBound(WBs) To UBound(WBs)
           Debug.Print WBs(i).Name
        Next

    End Sub

    Function WbArray() As Workbook()

        Dim WBs() As Workbook
        i = 0
        For Each wb In Workbooks
           If wb.Worksheets("Sheet1").Range("A1").Value = "Hello" Then
              ReDim WBs(0 To i)
              Set WBs(i) = wb
           End If
        Next
        WbArray = WBs
    End Function

    'サンプル2  Collectionを使う

    Sub sample2()

        Dim wb As Workbook

        For Each wb In WbCollection()
           Debug.Print wb.Name
        Next

    End Sub

    Function WbCollection() As Collection
        Dim wb As Workbook

        Set WbCollection = New Collection

        For Each wb In Workbooks
           If wb.Worksheets("Sheet1").Range("A1").Value = "Hello" Then
              WbCollection.Add wb
           End If
        Next

    End Function
(´・ω・`) 2020/03/11(水) 09:32

何だろう。
excel2016 win10で同じはずですけど。

sample2に適用したいということなら、

 Sub Sample2(wb() As Workbook)
    Dim i As Long
    If Not Not wb Then
        For i = LBound(wb) To UBound(wb)
            wb(i).Worksheets("Sheet1").Range("A2").Value = "World"
        Next i
    End If
 End Sub

質問が、
 >配列が空かどうかを判定するには
ですので、先をご紹介(ヤフー検索ワードです)しましたが、
わたしなら、Sample1() で必ず1要素作成し、wb(0)がNothingかで判定しますね。

(kazuo) 2020/03/11(水) 10:43


Option Explicit

Sub Sample0()

    Dim v As Variant

    If Sample1(v) = False Then
        MsgBox "該当ブックがありません。"
        Exit Sub
    End If

    If MsgBox("確認", vbOKCancel) = vbCancel Then Exit Sub

    Sample2 v
End Sub

Function Sample1(ByRef v As Variant) As Boolean

    Dim wb As Workbook
    Dim temp() As String
    Dim i As Long
    ReDim temp(1 To 100)

    For Each wb In Workbooks
        If wb.Worksheets("Sheet1").Range("A1").Value = "Hello" Then
            i = i + 1
            temp(i) = wb.Name
        End If
    Next wb

    If i > 0 Then
        ReDim Preserve temp(1 To i)
        v = temp
        Sample1 = True
    End If
End Function

Sub Sample2(ByVal v As Variant)

    Dim n As Variant

    For Each n In v
        Workbooks(n).Worksheets("Sheet1").Range("A2").Value = "World"
    Next
End Sub

こんなのもあり?。。。
関数には有無の判定結果を返す機能を持たせ、変数は参照渡しで渡す。
こうしておけば2つの結果を利用できます。
(まっつわん) 2020/03/11(水) 11:36


みなさん回答ありがとうございます。
たくさんの回答をいただき、試行するだけでもとても勉強になりました。

どの方法もとても素晴らしいものでしたが、
その中で(´・ω・`)さんが教えてくださったCollectionを使う方法が
私にとって一番わかりやすく簡単に扱えたので、こちらを使いたいと思います。

みなさんどうもありがとうございました。
また何かありましたらよろしくお願いします。

(自宅待機) 2020/03/11(水) 11:57


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.