簡體   English   中英

使用公式/ VBA將長度分隔的CSV文件解析為140列

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM