ポイント
- CSV 形式のファイル、つまりカンマで区切られたデータのファイルを読み込むことができる。ファイル拡張子が .csv でなくても読み込める。
- 必ずテキスト形式でインポートされるように TextFileColumnDataTypes に指定する配列の作り方を工夫した。
- コネクションは生成されたものだけ削除するように改善した。
- Name オブジェクトの削除方法を改善し、シート名に影響を受けないようにした。
- 他のエクセルなどからも呼び出せるようにブック名を指名するようにした。
読み込まれる CSV ファイル
これは前回と同じです。
No,氏名,電話番号 1,伊藤健一,0112223333 2,高橋哲也,0114445555 3,佐藤誠,0116667777
VBA コード
''' <summary> ''' CSV ファイルを指定ブックのシートにインポートするクラスです。 ''' エクセルへはテキスト形式で書き込みます。 ''' </summary> Option Explicit Private mstrCsvFilePath As String Private mstrBook As String Private mobjSheet As Worksheet Private mstrStartCell As String Private mstrAutoCreatedName As String ''' <summary> ''' コンストラクタ ''' </summary> Private Sub Class_Initialize() ' インポート時にセル範囲に付く「名前」 ' 既存の Name オブジェクトと重複しないよう、年月日時分秒の文字列を末尾に付加 Dim strSalt as String: strSalt = Format(Now, "yyyymmddhhnnss") mstrAutoCreatedName = "CsvImporterName" & strSalt End Sub ''' <summary> ''' 初期化処理を実行します。 ''' </summary> ''' <param name="strCsvFilePath">CSV ファイルフルパス</param> ''' <param name="strBook">書き込み対象ブック名</param> ''' <param name="strSheet">書き込み対象ワークシート名</param> ''' <param name="strStartCell">インポート開始セル名</param> Public Sub Init( _ ByVal strCsvFilePath as String, _ ByVal strBook as String, _ ByVal strSheet As String, _ ByVal strStartCell As String) ' 変数をセット mstrCsvFilePath = strCsvFilePath Set mobjSheet = Workbooks(strBook).Sheets(strSheet) mstrStartCell = strStartCell End Function ''' <summary> ''' CSV ファイルを読み込み、ワークシートに書き込みます。 ''' </summary> Public Sub Import() ' ファイルの各列に適用されるデータ型をテキスト形式のみに指定 Dim vntColDataTypes() As Variant, i As Long: ReDim vntColDataTypes(Column.Count) For i = 0 To Column.Count: vntColDataTypes(i) = xlTextFormat: Next i ' ファイル読み込み、および、書き込み With mobjSheet.QueryTables.Add( _ Connection:="Text;" & mstrCsvFilePath, _ Destination:=mobjSheet.Range(mstrStartCell)) .Name = mstrAutoCreatedName .RowNumbers = False .RefreshStyle = xlOverwriteCells .SavePassword = False .SaveData = True .RefreshPeriod = 0 .TextFilePlatform = 932 .TextFileCommaDelimiter = True .TextFileColumnDataTypes = vntColDataTypes .TextFileTrailingMinusNumbers = True .Refresh BackgroundQuery:=False Dim strConName As String: strConName = .WorkbookConnection.Name End With ' 後処理。作成されるコネクションと Name オブジェクトを削除 Call DeleteConnection(mstrBook, strConName) Call DeleteName(mstrBook, mstrAutoCreatedName) End Sub ''' <summary> ''' 指定したコネクションを削除します。 ''' </summary> ''' <param name="strBook">ブック名文字列</param> ''' <param name="strConName">コネクション名文字列</param> Private Sub DeleteConnection( _ ByVal strBook As String, _ ByVal strConName As String) Workbooks(strBook).Connections(strConName).Delete End Sub ''' <summary> ''' 指定した名前 (Name オブジェクト) を削除します。 ''' </summary> ''' <param name="strBook">ブック名文字列</param> ''' <param name="strName">名前 (Name オブジェクト) 文字列</param> Private Sub DeleteName( _ ByVal strBook As String, _ ByVal strName As String) ' シート名が [Sheet1!] など ! を含む場合、Name を指定しての削除ができずエラーとなった。 ' よって、Name に対応する Index を取得し、Index を指定して削除する。 ' 削除対象の Name オブジェクトを特定 Dim colIndexes As Collection: Set colIndexes = New Collection Dim vntItem As Variant For Each vntItem In Workbooks(strBook).Names If vntItem.Name Like "*" & strName & "*" Then Call colIndexes.Add(vntItem.Index) End If Next vntItem ' 特定した Name オブジェクトを削除 Dim vntIndex As Variant For Each vntIndex In colIndexes Workbooks(strBook).Names.Item(vntIndex).Delete Next vntIndex End Sub
続いては上記のクラスを確認するコードです。CSV のインポート先は VBA のエクセルファイル自身としています。
Option Explicit Public Sub Test() ' 準備 ' CSV ファイルパス取得 Dim strCsvFilePath As String strCsvFilePath = Application.GetOpenfilename( _ Filefilter:="CSVファイル(*.csv),*.csv", _ Title:="CSVファイルの選択") If strCsvFilePath = "False" Then Debug.Print ("CSV ファイルが指定されなかったため、終了") End End If ' CSV インポート Dim udtCi As CsvImporter: Set udtCi = New CsvImporter Call udtCi.Init(strCsvFilePath, "VbaCsvImporter.xlsm" "Sheet1", "A1") Call udtCi.Import End Sub
おわりに
参考ページです。ありがとう存じます!
- ExcelでCSVをそのまま開く – @jitteの日記
- 【Excel VBA】CSV ファイルをワークシートにインポートするクラスのコード♪ – oki2a24
- 【Excel VBA】配列の要素数に変数の数字を設定する方法 – oki2a24
以前の投稿のコードをベースにしましたけれども、タイポなどがあり直すこともできました。一石二鳥ですの♪
以上です。