[英]Using formulas/VBA for parsing a length-delimited CSV file into 140 columns
在我的工作中,我必須每周進行一次清理原始數據文件的工作,以使其與特定格式匹配。
數據位於CSV文件中,因此一條記錄的所有數據都在一行中。 CSV如下所示:
每個記錄(行)必須分為140列。
一個CSV可以包含20,000多行。
該文件不是用符號定界的,而是每一列都是
在行數據字符串中使用特定數量的字符
具體長度。
列的分配空間不是恆定的。 姓氏列長於產品代碼列。
我們還需要在之后更改某些列的格式
輸入。 這就是為什么在代碼部分我為data(1)提供“ 00” +的原因。 我打算在以后的代碼中添加更多的代碼
相當快。
到目前為止,所使用的是一種簡單的方法,我們將CSV文件的內容轉儲到Sheet1的第一列中,然后Sheet2中的公式使用mid()函數來解析20,000多行數據並將其拆分為列。 (例如:= MID(Sheet1!$ A1,B $ 1,B $ 2),其中B $ 1和B $ 2包含此列的特定位置和長度)
但是,由於Sheet2實際上完全充滿了mid()公式,因此文件大小超過50 mb。 這使工作簿的處理速度變慢,並且已知大文件會崩潰。
對我來說,解析行的更好方法是使用VBA。 但是,我嘗試創建一個數組循環,該循環將解析一行,將值放入Sheet2,然后循環直到所有行都完成。 該代碼有效,但是當我嘗試使用23,943行數據時,它將計算機鎖定了11分鍾。
所以問題是:我是否堅持使用公式,我的代碼是否有問題,或者是否有解析此方法的有效方法?
這是我的代碼:
Option Explicit
Sub Attempt2()
Dim Data(1 To 140) As Variant
Dim shSource As Range
Dim i As Integer
Dim location As Integer
Dim Rows As Integer
Dim LastRow As Integer
LastRow = Worksheets("Sheet1").Range("A65536").End(xlUp).Row
For Rows = 1 To LastRow
'Set the source cell that is being parsed
Set shSource = Worksheets("Sheet1").Cells(Rows, 1)
'Array picks up all 140 values
Data(1) = "00" + Mid(shSource, 1, 2)
Data(2) = Mid(shSource, 3, 9)
Data(3) = Mid(shSource, 12, 16)
Data(4) = Mid(shSource, 28, 12)
Data(5) = Mid(shSource, 40, 1)
Data(6) = Mid(shSource, 41, 35)
Data(7) = Mid(shSource, 76, 19)
Data(8) = Mid(shSource, 95, 2)
Data(9) = Mid(shSource, 97, 5)
Data(10) = Mid(shSource, 102, 4)
Data(11) = Mid(shSource, 106, 8)
Data(12) = Mid(shSource, 114, 5)
Data(13) = Mid(shSource, 120, 5)
Data(14) = Mid(shSource, 125, 5)
location = 130
For i = 15 To 113
Data(i) = Mid(shSource, location, 6)
location = location + 6
Next i
Data(114) = Mid(shSource, 724, 3)
location = location + 3
For i = 115 To 118
Data(i) = Mid(shSource, location, 6)
location = location + 6
Next i
Data(119) = Mid(shSource, 751, 3)
location = location + 3
For i = 120 To 123
Data(i) = Mid(shSource, location, 6)
location = location + 6
Next i
Data(124) = Mid(shSource, 778, 3)
location = location + 3
For i = 125 To 140
Data(i) = Mid(shSource, location, 6)
location = location + 6
Next i
'Print one row
For i = 1 To 140
Worksheets("Sheet2").Cells(Rows + 1, i).Value = Data(i)
Next i
Next Rows
End Sub
謝謝您的幫助!
您可以通過關閉ScreenUpdating並將Application.Calculation設置為手動來加速代碼(完成后不要忘記將其重置為自動!)
也
(1)您正在為每個循環讀取輸入單元格值140次:更快地將值讀入變量,然后對該變量運行Mid()
調用
Dim v As String
v = Worksheets("Sheet1").Cells(Rows, 1).Value
Data(1) = "00" + Mid(v, 1, 2)
'etc
(2)將數組分配給工作表時,您可以在一行中完成以下操作:
Worksheets("Sheet2").Cells(Rows + 1, 1).Resize(1, 140).Value = Data
(無需循環)
一種更高級的方法是使用數組在內存中進行所有操作,但我首先將嘗試上述步驟,然后看看您會獲得什么樣的改進。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.