在平时的工作中经常会遇到固定分隔符或固定宽度的文本文档,如下图所示:

如果遇到大量的如上图所示的文本文档,可以借助vba批量将其另存为excel文档。
方法一、批量读取文本文档,用数组逐行写入excel单元格中,然后另存为excel文件。
以下代码将批量将同一文件夹下的所有按照固定分隔符分隔的文本文档另存为xlsx格式的Excel文档:
'文本文档所在的路径
Public sPath As String
'固定的分隔符
Public sDelimiter As String
Const ForAppending = 8
Const ForReading = 1
Const ForWriting = 2
'以系统默认的方式打开文本文档
Const TristateUseDefault = -2
'以Unicode方式打开文本文档
Const TristateTrue = -1
'以ASCII方式打开文本文档
Const TristateFalse = 0
Sub QQ1722187970()
Excel.Application.ScreenUpdating = False
Excel.Application.Calculation = xlCalculationManual
Excel.Application.DisplayAlerts = False
sDelimiter = ","
'获取文件或者文件夹的路径
sPath = GetPath()
If Len(sPath) Then
EnuAllFiles (sPath)
MsgBox "处理完成!!!"
End If
Excel.Application.ScreenUpdating = True
Excel.Application.Calculation = xlCalculationAutomatic
Excel.Application.DisplayAlerts = True
End Sub
Function GetPath() As String
'声明一个FileDialog对象变量
Dim oFD As FileDialog
' '创建一个选择文件对话框
' Set oFD = Application.FileDialog(msoFileDialogFilePicker)
'创建一个选择文件夹对话框
Set oFD = Application.FileDialog(msoFileDialogFolderPicker)
'声明一个变量用来存储选择的文件名
Dim vrtSelectedItem As Variant
With oFD
'允许选择多个文件
.AllowMultiSelect = True
'使用Show方法显示对话框,如果单击了确定按钮则返回-1。
If .Show = -1 Then
'遍历所有选择的文件
For Each vrtSelectedItem In .SelectedItems
'获取所有选择的文件的完整路径,用于各种操作
GetPath = vrtSelectedItem
Next
'如果单击了取消按钮则返回0
Else
End If
End With
'释放对象变量
Set oFD = Nothing
End Function
Sub EnuAllFiles(ByVal sPath As String, Optional bEnuSub As Boolean = False)
'定义文件系统对象
Dim oFso As Object
Set oFso = CreateObject("Scripting.FileSystemObject")
'定义文件夹对象
Dim oFolder As Object
Set oFolder = oFso.GetFolder(sPath)
'定义文件对象
Dim oFile As Object
'如果指定的文件夹含有文件
If oFolder.Files.Count Then
For Each oFile In oFolder.Files
With oFile
'输出文件所在的盘符
Dim sDrive As String
sDrive = .Drive
'输出文件的类型
Dim sType As String
sType = .Type
'输出含后缀名的文件名称
Dim sName As String
sName = .Name
'输出含文件名的完整路径
Dim sFilePath As String
sFilePath = .Path
If sType Like "文本文档" And Not (sName Like "*~$*") Then
If VBA.FileLen(sFilePath) = 0 Then
'空白文本文档不打开,直接删除
VBA.Kill sFilePath
Else
'获取文件名称
sName = GetFileName(sName)
Dim oWB As Workbook
Set oWB = Excel.Workbooks.Add
Set oWK = oWB.Worksheets(1)
i = 1
'打开文本文档
Set oTextStream = oFso.OpenTextFile(sFilePath, ForReading)
With oTextStream
'逐行导入
Do Until .AtEndOfStream
'获取每行的文本内容
sContent = .ReadLine
'按照分隔符拆分
arr = Split(sContent, sDelimiter)
'填充数组
oWK.Cells(i, 1).Resize(1, 1 + UBound(arr)) = arr
i = i + 1
Loop
End With
'另存为xlsx文件
oWB.SaveAs sPath & "\" & sName & ".xlsx"
oWB.Close
End If
End If
End With
Next
'如果指定的文件夹不含有文件
Else
End If
'如果要遍历子文件夹
If bEnuSub = True Then
'定义子文件夹集合对象
Dim oSubFolders As Object
Set oSubFolders = oFolder.SubFolders
If oSubFolders.Count > 0 Then
For Each oTempFolder In oSubFolders
sTempPath = oTempFolder.Path
Call EnuAllFiles(sTempPath, True)
Next
End If
Set oSubFolders = Nothing
End If
Set oFile = Nothing
Set oFolder = Nothing
Set oFso = Nothing
End Sub
Function GetFileName(ByVal sName As String)
'获取纯文件名的自定义函数
'QQ1722187970
Dim sTemp As String
sTemp = sName
'判断后缀名分隔符.的位置
iPos = Len(sTemp) - VBA.InStr(1, VBA.StrReverse(sTemp), ".")
If iPos <> 0 Then
sTemp = Mid(sTemp, 1, iPos)
End If
'判断路径分隔符\的位置
iPos = VBA.InStr(1, sTemp, "\")
If iPos <> 0 Then
'反转后好取字符
iPos = VBA.InStr(1, VBA.StrReverse(sTemp), "\")
sTemp = Mid(VBA.StrReverse(sTemp), 1, iPos - 1)
sTemp = VBA.StrReverse(sTemp)
End If
GetFileName = sTemp
End Function
该方法的优缺点如下:
1.适用于每个文本文档的行数不多的情况。
2.速度快。
3.但是导入的数据格式无法自动识别。
4.不能用于固定宽度的文本文档的导入
方法二、批量读取文本文档,逐行导入excel文档中,然后用分列功能将整列分列,另存为excel文档。
代码如下:
'文本文档所在的路径
Public sPath As String
'固定的分隔符
Public sDelimiter As String
Const ForAppending = 8
Const ForReading = 1
Const ForWriting = 2
'以系统默认的方式打开文本文档
Const TristateUseDefault = -2
'以Unicode方式打开文本文档
Const TristateTrue = -1
'以ASCII方式打开文本文档
Const TristateFalse = 0
Sub QQ1722187970()
Excel.Application.ScreenUpdating = False
Excel.Application.Calculation = xlCalculationManual
Excel.Application.DisplayAlerts = False
sDelimiter = ","
'获取文件或者文件夹的路径
sPath = GetPath()
If Len(sPath) Then
EnuAllFiles (sPath)
MsgBox "处理完成!!!"
End If
Excel.Application.ScreenUpdating = True
Excel.Application.Calculation = xlCalculationAutomatic
Excel.Application.DisplayAlerts = True
End Sub
Function GetPath() As String
'声明一个FileDialog对象变量
Dim oFD As FileDialog
' '创建一个选择文件对话框
' Set oFD = Application.FileDialog(msoFileDialogFilePicker)
'创建一个选择文件夹对话框
Set oFD = Application.FileDialog(msoFileDialogFolderPicker)
'声明一个变量用来存储选择的文件名
Dim vrtSelectedItem As Variant
With oFD
'允许选择多个文件
.AllowMultiSelect = True
'使用Show方法显示对话框,如果单击了确定按钮则返回-1。
If .Show = -1 Then
'遍历所有选择的文件
For Each vrtSelectedItem In .SelectedItems
'获取所有选择的文件的完整路径,用于各种操作
GetPath = vrtSelectedItem
Next
'如果单击了取消按钮则返回0
Else
End If
End With
'释放对象变量
Set oFD = Nothing
End Function
Sub EnuAllFiles(ByVal sPath As String, Optional bEnuSub As Boolean = False)
'定义文件系统对象
Dim oFso As Object
Set oFso = CreateObject("Scripting.FileSystemObject")
'定义文件夹对象
Dim oFolder As Object
Set oFolder = oFso.GetFolder(sPath)
'定义文件对象
Dim oFile As Object
'如果指定的文件夹含有文件
If oFolder.Files.Count Then
For Each oFile In oFolder.Files
With oFile
'输出文件所在的盘符
Dim sDrive As String
sDrive = .Drive
'输出文件的类型
Dim sType As String
sType = .Type
'输出含后缀名的文件名称
Dim sName As String
sName = .Name
'输出含文件名的完整路径
Dim sFilePath As String
sFilePath = .Path
If sType Like "文本文档" And Not (sName Like "*~$*") Then
If VBA.FileLen(sFilePath) = 0 Then
'空白文本文档不打开,直接删除
VBA.Kill sFilePath
Else
'获取文件名称
sName = GetFileName(sName)
Dim oWB As Workbook
Set oWB = Excel.Workbooks.Add
Dim oWK As Worksheet
Set oWK = oWB.Worksheets(1)
i = 1
'打开文本文档
Set oTextStream = oFso.OpenTextFile(sFilePath, ForReading)
With oTextStream
'逐行导入
Do Until .AtEndOfStream
'获取每行的文本内容
sContent = .ReadLine
oWK.Cells(i, 1) = sContent
i = i + 1
Loop
'批量分列
With oWK
.Range("a1").EntireColumn.TextToColumns Destination:=.Range("a1"), DataType:=xlDelimited, comma:=True
.Columns.AutoFit
End With
End With
'另存为xlsx文件
oWB.SaveAs sPath & "\" & sName & ".xlsx"
oWB.Close
End If
End If
End With
Next
'如果指定的文件夹不含有文件
Else
End If
'如果要遍历子文件夹
If bEnuSub = True Then
'定义子文件夹集合对象
Dim oSubFolders As Object
Set oSubFolders = oFolder.SubFolders
If oSubFolders.Count > 0 Then
For Each oTempFolder In oSubFolders
sTempPath = oTempFolder.Path
Call EnuAllFiles(sTempPath, True)
Next
End If
Set oSubFolders = Nothing
End If
Set oFile = Nothing
Set oFolder = Nothing
Set oFso = Nothing
End Sub
Function GetFileName(ByVal sName As String)
'获取纯文件名的自定义函数
'QQ1722187970
Dim sTemp As String
sTemp = sName
'判断后缀名分隔符.的位置
iPos = Len(sTemp) - VBA.InStr(1, VBA.StrReverse(sTemp), ".")
If iPos <> 0 Then
sTemp = Mid(sTemp, 1, iPos)
End If
'判断路径分隔符\的位置
iPos = VBA.InStr(1, sTemp, "\")
If iPos <> 0 Then
'反转后好取字符
iPos = VBA.InStr(1, VBA.StrReverse(sTemp), "\")
sTemp = Mid(VBA.StrReverse(sTemp), 1, iPos - 1)
sTemp = VBA.StrReverse(sTemp)
End If
GetFileName = sTemp
End Function
该方法的优缺点如下:
1.适用于每个文本文档的行数不多的情况。
2.速度快。
3.导入的数据格式可以被excel自动转换。
方法三、直接用导入外部数据的方式导入文本文档,然后另存为excel文档。
代码如下:
'文本文档所在的路径
Public sPath As String
'固定的分隔符
Public sDelimiter As String
Const ForAppending = 8
Const ForReading = 1
Const ForWriting = 2
'以系统默认的方式打开文本文档
Const TristateUseDefault = -2
'以Unicode方式打开文本文档
Const TristateTrue = -1
'以ASCII方式打开文本文档
Const TristateFalse = 0
Sub QQ1722187970()
Excel.Application.ScreenUpdating = False
Excel.Application.Calculation = xlCalculationManual
Excel.Application.DisplayAlerts = False
sDelimiter = ","
'获取文件或者文件夹的路径
sPath = GetPath()
If Len(sPath) Then
EnuAllFiles (sPath)
MsgBox "处理完成!!!"
End If
Excel.Application.ScreenUpdating = True
Excel.Application.Calculation = xlCalculationAutomatic
Excel.Application.DisplayAlerts = True
End Sub
Function GetPath() As String
'声明一个FileDialog对象变量
Dim oFD As FileDialog
' '创建一个选择文件对话框
' Set oFD = Application.FileDialog(msoFileDialogFilePicker)
'创建一个选择文件夹对话框
Set oFD = Application.FileDialog(msoFileDialogFolderPicker)
'声明一个变量用来存储选择的文件名
Dim vrtSelectedItem As Variant
With oFD
'允许选择多个文件
.AllowMultiSelect = True
'使用Show方法显示对话框,如果单击了确定按钮则返回-1。
If .Show = -1 Then
'遍历所有选择的文件
For Each vrtSelectedItem In .SelectedItems
'获取所有选择的文件的完整路径,用于各种操作
GetPath = vrtSelectedItem
Next
'如果单击了取消按钮则返回0
Else
End If
End With
'释放对象变量
Set oFD = Nothing
End Function
Sub EnuAllFiles(ByVal sPath As String, Optional bEnuSub As Boolean = False)
'定义文件系统对象
Dim oFso As Object
Set oFso = CreateObject("Scripting.FileSystemObject")
'定义文件夹对象
Dim oFolder As Object
Set oFolder = oFso.GetFolder(sPath)
'定义文件对象
Dim oFile As Object
'如果指定的文件夹含有文件
If oFolder.Files.Count Then
For Each oFile In oFolder.Files
With oFile
'输出文件所在的盘符
Dim sDrive As String
sDrive = .Drive
'输出文件的类型
Dim sType As String
sType = .Type
'输出含后缀名的文件名称
Dim sName As String
sName = .Name
'输出含文件名的完整路径
Dim sFilePath As String
sFilePath = .Path
'如果文件是Word文件且不是隐藏文件
If sType Like "文本文档" And Not (sName Like "*~$*") Then
If VBA.FileLen(sFilePath) = 0 Then
'空白文本文档不打开,直接删除
VBA.Kill sFilePath
Else
'获取文件名称
sName = GetFileName(sName)
Dim oWB As Workbook
Set oWB = Excel.Workbooks.Add
Dim oWK As Worksheet
Set oWK = oWB.Worksheets(1)
sText = "TEXT;" & sFilePath
Dim oQB As QueryTable
With oWK
Set oQB = oWK.QueryTables.Add(sText, .Range("a1"))
With oQB
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlOverwriteCells
.SavePassword = False
.SaveData = False
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
'指定是从第几行开始导入数据
.TextFileStartRow = 1
'设置文本的解析类型是以固定宽度还是以固定分隔符
.TextFileParseType = xlDelimited
'设置文本的限定符
.TextFileTextQualifier = xlTextQualifierDoubleQuote
'设置是否将连续的分隔符视为一个
.TextFileConsecutiveDelimiter = False
'设置是否以Tab为分隔符
.TextFileTabDelimiter = False
'设置是否以分号为分隔符
.TextFileSemicolonDelimiter = False
'设置是否以逗号为分隔符
.TextFileCommaDelimiter = True
'设置是否以空格为分隔符
.TextFileSpaceDelimiter = False
'设置其它的分隔符
.TextFileOtherDelimiter = ""
' '每个列用的格式
'' .TextFileColumnDataTypes = Array(1, 1, 1, 1)
' '当以固定宽度导入时,设置每个列指定的列宽
' .TextFileFixedColumnWidths = Array(3, 5, 31)
'把带负号-的文本当做数字
.TextFileTrailingMinusNumbers = True
'异步更新
.Refresh BackgroundQuery:=False
.MaintainConnection = False
'以下两句最关键,只有加这两句,才不会再更新
.WorkbookConnection.Delete
.Delete
End With
End With
'另存为xlsx文件
oWB.SaveAs sPath & "\" & sName & ".xlsx"
oWB.Close
End If
End If
End With
Next
'如果指定的文件夹不含有文件
Else
End If
'如果要遍历子文件夹
If bEnuSub = True Then
'定义子文件夹集合对象
Dim oSubFolders As Object
Set oSubFolders = oFolder.SubFolders
If oSubFolders.Count > 0 Then
For Each oTempFolder In oSubFolders
sTempPath = oTempFolder.Path
Call EnuAllFiles(sTempPath, True)
Next
End If
Set oSubFolders = Nothing
End If
Set oFile = Nothing
Set oFolder = Nothing
Set oFso = Nothing
End Sub
Function GetFileName(ByVal sName As String)
'获取纯文件名的自定义函数
'QQ1722187970
Dim sTemp As String
sTemp = sName
'判断后缀名分隔符.的位置
iPos = Len(sTemp) - VBA.InStr(1, VBA.StrReverse(sTemp), ".")
If iPos <> 0 Then
sTemp = Mid(sTemp, 1, iPos)
End If
'判断路径分隔符\的位置
iPos = VBA.InStr(1, sTemp, "\")
If iPos <> 0 Then
'反转后好取字符
iPos = VBA.InStr(1, VBA.StrReverse(sTemp), "\")
sTemp = Mid(VBA.StrReverse(sTemp), 1, iPos - 1)
sTemp = VBA.StrReverse(sTemp)
End If
GetFileName = sTemp
End Function
本方法的优点是全程一气呵成,不需要打开文本文档,另外还可以选择是从第几行开始导入,速度也快。
四、总结
本文介绍了3种导入外部文本文档,并将其另存为excel文档的方法,各有优缺点,大家在平时的应用中可以根据自己的文档特点选择。


发表评论