|
一応、読み込みは、行処理(1行読み込み→1行分出力)なので、
コードが使うリソースは、少ないのですが?
なんせ、120万行は無理かも?(時間も掛かるし?)
Option Explicit
Public Sub DataRead()
Dim i As Long
Dim vntFileName As Variant
Dim lngRow As Long
Dim strPath As String
Dim rngResult As Range
Dim strProm As String
Dim blnStatusBar As Boolean
Dim objFso As Object
'指定形式のファイル名を取得
strPath = ThisWorkbook.Path
If Not GetReadFile(vntFileName, strPath) Then
strProm = "マクロがキャンセルされました"
GoTo Wayout
End If
'◆出力先頭セル位置を設定(基準セル位置)
Set rngResult = Workbooks.Add.Worksheets(1).Cells(1, "A")
' Set rngResult = ActiveSheet.Cells(1, "A")
With Application
'現状のステータスバーの状態を保存
blnStatusBar = .DisplayStatusBar
'ステータスバーを表示
.DisplayStatusBar = True
'画面更新を停止
.ScreenUpdating = False
End With
'警告をキャンセル
Application.DisplayAlerts = False
'追加したBookのシートを先頭を残し削除
With rngResult.Parent.Parent
For i = .Worksheets.Count To 2 Step -1
.Worksheets(i).Delete
Next i
End With
'警告を受け付ける
Application.DisplayAlerts = False
'FSOのオブジェクトを取得
Set objFso = CreateObject("Scripting.FileSystemObject")
'シート名をファイル名に変更
rngResult.Parent.Name = objFso.GetBaseName(vntFileName)
'データの読み込み
CSVRead vntFileName, rngResult, lngRow
strProm = "処理が完了しました"
Wayout:
Set objFso = Nothing
Set rngResult = Nothing
With Application
'画面更新を再開
.ScreenUpdating = True
'ステータス バーの文字列を既定値に戻す
.StatusBar = False
'ステータス バーの設定を元に戻す
.DisplayStatusBar = blnStatusBar
End With
MsgBox strProm, vbInformation
End Sub
Private Sub CSVRead(ByVal strFileName As String, _
ByRef rngWrite As Range, _
Optional ByRef lngRow As Long = 1, _
Optional strDelim As String = ",")
Dim i As Long
Dim dfn As Integer
Dim vntField As Variant
Dim strBuff As String
Dim blnMulti As Boolean
Dim strRec As String
Dim strSheetName As String
Dim lngSheetsCount As Long
Dim lngTop As Long
'シート基準行位置を取得
lngTop = rngWrite.Row
'書き込みシート数
lngSheetsCount = 1
'現在のシート名を保存
strSheetName = rngWrite.Parent.Name
'ファイルをOpen
dfn = FreeFile
Open strFileName For Input As dfn
Do Until EOF(dfn)
'1行読み込み
Line Input #dfn, strBuff
'論理レコードに物理レコードを追加
strRec = strRec & strBuff
'論理レコードをフィールドに分割
vntField = SplitCsv(strRec, strDelim, , , blnMulti)
'フィールド内で改行が有る場合
If Not blnMulti Then
With rngWrite.Offset(lngRow)
'出力範囲を文字列に設定
.Offset(, 1).Resize(, 2).NumberFormat = "@"
'データを出力
.Resize(, UBound(vntField) + 1).Value = vntField
End With
'読み込み行数のカウントをとる
i = i + 1
Application.StatusBar = "読み込み中です...." & i & " レコード目"
'出力行をインクリメント
lngRow = lngRow + 1
'書き込み行が、SheetEndを超えた場合
' If lngRow > Rows.Count - lngTop Then
If lngRow > 65000 Then
With rngWrite
'書き込み行を初期値に
lngRow = 0
'シートを追加
Set rngWrite = .Parent.Parent.Worksheets. _
Add(after:=.Parent).Cells(.Row, .Column)
'書き込みシート数
lngSheetsCount = lngSheetsCount + 1
'シート名を変更
rngWrite.Parent.Name _
= strSheetName & "(" & lngSheetsCount & ")"
DoEvents
End With
End If
strRec = ""
Else
'セル内改行として残す場合
strRec = strRec & vbLf
End If
Loop
Close #dfn
End Sub
Private Function SplitCsv(ByVal strLine As String, _
Optional strDelimiter As String = ",", _
Optional strQuote As String = """", _
Optional strRet As String = vbCrLf, _
Optional blnMulti As Boolean) As Variant
Dim i As Long
Dim lngDPos As Long
Dim vntData() As Variant
Dim lngStart As Long
Dim vntField As Variant
Dim lngLength As Long
i = 0
lngStart = 1
lngLength = Len(strLine)
blnMulti = False
Do
ReDim Preserve vntData(i)
If Mid$(strLine, lngStart, 1) <> strQuote Then
lngDPos = InStr(lngStart, strLine, _
strDelimiter, vbBinaryCompare)
If lngDPos > 0 Then
vntField = Mid$(strLine, lngStart, _
lngDPos - lngStart)
If lngDPos = lngLength Then
ReDim Preserve vntData(i + 1)
End If
lngStart = lngDPos + 1
Else
vntField = Mid$(strLine, lngStart)
lngStart = lngLength + 1
End If
Else
lngStart = lngStart + 1
Do
lngDPos = InStr(lngStart, strLine, _
strQuote, vbBinaryCompare)
If lngDPos > 0 Then
vntField = vntField & Mid$(strLine, _
lngStart, lngDPos - lngStart)
lngStart = lngDPos + 1
Select Case Mid$(strLine, lngStart, 1)
Case ""
Exit Do
Case strDelimiter
lngStart = lngStart + 1
Exit Do
Case strQuote
lngStart = lngStart + 1
vntField = vntField & strQuote
End Select
Else
blnMulti = True
vntField = Mid$(strLine, lngStart)
lngStart = lngLength + 1
Exit Do
End If
Loop
End If
vntData(i) = vntField
vntField = Empty
i = i + 1
Loop Until lngLength < lngStart
SplitCsv = vntData()
End Function
Private Function GetReadFile(vntFileNames As Variant, _
Optional strFilePath As String, _
Optional blnMultiSel As Boolean _
= False) As Boolean
Dim strFilter As String
'フィルタ文字列を作成
strFilter = "CSV File (*.csv),*.csv," _
& "Text File (*.txt),*.txt," _
& "CSV and Text (*.csv; *.txt),*.csv;*.txt," _
& "全て (*.*),*.*"
'読み込むファイルの有るフォルダを指定
If strFilePath <> "" Then
'ファイルを開くダイアログ表示ホルダに移動
ChDrive Left(strFilePath, 1)
ChDir strFilePath
End If
'もし、ディフォルトのファイル名が有る場合
If vntFileNames <> "" Then
SendKeys vntFileNames & "{TAB}", False
End If
'「ファイルを開く」ダイアログを表示
vntFileNames _
= Application.GetOpenFilename(strFilter, 1, , , blnMultiSel)
If VarType(vntFileNames) = vbBoolean Then
Exit Function
End If
GetReadFile = True
End Function
|
|