• ベストアンサー

vlookupを使ったマクロの書き方

マクロ中で、VLOOKUPを使用して、下記②のExcelファイルの職員番号と、下記①の職員番号が一致していて、①のD列にメールアドレスが入ってない場合のみ、②のファイルのメールアドレスを、①のD列へ挿入したいのですが、マクロの書き方がわかりません、何方かご教示頂けましたら、大変助かります。 ①ファイル名=F:\11_データ\課題参画者リストまとめ\2024参画者リストまとめ_20240311.xlsx  シート名=参画者リスト  職員番号=B列2行目以降  メールアドレス=D列の2行目以降  シートのA列~H列に値が入っていますが、メールアドレスのセルは、記載無し、記載有りのセルがあります。   ②ファイル名=F:\12_データ\課題参画者リストまとめ\職員マスタ.xlsx  シート名=職員マスタ420227  職員番号=A列2行目以降  メールアドレス=C列2行目以降  シートのA列~C列は値が入っています。   ※①のファイルは、データ連結マクロで複数のファイルを纏めたExcelファイルになります。  タイムスケジューラで自動で起動させる為、vbsファイル中に、マクロファイルを設定させて、  バッチファイルでこのvbsファイルを起動して作成しております。   2024年度-参画者リスト作成.vbsの中身は以下の通りで、このファイルをバッチファイルに設定して使っております。 Dim WB_PATH Const PROC_NAME = "参画者リストおまとめ" Dim excelApp Set excelApp = CreateObject("Excel.Application") WB_PATH = "C:\Users\watan\Documents\27_EXCEL教習\TEST\11_2024-課題参画者リスト\スクリプト\【自動起動】課題参画者リストまとめシートv4.xlsm" With excelApp .Visible = False Dim wb Set wb = .Workbooks.Open(WB_PATH) .Run "'" & wb.Name & "'!" & PROC_NAME .DisplayAlerts = False wb.Save wb.Close End With excelApp.Quit Set excelApp= Nothing

質問者が選んだベストアンサー

  • ベストアンサー
  • HohoPapa
  • ベストアンサー率65% (454/690)
回答No.8

お話しされている挙動からの推測となりますが、 今回のマクロが終了しきれていないものと思います。 vbsでの経験がないので、シャープなコメントは困難です。 私だったら、先に、 https://okwave.jp/qa/q10237306/a28380485.html で案内しました https://website-note.net/windows/how-to-open-an-excel-file-from-task/ の機能で実装してみます。 この機能での実装経験ならいくつもありますし、 課題のトラブルになったことはありません。 おそらく、 Private Sub Workbook_Open() '今回のマクロ End Sub といった記述になっているものと思いますが、 この終盤で自身を終了するようにコードを追加するわけですが、 どのように記述するのか、さらに、 組み込むと起動後勝手に終わってしまうので、 VBAのメンテナンスのチャンスを失う課題もあります。 この辺りの話は、新たな話題になりますので このスレッドをクローズし 新たなスレッド立ててほしいです。 そうすれば、 もっと別な、より識者の方の支援を受けることができるだろうと思います。 (私も非力ながら参加させてもらうかも知れませんが)

nnirosan
質問者

お礼

本日、タイムスケジューラー上で再設定し、マクロの正常稼働を確認しました。また、ログファイルも上書きモードで設定し、正常に作成された事を確認しました。 本当に色々とご教示を頂きまして、誠に有難うございました。

nnirosan
質問者

補足

早速の有難いご教示ありがとうございました。 バッチファイルを起動した時のエラーメッセージを確認した所、VBSファイル起動時、下記コードで認識出来ない旨のメッセージが出ている事がわかりました。  Const PROC_NAME = "UpdateEmailAddressesWithLog" 以下のようにへ変更し、ExcelのマクロはVBSファイルで正常に起動する事が出来ました。      Const PROC_NAME = "Mainjob" ←Excelのマクロ名を入れる 直ぐに、根を上げてお騒がせしてしまいまして申し訳ありませんでした。 タイムスケジューラに設定し、無事正常稼働する事が出来ましたので、ご報告致します。 ログファイルについては、ご教示頂きました事を月曜日に実施し、その結果をご報告してから、今回のご質問は閉じさせて頂きたいと思っております。 色々と親身にご教示頂きまして、本当に有難うございました。

その他の回答 (7)

  • HohoPapa
  • ベストアンサー率65% (454/690)
回答No.7

LogFile = ThisWorkbook.Path & "\" & _ Format(Now, "YYYYMMDDHHNNSS") & "MentLog.csv" 以上のコードを直すと、以下のバリエーションになります。 日ごとに1つのファイルにする場合 LogFile = ThisWorkbook.Path & "\" & _ Format(Now, "YYYYMMDD") & "MentLog.csv" 月ごとに1つのファイルにする場合 LogFile = ThisWorkbook.Path & "\" & _ Format(Now, "YYYYMM") & "MentLog.csv" 1つのファイルに止めどなく追記し続ける場合 LogFile = ThisWorkbook.Path & "\" & _ "MentLog.csv" 1つのファイルに常に新規作成(処理の都度上書き)する場合 LogFile = ThisWorkbook.Path & "\" & _ "MentLog.csv" Open LogFile For Output As #2 Close #2 以下、加えて、仕様上の制限を書きます。 SQL = SQL & "FROM [" & TblSheet & "$A1:Z50000]" & vbCrLf このコードから推測できるかもしれませんが 職員DBファイルは最大50000行です。 また、 [メールアドレス]、[nimsID]の列は、 A列以降、Z列までの間に配置する必要があります。 SQL = SQL & "FROM [" & TblSheet & "$A1:Z50000]" & vbCrLf を SQL = SQL & "FROM [" & TblSheet & "$A1:F500]" & vbCrLf といったようにコンパクトにすることも可能ですが コンパクトにしても、おそらく、 処理スピードが体感できるほど改善することはありません。

nnirosan
質問者

補足

ログファイルやデータの設定についてのご教示ありがとうございます。 本日、マクロファイルをバッチファイルで起動させた所、参画者リストへのメールアドレスの追記は正常に出来たようですが、ログファイルが作成されず、マクロファイルも再び開こうとすると、『編集のためロックされています』のメッセージが出て、読み取り専用になってしまいました。 因みに、マクロファイル内で直接マクロを実施した時は、ログファイルは正常に作成されて、マクロファイルも正常に終了します。 VBSファイル、またはバッチファイルの何れか影響しているようです。 もう一歩と言う所なのですが、なかなか難しいものです。 大変大変、恐縮なのですが、もし対処方法をお気づきのようでしたら、ご教示頂けると大変助かります。 下記はVBSファイルの記載になります。 Dim WB_PATH Const PROC_NAME = "UpdateEmailAddressesWithLog" Dim excelApp Set excelApp = CreateObject("Excel.Application") WB_PATH = "C:\Users\watan\Documents\スクリプト\メールアド挿入マクロ-ログファイル有り【メールアド記載有りはそのまま】-2.xlsm" With excelApp .Visible = False Dim wb Set wb = .Workbooks.Open(WB_PATH) .Run "'" & wb.Name & "'!" & PROC_NAME .DisplayAlerts = False wb.Save wb.Close End With excelApp.Quit Set excelApp= Nothing

  • HohoPapa
  • ベストアンサー率65% (454/690)
回答No.6

>『20240311』を現在の日時(20240319)に変更 >既に記載しているメールアドレスを比較し、 > 記載が違っていたら、ログファイルにその情報を書き込む それぞれ対応してみました。 なお 当初の想定よりも多くのIF文を使うコードとなり、 相当書き換えましたので 十分なテスト、評価をゼロベースで行ってください。 Option Explicit Const tgSheet = "参画者リスト" Const TblBook = "D:\TestDir\職員DB.xlsx" Const TblSheet = "職員DB" Const NumCol = 2 '転記先職員番号列番号 Const AddressCol = 4 '転記先メールアドレス列番号 Dim LogFile As String Dim tgBookName As String Sub Mainjob() Dim tgBook As Workbook Dim r As Long Dim HitAddress As String LogFile = ThisWorkbook.Path & "\" & _ Format(Now, "YYYYMMDDHHNNSS") & "MentLog.csv" Logput "M0", "", "", "", "転記処理開始" '対象ファイル名の組立 tgBookName = _ "D:\TestDir\" & _ Format(Now, "YYYY") & _ "参画者リストまとめ_" & _ Format(Now, "YYYYMMDD") & _ ".xlsx" '対象ブックを開く Set tgBook = Workbooks.Open(tgBookName) 'メイン処理 r = 1 With tgBook.Sheets(tgSheet) Do r = r + 1 If .Cells(r, NumCol).Value = "" Then Exit Do If IsNumeric(.Cells(r, NumCol).Value) = False Then Logput "M2", Format(r, "0"), _ .Cells(r, NumCol).Value, "", "職員番号が不正" Else HitAddress = GetMailAdress(.Cells(r, NumCol).Value) If HitAddress = "Not Found" Then Logput "M3", Format(r, "0"), _ .Cells(r, NumCol).Value, "", "職員番号が見つからない" ElseIf ((HitAddress = "Null") Or (HitAddress = "")) Then Logput "M4", Format(r, "0"), _ .Cells(r, NumCol).Value, "", "マスターのメールアドレスが空欄" ElseIf .Cells(r, AddressCol).Value <> "" Then If HitAddress <> .Cells(r, AddressCol).Value Then Logput "M5", Format(r, "0"), _ .Cells(r, NumCol).Value, .Cells(r, AddressCol).Value, "既に異なるアドレスが埋まっている" & "," & HitAddress Else Logput "M6", Format(r, "0"), _ .Cells(r, NumCol).Value, .Cells(r, AddressCol).Value, "既に同じアドレスが埋まっている" End If Else .Cells(r, AddressCol).Value = HitAddress Logput "M1", Format(r, "0"), _ .Cells(r, NumCol).Value, HitAddress, "メールアドレスをセット" End If End If Loop End With '対象ブックを保存して閉じる tgBook.Save tgBook.Close Logput "M9", "", "", "", "転記処理終了" End Sub 以下、 '職員番号を引数にメールアドレスを返す関数 Function GetMailAdress(sNum As Long) As String と '//ログ出力ルーチン Sub Logput(MsgCode As String, _ は、前回ポストしたものと変更が無いので、 今回はポストしていません。

nnirosan
質問者

補足

早速、希望した項目に対応下さいまして、誠に有難うございました。 早速、マクロを実行した所、正常に稼働出来、又ログファイルも正常に作成された事を確認しました。 ログファイルでメールアドレスの記載状況が一目で分かり、大変効率が良くなりそうです。 メールアドレスの記載状態の項目もこれで完璧です。 明日以降で、タイムスケジューラでマクロを実行し、結果をご報告させて頂きます。 職員DBファイルは2週間毎に更新しますが、課題毎のファイルの連結マクロと、今回作成頂いたマクロはタイムスケジューラで1日に5回実行します。 ログファイルが1日5個作成される事になるので、やはりログファイルは上書きコピーするか、削除した方が良いかなと考えております。 大変お手数なのですが、ログファイルの上書き又は、削除をするマクロについても、ご教示頂けましたら大変助かります。 ログファイルを残す今回のマクロも、このルーチン作業で問題が生じた時は必要と思いますので、その時は使わせて頂きます。

  • HohoPapa
  • ベストアンサー率65% (454/690)
回答No.5

>職員DBに職員番号は存在するが、 >メールアドレスの欄が空白の時にこのエラーが出ているようです エラーにならないようにしてみました。 また、その旨ログが残るようにし 合わせて、ログのフォーマットを以下のように再考しました。 実行日時、メッセージコード、   転記先行番号、職員番号、メールアドレス、   メッセージテキスト Option Explicit Const tgBookName = "D:\TestDir\2024参画者リストまとめ_20240311.xlsx" Const tgSheet = "参画者リスト" Const TblBook = "D:\TestDir\職員DB.xlsx" Const TblSheet = "職員DB" Const NumCol = 2 '転記先職員番号列番号 Const AddressCol = 4 '転記先メールアドレス列番号 Dim LogFile As String Sub Mainjob() Dim tgBook As Workbook Dim r As Long Dim HitAddress As String LogFile = ThisWorkbook.Path & "\" & _ Format(Now, "YYYYMMDDHHNNSS") & "MentLog.csv" Logput "M0", "", "", "", "転記処理開始" '対象ブックを開く Set tgBook = Workbooks.Open(tgBookName) 'メイン処理 r = 2 With tgBook.Sheets(tgSheet) Do If .Cells(r, NumCol).Value = "" Then Exit Do If IsNumeric(.Cells(r, NumCol).Value) = False Then Logput "M2", Format(r, "0"), _ .Cells(r, NumCol).Value, "", "職員番号が不正" ElseIf .Cells(r, AddressCol).Value <> "" Then Logput "M3", Format(r, "0"), _ .Cells(r, NumCol).Value, .Cells(r, AddressCol).Value, "既にアドレスが埋まっている" Else HitAddress = GetMailAdress(.Cells(r, NumCol).Value) If HitAddress = "Not Found" Then Logput "M2", Format(r, "0"), _ .Cells(r, NumCol).Value, "", "職員番号が見つからない" ElseIf ((HitAddress = "Null") Or _ (HitAddress = "")) Then Logput "M4", Format(r, "0"), _ .Cells(r, NumCol).Value, "", "マスターのメールアドレスが空欄" Else .Cells(r, AddressCol).Value = HitAddress Logput "M1", Format(r, "0"), _ .Cells(r, NumCol).Value, HitAddress, "メールアドレスをセット" End If End If r = r + 1 Loop End With '対象ブックを保存して閉じる tgBook.Save tgBook.Close Logput "M9", "", "", "", "転記処理終了" End Sub '職員番号を引数にメールアドレスを返す関数 Function GetMailAdress(sNum As Long) As String Dim SQL As String Dim cn As Object Dim rs As Object 'SQL文の実行準備 Set cn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") cn.Provider = "Microsoft.ACE.OLEDB.12.0" cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=1" cn.Open TblBook 'SQL文の組立 SQL = "" SQL = SQL & "select [メールアドレス]" & vbCrLf SQL = SQL & "FROM [" & TblSheet & "$A1:Z50000]" & vbCrLf SQL = SQL & "Where [nimsID] = " & sNum & vbCrLf rs.Open SQL, cn 'ヒットする行が無かったら抜ける If rs.EOF = True Then GetMailAdress = "Not Found" Exit Function Else If IsNull(rs("メールアドレス")) Then GetMailAdress = "Null" Else GetMailAdress = rs("メールアドレス") End If End If '後処理 rs.Close Set rs = Nothing cn.Close Set cn = Nothing End Function '//ログ出力ルーチン Sub Logput(MsgCode As String, _ LineNum As String, _ sNum As String, _ address As String, _ MsgText As String) Dim LineData As String LineData = Format(Now, "YYYY/MM/DD HH:NN:SS") & "," & _ MsgCode & "," & _ LineNum & "," & _ sNum & "," & _ address & "," & _ MsgText Open LogFile For Append As #2 Print #2, LineData Close #2 End Sub

nnirosan
質問者

補足

早速、マクロを修正頂きましてありがとうございました。マクロは正常に動きました。 メールアドレス追加状況のログファイルを確認しまして、大変見やすく関心致しました。 日々お忙しい中大変恐縮なのですが、2つ程、お願いがございます。もし、可能でしたら、ご教示頂けましたら幸いです。 ①下記コードですが、『20240311』を現在の日時(20240319)に変更して頂く事は可能でしょうか?  Const tgBookName = "D:\TestDir\2024参画者リストまとめ_20240311.xlsx"  ※連結ファイルの2024参画者リストまとめ_20240311.xlsxは、タイムスケジューラで実行する毎に、実行日時の名前が入ったファイル名で作成されます。  ※コードを色々といじってみたのですが、未熟な知識な為、修正する事が出来ませんでした。 ②メールアドレスを追加する条件はそのままで、  職員DBのメールアドレスと2024参画者リストまとめ_20240311.xlsxに既に記載しているメールアドレスを比較し、記載が違っていたら、ログファイルにその情報を書き込む事は可能でしょうか?  ※既に記載されている、2024参画者リストまとめ_20240311.xlsx中メールアドレスは手動で打ち込んでいる為、記載ミスが発生する可能性があります。 既に記載されている2024参画者リストまとめ_20240311.xlsxのメールアドレスは上書きせず、ログファイルで職員DBとの違いを確認したいです。

  • HohoPapa
  • ベストアンサー率65% (454/690)
回答No.4

>②のファイル名、シート名、タイトル名が今後変更になりそうなのですが、 >ご教示頂いたマクロの何処を修正すれば良いのか分かりませんでした。 職員DB側はSQL文でアクセスする関係で、列番号の概念はありません。 列タイトル(1行目の列名)でアクセスします。 SQL文に記述される名前と1行目の列名を合わせてください。 フルパス、シート名は定数に埋めています。 >①のファイルについても、変更があるかもです。 この部分はごく一般的なコードですの想像できると思いましたが 定数として宣言するようにしました。 >職員DB.xlsxに記載されているメールアドレスは、無記入の行が度々ありましたが 職員番号を使いアクセスしていますので、 ゴミレコードがあっても悪さはしません。 まずは、 >お薦めの『YYYYMMDDHHMM_メール抽出.log』を希望します で書いてみました。 これで期待通りなら、 その後、 >マクロ起動前にログファイルを削除し、再作製するやり方 をポストします。 何度もやり取りしたくないからです。 当方、昼間は本業に追われ、このサイトでやり取りできるのは 夜か、休日です。 つまり、タイムリーには返答できませんので この点を理解してもらうか、別な識者のコメントを待ってください。 Option Explicit Const tgBookName = "D:\TestDir\2024参画者リストまとめ_20240311.xlsx" Const tgSheet = "参画者リスト" Const TblBook = "D:\TestDir\職員DB.xlsx" Const TblSheet = "職員DB" Const NumCol = 2 '転記先職員番号列番号 Const AddressCol = 4 '転記先メールアドレス列番号 Dim LogFile As String Sub Mainjob() Dim tgBook As Workbook Dim r As Long Dim HitAddress As String LogFile = ThisWorkbook.Path & "\" & _ Format(Now, "YYYYMMDDHHNNSS") & "MentLog.csv" Logput "M0", "転記処理開始" '対象ブックを開く Set tgBook = Workbooks.Open(tgBookName) 'メイン処理 r = 2 With tgBook.Sheets(tgSheet) Do If .Cells(r, NumCol).Value = "" Then Exit Do If IsNumeric(.Cells(r, NumCol).Value) = False Then Logput "M4", r & "行目は職員番号ではない" ElseIf .Cells(r, AddressCol).Value <> "" Then Logput "M3", r & "行目には既にアドレスが埋まっている" Else HitAddress = GetMailAdress(.Cells(r, NumCol).Value) If HitAddress <> "Not Found" Then .Cells(r, AddressCol).Value = HitAddress Logput "M1", r & "行目に" & HitAddress & "をセット" Else Logput "M2", "職員番号:" & .Cells(r, NumCol).Value & "がマスターにいない" End If End If r = r + 1 Loop End With '対象ブックを保存して閉じる tgBook.Save tgBook.Close Logput "M9", "転記処理終了" End Sub '職員番号を引数にメールアドレスを返す関数 Function GetMailAdress(sNum As Long) As String Dim SQL As String Dim cn As Object Dim rs As Object 'SQL文の実行準備 Set cn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") cn.Provider = "Microsoft.ACE.OLEDB.12.0" cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=1" cn.Open TblBook 'SQL文の組立 SQL = "" SQL = SQL & "select [メールアドレス]" & vbCrLf SQL = SQL & "FROM [" & TblSheet & "$A1:Z50000]" & vbCrLf SQL = SQL & "Where [nimsID] = " & sNum & vbCrLf rs.Open SQL, cn 'ヒットする行が無かったら抜ける If rs.EOF = True Then GetMailAdress = "Not Found" Exit Function Else GetMailAdress = rs("メールアドレス") End If '後処理 rs.Close Set rs = Nothing cn.Close Set cn = Nothing End Function '//ログ出力ルーチン Sub Logput(MsgCode As String, MsgText As String) Dim LineData As String LineData = Format(Now, "YYYY/MM/DD HH:NN:SS") & "," & MsgCode & "," & MsgText Open LogFile For Append As #2 Print #2, LineData Close #2 End Sub

nnirosan
質問者

補足

早速のマクロの修正をして頂きまして、大変恐縮です。 お忙しい中、もうしわけありませんでした。 ・タイトル行については、①も②の同じに記載にして、修正マクロを起動してみました。 ・下記のコードで、『Nullの使い方が不正です。』のエラーが出て、マクロが止まりました。 GetMailAdress = rs("メールアドレス") 職員DBに職員番号の記載が無い時は、エラーが出ず、 恐らく、職員DBに職員番号は存在するが、メールアドレスの欄が空白の時にこのエラーが出ているようです。 ※このエラーが出た時点で、①ファイルへのメールアドレス追記も止まっています。 お手数の時にでも、対処方法をご教示頂けましたら幸いです。

  • HohoPapa
  • ベストアンサー率65% (454/690)
回答No.3

>①ファイルのB列は、通常は数値として認識し抽出するが、 >メッセージ的な値が入っている行は無視するようにしたいのです 数字以外が含まれていたら、その行は無視する。 というコードとしてみました。いかがでしょうか。 >このマクロはタイムスケジューラーで自動起動させますので、 >マクロ開始、終了時刻と >メールアドレス抽出状態をログファイルへ記載するようにしたいです。 >起動開始前に、ログファイルの中身をクリアーさせるコード 予め決まったファイル名とし、 作成の都度上書き(あるいは削除して新規作成)する動作でいいですか? これの場合、 >マクロは1日3回起動させる為 とのことですから、2回目が走ると1回目のログが消えます。 それでいいですか? 私だったら、YYYYMMDDHHMM.log といったファイル名にし 実行の都度作成し、 数日後、数週後など適当な時に適当な範囲のlogファイルを手作業で削除します。 ロゴの出力機能は、仕様がブレそうなので,まだ組み込んでいません。 Option Explicit Const tgBookName = "D:\TestDir\2024参画者リストまとめ_20240311.xlsx" Const tgSheet = "参画者リスト" Const TblBook = "D:\TestDir\職員マスタ.xlsx" Const TblSheet = "職員マスタ420227" Sub Mainjob() Dim tgBook As Workbook Dim r As Long Dim HitAddress As String '対象ブックを開く Set tgBook = Workbooks.Open(tgBookName) 'メイン処理 r = 2 With tgBook.Sheets(tgSheet) Do If .Cells(r, 2).Value = "" Then Exit Do If IsNumeric(.Cells(r, 2).Value) = False Then 'ここで職員番号が数値ではないログを出力 ElseIf .Cells(r, 4).Value <> "" Then 'ここでアドレスが既に埋まっているログを出力 Else HitAddress = GetMailAdress(.Cells(r, 2).Value) If HitAddress <> "Not Found" Then .Cells(r, 4).Value = HitAddress 'ここでアドレスをセットしたログを出力 Else 'ここで職員が見つからなかったログを出力 End If End If r = r + 1 Loop End With '対象ブックを保存して閉じる tgBook.Save tgBook.Close End Sub '職員番号を引数にメールアドレスを返す関数 Function GetMailAdress(sNum As Long) As String Dim SQL As String Dim cn As Object Dim rs As Object 'SQL文の実行準備 Set cn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") cn.Provider = "Microsoft.ACE.OLEDB.12.0" cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=1" cn.Open TblBook 'SQL文の組立 SQL = "" SQL = SQL & "select [メールアドレス]" & vbCrLf SQL = SQL & "FROM [" & TblSheet & "$A1:Z50000]" & vbCrLf SQL = SQL & "Where [職員番号] = " & sNum & vbCrLf rs.Open SQL, cn 'ヒットする行が無かったら抜ける If rs.EOF = True Then GetMailAdress = "Not Found" Exit Function Else GetMailAdress = rs("メールアドレス") End If '後処理 rs.Close Set rs = Nothing cn.Close Set cn = Nothing End Function

nnirosan
質問者

補足

早速のご教示ありがとうございました。 修正頂いたマクロを実行し、文字記載の列はエラーにならずに無視されて、正常終了出来ました。 ②のファイル名、シート名、タイトル名が今後変更になりそうなのですが、ご教示頂いたマクロの何処を修正すれば良いのか分かりませんでした。 ①のファイルについても、変更があるかもです。 取り合えず、②ファイルのシートは『職員DB』へ変更、職員IDが入っている列はA列でタイトル名は『nimsID』へ変更。 メールアドレスが入っている列はP列へ変更、タイトル名は『メールアドレス』になります。 今後も更に変更になる可能性がありますので、コードの変更方法のご教示を頂けましたら大変助かります。 職員DB.xlsxに記載されているメールアドレスは、無記入の行が度々ありましたが、マクロ起動時、エラーが出なかったので問題ないと思われます、そのように作られているマクロでしょうか? 2024参画者リストまとめ_20240311.xlsxファイルは、1日1回程度、手動でファイルを開いてデータを確認する予定です。 ログファイルは、可能でしたら、マクロの正常稼働状況(マクロ起動開始時刻と終了時刻と処理数)とメールアドレスを抽出出来なかった職員IDを記載させたいです。 また、ログのファイル名ですが、お薦めの『YYYYMMDDHHMM_メール抽出.log』を希望します。 我儘なお願いで、大変恐縮ですが、 マクロ起動前にログファイルを削除し、再作製するやり方と、ログファイルを残すやり方のコードを 両方記載して頂き、切り替えが出来るよう、コメント文にするとか、コードを部分的に修正すれば良いようにして頂けましたら嬉しいです。 大変お手数ですが、宜しくお願いします。

  • HohoPapa
  • ベストアンサー率65% (454/690)
回答No.2

職員番号は数値と思っていました。 文字列とのことであれば、 以下のコードで行けるのではないかと思います。 Option Explicit Const tgBookName = "D:\TestDir\2024参画者リストまとめ_20240311.xlsx" Const tgSheet = "参画者リスト" Const TblBook = "D:\TestDir\職員マスタ.xlsx" Const TblSheet = "職員マスタ420227" Sub Mainjob() Dim tgBook As Workbook Dim r As Long Dim HitAddress As String '対象ブックを開く Set tgBook = Workbooks.Open(tgBookName) 'メイン処理 r = 2 With tgBook.Sheets(tgSheet) Do If .Cells(r, 2).Value = "" Then Exit Do If .Cells(r, 4).Value = "" Then HitAddress = GetMailAdress(.Cells(r, 2).Text) If HitAddress <> "Not Found" Then .Cells(r, 4).Value = HitAddress End If End If r = r + 1 Loop End With '対象ブックを保存して閉じる tgBook.Save tgBook.Close End Sub '職員番号を引数にメールアドレスを返す関数 Function GetMailAdress(sNum As String) As String Dim SQL As String Dim cn As Object Dim rs As Object 'SQL文の実行準備 Set cn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") cn.Provider = "Microsoft.ACE.OLEDB.12.0" cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=1" cn.Open TblBook 'SQL文の組立 SQL = "" SQL = SQL & "select [メールアドレス]" & vbCrLf SQL = SQL & "FROM [" & TblSheet & "$A1:Z50000]" & vbCrLf SQL = SQL & "Where [職員番号] = '" & sNum & "'" & vbCrLf rs.Open SQL, cn 'ヒットする行が無かったら抜ける If rs.EOF = True Then GetMailAdress = "Not Found" Exit Function Else GetMailAdress = rs("メールアドレス") End If '後処理 rs.Close Set rs = Nothing cn.Close Set cn = Nothing End Function

nnirosan
質問者

補足

早速のコードのご教示有り難うございました。 ①の2024参画者リストまとめ_20240311.xlsxは、 複数のExcelファイルから特定列データを連結して作成しています。 ①のファイルは以下のコードで書式を設定して作成しているので、B列は数値の値が入っていると認識しています。 しかしながら、特例でB列に1行のみ、メッセージ的な値が入っております。これは、備忘録の意味で後から手動で書き込んだものになります。 sakiSheet.Range("B:B").Value = sakiSheet.Range("B:B").Value Range("B:B").Replace What:=vbTab, Replacement:="" ①ファイルのB列は、通常は数値として認識し抽出するが、メッセージ的な値が入っている行は無視するようにしたいのですが可能でしょうか? また、お願いがあります。 このマクロはタイムスケジューラーで自動起動させますので、マクロ開始、終了時刻とメールアドレス抽出状態をログファイルへ記載するようにしたいです。 マクロは1日3回起動させる為、ログファイルはメールアドレス抽出マクロの起動開始前に、ログファイルの中身をクリアーさせるコードを作成する事は可能でしょうか? 大変お手数をおかけしますが宜しくお願い致します。

  • HohoPapa
  • ベストアンサー率65% (454/690)
回答No.1

"参画者リスト"シートにメールアドレスが埋まっていなかったら "職員マスタ420227"から職員番号をキーにメールアドレスを取得して埋める。 という動作ということでいいですね? vlookupにこだわるとか、メールアドレスが取得できるように "参画者リスト"シートにvlookup関数を埋めることを期待してはいないですね? また、 >①のD列へ挿入したい とは、 行挿入(あるいは列挿入)をするということではないですね? SQLを使ったVBAのコードを書いてみましたので、 よかったら参考にしてください。 なお、 "職員マスタ420227"シートについては、 A1=職員番号 C1=メールアドレス という列名になっている前提です。 以下に気になった点を列挙します。 タスクスケジューラーを使った自動運転をする場合、 https://website-note.net/windows/how-to-open-an-excel-file-from-task/ のようにすれば、あえて、 2024年度-参画者リスト作成.vbs といったスクリプトを用意する必要はありません。 なにか意図したものがあれば気にしないでください。 自動運転するのであれば、マクロブックを開いたら自動的に開始し マクロの終盤でマクロブック自身を閉じる必要があります。 この仕組みを組み込むと、勝手に閉じてしまうので ソースコードの修正をする機会を失ってしまいます。 (なにか手当が必要です) また、無人運転をさせるのでしょうから 実行ログを残す機能も欲しいと思います。 どこまで理解されているのかよくわからなかったので 転記部分だけのコードをポストしました。 コードに限らず、コメントを頂ければ助言できるだろうと思います。 Option Explicit Const tgBookName = "D:\TestDir\2024参画者リストまとめ_20240311.xlsx" Const tgSheet = "参画者リスト" Const TblBook = "D:\TestDir\職員マスタ.xlsx" Const TblSheet = "職員マスタ420227" Sub Mainjob() Dim tgBook As Workbook Dim r As Long Dim HitAddress As String '対象ブックを開く Set tgBook = Workbooks.Open(tgBookName) 'メイン処理 r = 2 With tgBook.Sheets(tgSheet) Do If .Cells(r, 2).Value = "" Then Exit Do If .Cells(r, 4).Value = "" Then HitAddress = GetMailAdress(.Cells(r, 2).Value) If HitAddress <> "Not Found" Then .Cells(r, 4).Value = HitAddress End If End If r = r + 1 Loop End With '対象ブックを保存して閉じる tgBook.Save tgBook.Close End Sub '職員番号を引数にメールアドレスを返す関数 Function GetMailAdress(sNum As Long) As String Dim SQL As String Dim cn As Object Dim rs As Object 'SQL文の実行準備 Set cn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") cn.Provider = "Microsoft.ACE.OLEDB.12.0" cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=1" cn.Open TblBook 'SQL文の組立 SQL = "" SQL = SQL & "select [メールアドレス]" & vbCrLf SQL = SQL & "FROM [" & TblSheet & "$A1:Z50000]" & vbCrLf SQL = SQL & "Where [職員番号] = " & sNum & vbCrLf rs.Open SQL, cn 'ヒットする行が無かったら抜ける If rs.EOF = True Then GetMailAdress = "Not Found" Exit Function Else GetMailAdress = rs("メールアドレス") End If '後処理 rs.Close Set rs = Nothing cn.Close Set cn = Nothing End Function

nnirosan
質問者

補足

早速ご教示頂きまして、誠に有難うございます。 SQL文は今回初めてです。コードがスッキリしていて、使い慣れれば便利になると感じました。 マクロを起動させると、正常起動したようですが、 HitAddress = GetMailAdress(.Cells(r, 2).Value)のコードの所で、『型が一致しません』のエラーが出ました。 ①のファイルへは途中までメールアドレスが書き込まれています。 職員番号を確認すると、数字以外の『23NM5038で処理』が書かれたセルの行で止まっています。 対処方法がお分かりでしたら、ご教示頂けると助かります。 ①のファイルは、サーバからファイルのコピーや削除を行った後、Excelのマクロを起動して作成しております。 EXCELのマクロでサーバからファイルのコピーや削除のコードを書く事が難しかった為、バッチファイルで作成する事にしました。 4月1日より、更に、今回お聞きしたマクロの追加が必要になりましたので、今回は今動いているバッチファイル中で、このマクロを設定しようと思っています。

関連するQ&A

  • マクロでvlookup 

    マクロでvlookupを使用したいのですが、 動かした結果が #N/A になります。 どこが間違っているのでしょうか? マクロはこれ Sub macro1() Worksheets("訪問予定").Select Cells(3, 2).Value = Application.VLookup(Cells(1, 2).Value, Worksheets("担当").Range("A1:C5"), 2) End Sub 日本語で次のように私は認識してます。 「サブマクロ 訪問予定シートを選択 3行2列目の値は担当シートの日付と一致する行の2列目の値 エンドサブ」 やりたいことは 担当シートをもとに 訪問予定シートの担当蘭を埋めることです。 上記のマクロでは ループさせてないので 一か所しか埋められませんが ループを使ってひと月の担当予定を埋める方法を考えてます。

  • エクセルのマクロについての質問です。

    エクセルのマクロについての質問です。 長文申し訳ございません。 Excelマクロが何度作り直してもうまく作動せず非常に困っております。 (1)ファイルAのシート1のDB列3行目に1の値をいれます。 (2)ファイルAのDC列172行目の値をファイルBのシート名が「1」のシートのD列4行目に入れます。 (3)ファイルAのDC列2733行目の値をファイルBのシート名が「1」のシートのD列6行目に入れます。 (4)ファイルAのDC列3128行目の値をファイルBのシート名が「1」のシートのD列7行目に入れます。 (5)ファイルAのシート1のDB列3行目に1.2の値をいれます。 (6)ファイルAのDC列172行目の値をファイルBのシート名が「1.2」のシートのD列4行目に入れます。 (7)ファイルAのDC列2733行目の値をファイルBのシート名が「1.2」のシートのD列6行目に入れます。 (8)ファイルAのDC列3128行目の値をファイルBのシート名が「1.2」のシートのD列7行目に入れます。 (9)以上のようにファイルAのシート1のDB列3行目に入れる値を0.2ずつ増やしていき、その値に対応したファイルBのシートに上記のように値を入れていくという動作を20まで繰り返す。 以上のようなマクロを作る事は可能でしょうか? マクロについて勉強はしているのですが上手く使いこなせず苦労しております。 長文の質問で大変申し訳ございませんがよろしければ皆さまのお知恵をお貸しください。 宜しくお願い致します。

  • このようなエクセルマクロを組みたいのですが...

    下記のようなマクロを組みたいと思っていますが、 知見がほとんどないので教えていただきたいと思います。 "csv"というフォルダにランダムなファイル名でcsv形式のファイルが100以上保存されています。 目的は、 そのcsvファイル内の一部のデータをひとつのファイル(ファイル名を"まとめ"とします)に移して並べたいと思います。 <前提> "csv"フォルダと"まとめ"ファイルは既に開かれている状態とします。 "まとめ"ファイルを開いた状態で、マクロを走らせると、 (1)csvファイルが開く (2)セルA1とB1をコピー (3)"まとめ"ファイルのA1、A2へ貼り付け(行と列を変更) (4)csvファイルを閉じる (5)次のcsvファイルが開く (6)セルA1とB1をコピー (7)"まとめ"ファイルのB1、B2へ貼り付け(行と列を変更) (8)csvファイルを閉じる 以降、"csv"フォルダの中身をすべて処理できるまで繰り返し。 という風に考えていますが、 当方あまり知識が無くアレンジが難しいためできる限りシンプルにと考えています。 そのため、もしこうした方が...等あればアドバイスいただけるとありがたいです。 すみませんがよろしくお願いいたします。

  • 複数ファイルのデータを1つのファイルへ纏めるマクロ

    マクロの実行で、Excel形式の約400個のファイル中のデータを1つの出力ファイルへ纏める為のマクロを作成したいのですが、VBAの初心者で、スクリプトの書き方が分からず大変困っております。 入力ファイルの中身は頻繁に追加、削除を繰り返しており、そのたびに入力ファイルを目視確認後、出力ファイルを手動で修正している状況でございます。 大変お手数ですが、マクロがお分かりの方がいらっしゃいましたら、ご教示を宜しくお願い致します。 ・入力ファイルは、以下ような名前になっております。 課題参加者_23RF3001.xlsx 課題参加者_23RF3005.xlsx 課題参加者_23RF3072★.xlsx 課題参加者_23RF3073.xlsx 課題参加者_23RF3199.xlsx 課題参加者_23RF3543.xlsx ・入力ファイルのデータは、添付しました画面イメージの通りで、  フォーマットは全て同じです。 ・出力ファイルに吐き出す入力データはB列~K列とN列になります。 ・出力ファイルのタイトルは、1番目に呼び出したファイルのB列~K列とN列を使う。 ・出力ファイルのA列のデータは、入力ファイル名の『23RF3001』、『23RF3543』などを入力データ分入れる。 ・出力ファイルのタイトルに使う、入力ファイルのタイトルは以下のようになっています。   B列~E列のタイトルは、6行目、7行目が結合されたセルに入っています。  F列のタイトルは、5行目、6行目、7行目が結合したセルに入っています。  G列~H列のタイトルは、6行目、7行目が結合されたセルに入っています。  I列~K列のタイトルは、7行目のセルに入っています。  N列のタイトルは、6行目、7行目が結合されたセルに入っています。 ・出力ファイルへ吐き出したい、入力ファイルデータの範囲は、  B列~K列の8行目以降とN列の8行目以降のデータになりますが、  『職員番号』、『名前』、『部門』に記載が有る行のみを出力ファイルへ吐き出します。  N列はリストの最後の行まで文字が入力されていますが、  N列についても、上記の『職員番号』、『名前』、『部門』に記載が有る行のみを出力ファイルへ吐き出します。 ・出力データへ吐き出す時の書式フォーマットは以下の通りになります。  A列=文字形式  B列=数値形式  C列~F列=文字形式  G列、H列=日付形式  I列~K列=チェックボックス(フォームコントロール形式(入力データと同じ形式))  N列=文字形式 ・入力データは今の所50行まで入力可能としています。

  • 自動入力マクロ教えてください

    sheet1のB列に数値を入力していますデータは10行目以降に入力されています。 データが1,10.20ならsheet2のB列、2.15.35ならsheet2のC列5.40ならsheet2のD列それ以外はsheet2のE列に自動的に入力したいのですがそのマクロを教えていただけないでしょか。行はsheet1と同じ行に入力します

  • マクロでVLOOKUP関数をつかいたいのですが

    エクセルでマクロを使ってVLOOKUP関数みたいなことを したいのですが(文章力が無くてすみません。) sheet1のセルb4を検索値にして、 sheet2のリストb3:C32を範囲に指定します 列番号は 2  検索の型ほ FALSE      です。 この値をsheet1のセル"O4"に表示させて、 なおかつ”O4:O33"までオートフィルで数式を入れたいときは どのようにマクロを組めばよいのでしょうか。 ほとんど初心者なのでマクロの記録を使ってやってみたのですが エラーになってしまい、うまくいきません。 他力本願で申し訳ないのですがどなたか詳しい方 ご回答をお願いいたします。

  • マクロでVLookupが出来ません。

    マクロでVLookupが出来ません。 A列からE列までデータがあるシート1のA,B,C列の値が全て一致する シート2の行削除をしたいです。 2000行中500行残るはずのダミーで実験してますが全行削除されてしまいます。 Do Until Cells(Line, 6).Value →6の部分を1 VLookup(Cells(Line, 6) →6の部分を1にすれば 500行残ります。ですがこれでは検索値がA列のみの値です。 またそれぞれ1→2、1→3、1→4にしても同じく全行消えこんがらがってます。 シート1のA列のみ検索しているような動きです。どこを修正すればいいのでしょうか? Sub 行削除() 'シート1→8月シート2→9月 Sheets("8月").Select Range("F2").Select ActiveCell.FormulaR1C1 = "=RC[-5]&RC[-4]&RC[-3]" Selection.AutoFill Destination:=Range("F2:F10000") Sheets("9月").Select Range("F2").Select ActiveCell.FormulaR1C1 = "=RC[-5]&RC[-4]&RC[-3]" Selection.AutoFill Destination:=Range("F2:F10000") '検索する対象値があるシート選択 Sheets("9月").Select 'そのシートの検索開始の行数を選択2行目。 Line = 2 'そのシートの検索値の列指定6=F列。セルF2の値が検索したい値。 'その値がなくなったら検索を終了させる.Value = ""を追加。 Do Until Cells(Line, 6).Value = "" 'エラーとなっても次に進む On Error Resume Next '検索結果を記入する列を指定。Line7=G列(※1) '検索する値があるシートとその列を指定 'VLookup(Cells(Line, 6)の部分。6=F列 '検索されるシートと検索範囲を指定 'Worksheets("9月").Range("A2:F10000")→セルA2からセルF10000まで '検索されたらその行のどの列の値を結果とするのか指定 1=A列 '検索方法指定0=FALSE完全一致。 Cells(Line, 7).Value = Application.WorksheetFunction.VLookup(Cells(Line, 6)_ .Value, Worksheets("8月").Range("A2:F10000"), 1, 0) 'VLOOKUP関数が終了又はエラーが発生したら止まる On Error GoTo 0 '検索されなかったときの処理 '上記(※1)の部分Line7=G列に値がない If Cells(Line, 7).Value = "" Then 'Line7=M列に無と表示 Cells(Line, 7).Value = "無" End If '2行目から開始なので次の行の値を検索値とする Line = Line + 1 '検索する値がなくなるまで繰返す Loop '1行目が削除されるのを防止セルG1に無とセット Sheets("9月").Select Range("G1").Select ActiveCell.FormulaR1C1 = "無" 'データの最終行の行番号を保持する変数 Dim RwMax As Long '現在処理中の行番号を保持する変数 Dim Rw As Long '対象となるシートを選択。 Worksheets("9月").Select 'データの最終行の行番号を取得。 'Count, 7=G列 においてデータが入っている一番下のセルの行番号 RwMax = Cells(Rows.Count, 7).End(xlUp).Row '最終行から1行目まで繰返し処理。 '行の削除の為下から上へと処理。 For Rw = RwMax To 1 Step -1 '値が無ならそのまま If Cells(Rw, 7).Value = "無" Then Cells(Rw, 7).Value = "無" '無でなかったら行削除 Else Rows(Rw).Delete End If Next Rw 'シート2のF,G列を列削除 Sheets("9月").Select Columns("F:G").Select Application.CutCopyMode = False Selection.Delete Shift:=xlToLeft End Sub

  • エクセル 複数シートのデータを1シートにまとめるマクロ

    エクセルの複数シートにデータがあります。同じ条件の人のデータだけをひとつのシートにまとめたいのですが、マクロを教えていただけますでしょうか。それとも、マクロ以外に良い方法がありますか? エクセル初心者なので、あたりまえのことも知らないかもしれません。。。  【データ】 ●シート1からシート20まで、同じ配列でデータがあります。 ●1行目は見出しです。2行目から1人づつのデータです。(多くても65行までと思っています。) ●A列に到達度、B列に出欠をいれました。 ●C列からM列が氏名、課題、その他のデータです。 ●リストはシート21にあります。  【こんな作業でしょうか?】 ●シート1から20で A列が「C」または「D」ならば その行のA列からM列をコピーして シート21のA列からM列に形式を値にして張り付ける ●シート1から20で B列が「欠」ならば その行のA列からM列をコピーしてシート21のA列からM列に形式を値にして張り付ける (っというのが私の乏しい知識で考えた方法なのですが、これでは不具合がでますか? もちろん、この方法じゃなくもっといいのがあれば、それをやってみたいです。)

  • エクセルのマクロ

    あるエクセルのファイルにLIST(A列に呼びだすエクセルファイル名、B列からD列に呼びだしたエクセルに貼り付ける文字列があり、それが100行程度ある)があり、そのLIST A列に書かれているエクセルファイルを開き、その開いたエクセルファイルのある特定のセルにB列からD列にあるセルをそれぞれに貼りつける作業を繰り返すようなマクロはできないでしょうか? [流れ] LISTに書いてあるエクセルファイルを呼び出す→文字列を貼りつける→保存(できれば名前を変えて保存(その場合は、LISTのE列に名称を記載)→閉じる→次のLISTのエクセルファイルを開く→それをLISTの最後の行まで終わるまで繰り返す。 よろしくお願いします。

  • エクセルマクロでVLOOKUPのよう列を貼る

    初めましてよろしくお願いします。 シート2に       A     B     ・・・・・・・・・   Z 1   900     5               5 ・   903     40              60 ・    ・       ・               ・ 300 220     1     ・・・        100 301 210     10    ・・・        1000   302 200     15    ・・・         20 ・ ・ ・ が有ります。シート1のE10に210と入力されている場合、マクロを実行するとA列を検索し、シート2のA301の値と一致する301行をシート1のE11から列に変換しコピーされるようにしたいと思います。 シート1結果    A     B     C     D     E 1 2 ・ ・ 10                        210 11                         10 ・                           ・ ・                           ・ 35                        1000  解る方、よろしくお願いします。

専門家に質問してみよう