|
選択範囲をCSV出力するコードです
この中の、Csv2形式の出力は、
特殊文字を含まない文字列フィールドも、ダブルクォーツで括りません
Option Explicit
Public Sub OutPutCsv()
Dim vntFileName As Variant
Dim rngTarget As Range
Dim strPrompt As String
Dim strTitle As String
Dim blnCsv1 As Boolean
strPrompt = "Csv出力するRangeを選択して下さい"
strTitle = "Csv出力"
On Error GoTo ErrorHandler
'選択範囲の取得
With Application
'もし、選択範囲が無いなら
If .Selection.Count = 1 Then
Set rngTarget = ActiveSheet.UsedRange
Else
Set rngTarget = .Selection
End If
'選択範囲の取得
Set rngTarget = .InputBox(Prompt:=strPrompt, _
Title:=strTitle, _
Default:=rngTarget.Address, _
Type:=8)
rngTarget.Select
End With
'出力形式の選択
If MsgBox("CSV1形式出力を行います" & vbCrLf _
& " CSV1形式 = はい" & vbCrLf _
& " CSV2形式 = いいえ", _
vbYesNo + vbDefaultButton2 + vbQuestion, _
"出力形式選択") = vbYes Then
blnCsv1 = True
End If
'Default出力名の設定
' vntFileName = ThisWorkbook.Path & "\" & "TestFile.csv"
'出力名を取得
If Not GetWriteFile(vntFileName, ThisWorkbook.Path) Then
GoTo ErrorHandler
End If
'ファイルに出力
CsvWrite vntFileName, rngTarget, blnCsv1
Beep
MsgBox "処理が終了しました", vbOKOnly, "終了"
ErrorHandler:
'選択範囲の解除
rngTarget(1).Select
Set rngTarget = Nothing
End Sub
Private Sub CsvWrite(ByVal strFileName As String, _
ByVal rngTarget As Range, _
Optional blnCsv1 As Boolean = False, _
Optional strRetCode As String = vbCrLf)
Dim dfn As Integer
Dim i As Long
Dim j As Long
Dim strBuf As String
Dim lngCount As Long
Dim vntField As Variant
'空きファイル番号を取得します
dfn = FreeFile
'出力ファイルをOpenします
Open strFileName For Output As dfn
With rngTarget
lngCount = .Columns.Count
For i = 1 To .Rows.Count
'1行分のDataをシートから読みこむ
vntField = .Item(i, 1).Resize(, lngCount)
'出力1レコード作成
strBuf = ComposeLine(vntField, blnCsv1, ",") _
& strRetCode
'1レコード書き出し
Print #dfn, strBuf;
Next i
End With
'出力ファイルを閉じる
Close #dfn
End Sub
Private Function ComposeLine(vntField As Variant, _
Optional blnCsv1 As Boolean = False, _
Optional strDelim As String = ",") As String
' レコード作成
Dim i As Long
Dim strResult As String
Dim strField As String
Dim lngFieldEnd As Long
Dim vntFieldTmp As Variant
'もし、データが複数なら
If VarType(vntField) = vbArray + vbVariant Then
vntFieldTmp = vntField
Else
ReDim vntFieldTmp(1 To 1, 1 To 1)
vntFieldTmp(1, 1) = vntField
End If
'データ数の取得
lngFieldEnd = UBound(vntFieldTmp, 2)
'データ数繰り返し
For i = 1 To lngFieldEnd
'もし、Csv1出力の場合
If blnCsv1 Then
strField = PrepareCsv1Field(vntFieldTmp(1, i))
Else
strField = PrepareCsv2Field(vntFieldTmp(1, i))
End If
'結果変数にフィール文字列を加算
strResult = strResult & strField
'データカウントがデータ数未満の場合
If i < lngFieldEnd Then
'区切り文字を結果変数に加算
strResult = strResult & strDelim
End If
Next i
ComposeLine = strResult
End Function
Private Function PrepareCsv1Field(ByVal vntValue As Variant) As String
' Csv1出力形式の調整
Dim i As Long
Dim lngPos As Long
Const strQuot As String = """"
'引数の変数内部形式に就いて
Select Case VarType(vntValue)
Case vbString '文字列型
'ダブルクォーツの処理
i = 1
lngPos = InStr(i, vntValue, strQuot, vbBinaryCompare)
Do Until lngPos = 0
vntValue = Left(vntValue, lngPos) & Mid(vntValue, lngPos + 1)
i = lngPos + 2
lngPos = InStr(i, vntValue, strQuot, vbBinaryCompare)
Loop
'両端にダブルクォーツを付加
vntValue = strQuot & vntValue & strQuot
Case vbDate '日付型
'日付が時分秒を持つなら
If TimeValue(vntValue) > 0 Then
vntValue = Format(vntValue, "yyyy/mm/dd h:mm:ss")
Else
vntValue = Format(vntValue, "yyyy/mm/dd")
End If
End Select
PrepareCsv1Field = CStr(vntValue)
End Function
Private Function PrepareCsv2Field(ByVal vntValue As Variant) As String
' Csv2出力形式の調整
Dim i As Long
Dim blnQuot As Boolean
Dim lngPos As Long
Const strQuot As String = """"
'引数の変数内部形式に就いて
Select Case VarType(vntValue)
Case vbString '文字列型
'ダブルクォーツの処理
i = 1
lngPos = InStr(i, vntValue, strQuot, vbBinaryCompare)
Do Until lngPos = 0
vntValue = Left(vntValue, lngPos) & Mid(vntValue, lngPos + 1)
i = lngPos + 2
lngPos = InStr(i, vntValue, strQuot, vbBinaryCompare)
Loop
'ダブルクォーツで括るか否かの判断処理
For i = 1 To 5
lngPos = InStr(1, vntValue, Choose(i, ",", strQuot, _
vbCr, vbLf, vbTab), vbBinaryCompare)
If lngPos <> 0 Then
blnQuot = True
Exit For
End If
Next i
'ダブルクォーツで括るの判断の場合
If blnQuot Then
vntValue = strQuot & vntValue & strQuot
End If
Case vbDate '日付型
'日付が時分秒を持つなら
If TimeValue(vntValue) > 0 Then
vntValue = Format(vntValue, "yyyy/mm/dd h:mm:ss")
Else
vntValue = Format(vntValue, "yyyy/mm/dd")
End If
End Select
PrepareCsv2Field = CStr(vntValue)
End Function
Private Function GetWriteFile(vntFileName As Variant, _
Optional strFilePath As String) As Boolean
Dim strFilter As String
Dim strInitialFile As String
'フィルタ文字列を作成
strFilter = "CSV File (*.csv),*.csv," _
& "Text File (*.txt),*.txt"
'既定値のファイル名を設定
strInitialFile = vntFileName
'読み込むファイルの有るフォルダを指定
If strFilePath <> "" Then
'ファイルを開くダイアログ表示ホルダに移動
ChDrive Left(strFilePath, 1)
ChDir strFilePath
End If
'「ファイルを保存」ダイアログを表示
vntFileName _
= Application.GetSaveAsFilename(vntFileName, strFilter, 1)
If vntFileName = False Then
Exit Function
End If
GetWriteFile = True
End Function
|
|