【问题标题】:How can I Count the number of columns in a .txt file in VBA如何计算 VBA 中 .txt 文件中的列数
【发布时间】:2021-10-14 22:47:38
【问题描述】:

我正在尝试使用宏来计算 .txt 文件的列数。我的代码需要永远运行,罪魁祸首就是这段代码

Set wb = Workbooks.Open(FName)
            Dim lastColumn As Integer
            Dim rng As Range
            Set rng = wb.Worksheets(1).Cells
            lastColumn = rng.Find(What:="*", After:=rng.Cells(1), Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False).Column
    wb.Close False

基本上我打开我认为的 .txt 文件,计算它们,将其存储在一个值中,然后关闭它,这需要很长时间,有没有更好的方法来做到这一点?

【问题讨论】:

  • 你说的是 CSV 吗?比如一行有多少个逗号?
  • 它不是逗号分隔,而是制表符分隔,大约有 930 列和 12,000 行,未来可能会发生变化。
  • 请找出“永远”的部分。因此,使用 F8 逐步运行此代码。看看哪个代码行需要这么长时间。可能打开文件需要很长时间,然后该代码没有问题,然后打开文件只需要那个时间。请检查打开文件Set wb = Workbooks.Open(FName) 是否需要很长时间或lastColumn = rng.Find 是否需要很长时间或wb.Close False
  • 您可能会发现以下链接中的 ImportCSV 函数很容易适应您的列号:stackoverflow.com/questions/68545448/…

标签: excel vba import


【解决方案1】:

我喜欢在晨练中解决这些类型的事情,所以我创建了一个函数来计算“csv”的列数,而无需将文件打开到 excel 应用程序中。

VBA 具有 I/O 接口,允许它打开文本文件而无需花费过多资源将其作为工作簿加载到应用程序中。使用这种方法应该比Workbooks.Open快很多。

要将其从“csv”更改为制表符分隔,请将 SEPARATOR 更改为您文件的特定字符。

Sub test2() 'Example usage of the function
    Const FilePath As String = "C:\Users\Me\Desktop\Book1.csv"
    MsgBox CSVColumnCount(FilePath)
End Sub

Function CSVColumnCount(FileName As String, Optional CheckAll As Boolean = True) As Long
    Const SEPARATOR As String = ","
    
    Dim FileNum As Long
    FileNum = FreeFile
    
    Open FileName For Input As #FileNum
    
    Dim LineText As String, ColCount As Long, LineCol As Long

    Do While Not EOF(FileNum)
        Line Input #FileNum, LineText
        LineCol = CountOccur(SEPARATOR, LineText) + 1
        If LineCol > ColCount Then ColCount = LineCol
        If Not CheckAll Then Exit Do
    Loop
    CSVColumnCount = ColCount
    Close FileNum
End Function
Function CountOccur(look_for As String, within_text As String, Optional CompareMethod As VbCompareMethod = vbBinaryCompare) As Long
    'Count the number of times the given string appears within the larger text body.
    Dim Count As Long, Start As Long
    While InStr(Start + 1, within_text, look_for, CompareMethod) <> 0
        Start = InStr(Start + 1, within_text, look_for, CompareMethod)
        Count = Count + 1
    Wend
    CountOccur = Count
End Function

我让函数检查每行的长度并报告最大值,因为我认为可能存在短行或长行,但我意识到大多数“csv”类型文件不应该是这种情况。所以我添加了一个只检查第一行的选项。

【讨论】:

  • in CountOccur 而不是耗时的循环,只需用 vbnullstring (无)替换分隔符并比较长度:CountOccur = (Len(within_text) - Len(Replace$(within_text, look_for, vbNullString))) / Len(look_for) 会快得多(并且您需要的唯一代码行在这个函数中)并且对于大多数分隔符CompareMethod 无论如何都无关紧要。
  • 或者使用拆分CountOccur = Ubound(Split(within_text,look_for))+1?
  • 之后需要关闭文件吗?
  • 根据文本文件数据的情况(例如,如果每行中都有所有分隔符,无论列中是否有数据),计算分隔符可能就足够了第一行(而不是所有行)。会让它更快。
  • 值得注意的是,至少对于 CSV,值包含要引用的逗号的字段是必需的,例如 "hello, Jim",因此您也需要考虑这一点...
【解决方案2】:

您也可以使用 ADO 进行调查。

Function ColumnCount(strPath As String, strFileName As String) As Long

Dim c As New ADODB.Connection
Dim r As New ADODB.Recordset

c.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strPath & ";Extended Properties='text;HDR=Yes;FMT=Delimited';"
c.Open

r.Open "select * from [" & strFileName & "]", c

ColumnCount = r.Fields.Count

r.Close
c.Close

Set c = Nothing
Set r = Nothing

End Function

像这样调用ColumnCount("c:\dev","test_csv.csv") 可以做一些工作来检查文件是否存在,拆分路径等。只是一个想法。

【讨论】:

    猜你喜欢
    • 2012-09-26
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    相关资源
    最近更新 更多