我想在VBA中阅读一个大文件并在线查看此代码:
Dim MyChar As String, Pointer As Long, LastLine As String
Open "MyTextFile.Txt" For Binary As #1
Pointer = LOF(1) - 2
MyChar = Chr$(32)
Do
Get #1, Pointer, MyChar
If MyChar = vbCr Or MyChar = vbLf Then
Exit Do
Else: Pointer = Pointer - 1
LastLine = MyChar & LastLine
End If
Loop
MsgBox "Last Line is " & LastLine
如何更改此代码以获取倒数第二行?需要一些帮助。
想到这个:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
"MyTextFile.Txt", 1)
objTextFile.ReadAll
MsgBox objTextFile.Line
但我无法进入第2行。
答案 0 :(得分:1)
取决于你的方法。但是如果文件真的那么大,那么你可能不希望Excel加载整个文件。因此,您可能会打开文件并逐行读取,而不知道文件有多大以及文件有多少行。在这种情况下,最简单的方法是在两个单独的字符串变量中一次存储两行。一旦你到达最后一行,你可以退出你的循环 - 如上面的代码所示 - 并且不仅输出最后一行(如代码中已经完成的那样),还输出该文件中第二行的内容。
Public Sub GetSecondLastRow()
Dim strSecondLastLine As String
Dim strFileToImport As String
Dim strLastLine As String
Dim intPointer As Integer
Dim lngCounter As Long
strFileToImport = ThisWorkbook.Path & IIf(InStr(1, ThisWorkbook.Path, "\") > 0, "\", "/") & "MyTextFile.txt"
intPointer = FreeFile()
Open strFileToImport For Input Access Read Lock Read As #intPointer
lngCounter = 0
Do Until EOF(lngCounter)
strSecondLastLine = strLastLine
Line Input #intPointer, strLastLine
lngCounter = lngCounter + 1
Loop
Close intPointer
Debug.Print "Content of the second last row:"
Debug.Print "---------------------------------------"
Debug.Print strSecondLastLine
Debug.Print "---------------------------------------"
Debug.Print "Content of the last row:"
Debug.Print "---------------------------------------"
Debug.Print strLastLine
End Sub
另一种方法是先查询文件的行数,然后使用ADO获取该文件中的倒数第二条记录。但我怀疑那会更快。 ADO的问题在于你得到一个包含整个文本文件的巨大recordset
背面。这是因为您在SELECT * from MyTextFile.txt
条款中没有任何限制。因此,整个文本文件进入内存之前您可以对其执行任何操作。然后 - 当然 - 您可以检查RecordCount
并再次使用光标快速返回所有记录,直到您到达倒数第二行。不幸的是,ADO不支持
row_number()结束(按@@ ROWCOUNT排序)。
否则,您可以先使用select count(1) from MyTextFile.txt
获取行计数,然后再使用适用的行。
所以,无论如何,我几乎可以肯定(没有经过测试)ADO的性能低于标准,如果文本文件和你说的一样大,那么第一个解决方案就是这样。如果您仍然喜欢ADO,那么这就是代码(基于以下SO问题/答案:Copying text from .txt file in Excel using ADO ignores first row)。
Sub ImportTextFile()
'Imports text file into Excel workbook using ADO.
'If the number of records exceeds 65536 then it splits it over more than one sheet.
Dim strFilePath As String, strFilename As String, strFullPath As String
Dim lngCounter As Long
Dim oConn As ADODB.Connection
Dim oRS As ADODB.Recordset
Dim oFSObj As Object
'Get a text file name
strFullPath = Application.GetOpenFilename("Text Files (*.txt),*.txt", , "Please select text file...")
If strFullPath = "False" Then Exit Sub 'User pressed Cancel on the open file dialog
'This gives us a full path name e.g. C:\temp\folder\file.txt
'We need to split this into path and file name
Set oFSObj = CreateObject("SCRIPTING.FILESYSTEMOBJECT")
strFilePath = oFSObj.GetFile(strFullPath).ParentFolder.Path
strFilename = oFSObj.GetFile(strFullPath).Name
'Open an ADO connection to the folder specified
Set oConn = New ADODB.Connection
oConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strFilePath & ";" & _
"Extended Properties=""text;HDR=No;FMT=Delimited"""
Set oRS = New ADODB.Recordset
'Now actually open the text file and import into Excel
oRS.Open "SELECT count(1) FROM [" & strFilename & "]", oConn, 3, 1, 1
Range("A1").CopyFromRecordset oRS
Set oRS = New ADODB.Recordset
'Now actually open the text file and import into Excel
oRS.Open "SELECT * FROM [" & strFilename & "]", oConn, 3, 1, 1
While Not oRS.EOF And Not oRS.BOF
If oRS.AbsolutePosition = Range("A1").Value2 Then
Range("A2").Value = oRS.Fields(0).Value
End If
oRS.MoveNext
Wend
oRS.Close
oConn.Close
End Sub
答案 1 :(得分:0)
您提供的代码如下:
为了根据您的需要进行修改,我添加了一个Boolean secondRun
,让代码再次运行第2步,从而记录第二行:
Dim MyChar As String, Pointer As Long, LastLine As String
Open "MyTextFile.Txt" For Binary As #1
Pointer = LOF(1) - 2
MyChar = Chr$(32)
Dim secondRun As Boolean
Do
' Read character at position "Pointer" into variable "MyChar"
Get #1, Pointer, MyChar
If MyChar = vbCr Or MyChar = vbLf Then ' Linebreak = line read completely
If Not secondRun Then
' Run again if we've read only one line so far
secondRun = True
LastLine = ""
Pointer = Pointer - 2
Else
Exit Do
End If
Else: Pointer = Pointer - 1
' Add character to result String
LastLine = MyChar & LastLine
End If
Loop
MsgBox " 2nd last line is " & LastLine
答案 2 :(得分:0)
你可以试试这个:
Public Function GetSecondLastLine(sFileName As String, Optional sLineDelimiter As String = vbCrLf) As String
Dim sContent As String
Dim aLines() As String
sContent = TextFromFile(sFileName)
aLines = Split(sContent, sLineDelimiter)
GetSecondLastLine = aLines(UBound(aLines) - 1)
End Function
Public Function TextFromFile(sFileName As String) As String
Dim lFile As Long
lFile = FreeFile
Open sFileName For Input As #lFile
TextFromFile = Input$(LOF(lFile), lFile)
Close #lFile
End Function
如有必要,您可以更改行分隔符(例如vbLF的vbCR)