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

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

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

Q&A

解決済

1回答

211閲覧

ExcelVBAで、呼び出す関数に与える引数が、関数側で初期化される

Hayashi_Jelly

総合スコア26

0グッド

1クリップ

投稿2018/12/08 04:49

すみません。長くなります。

特定のフォルダにあるBASファイルをインポートするマクロを作成しています。
0. 特定フォルダのファイルコレクションを取得する
0. 各ファイルコレクションのファイル名をチェックして、それがブックに存在すれば削除してからインポート、なければ単純にインポートする

嵌ってるところ

importer()という、2.のロジックが記述されているサブルーチンがあるのですが、ここで、ファイルチェックを関数checkBasExist()に処理が移る際に、引数が初期化? ""になります。

具体的に、checkBasExist(flist(i))で関数を呼ぶ際、
flist(i) = "hoge.bas" という値があることはデバック機能で確認できてます。
しかし、checkBasExist(bas)内では、bas = "" になってしまいます。

解決したいこと

何故こうなってしまうのか知りたい。

excelvba

1 2Option Explicit 3Dim TARGET_PATH As String 4 5Sub removeMod(bas As String) 6 'モジュール削除 7 ThisWorkbook.VBProject.VBComponents.Remove ThisWorkbook.VBProject.VBComponents(bas) 8End Sub 9 10Sub importMod(bas As String) 11 'モジュールインポート 12 ThisWorkbook.VBProject.VBComponents.Import bas 13End Sub 14 15'Function checkBasExist(bas As String) As Boolean 16Function checkBasExist(ByVal bas As String) As Boolean 17 'ブック内の各モジュールに、引数で指定したモジュールが存在するかどうかを返す 18 Dim i As Integer 19 With ThisWorkbook.VBProject 20 For i = 1 To .VBComponents.Count 21 If .VBComponents(i).Type = 1 Then 22 If .VBComponents(i).Name = bas Then 23 checkBasExist = True 24 Exit Function 25 End If 26 End If 27 Next 28 checkBasExist = False 29 End With 30End Function 31 32Function whatImport(w) 33 'フォルダー内のbasファイルから、指定のbasを除いた名前一覧を返す 34 Dim fso, fs As Object 35 Dim tmp() As String 36 Set fso = CreateObject("Scripting.FileSystemObject") 37 Set fs = fso.GetFolder(w).Files 38 39 tmp = hyFolderer.convertFilesToStrs(fs) 40 whatImport = hyStr.removeElementOfList("importBas.bas", tmp) 41 42 Set fso = Nothing 43 Set fs = Nothing 44End Function 45 46Sub importer(flist) 47 'ブック内にモジュールが存在するか確認して、インポートの仕方を変える 48 Dim i As Integer 49 50 For i = LBound(flist) To UBound(flist) 51 If flist(i) <> vbNullString Then 52'-------------------------------------------------------------------- 53 '問題の部分 54 If checkBasExist(flist(i)) Then 55 'ちゃんと実引数は入ってると思われる。デバッグ機能で確認できる 56 'checkBasExist()側では "" になってしまうので、必ずElseの方を通ってしまう 57'-------------------------------------------------------------------- 58 Call removeMod(flist(i)) 59 Call importMod(TARGET_PATH & "\" & flist(i)) 60 Else 61 Call importMod(TARGET_PATH & "\" & flist(i)) 62 End If 63 End If 64 Next 65End Sub 66 67Sub main(e As String) 68 'メインルーチン 69 TARGET_PATH = ThisWorkbook.PATH & "\bas" 70 71 Dim WHAT As String: WHAT = TARGET_PATH 72 73 Select Case e 74 Case "import" 75 Call importer(whatImport(WHAT)) 76 Case "export" 77 End Select 78 79 TARGET_PATH = vbNullString 80End Sub 81

hyFoldererモジュール

excelvba

1Function convertFilesToStrs(fs) As String() 2 'ファイルコレクションのファイル名一覧を返す関数 3 4 Dim l() As String 5 Dim i As Integer 6 7 Dim f As Object 8 9 ReDim l(fs.Count) 10 11 For Each f In fs 12 l(i) = f.Name 13 i = i + 1 14 Next 15 16 convertFilesToStrs = l() 17 18 Set f = Nothing 19 Set fs = Nothing 20 21End Function

hyStrモジュール

excelvba

1Function removeElementOfList(el As String, list() As String) 2 '文字列の配列から、特定要素を除外した配列を返す関数 3 Dim i As Integer 4 Dim flg As Boolean: flg = False 5 For i = LBound(list) To UBound(list) 6 If list(i) = el Then 7 list(i) = list(i + 1) 8 i = i + 1 9 flg = True 10 End If 11 Next 12 13 If flg Then 14 ReDim Preserve list(UBound(list) - 1) 15 End If 16 17 removeElementOfList = list 18 19End Function

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

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

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

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

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

guest

回答1

0

ベストアンサー

直接の回答ではありません(私の環境では質問の内容が再現できなかったため)。

いくつか気になった点を記載しておきます。

通常の場合checkBasExistは常にFalseを返す

flistには、見つかったファイルの名前が「拡張子付き」で格納されています。
しかし、比較しているものがモジュール名のため、拡張子は付いておらず、違うものと判定されます。

そのため、通常の手段でモジュールをエクスポートしているのであれば、checkBasExistは常にFalseを返します。


ここからは参考程度の話です。

プロシージャの並び順

VBAでは、モジュール内におけるプロシージャの並び順に制限はありません(使うものを先に記述する必要はありません)。

私の感覚ですが、全体をまとめる処理(今回であればmain)が上の方にあり、子処理は下の方にある方が読みやすいと思われます。
子処理の中身を見たいときはShift+F2を押せば良いだけですし。

convertFilesToStrsの返り値

ローカルウィンドウなどを見ていればすぐわかる話だと思いますが、現状のconvertFilesToStrsでは末尾に空文字列が必ず入ります。
ReDim l(fs.Count)で0からfs.Countまでの大きさの配列、つまりfs.Count+1の大きさの配列を確保しているためです。

その無駄に確保している分があるため、importerの中でIf flist(i) <> vbNullString Thenを行う必要が出てきていると思われます。

結果が無かったことを示したい場合、Split(VBA.vbNullString)を評価するとString(0 To -1)の配列が得られるので、それを使う手もあります。

投稿2018/12/08 06:36

imihito

総合スコア2166

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

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

Hayashi_Jelly

2018/12/08 08:08

checkBasExistに拡張子を除いた文字列を渡すように変更したところ、質問した現象は解消されました。解せないところではありますが・・・ その他にも色々と参考になるご意見ありがとうございました。プログラミング自体独学なので非常に参考になります
imihito

2018/12/08 08:17

`bas = ""`をどのタイミングで確認されたかにもよるかもしれませんね。 ステップ実行時に`Function checkBasExist~`が黄色になっている段階では実引数が代入されておらず、そこから進むことで代入されます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問