[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『配列が空かどうかを判定するには』(自宅待機)
開いているブックのうち、条件に合うブックだけを配列に納める関数をつくりましたが
その条件に合うブックがあるときは良いのですが、条件に合うブックがないときにエラーが起きてしまいます。
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
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
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.