Import dữ liệu từ hàng loạt file text vào từng hàng ? (3 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Tôi sửa lại rồi đó bạn. T không để ý là chỉ lấy 3 số đầu.
hình như hết dung lượng tải file :S

cái phần Endrow là để chắc ăn cho việc có quá nhiều hàng so với tưởng tượng vì tôi hay có thói quen làm đến khoảng vài trăm đến đơn vị nghìn của row là kinh khủng lắm rồi :)

For Each mYfile In fSo.getfolder(myfoldEr).Files
If (mYfile Like "*.txt") Or (mYfile Like "*.TXT") Then


Open mYfile For Input As #1
endroW = Range("A" & Rows.Count - 1).End(xlUp).Row


k = 1
n = endroW
Do Until EOF(1)
Line Input #1, buf
n = n + 1
Range(Cells(n, 1), Cells(n, 4)).Value = Array(k, (Left(buf, 3)), (Right(buf, Len(buf) - InStr(buf, ","))), (Left(mYfile.Name, InStr(mYfile.Name, ".") - 1)))
k = k + 1
 
Lần chỉnh sửa cuối:
Tôi sửa lại rồi đó bạn. T không để ý là chỉ lấy 3 số đầu.
hình như hết dung lượng tải file :S

cái phần Endrow là để chắc ăn cho việc có quá nhiều hàng so với tưởng tượng vì tôi hay có thói quen làm đến khoảng vài trăm đến đơn vị nghìn của row là kinh khủng lắm rồi :)

Code này gán trực tiếp lên cell (dùng Range, Cells) thì xem như không ăn thua rồii. Cứ thử 1 file txt 60000 dòng sẽ biết
Nói chung: Dữ liệu lớn phải dùng mảng. Thậm chí còn phải suy nghĩ đến việc tối ưu hóa thuật toán mới mong "xơi tái" được
Và cũng vì muốn test tốc độ và tối ưu code nên tôi cần tác giã gửi lên một vài file có dung lượng lớn (60000 dòng chẳng hạn)... nếu không thì lấy cái gì mà test đây?
 
Lần chỉnh sửa cuối:
Tôi sửa lại rồi đó bạn. T không để ý là chỉ lấy 3 số đầu.
hình như hết dung lượng tải file :S

cái phần Endrow là để chắc ăn cho việc có quá nhiều hàng so với tưởng tượng vì tôi hay có thói quen làm đến khoảng vài trăm đến đơn vị nghìn của row là kinh khủng lắm rồi :)

Gửi dovanhoc84
Bạn có thể sửa lại code dùng GetOpenFilename không ?, vì như vậy mình có thể chọn được những file mình muốn lấy (hay quét chọn lấy tất cả) thay vì cứ chạy code là lấy toàn bộ file trong thư mục, mình nghĩ lấy như vậy sẽ hay hơn
Cám ơn dovanhoc84
 
Code này gán trực tiếp lên cell (dùng Range, Cells) thì xem như không ăn thua rồii. Cứ thử 1 file txt 60000 dòng sẽ biết
Nói chung: Dữ liệu lớn phải dùng mảng. Thậm chí còn phải suy nghĩ đến việc tối ưu hóa thuật toán mới mong "xơi tái" được
Và cũng vì muốn test tốc độ và tối ưu code nên tôi cần tác giã gửi lên một vài file có dung lượng lớn (60000 dòng chẳng hạn)... nếu không thì lấy cái gì mà test đây?

gửi anh ndu96081631 link tải file text

http://www.mediafire.com/download/8kujmhb2j2ktn6y/TEXTTONGHOP(2).txt

http://www.mediafire.com/download/1zttm9tml5o555e/TEXT10(2).txt

http://www.mediafire.com/download/uhuf54yg83lqkn1/TEXT11.txt

Cảm ơn anh rất nhiều
 
Lần chỉnh sửa cuối:

Kiểm tra file txt thấy có trên 700,000 dòng. Trong khi bảng tính Excel chỉ chứa tối đa 1,048,576 dòng. Vậy làm sao bạn có thể load NHIỀU FILE cùng lúc được đây? 2 file thôi đã quá số dòng quy định trong Excel rồi chứ đừng nói là NHIỀU
 
Kiểm tra file txt thấy có trên 700,000 dòng. Trong khi bảng tính Excel chỉ chứa tối đa 1,048,576 dòng. Vậy làm sao bạn có thể load NHIỀU FILE cùng lúc được đây? 2 file thôi đã quá số dòng quy định trong Excel rồi chứ đừng nói là NHIỀU

Gửi anh ndu9681631
File tổng hợp là file tổng hết tất cả các file nếu lấy thì ta chỉ lấy 1 file này thôi (hoặc 2 file còn lại là 2 file nhỏ cắt từ file tổng hợp có số dòng là 65534 dòng)
 
Gửi anh ndu96081631
File Tổng hợp là file tổng hêt hết tất cả các file nếu lấy thì ta chỉ lấy 1 file này là đủ
Các file còn lại là file text10, text11 cắt từ file tổng hợp ra (có tất cả 11 file này lận nhưng do mạng lúc vào được lúc không nên chỉ gửi nên 2 file đỡ)
Tóm lại nếu lấy vào thì ta chọn 1 trong 2 (lấy file ổng hợp hoặc lấy file nó cắt ra gồm 11 file có số dòng 65534 dòng)
 
trong lúc chờ đợi bạn có thể giải trí với nút hello trong file này
http://www.mediafire.com/download/s4ojyl2j5id32xk/read+Tex.rar

Đồng chí này siêu ADO nhỉ! Cở Hai Lúa chứ chẳng chơi!
Mình thì ngu môn này nên sẽ làm theo cách bình thường: Dùng FileSystemObject để đọc file txt
Cách bình thường mà người ta vẫn làm là đọc nội dung text, sau đó dùng Split với dấu phân cách là vbCrLf để chia ra từng dòng. Nhận thấy Split cho tốc độ kém với dữ liệu lớn nên mình sẽ chơi kiểu hơi "bất thường" chút
Mã:
Sub Main()
  Dim FSO As Object, ts As Object
  Dim txtFile, fName As String, sTmp As String
  Dim n As Long, lPos As Long, t As Double
  On Error GoTo ErrHandler
  txtFile = Application.GetOpenFilename("Text Files (*.txt), *.txt")
  If TypeName(txtFile) = "String" Then
    Set FSO = CreateObject("Scripting.FileSystemObject")
    If FSO.GetFile(txtFile).Size > 0 Then
      t = Timer
      fName = FSO.GetFile(txtFile).Name
      fName = Left(fName, Len(fName) - 4)
      Set ts = FSO.OpenTextFile(txtFile, 1)
      sTmp = ts.ReadAll
      ts.Close: Set ts = Nothing: Set FSO = Nothing
      If Left(sTmp, 2) <> vbCrLf Then sTmp = vbCrLf & sTmp
      If Right(sTmp, 2) <> vbCrLf Then sTmp = sTmp & vbCrLf
      Dim lPos1 As Long, lPos2 As Long
      lPos1 = InStr(1, sTmp, vbCrLf)
      lPos2 = InStr(1, sTmp, ",")
      If (lPos1 * lPos2) Then
        Dim arr(1 To 1000000, 1 To 4)
        Do While lPos2
          n = n + 1
          arr(n, 1) = n
          arr(n, 2) = Mid(sTmp, lPos1 + 2, 3)
          lPos1 = InStr(lPos2, sTmp, vbCrLf)
          arr(n, 3) = Mid(sTmp, lPos2 + 1, lPos1 - lPos2 - 1)
          arr(n, 4) = fName
          lPos2 = InStr(lPos1, sTmp, ",")
        Loop
        Application.ScreenUpdating = False
        If n Then Range("A1000000").End(xlUp).Offset(1).Resize(n, 4).Value = arr
        Application.ScreenUpdating = True
        MsgBox Timer - t, , n & " items"
      End If
    End If
  End If
  Exit Sub
ErrHandler:       MsgBox Err.Description
End Sub
Các bạn test giúp xem tốc độ ra sao nhé!
(lấy file TEXTTONGHOP(2).txt của tác giả để test)
 

File đính kèm

Lần chỉnh sửa cuối:
Đồng chí này siêu ADO nhỉ! Cở Hai Lúa chứ chẳng chơi!
Mình thì ngu môn này nên sẽ làm theo cách bình thường: Dùng FileSystemObject để đọc file txt
Cách bình thường mà người ta vẫn làm là đọc nội dung text, sau đó dùng Split với dấu phân cách là vbCrLf để chia ra từng dòng. Nhận thấy Split cho tốc độ kém với dữ liệu lớn nên mình sẽ chơi kiểu hơi "bất thường" chút
Mã:
Sub Main()
  Dim FSO As Scripting.FileSystemObject, ts As Object
  Dim txtFile, fName As String, sTmp As String
  Dim n As Long, lPos As Long, t As Double
  On Error GoTo ErrHandler
  .......................................

        MsgBox Timer - t, , n & " items"
      End If
    End If
  End If
  Exit Sub
ErrHandler:       MsgBox Err.Description
End Sub
Các bạn test giúp xem tốc độ ra sao nhé!
(lấy file TEXTTONGHOP(2).txt của tác giả để test)


Gửi anh ndu96081631
Code chạy rất nhanh chỉ mất có hơn 3 giấy một chút lấy được hơn 700.000 dòng
Nhưng code chỉ lấy có 1 file duy nhất, anh có thể sửa lại cho lấy nhiều file (tổng số dòng của các file không vượt qua con số 1.000.000 dòng) để dùng cho nhiều trường hợp được không anh
Cám ơn anh rất nhiều
 

File đính kèm

Lần chỉnh sửa cuối:
Gửi anh ndu96081631
Code chạy rất nhanh chỉ mất có hơn 3 giấy một chút lấy được hơn 700.000 dòng
Nhưng code chỉ lấy có 1 file duy nhất, anh có thể sửa lại cho lấy nhiều file (tổng số dòng của các file không vượt qua con số 1.000.000 dòng) để dùng cho nhiều trường hợp được không anh
Cám ơn anh rất nhiều

Cố nghiên cứu thử xem (có tí xíu thôi mà) --=0
-------------------------------
Tại lúc đầu bạn nói file tổng có 700,000 dòng nên tôi viết code "chắc ăn" luôn: không cho phép chọn nhiều file
 
Gửi anh ndu96081631
em sửa lại như vậy, nhưng đến cột stt (arr(n, 1) = n) thì không biết sửa làm sao, anh chỉ giùm em nha


Sub Main()
Dim FSO As Object, ts As Object
Dim txtFile, fName As String, sTmp As String
Dim n As Long, lPos As Long, t As Double, X As Long
On Error GoTo ErrHandler
txtFile = Application.GetOpenFilename("Text Files (*.txt), *.txt", , , , True)
t = Timer
For X = LBound(txtFile) To UBound(txtFile)
If TypeName(txtFile(X)) = "String" Then
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.GetFile(txtFile(X)).Size > 0 Then
fName = FSO.GetFile(txtFile(X)).Name
fName = Left(fName, Len(fName) - 4)
Set ts = FSO.OpenTextFile(txtFile(X), 1, , -2)
sTmp = ts.ReadAll
ts.Close: Set ts = Nothing: Set FSO = Nothing
If Left(sTmp, 2) <> vbCrLf Then sTmp = vbCrLf & sTmp
If Right(sTmp, 2) <> vbCrLf Then sTmp = sTmp & vbCrLf
Dim lPos1 As Long, lPos2 As Long
lPos1 = InStr(1, sTmp, vbCrLf)
lPos2 = InStr(1, sTmp, ",")
If (lPos1 * lPos2) Then
Dim arr(1 To 1000000, 1 To 4)
Do While lPos2
n = n + 1
arr(n, 1) = n
arr(n, 2) = Mid(sTmp, lPos1 + 2, 3)
lPos1 = InStr(lPos2, sTmp, vbCrLf)
arr(n, 3) = Mid(sTmp, lPos2 + 1, lPos1 - lPos2 - 1)
arr(n, 4) = fName
lPos2 = InStr(lPos1, sTmp, ",")
Loop
Application.ScreenUpdating = False
If n Then Range("A1000000").End(xlUp).Offset(1).Resize(n, 4).Value = arr
Application.ScreenUpdating = True
End If
End If
End If
Next
MsgBox Timer - t, , n & " items"
Exit Sub
ErrHandler: MsgBox Err.Description
End Sub
 
Gửi anh ndu96081631
em sửa lại như vậy, nhưng đến cột stt (arr(n, 1) = n) thì không biết sửa làm sao, anh chỉ giùm em nha

Sửa thành vầy thử xem:
Mã:
Sub Main()
  Dim FSO As Object, ts As Object
  Dim txtFile, fName As String, sTmp As String
  Dim n As Long, lPos As Long, t As Double, X As Long
  On Error GoTo ErrHandler
  txtFile = Application.GetOpenFilename("Text Files (*.txt), *.txt", , , , True)
  [COLOR=#ff0000]If TypeName(txtFile) = "Variant()" Then[/COLOR]
    [COLOR=#0000cd]Set FSO = CreateObject("Scripting.FileSystemObject")[/COLOR]
    t = Timer
    Application.ScreenUpdating = False
    For X = LBound(txtFile) To UBound(txtFile)
      If FSO.GetFile(txtFile(X)).Size > 0 Then
        fName = FSO.GetFile(txtFile(X)).Name
        fName = Left(fName, Len(fName) - 4)
        Set ts = FSO.OpenTextFile(txtFile(X), 1)
        sTmp = ts.ReadAll
        ts.Close: Set ts = Nothing
        If Left(sTmp, 2) <> vbCrLf Then sTmp = vbCrLf & sTmp
        If Right(sTmp, 2) <> vbCrLf Then sTmp = sTmp & vbCrLf
        Dim lPos1 As Long, lPos2 As Long
        lPos1 = InStr(1, sTmp, vbCrLf)
        lPos2 = InStr(1, sTmp, ",")
        If (lPos1 * lPos2) Then
          Dim arr(1 To 1000000, 1 To 4)
          [COLOR=#ff0000]n = 0[/COLOR]
          Do While lPos2
            n = n + 1
            arr(n, 1) = n
            arr(n, 2) = Mid(sTmp, lPos1 + 2, 3)
            lPos1 = InStr(lPos2, sTmp, vbCrLf)
            arr(n, 3) = Mid(sTmp, lPos2 + 1, lPos1 - lPos2 - 1)
            arr(n, 4) = fName
            lPos2 = InStr(lPos1, sTmp, ",")
          Loop
          If n Then Range("A1000000").End(xlUp).Offset(1).Resize(n, 4).Value = arr
        End If
      End If
    Next
    Application.ScreenUpdating = True
  End If
  MsgBox Timer - t, , n & " items"
  [COLOR=#0000cd]Set FSO = Nothing[/COLOR]
  Exit Sub
ErrHandler:   MsgBox Err.Description
[COLOR=#ff0000]Set FSO = Nothing[/COLOR]
End Sub
Lưu ý:
- Những chỗ màu đỏ là chỗ sửa lại hoặc thêm vào
- Những chỗ màu xanh là dời vị trí (code của bạn nó nằm không đúng)
- Cái chỗ If TypeName(txtFile) = "Variant()" Then khác với code cũ là vì: 1 file thì TypeName(...) = "String" nhưng nhiều file thì TypeName(...) = "Variant()"
- Set FSO = CreateObject("Scripting.FileSystemObject") phải nằm ngoài vòng lập --> Dẫn đến Set FSO = Nothing cũng nằm ngoài vòng lập
- Trước khi vào vòng lập Do.. phải cho n=0 chứ
-----------------------------------
Nói chung là: Bạn gần gần đến La Mã rồi đấy... Ẹc.. Ẹc...
Cố gắng lần sau nhé!
 
Lần chỉnh sửa cuối:
Gửi bạn doveandrose
Code của bạn không biết tại sao bị lỗi khi mình thử lấy file.txt này (file mình gửi kèm)
bạn tìm trong code có dòng
Mã:
rsArr(n, 2) = Left(arr(0, r), 3)
sửa lại thành
Mã:
rsArr(n, 2) = [COLOR=#ff0000][B]"'" & [/B][/COLOR]Left(arr(0, r), 3)
 
Sửa thành vầy thử xem:
Lưu ý:
- Những chỗ màu đỏ là chỗ sửa lại hoặc thêm vào
- Những chỗ màu xanh là dời vị trí (code của bạn nó nằm không đúng)
- Cái chỗ If TypeName(txtFile) = "Variant()" Then khác với code cũ là vì: 1 file thì TypeName(...) = "String" nhưng nhiều file thì TypeName(...) = "Variant()"
- Set FSO = CreateObject("Scripting.FileSystemObject") phải nằm ngoài vòng lập --> Dẫn đến Set FSO = Nothing cũng nằm ngoài vòng lập
- Trước khi vào vòng lập Do.. phải cho n=0 chứ
-----------------------------------
Nói chung là: Bạn gần gần đến La Mã rồi đấy... Ẹc.. Ẹc...
Cố gắng lần sau nhé!

Gửi anh ndu96081631
cho em hỏi anh câu hỏi cuối cùng trong đề tài này, anh có thể giải thích code trên giùm em được không ?, em rất muốn hiểu rõ giải thuật của code trên vì chỉ có hiểu rõ thì mới có thể sử dụng tốt được.
Cảm ơn anh đã giúp đỡ
 
Gửi anh ndu96081631
cho em hỏi anh câu hỏi cuối cùng trong đề tài này, anh có thể giải thích code trên giùm em được không ?, em rất muốn hiểu rõ giải thuật của code trên vì chỉ có hiểu rõ thì mới có thể sử dụng tốt được.
Cảm ơn anh đã giúp đỡ

Biết giải thích sao đây ta? Nói ngắn gọn thế này:
- Sau khi ReadAll toàn bộ dữ liệu trong file txt, ta được sTmp (sTmp = ts.ReadAll)
- Tiếp theo, dùng 2 biến lPos1lPos2 để lấy vị trí của dấu xuống dòng (vbCrLf) và dấu phẩy
- Dựa vào lPos1, ta lấy được giá trị cho cột B (lấy 3 ký tự)
- Di dời lPos1 để lấy vị trí vbCrLf tiếp theo rồi lấy giá trị số sau dấu phẩy
- Cứ thế tiếp tục đến khi nào không tìm thấy dấu phẩy nữa thì ngưng

------------------------
Công việc gần tương tự như trên bảng tính ta dùng hàm FIND để tìm vị trí rồi dùng hàm MID để lấy giá trị vậy (dựa vào vị trí tìm được của FIND)
Ôi! Lòng vòng quá, nói xong cũng không biết có ai hiểu không nữa. Ẹc... Ẹc...
 
Web KT

Bài viết mới nhất

Back
Top Bottom