Tìm số Cột trong file Text bằng VBA (1 người xem)

Liên hệ QC

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

thnghiachau

Chỉ biết ngồi BÈ và PHÁN chuyện!!!
Tham gia
14/9/09
Bài viết
844
Được thích
710
Giới tính
Nam
Nghề nghiệp
Search
Chào GPE,
Xin cho hỏi có cách nào để xác định File text có bao nhiêu cột như trong tập tin đính kèm bằng VBA không ạ?
Ví dụ trong tập tin đính kèm là có 10 cột.
Xin cám ơn.
 

File đính kèm

Tôi chưa xem tập tin của bạn. Tôi trả lời theo tin tưởng là bạn đã giải thích vấn đề mạch lạc, không có uẩnn khúc "nhưng mà..."
Có hai cách để thực hiện, tuỳ theo tập tin lớn hay vừa phải.
1. nếu không lớn lắm thì dùng cách stream cả file vào một string. Sau đó dùng vbCRLF để split string ra thành từng dòng. Tìm số dấu phẩy. Lấy Max
2. nếu tập tin lớn thì bắt buộc phải đọc từng dòng.

Mở file bằng FileSSystemObject cũng được mà mở theo channel thì giản dị hơn.
Đại khái:
Dim fName As String, sLine As String
Dim cMax As Long, cCur As Long
strFile = "C:\Test\abcdef.txt"
Open fName For Input As #1
Do Until EOF(1)
Line Input #1, sLine
cCur = Len(sLine) - Len(Replace(sLine, ",", "")) + 1
If cCur > cMax Then cMax = cCur
Loop
Close #1
' cMax là số cột

Nếu trong dữ liệu có dấu phẩy thì hơi rắc rối hơn. Phải dùng RegEx để duyệt chuỗi.
 
Upvote 0
Tôi chưa xem tập tin của bạn. Tôi trả lời theo tin tưởng là bạn đã giải thích vấn đề mạch lạc, không có uẩnn khúc "nhưng mà..."
Có hai cách để thực hiện, tuỳ theo tập tin lớn hay vừa phải.
1. nếu không lớn lắm thì dùng cách stream cả file vào một string. Sau đó dùng vbCRLF để split string ra thành từng dòng. Tìm số dấu phẩy. Lấy Max
2. nếu tập tin lớn thì bắt buộc phải đọc từng dòng.

Mở file bằng FileSSystemObject cũng được mà mở theo channel thì giản dị hơn.
Đại khái:
Dim fName As String, sLine As String
Dim cMax As Long, cCur As Long
strFile = "C:\Test\abcdef.txt"
Open fName For Input As #1
Do Until EOF(1)
Line Input #1, sLine
cCur = Len(sLine) - Len(Replace(sLine, ",", "")) + 1
If cCur > cMax Then cMax = cCur
Loop
Close #1
' cMax là số cột

Nếu trong dữ liệu có dấu phẩy thì hơi rắc rối hơn. Phải dùng RegEx để duyệt chuỗi.
Mở file xem cấu trúc dữ liệu sẽ té ngửa :)
Chào GPE,
Xin cho hỏi có cách nào để xác định File text có bao nhiêu cột như trong tập tin đính kèm bằng VBA không ạ?
Ví dụ trong tập tin đính kèm là có 10 cột.
Xin cám ơn.
Làm sao biết 10 cột?
 
Upvote 0
Đúng là 10 cột thật!
 
Upvote 0
Chào GPE,
Xin cho hỏi có cách nào để xác định File text có bao nhiêu cột như trong tập tin đính kèm bằng VBA không ạ?
Ví dụ trong tập tin đính kèm là có 10 cột.
Xin cám ơn.
Em bon chen tý, bác thử xem:
Mã:
Option Explicit

Public Function co_lùm(ByVal sPath As String, ByVal sBookName As String) As Integer
    Dim sFileName As String, book As Workbook
    sFileName = sPath & "\" & sBookName
    Call Workbooks.OpenText(sFileName, Origin:=65001, Tab:=True, Comma:=False, Semicolon:=False)
    Set book = Workbooks(Workbooks.Count)
    co_lùm = book.Worksheets(1).UsedRange.Columns.Count
    book.Close False
End Function
Sub tét()
    Dim i As Integer
    i = co_lùm("C:\Users\N\Downloads", "abcdef.txt")
    MsgBox i
End Sub
 
Upvote 0
1648707998200.png
10 cột là như thế ah.
Vì nó "lạ" nên em code không ra ... hic
Bài đã được tự động gộp:

Em bon chen tý, bác thử xem:
Mã:
Option Explicit

Public Function co_lùm(ByVal sPath As String, ByVal sBookName As String) As Integer
    Dim sFileName As String, book As Workbook
    sFileName = sPath & "\" & sBookName
    Call Workbooks.OpenText(sFileName, Origin:=65001, Tab:=True, Comma:=False, Semicolon:=False)
    Set book = Workbooks(Workbooks.Count)
    co_lùm = book.Worksheets(1).UsedRange.Columns.Count
    book.Close False
End Function
Sub tét()
    Dim i As Integer
    i = co_lùm("C:\Users\N\Downloads", "abcdef.txt")
    MsgBox i
End Sub
ý kiến này khá là "hay" đây...
nhưng mà phải mượn tạm open workbook excel...
Bài đã được tự động gộp:

Tôi chưa xem tập tin của bạn. Tôi trả lời theo tin tưởng là bạn đã giải thích vấn đề mạch lạc, không có uẩnn khúc "nhưng mà..."
Có hai cách để thực hiện, tuỳ theo tập tin lớn hay vừa phải.
1. nếu không lớn lắm thì dùng cách stream cả file vào một string. Sau đó dùng vbCRLF để split string ra thành từng dòng. Tìm số dấu phẩy. Lấy Max
2. nếu tập tin lớn thì bắt buộc phải đọc từng dòng.

Mở file bằng FileSSystemObject cũng được mà mở theo channel thì giản dị hơn.
Đại khái:
Dim fName As String, sLine As String
Dim cMax As Long, cCur As Long
strFile = "C:\Test\abcdef.txt"
Open fName For Input As #1
Do Until EOF(1)
Line Input #1, sLine
cCur = Len(sLine) - Len(Replace(sLine, ",", "")) + 1
If cCur > cMax Then cMax = cCur
Loop
Close #1
' cMax là số cột

Nếu trong dữ liệu có dấu phẩy thì hơi rắc rối hơn. Phải dùng RegEx để duyệt chuỗi.
Cám ơn Bác nhiều...
nhưng mà hình như con không áp dụng với cái file text dang này thì phải... hic
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu như cần xác định lấy dữ liệu cột nào thì theo cách của bạn @Ngày mai trời lại sáng không thể được thì phải?
Mình có cách nào để xác định:
1/ số cột
2/ độ dài mỗi cột (trừ cột cuối) - có nghĩa là mỗi cột có bao nhiêu ký tự từ đầu cột tới điểm cuối và bắt đầu cột kế tiếp?
1648709648732.png
 
Upvote 0
10 cột là như thế ah.
Vì nó "lạ" nên em code không ra ... hic
File này phân cách cột bằng các khoảng trắng, không phải Tab, không phải dấu phẩy nên dùng kiểu của anh Vetmini không ra. Tôi thường dùng cách của Vetmini (dùng FreeFile) đối với file Text (CSV), nhưng dạng này thì chưa ra.

Screen Shot 2022-03-31 at 13.56.05.png
 
Upvote 0
Có làm sao đâu bạn.
Khai báo 2 danh sách: vị trí bắt đầu, và số lượng ký tự. Vậy là được.
để được như vậy thì phải thêm "điều kiện" để biết được khi nào là bắt đầu cột khác... Bởi vì trong một cột, dữ liệu có thể có khoảng trắng chèn vào!
Hazzz... vậy mình chắc phải qui định ít nhất là 2 khoảng trắng cuối cột trước khi vào cột mới?
 
Upvote 0
để được như vậy thì phải thêm "điều kiện" để biết được khi nào là bắt đầu cột khác... Bởi vì trong một cột, dữ liệu có thể có khoảng trắng chèn vào!
Hazzz... vậy mình chắc phải qui định ít nhất là 2 khoảng trắng cuối cột trước khi vào cột mới?
Theo kiểu mà befaint gợi ý ở bài #10, tôi nhớ là trước đây cũng có một bài như vậy và nó ở link này. Link.
Bạn xem và chỉnh sửa lại. File của bạn đơn giản hơn file trong bài trên.
 
Upvote 0
File này phân cách cột bằng các khoảng trắng, không phải Tab, không phải dấu phẩy nên dùng kiểu của anh Vetmini không ra. Tôi thường dùng cách của Vetmini (dùng FreeFile) đối với file Text (CSV), nhưng dạng này thì chưa ra.

View attachment 273816
Anh dùng option gì trong Notepad++ để hiện thị thay thế "khoảng trắng" vậy.
Em tìm thấy rồi. Chắc lại bị la chưa tìm hiểu mà đã hỏi :D
1648712150626.png
 
Upvote 0
Mã:
Function TotalColumn(ByVal strFullNameTextFile As String) As integer
Const FORREADING = 1
Dim strLineText As String
Dim i As Long
Dim objDic As Object

    Set objDic = CreateObject("Scripting.Dictionary")
    objDic.Add 1, "" '1stPos of Col
    With CreateObject("Scripting.FileSystemObject").OpenTextFile(strFullNameTextFile, FORREADING)
        Do While .AtEndOfStream <> True
            strLineText = .ReadLine
            ' Get Pos of Column of Existing Text File => size of Column
            i = 3
            Do While i <= Len(strLineText)
                If Mid(strLineText, i - 2, 2) = "  " And Mid(strLineText, i, 1) <> " " Then
                    If Not objDic.Exists(i) Then objDic.Add i, ""
                End If
                i = i + 1
            Loop
        Loop
        .Close
    End With
    TotalColumn = objDic.Count
   
End Function

Có lẽ là vậy theo bác @befaint nhỉ...
 
Lần chỉnh sửa cuối:
Upvote 0
Có lẽ là vậy theo bác @befaint nhỉ...

Những file dạng này sẽ có cấu trúc cố định. Phân tích cấu trúc rồi mình xử lý lấy dữ liệu.
Việc phân tích chỉ làm duy nhất 1 lần, làm trước khi viết code.
Có kết quả phân tích rồi thì mình viết code xử lý dữ liệu thôi.
Và nội dung trên mình nêu là để xử lý lấy dữ liệu, chứ viết code đếm cột làm gì. @@
 
Upvote 0
Và nội dung trên mình nêu là để xử lý lấy dữ liệu, chứ viết code đếm cột làm gì. @@
Dạ, Em muốn từ việc "biết cách tìm số cột" mà mình sẽ tìm ra ý tưởng cho việc lấy dữ liệu ah.
và code em làm trên là e đã tìm được từng vị trí đầu tiên của cột! và dễ dàng lấy dữ liệu bất cứ đâu!!
Cám ơn anh nhiều
Bài đã được tự động gộp:

Theo kiểu mà befaint gợi ý ở bài #10, tôi nhớ là trước đây cũng có một bài như vậy và nó ở link này. Link.
Bạn xem và chỉnh sửa lại. File của bạn đơn giản hơn file trong bài trên.
Cám ơn anh, em coi code trong bài anh gởi đã ra cái em muốn rồi ah...
 
Upvote 0
Mở file xem cấu trúc dữ liệu sẽ té ngửa :)

Làm sao biết 10 cột?
Muốn phân tích file text thì phải biết trước delimiter của cacxs trường là gì. Ở trên, tôi chỉ minh hoạ điển hình nếu nó là dấu phẩy.

Cái này cho vào Python chạy ngon.
Python có nhiều dính dáng đến Unix. Trong Unix, Lisp và Perl xử lý text rất êm.
Tuy nhiên, đối với dân giỏi PowerShell thì cũng êm không kém.

File này phân cách cột bằng các khoảng trắng, không phải Tab, không phải dấu phẩy nên dùng kiểu của anh Vetmini không ra. Tôi thường dùng cách của Vetmini (dùng FreeFile) đối với file Text (CSV), nhưng dạng này thì chưa ra.
...
Tôi có nói, nếu dạng phức tạp thì phải dùng RegEx để tính.
Ví dụ nếu 2 khoảng trắng trở lên xác định là phân cách giữa 2 cột thì RegEx có thể nhận ra chúng dễ dàng.

@Thớt: nếu không bắt buộc phải dùng FileSystemObject thì không nên dùng. Mở file bằng đường lối channel truyền thống ít lệ thuộc vào hệ thống điều hành.
 
Upvote 0
@Thớt: nếu không bắt buộc phải dùng FileSystemObject thì không nên dùng. Mở file bằng đường lối channel truyền thống ít lệ thuộc vào hệ thống điều hành.
Khi sử dụng FileSystemObject thì data từng hàng sẽ OK
1648720126656.png

nhưng khi dùng Open strFullNameTextFile For Input As #iFileNumber thì data sẽ bị "trim" mất dẫy khoảng trắng đầu...
1648720241506.png
 
Upvote 0
Upvote 0
Người ta dùng Line Input, bạn sửa thành Input rồi kêu ca. Bạn chuyển lại về Line Input xem sao.

View attachment 273832
Dạ... Cám ơn Bác nhiều...
Đúng là con sai rồi ah....
Nhân tiện cho con hỏi thêm: Nếu muốn mở file text (UNICODE) thì câu lệnh
Open strFullNameTextFile For Input As #1
mình phải chỉnh lại như thế nào ah?
Cám ơn Bác nhiều
 
Upvote 0
Dạ... Cám ơn Bác nhiều...
Đúng là con sai rồi ah....
Nhân tiện cho con hỏi thêm: Nếu muốn mở file text (UNICODE) thì câu lệnh
Open strFullNameTextFile For Input As #1
mình phải chỉnh lại như thế nào ah?
Cám ơn Bác nhiều
Trong công việc bạn phải giải quyết nhiều vấn đề, chọn phương pháp nào là do bạn quyết định, không ai bắt bạn phải dùng phương pháp này hay cấm dùng phương pháp kia.

Nếu là tôi tôi sẽ dùng Open của VBA trong các trường hợp đơn giản. Trong trường hợp unicoded thì tôi dùng CreateObject với FileSystemObject. Nếu cứ cố tình làm khổ mình thì tôi có lẽ dùng Open nhưng với mode = Binary.

Open sFile For Binary As #1

Lúc này dùng Get để đọc dữ liệu. Có lẽ phải đọc toàn bộ. Sau đó nếu muốn chia thành từng dòng, mỗi dòng chia theo từng đoạn ngăn cách bởi dấu phẩy, chấm phẩy hay gì đó thì phải tự làm, vd. dùng Instr để tìm chỗ phân cách. Nếu bạn muốn vọc thì thử xem.

Dùng FileSystemObject cũng giải quyết được công việc thì chả lý gì lại cứ phải Open của VBA. Trừ phi phải thi thố, đố nhau kiểu: dùng ít FOR nhất, code ít chữ nhất, không được dùng FileSystemObject. Nếu thế thì bạn chờ người khác.
 
Upvote 0
Trong công việc bạn phải giải quyết nhiều vấn đề, chọn phương pháp nào là do bạn quyết định, không ai bắt bạn phải dùng phương pháp này hay cấm dùng phương pháp kia.

Nếu là tôi tôi sẽ dùng Open của VBA trong các trường hợp đơn giản. Trong trường hợp unicoded thì tôi dùng CreateObject với FileSystemObject. Nếu cứ cố tình làm khổ mình thì tôi có lẽ dùng Open nhưng với mode = Binary.

Open sFile For Binary As #1

Lúc này dùng Get để đọc dữ liệu. Có lẽ phải đọc toàn bộ. Sau đó nếu muốn chia thành từng dòng, mỗi dòng chia theo từng đoạn ngăn cách bởi dấu phẩy, chấm phẩy hay gì đó thì phải tự làm, vd. dùng Instr để tìm chỗ phân cách. Nếu bạn muốn vọc thì thử xem.

Dùng FileSystemObject cũng giải quyết được công việc thì chả lý gì lại cứ phải Open của VBA. Trừ phi phải thi thố, đố nhau kiểu: dùng ít FOR nhất, code ít chữ nhất, không được dùng FileSystemObject. Nếu thế thì bạn chờ người khác.
Con xin cám ơn Bác đã hướng dẫn.
Vì mấy nay con đang nghiên cứu cái dụ Text File này nên con mới tìm hiểu mọi vấn đề có thể xẩy ra mà con có thể biết về nó.
Về FileSystemObject con đã tim hiểu được về cái dụ Unicode này, còn Open thì con tìm mà chưa ra ah.
Đúng như Bác nói, khi mình sử dụng thì tùy theo cái mà mình làm mà cân nhắc dùng cái nào thì tốt hơn. Mà muốn đựợc thế thì phải hiểu rõ hết các loại mới biết dùng cái nào.
Đôi lúc mình muốn tìm hiểu về vấn đề nào đó thì cái quan trong là mình phải biết "Key Word", như vấn đề con hỏi thì Bác đã cho con cái key word là BINARY trong open... và con sẽ tìm hiểu về nó ah.

ah, bên Bác có "nghe ầm ầm từ Ukraine không vậy?
 
Upvote 0
...

Dùng FileSystemObject cũng giải quyết được công việc thì chả lý gì lại cứ phải Open của VBA. Trừ phi phải thi thố, đố nhau kiểu: dùng ít FOR nhất, code ít chữ nhất, không được dùng FileSystemObject. Nếu thế thì bạn chờ người khác.
Ở trên tôi có nói là FileSystemObject là công cụ của Wondows Script.
Đọc file qua channel truyền thống là để tránh phụ thuộc vào nền tảng.
Điển hình, máy Mac của tôi không chạy được những code sử dụng API/ActiveX.
 
Upvote 0
ah, bên Bác có "nghe ầm ầm từ Ukraine không vậy?
Từ chỗ tôi không nghe thấy. Nói thực ra thì anh hàng xóm của người ta có thể là ân nhân đối với nhiều người. Nhưng mình cứ nghĩ tới năm 1979 khi mà nhà cửa, trường học, bệnh viện của mình bị dội bom, người mình bị giết ... Nếu mình có chút đồng cảm thì không bao giờ mình cười trên đau khổ của người khác. Họ cũng có hàng xóm như mình.

Ở trên tôi có nói là FileSystemObject là công cụ của Wondows Script.
Đọc file qua channel truyền thống là để tránh phụ thuộc vào nền tảng.
Điển hình, máy Mac của tôi không chạy được những code sử dụng API/ActiveX.
Không có chỗ nào tôi nói là BẮT BUỘC phải dùng FileSystemObject. Tôi chỉ nói là nếu tôi thì tôi dùng. Còn ai đó không thể dùng mà cứ phải bắt buộc Open thì tôi cũng chỉ ra là làm được. Nhưng vất vả thêm thôi. Chứ nói như bác thì ta tìm tất cả các code trên GPE mà dùng FileSystemObject rồi khuyên mọi người chuyển sang channel truyền thống?
 
Lần chỉnh sửa cuối:
Upvote 0
... Chứ nói như bác thì ta tìm tất cả các code trên GPE mà dùng FileSystemObject rồi khuyên mọi người chuyển sang channel truyền thống?
Bác quên rằng tôi là tín đồ của "If it ain't broke, don't fix it".
Hơi đâu mà lôi đồ cũ ra sửa lại.
 
Upvote 0
Upvote 0
Té ra anh @batman1 nhầm. Lão này xúi thật chứ chẳng có "chả lẽ" gì sất.
 
Upvote 0
Upvote 0
... Nếu mình có chút đồng cảm thì không bao giờ mình cười trên đau khổ của người khác. Họ cũng có hàng xóm như mình.
Bác nói đúng. Con rất là ghét chiến tranh dù là bất cứ lý do nào... nhưng mình là "dân đen" thì không dám nói chính trị vậy... hic
 
Upvote 0

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

Back
Top Bottom