在我的工作中,我必须每周清理原始数据文件,使其与特定表格相匹配。
数据以CSV文件形式存在,因此一条记录的所有数据都在一行上。 CSV的样子:
每条记录(行)必须拆分为140列。
一个CSV中可以有超过20,000行。
文件不是用符号分隔的,而是每列都是一个 特定的字符数与行数据字符串的对应 特定长度。
列的指定空间不是常量。姓氏列是 比产品代码列长。
我们还需要在更改后更改某些列的格式 输入。这就是为什么在代码部分我对数据(1)有“00”+。一世 如果我得到代码工作,计划稍后添加更多 相当快。
到目前为止使用的是一种简单的方法,我们将CSV文件内容转储到Sheet1的第一列,然后Sheet2中的公式使用mid()函数来解析20,000多行数据并将其拆分为列。 (例如:= MID(Sheet1!$ A1,B $ 1,B $ 2),其中B $ 1和B $ 2包含此列的具体位置和长度)
但是,由于Sheet2实际上完全充满了mid()公式,因此文件大小超过50 MB。这使得Workbook工作缓慢,并且已知它会因大文件而崩溃。
对我来说,解析行的更好方法是使用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
感谢您的帮助!
答案 0 :(得分:0)
您可以通过关闭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
(无需循环)
更高级的方法是使用数组在内存中进行各种操作,但我首先尝试上面的步骤,看看你得到了什么样的改进。