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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

VBA

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

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

1回答

869閲覧

VBAでCSVをエクセル形式で開いたものに、さらにマクロを実行すると上手くいきません

opsy

総合スコア5

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

VBA

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

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2021/11/18 09:06

編集2021/11/19 01:52

前提・実現したいこと

VBA初心者です。
VBAでCSVをエクセル形式で開いたものに、さらにマクロを実行させたいと思っています。
何卒宜しくお願い申し上げます。

発生している問題・エラーメッセージ

VBAでCSVをエクセル形式で開いたものに、さらにマクロを実行すると上手くいきません。
具体的にはVBAでCSVをエクセル形式で開き、INDEX MATCH関数を用いて、
ほかのエクセルファイルを参照させて、値が自動で入力されるマクロを作ろうとしています。
CSVファイルの読み込みはできるのですが、そのファイルに別のモジュールで
INDEX MATCH関数を実行させると全く反応しません。
※手作業でCSVをエクセルで開いたものに、同様のマクロを実行すると上手くいきます。

該当のソースコード

●CSVファイルをエクセルで開くVBAのコードは以下です。

VBA

1Public Const targetsheet = "result" 2'結果を出力するシート名を指定 3 4Sub CSV取り込みUTF8() 5 6Dim SettingFileName As Variant 7 8Sheets(targetsheet).Cells.Clear 9'ファイルクリア 10 11SettingFileName = Application.GetOpenFilename(FileFilter:="CSVファイル(*.csv),*.csv", _ 12Title:="CSVファイルの選択") 13If SettingFileName = False Then 14Exit Sub 15End If 16 17With Sheets(targetsheet).QueryTables.Add(Connection:="text;" & SettingFileName, Destination:=Sheets(targetsheet).Range("A1")) 18.TextFilePlatform = 65001 'UTF-8 19.AdjustColumnWidth = False '列の幅を自動計算しない 20.TextFileCommaDelimiter = True 'コンマ区切り 21.TextFileColumnDataTypes = Array(xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat, xlTextFormat) 22.Refresh BackgroundQuery:=False 'シートに出力 23 24.Delete 25End With 26 27Sheets(targetsheet).Activate 28 29End Sub

●INDEX MATCH関数を用いて、ほかのエクセルファイルを参照させ、
値が自動で入力されるVBAのコードは以下です。
(ほかにも、値がある場合は1を、ない場合は3を返し、日付形式に変換する関数を
組み込んでいます)

VBA

1Option Explicit 2 3Sub 検索() 4Dim i As Integer 5Dim z As Integer 6Dim j As Integer 7Dim y As Integer 8 Dim x As String 9 Dim ex As New Excel.Application 10 Dim sPath As String 11 Dim wb As Workbook 12z = Worksheets("result").Cells(Rows.Count, "G").End(xlUp).Row 13For i = 2 To z 14 '発注番号を取得 15 x = Cells(i, 3).Value 16 '開くブックを指定 17 sPath = "C:\Users\XXXXXXX\Desktop\XXXXXXX.xlsx" 18 '読み取り専用で開く 19 Set wb = ex.Workbooks.Open(Filename:=sPath, UpdateLinks:=0, ReadOnly:=True, IgnoreReadOnlyRecommended:=True) 20 With ActiveSheet 21 '納品予定日の値を表示 22On Error Resume Next 23 Cells(i, 7).Value = _ 24 Application.WorksheetFunction.Index(wb.Worksheets("sheet1").Range("I1:AM" & Cells(Rows.Count, "AM").End(xlUp).Row), Application.WorksheetFunction.Match(x, wb.Worksheets("sheet1").Range("AM1:AM" & Cells(Rows.Count, "AM").End(xlUp).Row).Value, 0), 1) 25 End With 26On Error GoTo 0 27Next 28 29y = Worksheets("result").Cells(Rows.Count, "F").End(xlUp).Row 30For j = 2 To y 31If Cells(j, 7).Value = "" Then 32Cells(j, 6).Value = "3" 33Else: Cells(j, 6).Value = "1" 34End If 35Next 36 37 Dim myDate As Date 38 Dim v As Integer 39 With Worksheets("result") 40 v = .Cells(.Rows.Count, "G").End(xlUp).Row 41 For j = 2 To v 42 Dim strDate As String 43 strDate = Format(.Cells(j, 7).Value, " ####/##/##") 44 If IsDate(strDate) Then 45 .Cells(j, 7).NumberFormat = "yyyy/mm/dd" 46 .Cells(j, 7).Value = CDate(strDate) 47 End If 48 Next 49 End With 50 51End Sub

試したこと

こちらで質問をさせていただき、それぞれのVBA自体は動作するものができたようなのですが、
ひとつのエクセルファイル上で2つのモジュールを動作させようとすると上手くいかない現象が
起こっています。

補足情報(FW/ツールのバージョンなど)

Excel for Microsoft 365 を使用しています。

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

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

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

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

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

jinoji

2021/11/18 14:19

とりあえず質問の中にコードを書くときは「コードの挿入」を活用しましょう。
opsy

2021/11/19 01:53

ご教示ありがとうございます。「コードの挿入」を活用させていただきました。 こちらにてご確認くださりましたら幸いです。宜しくお願い申し上げます。
bebebe_

2021/11/19 06:01 編集

関係ない箇所だったので編集で削除しました。
opsy

2021/11/19 06:45

ご教示ありがとうございます。 そもそもVBAを実行してもエラーも何も出ず、何も起こらない状態なのです。 色々試してみたところ、Worksheetを指定すると動かないような気がします。 (Worksheetを指定しない簡単なコードだと動くようです) 調べているのですが、原因がわからず…。 恐れ入りますが、宜しくお願い申し上げます。
bebebe_

2021/11/19 07:21

On Error Resume Next を抜いて実行してもエラーはでませんか? シート指定に原因がありそうなら Worksheets("sheet1")だとSheet1という名前のシートを指定しますが シートの名前を変更されていないでしょうか Worksheets(1)と書けば1番目のシートを指定することもできますが
opsy

2021/11/19 07:44

>On Error Resume Next を抜いて実行してもエラーはでませんか? エラーは特に出ませんでした。反応なしという感じです。 シート名の変更等はしていません。Worksheets(1)に指定する方法も試してみましたが、 反応なしという感じです。ちなみにシート名が間違っているとエラーは出ます。 何かお心当たりはありませんでしょうか…?すみませんが、宜しくお願い申し上げます。
guest

回答1

0

ベストアンサー

<修正> こんな感じでどうでしょうか。

VBA

1Sub 検索() 2 3 Dim sPath As String, fn As String 4 Dim wb As Workbook, ws As Worksheet 5 Dim rng1 As Range, rng2 As Range 6 7 sPath = "C:\Users\XXXXXXX\Desktop\XXXXXXX.xlsx" 8 fn = "XXXXXXX.xlsx" 9 For Each wb In Workbooks 10 If wb.Name = fn Then Exit For 11 Next wb 12 If wb Is Nothing Then 13 Set wb = Workbooks.Open(Filename:=sPath, UpdateLinks:=0, ReadOnly:=True, IgnoreReadOnlyRecommended:=True) 14 End If 15 Set ws = wb.Worksheets("sheet1") 16 Set rng1 = ws.Range("I1:AM" & ws.Cells(ws.Rows.Count, "AM").End(xlUp).Row) 17 Set rng2 = ws.Range("AM1:AM" & ws.Cells(ws.Rows.Count, "AM").End(xlUp).Row) 18 19 Debug.Print "納品予定日の参照先:", wb.Name, ws.Name, rng2.Address 20 21 Dim res As Worksheet 22 Dim z As Long 23 24 Set res = Worksheets("result") 25 z = res.UsedRange.Rows.Count 26 Debug.Print "結果シート:"; res.Name, "最終行:", z 27 28 Dim i As Long 29 Dim x As String 30 Dim wsf As WorksheetFunction 31 Set wsf = WorksheetFunction 32 33 For i = 2 To z 34 '発注番号を取得 35 x = res.Cells(i, 3).Value 36 '納品予定日の値を表示 37 res.Cells(i, 7).Value = wsf.Index(rng1, wsf.Match(x, rng2.Value, 0), 1) 38 res.Cells(i, 7).NumberFormat = "yyyy/mm/dd" 39 40 If res.Cells(i, 7).Value = "" Then 41 res.Cells(i, 6).Value = "3" 42 Else 43 res.Cells(i, 6).Value = "1" 44 End If 45 46 Debug.Print "行番号", i, "発注番号", x, "F列", res.Cells(i, 6).Value, "G列(納品予定日)", res.Cells(i, 7).Value 47 Next 48 49 wb.Close False 50End Sub 51

<修正前>
起きている事象がよくつかめませんが、エラーが起きるわけではないんですね?
以下のようにデバッグ文を入れて、イミディエイトウィンドウにどう出るか確認してみては?

VBA

1Option Explicit 2 3Sub 検索() 4 5 Dim res As Worksheet 6 Dim z As Long 7 Set res = Worksheets("result") 8 z = res.Cells(res.Rows.Count, "G").End(xlUp).Row 9 10Debug.Print res.Name, z 11 12 Dim sPath As String 13 Dim wb As Workbook 14 Dim ws As Worksheet 15 Dim rng1 As Range, rng2 As Range 16 sPath = "C:\Users\XXXXXXX\Desktop\XXXXXXX.xlsx" 17 Set wb = Workbooks.Open(Filename:=sPath, UpdateLinks:=0, ReadOnly:=True, IgnoreReadOnlyRecommended:=True) 18 Set ws = wb.Worksheets("sheet1") 19 Set rng1 = ws.Range("I1:AM" & ws.Cells(ws.Rows.Count, "AM").End(xlUp).Row) 20 Set rng2 = ws.Range("AM1:AM" & ws.Cells(ws.Rows.Count, "AM").End(xlUp).Row) 21 22Debug.Print wb.Name, ws.Name, rng1.Address, rng2.Address 23 24 Dim i As Long 25 Dim x As String 26 For i = 2 To z 27 '発注番号を取得 28 x = res.Cells(i, 3).Value 29 '納品予定日の値を表示 30 With Application.WorksheetFunction 31 res.Cells(i, 7).Value = .Index(rng1, .Match(x, rng2.Value, 0), 1) 32 End With 33 34Debug.Print i, x, ws.Name, res.Cells(i, 7).Value 35 36 Next 37 38 Dim y As Long 39 y = res.Cells(res.Rows.Count, "F").End(xlUp).Row 40 41Debug.Print y 42 43 Dim j As Long 44 For j = 2 To y 45 If res.Cells(j, 7).Value = "" Then 46 res.Cells(j, 6).Value = "3" 47 Else 48 res.Cells(j, 6).Value = "1" 49 End If 50 51Debug.Print j, res.Cells(j, 6).Value 52 53 Next 54 55 Dim myDate As Date 56 Dim v As Long 57 With res 58 v = .Cells(.Rows.Count, "G").End(xlUp).Row 59 60Debug.Print v 61 62 For j = 2 To v 63 Dim strDate As String 64 strDate = Format(.Cells(j, 7).Value, " ####/##/##") 65 If IsDate(strDate) Then 66 .Cells(j, 7).NumberFormat = "yyyy/mm/dd" 67 .Cells(j, 7).Value = CDate(strDate) 68 End If 69 70Debug.Print j, strDate 71 72 Next 73 End With 74 75 76End Sub 77

投稿2021/11/19 02:05

編集2021/11/26 09:34
jinoji

総合スコア4585

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

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

opsy

2021/11/19 04:44

早々のご回答ありがとうございます。 いただいたコードを挿入してみましたが、やはりエクセルに変化は起こりません…。 手作業でCSVをエクセルで開いたものに、同様のマクロを実行すると上手くいくようなのですが…。 CSVをVBAで開いたものに適用すると上手くいかないのはなぜなのでしょうか…。 宜しくお願い申し上げます。
jinoji

2021/11/19 05:16 編集

Application.WorksheetFunction を ex.Application.WorksheetFunction に変えたらどうでしょうか。 というか、Dim ex As New Excel.Application とする理由は何でしょう。 Excelをもう一つ立ち上げる必要はないように思えます。
opsy

2021/11/19 05:50

早々のご回答ありがとうございます。 変えてみましたが、エクセルに変化は起こりません。 今回も手作業でCSVをエクセルで開いたものに、同様のマクロを実行すると上手くいきました。 >Dim ex As New Excel.Application とする理由は何でしょう。 こちらで定義しておかないと「変数が定義されていません」とのエラーが出るので、定義しているのですが…。 すみませんが、宜しくお願い申し上げます。
jinoji

2021/11/19 06:00 編集

「手作業でCSVをExcelで開く」作業を、マクロの記録でコードにしてみて、 CSVファイルをエクセルで開くVBAのコードと見比べてみてはいかがでしょうか。
opsy

2021/11/19 07:05

ご教示ありがとうございます。 見比べてみましたが、全く違うコードでよく分からず…、すみません。 また、毎日異なるCSVをエクセルで開きたいので、特定のCSVに依らないVBAを作成したいです。 色々試してみたところ、Worksheetを指定すると動かないような気がします。 (Worksheetを指定しない簡単なコードだと動くようです) 何かお心当たりはありませんでしょうか。 恐れ入りますが、宜しくお願い申し上げます。
opsy

2021/11/19 08:54

追記ありがとうございます。 エラーが起きているわけではありません。 イミディエイトウィンドウには対応する値が入力されましたので、動いてはいるようです。 ただ実際エクセルへの入力等は動作しないのです、なぜなんでしょう…。 もし何か他にも改善できそうな点等ありましたら、ご教示くださりましたら幸いです。 恐れ入りますが、宜しくお願い申し上げます。
jinoji

2021/11/19 15:02

>対応する値が入力されましたので、動いてはいるようです。 たとえば Debug.Print i, x, ws.Name, res.Cells(i, 7).Value の行ではどのように出力されていますか?
opsy

2021/11/26 04:20

コメントありがとうございます。お返事遅くなりまして申し訳ございません。 すみませんイミディエイトウィンドウの見方について理解不足なこともあり、 的を得ていない回答かもしれませんが、「1」が出力されているようです。 恐れ入りますが、宜しくお願い申し上げます。
bebebe_

2021/11/26 05:08

Debug.Print i, x, ws.Name, res.Cells(i, 7).Valueの出力が1ですか? 1はiの値だと思うのでx ws.name res.Cells(i, 7).Valueの値が入っていないように思えます。 Debug.Printに「wb.name」あたりを追加したら表示されますか?
opsy

2021/11/26 05:38

早々のご回答ありがとうございます。 結果は変わらないようです。出力されるのは、以下です。 私が知識不足なこともあり、とりあえず、動いてはいるのかな…と思ったのですが、 勘違いでしょうか。宜しくお願い申し上げます。 result 1 XXXXXXX.xlsx Sheet1 $I$1:$AM$85 $AM$1:$AM$85 1 1
jinoji

2021/11/26 06:50 編集

最初のデバッグ文の Debug.Print res.Name, z の結果が result 1 z = res.Cells(res.Rows.Count, "G").End(xlUp).Row つまり、resultシートの一番下の行が1 と判定されています。 resultシートのG列に値が入っていないのでは。 Debug.Print res.UsedRange.Address と入れてみて、 どう出力されるか確かめてみてください。
jinoji

2021/11/26 06:49

zが1 だと、For i = 2 To 1 ということになり、一度も処理されないことになります。 (y や v が 1 でも同じことになります。)
opsy

2021/11/26 07:38

ご回答ありがとうございます。やりとり続きましてすみません。 >resultシートのG列に値が入っていないのでは。 確かに初めからG列に値は入っていません。 "C:\Users\XXXXXXX\Desktop\XXXXXXX.xlsx"のAM列を参照し、resultシートC列の一致する発注番号を取得し、 "C:\Users\XXXXXXX\Desktop\XXXXXXX.xlsx"のI列の納品予定日の値をresultシートG列に 表示させたいと思っています。 >Debug.Print res.UsedRange.Address と入れてみて、 どう出力されるか確かめてみてください。 結果は以下のようになりました。 result 1 $A$1:$AP$49 XXXXXXX.xlsx Sheet1 $I$1:$AM$85 $AM$1:$AM$85 1 1 すみません、ここから何か分かりますでしょうか。 本当に知識不足で申し訳ないのですが、宜しくお願い申し上げます。
jinoji

2021/11/26 08:01 編集

実際は49行目までデータが入っていて、1行目は見出し行になっていて、F,G列は空白で、 処理の中で2行目から49行目までのF,G列の値を設定する感じでしょうか。 z = res.Cells(res.Rows.Count, "G").End(xlUp).Row を z = res.UsedRange.Rows.Count と変えたら、z の値が49になって、 その後の各処理が動くのではないかと思います。 A列は必ず全行に値があると保証されているのなら、 z = res.Cells(res.Rows.Count, "A").End(xlUp).Row でもいいです。
opsy

2021/11/26 08:52

早々のご回答ありがとうございます。 >実際は49行目までデータが入っていて、1行目は見出し行になっていて、F,G列は空白で、 >処理の中で2行目から49行目までのF,G列の値を設定する感じでしょうか。 仰る通りです。 一回上手くいったと思ったのですが、再度実行したところ 実行時エラー'9': インデックスが有効範囲にありません と出てきてしまいました。 あと少しで上手くいきそうなのですが… 申し訳ございません。何かお心当たりはありますでしょうか。 宜しくお願い申し上げます。
jinoji

2021/11/26 08:59

どの行で起きたエラーかわかりますか? デバッグ文の出力も手掛かりになるかと思います。
opsy

2021/11/26 09:09

すぐにお返事くださり本当にありがとうございます。 Set ws = wb.Worksheets("sheet1") が黄色でマークされています。 すみませんが、宜しくお願い申し上げます。
jinoji

2021/11/26 09:12

であれば、sheet1という名前のシートがないんだと思われます。
opsy

2021/11/26 09:29

sheet1はあるのですが… 何回か試してみたところ、 "C:\Users\XXXXXXX\Desktop\XXXXXXX.xlsx" のエクセルを開いた状態で動作させるとエラーが起きるようです。 (このエクセルを閉じた状態であれば理想通り動きます) このエクセルを開いた状態でも動作させる方法はないものでしょうか。 何度もすみませんが、宜しくお願い申し上げます。
jinoji

2021/11/26 09:36

開いているブックの中に"XXXXXXX.xlsx"が既にあった場合はそれを使い、 なかった場合にのみOpenするように変えてみました。
opsy

2021/11/26 09:42

修正VBAありがとうございます。 実行してみたところ、 実行時エラー'9': インデックスが有効範囲にありません とのエラーが出てしまい、 Set res = Worksheets("result") が黄色くマークされています。 本当に何度もすみませんが、解決法はないでしょうか。 宜しくお願い申し上げます。
jinoji

2021/11/26 10:23

Set res = ThisWorkbook.Worksheets("result") でどうでしょう。
opsy

2021/11/26 10:24

すみません、修正VBAをもう一度見直させていただき、 コードを色々といじったところ、上手くいきました! 長々とお付き合いいただき、本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問