Tổng hợp file .txt từ nhiều Folders vào file Excel (1 người xem)

Liên hệ QC

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

baquang1984

Thành viên tiêu biểu
Tham gia
3/6/10
Bài viết
429
Được thích
44
Nghề nghiệp
Kỹ sư Lâm nghiệp
Em chào thầy, cô và các anh chị trên diễn đàn GPE
Do công việc của em cần tổng hợp nhiều file .txt có cấu trúc giống nhau từ các thành viên gửi về mỗi thành viên là một Folder. Do vậy nhờ thầy, cô và anh chị trên diễn đàn viết giúp em chương trình VBA để tổng hợp các file .txt này từ các Folder vào file Excel ạ
Yêu cầu của chương trình là khi chọn vào Buttom TỔNG HỢP chương trình sẽ cho phép chọn nhiều Folder chứa các file .txt cần tổng hợp, khi chọn xong chương trình tổng hợp theo yêu cầu sau:
Ở cột A "Tên Folder" chương trình sẽ ghi lần lượt tên Folder chứa file cần tổng hợp vào cột này khi tổng hợp
Ở cột B "Tên File" chương trình sẽ ghi lần lượt tên File chữa dữ liệu cần tổng hợp vào cột này khi tổng hợp
Ở cột C "Số TT", Cột D "X", Cột E "Y" chương trình tổng hợp và ghi dữ liệu có trong các file vào
Như file mẫu em gửi kèm ạ
Em cảm ơn thầy, cô và các anh chị trên diễn đàn nhiều ạ
 

File đính kèm

Không đệ quy vào trong các folder, vào hết các subfolders để lấy hết các txt files hả bạn ? Chỉ chọn nhiều folder thôi rồi lấy txt files trong các folder đó ?
 
Upvote 0
Không đệ quy vào trong các folder, vào hết các subfolders để lấy hết các txt files hả bạn ? Chỉ chọn nhiều folder thôi rồi lấy txt files trong các folder đó ?
Vâng ạ. Chương trình chỉ cần cho phép chọn các thư mục chứa các file cần tổng hợp và thực hiện tổng hợp thôi ạ
 
Lần chỉnh sửa cuối:
Upvote 0
Mong được sự giúp đỡ của thầy, cô và anh chị trên diễn đàn ạ :victory::victory::victory::victory::victory::victory::victory::victory:
 
Upvote 0
Tự code đi bạn, mày mò tới đâu hay tới đó, kẹt thì up code đã làm lên. Chứ sao nhờ 100% người khác được bạn.
Bạn ở Bắc Giang mà có data của Đakrong hay vậy ?
 
Upvote 0
Tự code đi bạn, mày mò tới đâu hay tới đó, kẹt thì up code đã làm lên. Chứ sao nhờ 100% người khác được bạn.
Bạn ở Bắc Giang mà có data của Đakrong hay vậy ?
Em thì không biết nhiều về Code VBA do vậy em không thể tự code được chương trình tổng hợp từ nhiều Folder. Chủ yếu là nhờ thầy, cô và anh chị trên diễn đàn viết giúp sau đó vận dụng vào thực tiễn công việc của mình
Em cảm ơn anh ạ
 
Upvote 0
Cân nhắc, suy nghỉ các yêu cầu hết rồi post lên 1 lần luôn đi bạn. Chứ tui ngán các kiểu hỏi liên tu hồi tận, không kết thúc lắm. Làm A xong hỏi B, làm B xong hỏi C...
 
Upvote 0
Cân nhắc, suy nghỉ các yêu cầu hết rồi post lên 1 lần luôn đi bạn. Chứ tui ngán các kiểu hỏi liên tu hồi tận, không kết thúc lắm. Làm A xong hỏi B, làm B xong hỏi C...
Yêu cầu của chương trình em đã giải thích đầy đủ ở #1 mà anh mong anh viết giúp chương trình ạ
 
Upvote 0
Em chào thầy, cô và các anh chị trên diễn đàn GPE
Do công việc của em cần tổng hợp nhiều file .txt có cấu trúc giống nhau từ các thành viên gửi về mỗi thành viên là một Folder. Do vậy nhờ thầy, cô và anh chị trên diễn đàn viết giúp em chương trình VBA để tổng hợp các file .txt này từ các Folder vào file Excel ạ
Yêu cầu của chương trình là khi chọn vào Buttom TỔNG HỢP chương trình sẽ cho phép chọn nhiều Folder chứa các file .txt cần tổng hợp, khi chọn xong chương trình tổng hợp theo yêu cầu sau:
Ở cột A "Tên Folder" chương trình sẽ ghi lần lượt tên Folder chứa file cần tổng hợp vào cột này khi tổng hợp
Ở cột B "Tên File" chương trình sẽ ghi lần lượt tên File chữa dữ liệu cần tổng hợp vào cột này khi tổng hợp
Ở cột C "Số TT", Cột D "X", Cột E "Y" chương trình tổng hợp và ghi dữ liệu có trong các file vào
Như file mẫu em gửi kèm ạ
Em cảm ơn thầy, cô và các anh chị trên diễn đàn nhiều ạ
vấn đề chọn nhiều folders khó à nha, thầy chỉ cho chọn nhiều files thôi
 
Upvote 0
Yêu cầu của chương trình em đã giải thích đầy đủ ở #1 mà anh mong anh viết giúp chương trình ạ
Nếu chịu khó mày mò thì bài viết này có thể đáp ứng được yêu cầu của bạn. Bạn tham gia GPE cũng đã khoảng 10 năm sao không tự nghiên cứu để tự xử lý những yêu cầu công việc của mình cho khỏe.
 
Upvote 0
Nếu chịu khó mày mò thì bài viết này có thể đáp ứng được yêu cầu của bạn. Bạn tham gia GPE cũng đã khoảng 10 năm sao không tự nghiên cứu để tự xử lý những yêu cầu công việc của mình cho khỏe.
Lâu lắm mới thấy anh quanghai1969 xuất hiện trên diễn đàn em tham gia diễn đàn cũng lâu và cũng được rất nhiều thầy, cô và các anh chị giúp đỡ em cũng mày mò nghiên cứu về VBA nhưng vẫn chỉ dừng lại là ứng dụng và tùy biến từ những chương trình được các thành viên giúp đỡ anh ạ. Về bản chất của VBA như thế nào thì em lại không hiểu rõ do vậy có những chương trình em không biết phải bắt đầu từ đâu. Nên up lên hỏi trên diễn đàn và nhờ giúp đỡ để phục vụ cho công việc của mình
Em cảm ơn anh quanghai1969 đã giúp đỡ em rất nhiều từ các chương trình trước. Mong anh và các thành viên diễn đàn giúp em chương trình này ạ
 
Upvote 0
Lâu lắm mới thấy anh quanghai1969 xuất hiện trên diễn đàn em tham gia diễn đàn cũng lâu và cũng được rất nhiều thầy, cô và các anh chị giúp đỡ em cũng mày mò nghiên cứu về VBA nhưng vẫn chỉ dừng lại là ứng dụng và tùy biến từ những chương trình được các thành viên giúp đỡ anh ạ. Về bản chất của VBA như thế nào thì em lại không hiểu rõ do vậy có những chương trình em không biết phải bắt đầu từ đâu. Nên up lên hỏi trên diễn đàn và nhờ giúp đỡ để phục vụ cho công việc của mình
Em cảm ơn anh quanghai1969 đã giúp đỡ em rất nhiều từ các chương trình trước. Mong anh và các thành viên diễn đàn giúp em chương trình này ạ
Mình chỉ muốn giúp bạn hướng đi để tự giải quyết bài này. Code bên dưới sẽ cho bạn tên file đầy đủ của file để có thể dùng lệnh OpenTextFile của FSO để xử lý dữ liệu của file text. Phần tên file và tên folder cũng có kèm theo.
Chúc thành công
Mã:
Sub Main()
Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show Then           
            GetAllFiles .SelectedItems(1), fso
        End If
    End With
End Sub
Function GetAllFiles(ByVal StrFolder As String, fso As Object)
Dim objFolder As Object, objSubFolder As Object, File As Object
    Set objFolder = fso.GetFolder(StrFolder)
    For Each File In objFolder.Files
        MsgBox File.path 'ten day du cua file
        MsgBox File.Name 'ten file
        MsgBox objFolder.Name 'ten thu muc
    Next
    For Each objSubFolder In objFolder.SubFolders
        GetAllFiles objSubFolder.path, fso
    Next objSubFolder
End Function
 
Upvote 0
Mình chỉ muốn giúp bạn hướng đi để tự giải quyết bài này. Code bên dưới sẽ cho bạn tên file đầy đủ của file để có thể dùng lệnh OpenTextFile của FSO để xử lý dữ liệu của file text. Phần tên file và tên folder cũng có kèm theo.
Chúc thành công
Mã:
Sub Main()
Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show Then          
            GetAllFiles .SelectedItems(1), fso
        End If
    End With
End Sub
Function GetAllFiles(ByVal StrFolder As String, fso As Object)
Dim objFolder As Object, objSubFolder As Object, File As Object
    Set objFolder = fso.GetFolder(StrFolder)
    For Each File In objFolder.Files
        MsgBox File.path 'ten day du cua file
        MsgBox File.Name 'ten file
        MsgBox objFolder.Name 'ten thu muc
    Next
    For Each objSubFolder In objFolder.SubFolders
        GetAllFiles objSubFolder.path, fso
    Next objSubFolder
End Function
EM THẤY người ta keo ko đệ quy đó Anh
 
Upvote 0
EM THẤY người ta keo ko đệ quy đó Anh
Không đệ quy thì đơn giản hơn nhiều. Trong đường link có một Sub ImportTextToExcel để giải quyết vấn đề. Quan trọng là chủ thớt phải chịu khó vận động. Mình đã giúp tương đối rồi.
 
Upvote 0
Không đệ quy thì đơn giản hơn nhiều. Trong đường link có một Sub ImportTextToExcel để giải quyết vấn đề. Quan trọng là chủ thớt phải chịu khó vận động. Mình đã giúp tương đối rồi.
Em nghỉ chủ thớt nên làm 1 cột là thư mục , 1 cột là tên file ... xong muốn lấy cái gì căn cứ vào đó mà lấy là ok nhất
Hay thay đổi Folder , file nào thì vào đó mà sửa !
 
Upvote 0
Bạn có thể tổng hợp file qua công cụ Power query của Excel có file tham khảo cách bên dưới, thay đổi lại đường dẫn cho phù hợp trong máy của bạn ở sheet KQ ô H2. Nhược điểm công cụ này thì chỉ hỗ trợ từ Excel 2010 trở đi, do bạn gửi là Excel 2003 nên mình chỉ gửi file tham khảo
Khi bạn sử dụng thành thạo công Power Query, Power Pivot khi đó rất nhiều vấn đề không cần tới VBA hỗ trợ
 

File đính kèm

Upvote 0
Em thấy code không có phần chọn nhiều folders, vậy cho em hỏi có cách nào chọn 1 luc nhieu folder?
 
Upvote 0
Em thấy code không có phần chọn nhiều folders, vậy cho em hỏi có cách nào chọn 1 luc nhieu folder?
Code mình viết không thể chọn cùng lúc nhiều folders, code chỉ có thể lấy tên của tất cả các file trong thư mục gốc và file trong thư mục con nếu có
 
Upvote 0
Bạn có thể tổng hợp file qua công cụ Power query của Excel có file tham khảo cách bên dưới, thay đổi lại đường dẫn cho phù hợp trong máy của bạn ở sheet KQ ô H2. Nhược điểm công cụ này thì chỉ hỗ trợ từ Excel 2010 trở đi, do bạn gửi là Excel 2003 nên mình chỉ gửi file tham khảo
Khi bạn sử dụng thành thạo công Power Query, Power Pivot khi đó rất nhiều vấn đề không cần tới VBA hỗ trợ
Em tải file anh về chạy nhưng không thấy chạy được em đang sử dụng office 365 bản 64bit ạ
Bài đã được tự động gộp:

Mình chỉ muốn giúp bạn hướng đi để tự giải quyết bài này. Code bên dưới sẽ cho bạn tên file đầy đủ của file để có thể dùng lệnh OpenTextFile của FSO để xử lý dữ liệu của file text. Phần tên file và tên folder cũng có kèm theo.
Chúc thành công
Mã:
Sub Main()
Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    With Application.FileDialog(msoFileDialogFolderPicker)
        If .Show Then          
            GetAllFiles .SelectedItems(1), fso
        End If
    End With
End Sub
Function GetAllFiles(ByVal StrFolder As String, fso As Object)
Dim objFolder As Object, objSubFolder As Object, File As Object
    Set objFolder = fso.GetFolder(StrFolder)
    For Each File In objFolder.Files
        MsgBox File.path 'ten day du cua file
        MsgBox File.Name 'ten file
        MsgBox objFolder.Name 'ten thu muc
    Next
    For Each objSubFolder In objFolder.SubFolders
        GetAllFiles objSubFolder.path, fso
    Next objSubFolder
End Function
Anh quanghai1969 ơi giúp em chương trình này với anh ơi. Hiện tại với kiến thức VBA của em thì không đủ khả năng để làm được ạ
Em cảm ơn anh nhiều
Bài đã được tự động gộp:

Em nghỉ chủ thớt nên làm 1 cột là thư mục , 1 cột là tên file ... xong muốn lấy cái gì căn cứ vào đó mà lấy là ok nhất
Hay thay đổi Folder , file nào thì vào đó mà sửa !
Em làm từng cột tách biệt mà cột A sẽ ghi tên của Thư mục chứa các file, cột B lưu tên các file chứa dữ liệu, Cột C, D, E lưu dữ liệu cần tổng hợp có trong các file mà
 
Upvote 0
Em tải file anh về chạy nhưng không thấy chạy được em đang sử dụng office 365 bản 64bit ạ
Vậy quá tốt rồi, bạn phải gõ lại đường dẫn trong ô H2 nha

221363

Bạn thêm thử folder vào trong thư mục TXT_daKrong rồi nhấn nút Refersh hoặc Ctrl+ Alt +F5 xem sao
 
Upvote 0
Upvote 0
Dùng tool được thì cố dùng đi bạn, chứ code cái này nhìn thì đơn giản nhưng cũng lòng vòng, dài dòng lắm.
Giờ tui đang "nười nắm nắm nuôn" nữa. Cái gì ngắn ngắn thì được, chứ dài quá thì hơi mệt ;)
 
Upvote 0
Với những trường hợp xử lý công việc thực tế cần ngay và yêu cầu nhiều thì nên chi tiền kiếm người làm, nhanh gọn.

Nếu ai quá rảnh rỗi thì mới có thời gian làm được, mà chờ những cái miễn phí thường rất lâu.
 
Upvote 0
Với những trường hợp xử lý công việc thực tế cần ngay và yêu cầu nhiều thì nên chi tiền kiếm người làm, nhanh gọn.

Nếu ai quá rảnh rỗi thì mới có thời gian làm được, mà chờ những cái miễn phí thường rất lâu.
Hiiii cảm ơn bác befaint em trước cũng có anh trên diễn đàn hay viết giúp và cũng trả kinh phí nhưng giờ anh đó bận quá không viết code nữa anh ạ nên chưa tìm được người viết giúp ạ. Nếu anh có ai giới thiệu em với. Cảm ơn anh nhiều
 
Upvote 0
Vì thấy phiên bản của bạn dùng được power query thì mình hướng dẫn như sau:
Vào Data tab/Get data/ From File/From Folder

Bạn chọn thư mục chứa các file text, nó sẽ list tất cả files bạn cần gộp, sau đó bạn tại combobox: Combine thì chọn Combine & Load
Chọn OK đến khi dữ liệu được fill, bạn sẽ thấy nó có các cột như file text và thêm 1 cột là file name
Bạn muốn thêm cột cho đường dẫn folder thì vào Query tab chọn Edit, 1 cửa sổ power query hiện ra
Bạn vào Advance Edit, xem và thêm vào sau chỗ Source.Name bằng "Folder Path" là được. Lưu ý là làm theo cụm giống source.name nhé
 
Upvote 0
Vì thấy phiên bản của bạn dùng được power query thì mình hướng dẫn như sau:
Vào Data tab/Get data/ From File/From Folder

Bạn chọn thư mục chứa các file text, nó sẽ list tất cả files bạn cần gộp, sau đó bạn tại combobox: Combine thì chọn Combine & Load
Chọn OK đến khi dữ liệu được fill, bạn sẽ thấy nó có các cột như file text và thêm 1 cột là file name
Bạn muốn thêm cột cho đường dẫn folder thì vào Query tab chọn Edit, 1 cửa sổ power query hiện ra
Bạn vào Advance Edit, xem và thêm vào sau chỗ Source.Name bằng "Folder Path" là được. Lưu ý là làm theo cụm giống source.name nhé
Tuyệt vời quá anh ạ hôm qua xem anh làm em thấy công tác tổng hợp dữ liệu của em không còn là vấn đề khó khăn nữa. Chúc anh sức khỏe nhé
Nếu được anh có thể cho em xin đia chỉ Mail của anh hoặc facebook để gặp vấn đề gì xin phép được làm phiền anh
Em cảm ơn anh!
 
Upvote 0
Tuyệt vời quá anh ạ hôm qua xem anh làm em thấy công tác tổng hợp dữ liệu của em không còn là vấn đề khó khăn nữa. Chúc anh sức khỏe nhé
Nếu được anh có thể cho em xin đia chỉ Mail của anh hoặc facebook để gặp vấn đề gì xin phép được làm phiền anh
Em cảm ơn anh!
....
 
Lần chỉnh sửa cuối:
Upvote 0
Tuyệt vời quá anh ạ hôm qua xem anh làm em thấy công tác tổng hợp dữ liệu của em không còn là vấn đề khó khăn nữa. Chúc anh sức khỏe nhé
Nếu được anh có thể cho em xin đia chỉ Mail của anh hoặc facebook để gặp vấn đề gì xin phép được làm phiền anh
Em cảm ơn anh!

Với Power query thì việc tổng họp dữ liệu không thành vấn đề, bài trước mình đã nói với bạn chỉ cần tìm hiểu công cụ này sẽ có rất nhiều thứ không cần VBA hỗ trợ. Nếu muốn thành thạo Power query thì phải tìm hiểu thêm công thức xử lý liệu còn gọi là Power query M Function, khi thành thạo tôi đảm bảo với bạn tất cả những thứ VBA làm được thì Power Query làm được, vì chúng xin ra là xử lý dữ liệu thô thành dữ liệu sạch. Khi muốn dữ liệu sạch thành những con số biết nói chuyện thì dùng Power Pivot + Power View, còn muốn sinh động hơn nữa thì dùng Power BI

Còn file của mình gửi máy bạn không chạy được là do chưa set up vài tuỳ chọn, mình có ultra vào máy bạn hôm qua xem lại đã làm thành công, đính chính lại mình vs quanluu1989 là 2 người khác nhau.

Xin cảm ơn
 
Upvote 0
Hiiii cảm ơn bác befaint em trước cũng có anh trên diễn đàn hay viết giúp và cũng trả kinh phí nhưng giờ anh đó bận quá không viết code nữa anh ạ nên chưa tìm được người viết giúp ạ. Nếu anh có ai giới thiệu em với. Cảm ơn anh nhiều
Bạn vào chuyên mục "Thành viên giúp nhau.." đăng bài "Cần tìm người làm abc (gì đó) và có trả phí", rồi úp yêu cầu lên. Đảm bảo có người làm cho bạn liền.

Query như trên đâu có làm được cái đoạn khung đỏ đâu.

221448
 
Upvote 0
Kệ, dùng tính năng có sẵn của Excel thì chỉ mất công click mệt rồi nghỉ, rồi click tiếp thôi :) Nếu không ra như ý thì cũng đành chịu, đâu có can thiệp vào tính năng đó mà sữa được.
 
Upvote 0
Bạn vào chuyên mục "Thành viên giúp nhau.." đăng bài "Cần tìm người làm abc (gì đó) và có trả phí", rồi úp yêu cầu lên. Đảm bảo có người làm cho bạn liền.

Query như trên đâu có làm được cái đoạn khung đỏ đâu.

View attachment 221448
Ban đầu mình chọn thư mục cha, sau đó vào phần filter có thể chọn những thư mục cần gộp dữ liệu. Nói chung biết được power query sẽ rất hay.
 
Upvote 0
Với Power query thì việc tổng họp dữ liệu không thành vấn đề, bài trước mình đã nói với bạn chỉ cần tìm hiểu công cụ này sẽ có rất nhiều thứ không cần VBA hỗ trợ. Nếu muốn thành thạo Power query thì phải tìm hiểu thêm công thức xử lý liệu còn gọi là Power query M Function, khi thành thạo tôi đảm bảo với bạn tất cả những thứ VBA làm được thì Power Query làm được, vì chúng xin ra là xử lý dữ liệu thô thành dữ liệu sạch. Khi muốn dữ liệu sạch thành những con số biết nói chuyện thì dùng Power Pivot + Power View, còn muốn sinh động hơn nữa thì dùng Power BI

Còn file của mình gửi máy bạn không chạy được là do chưa set up vài tuỳ chọn, mình có ultra vào máy bạn hôm qua xem lại đã làm thành công, đính chính lại mình vs quanluu1989 là 2 người khác nhau.

Xin cảm ơn
Xin lỗi anh doanlong49 nhé nếu có thể anh cho em xin thông tin liên hệ nhé
Em cảm ơn anh
Bài đã được tự động gộp:

Bạn vào chuyên mục "Thành viên giúp nhau.." đăng bài "Cần tìm người làm abc (gì đó) và có trả phí", rồi úp yêu cầu lên. Đảm bảo có người làm cho bạn liền.

Query như trên đâu có làm được cái đoạn khung đỏ đâu.

View attachment 221448
Dùng Query cái phần đánh dấu màu đỏ của anh làm tốt mà em đã được anh doanlong49 truy cập vào máy hướng dẫn và cho ra kết quả như em nêu trong yêu cầu mà
Em cảm ơn anh ạ
 
Upvote 0
Chỉ 1 câu, chọn multi folder, mà bữa giờ em đào từ shlwapi.dll, shell32.dll tới msi.dll ra, mà không ra 1 hộp dialog nào cho chọn multi folder.
Viết C++, MFC thì em cho ra chục cái cũng được. Khổ. port qua DLL cho Excel, VBA à.
 
Upvote 0
Hay xài Fso duyệt đệ quy đi ... có bao nhiêu Folder con cháu chi đó nó lấy hết là xong có điều phát sinh linh tinh trong đó :p ;)
 
Upvote 0
Hì hì, cho user chọn nhiều folder = cách loop, chọn, OK thì dễ rồi. Ý tôi là chọn như Windows Explorer đó.
Bài đã được tự động gộp:
 
Lần chỉnh sửa cuối:
Upvote 0
Uhm, nó cũng dễ thôi. Nhưng đặt phương diện user hay người dùng code của mình thôi.
Bài đã được tự động gộp:

Code MFC/C++ từ hồi xưa lắc xưa lơ mình đã có rồi
 
Upvote 0
Upvote 0
OH VÃI THẾ TƯỞNG VBA .... HÓNG HỤT :p
MÀ C LẠI VIẾT *.DLL HẢ
 
Upvote 0
Uhm, C++, dùng MFC. Có xem lại code này rồi, port qua VBA được nhưng cực lắm.
Delphi sau này chắc cũng có đó, bạn Mạnh search help và thư mục Source VCL thử.
 
Lần chỉnh sửa cuối:
Upvote 0
Port dài quá, ngán, nên thôi, hì hì. Thôi tui up source code C++/MFC của nó lên đây cho bà con nào không có account ở CodeProject down về ngâm cứu, rãnh thì port từ từ qua VBA.
Chứ tui thì giờ độ lười nó hơi cao, và thấy không cần thiết lắm ;)
Bác Mạnh, bác Tuân nghiên cú source này và extent TOpenDialog, TOpenFileDialog trong Delphi để select multi folders được nè.
Về hook = VB/VBA với GetOpenFileName thì có thể tham khảo thêm ở đây:
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Port dài quá, ngán, nên thôi, hì hì. Thôi tui up source code C++/MFC của nó lên đây cho bà con nào không có account ở CodeProject down về ngâm cứu, rãnh thì port từ từ qua VBA.
Chứ tui thì giờ độ lười nó hơi cao, và thấy không cần thiết lắm ;)
Bác Mạnh, bác Tuân nghiên cú source này và extent TOpenDialog, TOpenFileDialog trong Delphi để select multi folders được nè.
Về hook = VB/VBA với GetOpenFileName thì có thể tham khảo thêm ở đây:
Mới coi xong cảm giác như Chim sẻ nhảy vào vườn rậm ấy ===\.-0-0-0-
Mã:
BOOL CSelectDialog::OnFileNameOK()
{
    if (CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle(GetParent()->m_hWnd))
    {
        CWnd* pWnd = pDlg->GetDlgItem(lst2);    //getting list
        if (pWnd == NULL)
            return FALSE;

        m_SelectedItemList.RemoveAll();            // emptying list
        
        CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));

        int nSelected = wndLst1->GetSelectedCount();
        if (!nSelected)        // nothing selected -- don't retrieve list
            return FALSE;
        CString strItemText, strDirectory = m_strCurrendDirectory;
        if (strDirectory.Right(1) != _T("\\"))
            strDirectory += _T("\\");

        CString fileslist = _T("");
        pDlg->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH,
            (LPARAM)fileslist.GetBuffer(MAX_PATH));
        fileslist.ReleaseBuffer();

        strItemText = strDirectory + fileslist;
        if(nSelected == 1 && fileslist != _T(""))
        {
            m_SelectedItemList.Add(strItemText);
            return CFileDialog::OnFileNameOK();
        }
    }
    ::MessageBeep( MB_ICONQUESTION );
    return 1; //don't let the dialog to close
};

void CSelectDialog::OnFolderChange()
{
    m_strCurrendDirectory = GetFolderPath();
    CFileDialog::OnFolderChange();
};

void CSelectDialog::OnInitDone()
{
    m_strCurrendDirectory = GetFolderPath();
    CWnd* pFD = GetParent();

    HideControl(edt1);
    HideControl(cmb1);
    HideControl(stc2);

    //HideControl(cmb13);
    //HideControl(stc3);

    CRect rectCancel; pFD->GetDlgItem(IDCANCEL)->GetWindowRect(&rectCancel);
    pFD->ScreenToClient(&rectCancel);

    CRect rectOK; pFD->GetDlgItem(IDOK)->GetWindowRect(&rectOK);
    pFD->ScreenToClient(&rectOK);
    pFD->GetDlgItem(IDOK)->SetWindowPos(0,rectCancel.left - rectOK.Width() - 5, rectCancel.top, 0,0, SWP_NOZORDER | SWP_NOSIZE);

    CRect rectList2; pFD->GetDlgItem(lst1)->GetWindowRect(&rectList2);
    pFD->ScreenToClient(&rectList2);
    pFD->GetDlgItem(lst1)->SetWindowPos(0,0,0,rectList2.Width(), abs(rectList2.top - (rectCancel.top - 5)), SWP_NOMOVE | SWP_NOZORDER);

    CRect rectStatic;pFD->GetDlgItem(stc3)->GetWindowRect(&rectStatic);
    pFD->ScreenToClient(&rectStatic);
    pFD->GetDlgItem(stc3)->SetWindowPos(0,rectCancel.left - 375,rectCancel.top + 5, rectStatic.Width(), rectStatic.Height(), SWP_NOZORDER);

    CRect rectEdit1;pFD->GetDlgItem(cmb13)->GetWindowRect(&rectEdit1);
    pFD->ScreenToClient(&rectEdit1);
    pFD->GetDlgItem(cmb13)->SetWindowPos(0,rectCancel.left - 320,rectCancel.top, rectEdit1.Width() - 15, rectEdit1.Height(), SWP_NOZORDER);

    SetControlText(stc3, _T("Item name:"));
    SetControlText(IDOK, _T("Select"));

    m_wndProc = (WNDPROC)::SetWindowLong(pFD->m_hWnd, GWL_WNDPROC, (long)WindowProcNew);
    pFD->CenterWindow();
};

LRESULT CALLBACK CSelectDialog::WindowProcNew(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message ==  WM_COMMAND)
    {
        if (HIWORD(wParam) == BN_CLICKED)
        {
            if (LOWORD(wParam) == IDOK)
            {
                if (CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle(hwnd))
                {
                    m_SelectedItemList.RemoveAll();            // emptying list
                    CWnd* pWnd = pDlg->GetDlgItem(lst2);    //getting list
                    if (pWnd == NULL)
                        return FALSE;

                    CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));

                    int nSelected = wndLst1->GetSelectedCount();
                    if (!nSelected)        // nothing selected -- don't retrieve list
                        return FALSE;
                    CString strItemText, strDirectory = m_strCurrendDirectory;
                    if (strDirectory.Right(1) != _T("\\"))
                        strDirectory += _T("\\");

                    int nItem = wndLst1->GetNextItem(-1,LVNI_SELECTED);
                    CString fileslist = _T("");
                    pDlg->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH,
                        (LPARAM)fileslist.GetBuffer(MAX_PATH));
                    fileslist.ReleaseBuffer();
                    //////////////////   Add directory names to list
                    while((nSelected--) > 0)
                    {
                        strItemText = wndLst1->GetItemText(nItem,0);
                        strItemText = strDirectory + strItemText;
                        DWORD attr = GetFileAttributes(strItemText);
                        if((attr != 0xFFFFFFFF) && (attr & FILE_ATTRIBUTE_DIRECTORY))
                            m_SelectedItemList.Add(strItemText);                           
                        nItem = wndLst1->GetNextItem(nItem, LVNI_SELECTED);
                    }
                    //////////////////   Add FILE names to list
                    strItemText = _T("");
                    nSelected = wndLst1->GetSelectedCount();
                    if(nSelected > m_SelectedItemList.GetCount())
                    {
                        int MoreThanOnFile = fileslist.Find(_T("\""));
                        if(MoreThanOnFile != -1)
                        {
                            for(int i=0; i<fileslist.GetLength(); i++)
                                if(fileslist[i] != '\"')
                                {
                                    strItemText.AppendFormat(_T("%c"),fileslist[i]);
                                    if(fileslist[i-1] == '\"' && fileslist[i] == ' ')
                                        strItemText.Delete(strItemText.GetLength()-1);
                                }
                                else if(!strItemText.IsEmpty())
                                {
                                    m_SelectedItemList.Add((strDirectory+strItemText));
                                    strItemText.Empty();
                                }
                        }
                        else
                            m_SelectedItemList.Add(strDirectory+fileslist);
                    }
                    pDlg->EndDialog(IDOK);
                    return NULL;
                } // if IDOK
            }
        } // if BN_CLICKED
    }// if WM_COMMAND
    return CallWindowProc(m_wndProc, hwnd, message, wParam, lParam);
 
Upvote 0
Mới coi xong cảm giác như Chim sẻ nhảy vào vườn rậm ấy ===\.-0-0-0-
Mã:
BOOL CSelectDialog::OnFileNameOK()
{
    if (CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle(GetParent()->m_hWnd))
    {
        CWnd* pWnd = pDlg->GetDlgItem(lst2);    //getting list
        if (pWnd == NULL)
            return FALSE;

        m_SelectedItemList.RemoveAll();            // emptying list
       
        CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));

        int nSelected = wndLst1->GetSelectedCount();
        if (!nSelected)        // nothing selected -- don't retrieve list
            return FALSE;
        CString strItemText, strDirectory = m_strCurrendDirectory;
        if (strDirectory.Right(1) != _T("\\"))
            strDirectory += _T("\\");

        CString fileslist = _T("");
        pDlg->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH,
            (LPARAM)fileslist.GetBuffer(MAX_PATH));
        fileslist.ReleaseBuffer();

        strItemText = strDirectory + fileslist;
        if(nSelected == 1 && fileslist != _T(""))
        {
            m_SelectedItemList.Add(strItemText);
            return CFileDialog::OnFileNameOK();
        }
    }
    ::MessageBeep( MB_ICONQUESTION );
    return 1; //don't let the dialog to close
};

void CSelectDialog::OnFolderChange()
{
    m_strCurrendDirectory = GetFolderPath();
    CFileDialog::OnFolderChange();
};

void CSelectDialog::OnInitDone()
{
    m_strCurrendDirectory = GetFolderPath();
    CWnd* pFD = GetParent();

    HideControl(edt1);
    HideControl(cmb1);
    HideControl(stc2);

    //HideControl(cmb13);
    //HideControl(stc3);

    CRect rectCancel; pFD->GetDlgItem(IDCANCEL)->GetWindowRect(&rectCancel);
    pFD->ScreenToClient(&rectCancel);

    CRect rectOK; pFD->GetDlgItem(IDOK)->GetWindowRect(&rectOK);
    pFD->ScreenToClient(&rectOK);
    pFD->GetDlgItem(IDOK)->SetWindowPos(0,rectCancel.left - rectOK.Width() - 5, rectCancel.top, 0,0, SWP_NOZORDER | SWP_NOSIZE);

    CRect rectList2; pFD->GetDlgItem(lst1)->GetWindowRect(&rectList2);
    pFD->ScreenToClient(&rectList2);
    pFD->GetDlgItem(lst1)->SetWindowPos(0,0,0,rectList2.Width(), abs(rectList2.top - (rectCancel.top - 5)), SWP_NOMOVE | SWP_NOZORDER);

    CRect rectStatic;pFD->GetDlgItem(stc3)->GetWindowRect(&rectStatic);
    pFD->ScreenToClient(&rectStatic);
    pFD->GetDlgItem(stc3)->SetWindowPos(0,rectCancel.left - 375,rectCancel.top + 5, rectStatic.Width(), rectStatic.Height(), SWP_NOZORDER);

    CRect rectEdit1;pFD->GetDlgItem(cmb13)->GetWindowRect(&rectEdit1);
    pFD->ScreenToClient(&rectEdit1);
    pFD->GetDlgItem(cmb13)->SetWindowPos(0,rectCancel.left - 320,rectCancel.top, rectEdit1.Width() - 15, rectEdit1.Height(), SWP_NOZORDER);

    SetControlText(stc3, _T("Item name:"));
    SetControlText(IDOK, _T("Select"));

    m_wndProc = (WNDPROC)::SetWindowLong(pFD->m_hWnd, GWL_WNDPROC, (long)WindowProcNew);
    pFD->CenterWindow();
};

LRESULT CALLBACK CSelectDialog::WindowProcNew(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message ==  WM_COMMAND)
    {
        if (HIWORD(wParam) == BN_CLICKED)
        {
            if (LOWORD(wParam) == IDOK)
            {
                if (CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle(hwnd))
                {
                    m_SelectedItemList.RemoveAll();            // emptying list
                    CWnd* pWnd = pDlg->GetDlgItem(lst2);    //getting list
                    if (pWnd == NULL)
                        return FALSE;

                    CListCtrl* wndLst1 = (CListCtrl*)(pWnd->GetDlgItem(1));

                    int nSelected = wndLst1->GetSelectedCount();
                    if (!nSelected)        // nothing selected -- don't retrieve list
                        return FALSE;
                    CString strItemText, strDirectory = m_strCurrendDirectory;
                    if (strDirectory.Right(1) != _T("\\"))
                        strDirectory += _T("\\");

                    int nItem = wndLst1->GetNextItem(-1,LVNI_SELECTED);
                    CString fileslist = _T("");
                    pDlg->SendMessage(CDM_GETSPEC, (WPARAM)MAX_PATH,
                        (LPARAM)fileslist.GetBuffer(MAX_PATH));
                    fileslist.ReleaseBuffer();
                    //////////////////   Add directory names to list
                    while((nSelected--) > 0)
                    {
                        strItemText = wndLst1->GetItemText(nItem,0);
                        strItemText = strDirectory + strItemText;
                        DWORD attr = GetFileAttributes(strItemText);
                        if((attr != 0xFFFFFFFF) && (attr & FILE_ATTRIBUTE_DIRECTORY))
                            m_SelectedItemList.Add(strItemText);                          
                        nItem = wndLst1->GetNextItem(nItem, LVNI_SELECTED);
                    }
                    //////////////////   Add FILE names to list
                    strItemText = _T("");
                    nSelected = wndLst1->GetSelectedCount();
                    if(nSelected > m_SelectedItemList.GetCount())
                    {
                        int MoreThanOnFile = fileslist.Find(_T("\""));
                        if(MoreThanOnFile != -1)
                        {
                            for(int i=0; i<fileslist.GetLength(); i++)
                                if(fileslist[i] != '\"')
                                {
                                    strItemText.AppendFormat(_T("%c"),fileslist[i]);
                                    if(fileslist[i-1] == '\"' && fileslist[i] == ' ')
                                        strItemText.Delete(strItemText.GetLength()-1);
                                }
                                else if(!strItemText.IsEmpty())
                                {
                                    m_SelectedItemList.Add((strDirectory+strItemText));
                                    strItemText.Empty();
                                }
                        }
                        else
                            m_SelectedItemList.Add(strDirectory+fileslist);
                    }
                    pDlg->EndDialog(IDOK);
                    return NULL;
                } // if IDOK
            }
        } // if BN_CLICKED
    }// if WM_COMMAND
    return CallWindowProc(m_wndProc, hwnd, message, wParam, lParam);
cái này có phải VBA không ạ. hicccc em xem mà không hiểu gì cả ạ. Mong bác kieu manh giúp em với
Cảm ơn bác nhiều!
 
Upvote 0
OH VÃI THẾ TƯỞNG VBA .... HÓNG HỤT :p
MÀ C LẠI VIẾT *.DLL HẢ
Vấn đề ở chỗ có thể tìm ra 1 lệnh duy nhất trong VBA để duyệt tới và chọn nhiều thư mục hay không. Tất nhiên không có 1 lệnh như thế. Còn nếu tự viết code thì có gì khó đâu.

Không có việc gì khó. Chỉ sợ ................ đầu lười suy nghĩ.

Nếu lập trình Windows API thì có thể dùng vd. (chỉ là ý tưởng sơ qua thôi) interface IShellFolder + method EnumObjects + ... Nhưng nói cho cùng thì sao phải khổ thế? Sao phải đi con đường đầy chông gai? Vì thực ra ta chỉ cần lấy về tên các thư mục được chọn, tức các chuỗi. Tất nhiên user phải có khả năng di chuyển tới thư mục đích trên drive cụ thể để chọn các thư mục con trong thư mục đích.

Thuật toán là:
1. Đặt trên UserForm 1 ListView với View = lvWIcon, 1 ComboBox, Label với Caption = "<"

2. Trong UserForm_Initialize dùng FileSystemObject để lấy các drive vào combobox. và chọn mục đầu tiên.

3. Trong combobox_change thì đọc ra thư mục hiện hành trên drive được chọn và nhập vào biến toàn cục currFolder. Đồng thời gọi sub listFolder

4. Sub listFolder: Trước hết xóa hết các item của ListView. Tiếp theo dùng FileSystemObject để lấy danh sách các thư mục con của thư mục currFolder. Với mỗi thư mục con thì tạo item cho ListView với Caption = tên thư mục con.

5. Với DoubleClick của ListView: đọc ra item đang được chọn với tên của thư mục được chọn -> đổi currFolder thành đường dẫn tới thư mục đang được chọn -> gọi listFolder.

6. Label2_Click: từ currFolder xác định thư mục cha của thư mục currFolder. Nếu có cha thì đổi currFolder thành thư mục cha rồi gọi listFolder. Nếu không có cha vì currFolder là thư mục chính trên drive thì không làm gì.

Như vậy user chuyển drive bằng cách chọn trong ComboBox. Đúp chuột lên item của ListView để chuyển thư mục currFolder thành thư mục được click và hiện các thư mục con trong ListView. Click Label2 để chuyển tới thư mục cha của thư mục hiện hành. Nếu user nhấn OK thì 1 mảng với tên các thư mục được chọn sẽ được trả về. Trong ví dụ thì các tên sẽ được hiện bằng Debug.Print.

Lưu ý:
1. Nếu lập trình trong Delphi thì Delphi có control ListView. Nhưng cũng có thể dùng API để tự tạo ListView. Nói cho cùng thì Delphi cũng tạo ListView bằng API. Trong VBA cũng có thể tạo ListView bằng API.

Tóm lại thuật toán là thế. Còn implement trong Delphi, VB, VBA thì tùy. Cũng có thể không dùng ListView mà thêm các Label thay cho thêm các item vào ListView. Tất nhiên phải sắp xếp các Label theo hàng và cột. Và thay đúp chuột trên ListView bằng đúp chuột trên các Label.

Thuật toán chỉ là 1 nhưng các chi tiết implement thuật toán đó có thể tùy biến (ngôn ngữ lập trình, controls).

2. Hiện code hiện cả thùng rác và các thư mục "cấm" của system. Đây chỉ là ví dụ, chi tiết thì ai thích người ấy tự làm.

3. Code chưa xử lý nhiều trường hợp lỗi có thể sảy ra vì nó chỉ là ví dụ.

4. Có thể chọn icon cho các item của ListView để đẹp mắt. Tôi không làm vì đây chỉ là ví dụ.

5. Code được test trên Windows XP Home 32 bit + Excel 2010 32 bit, và Windows 10 64 bit + Excel 2007 32 bit.
 

File đính kèm

Upvote 0
Chi khổ vậy, dùng quách cách của bạn khongtu19bk không đơn giản hơn à ? Phát minh lại cái bánh xe làm gì với UserForm, vBA củ chuối.
Bài đã được tự động gộp:

Kg thì chỉ cần msoFolderPicker hay API SHBrowseForFolder cũng đủ rồi, shoe, chọn, ok, chán, thôi thì click Cancel, cũng ra multi select folder, làm Gui UserForm cùi bắp chi cho cực
 
Lần chỉnh sửa cuối:
Upvote 0
Về code dài ngắn, khổ hay không, chưa chắc cái nào hơn cái nào. Chắc chắn code của ta không phức tạp với những người biết VBA, chắc chắn không dài. Vậy ai khổ đây, hay đọc mà không hiểu nhỉ. Không đơn giản hơn. Đọc code thì thấy code của ta thì tất cả các dòng rất nhiều người có thể tự viết. Cái mấu chốt chỉ là ý tưởng.

Không hiểu ý thì nói cho hiểu nhé. Ta cố tình không dùng API vì API với nhiều người vẫn còn xa lạ. Không phải ta không biết SHBrowseForFolder nhưng đó là API rồi. Nói chung là không hiểu được ý của người ta thì nên im lặng.

1. Về code của khongtu19bk khi mở thì ví dụ ta có thư mục C:\. Ví dụ trong C:\ có thư mục Excel. Nếu ta muốn liệt kê các thư mục con của Ecel thì lại phải nhấn nút Open -> duyệt tới và chọn Excel. Trong code của tôi chỉ là đúp chuột trên Excel.

2. Trong code của khongtu19bk nếu muốn chọn vài thư mục con thì phải click từng thư mục. Trong code của tôi có thể click 1 thư mục -> giữ Shift và click thư mục khác. Cũng có thể click "điểm trống" ở phía trên bên trái 1 thư mục rồi giữ nhấn và kéo tới điểm khác. Toàn bộ các icon trong vùng hình chữ nhật sẽ được chọn. Tất nhiên có thể giữ Ctrl và click từng icon để chọn nhiều.

Có đúng như thao tác trong Excplorer không? Y hệt hoặc gần y hệt như trong Explorer. Với code của khongtu19bk thì không như thế.

3. Với code của tôi mà thêm icon thì nhìn như trong các thư mục trên đĩa không? Đâu có là danh sách các tên trong từng dòng?

Đọc code, nhìn biểu diễn mà không nhìn thấy sự khác nhay giữa 2 code, không hiểu gì thì quá yếu.

Nói chung giỏi gì thì chuyên về cái đó đi, những cái không hiểu thì ngồi im mà nghe người khác nói. Ta đã chỉ ra cái vụ unicode hồi nào với BOM và không BOM, cãi chầy cối rồi cuối cùng vẫn không biết mở tập tin sao cho đúng. Còn lý lẽ: thế ai đó không biết chọn encoding thì sao. Thì cho nghỉ việc thôi chứ sao nữa. Thế sếp giao cho việc mà cần mở CSV trong Excel mà lại không biết mở thì sao? Thì xin nghỉ việc chứ sao nữa. Lý lẽ là tôi có tập tin unicode nhưng tôi mở trong Word nhưng không biết chọn encoding sao cho đúng thì chỉ là lý sự cùn. Không biết mở thì học cách mở. Học mà vẫn không biết thì xin nghỉ việc. Thế thôi.

Dù sao đây chỉ là ví dụ khác với ví dụ của khongtu19bk. Còn hơn nhiều những người chỉ biết mỗi cách LOOP hoặc copy code của người khác từ trên mạng về và tìm cách dịch sang VBA. Con người ta ăn nhau ở cái ý tưởng, cách tư duy, chịu suy nghĩ. Còn trưng code của người khác để người ta nhìn vào thấy hoa mắt, dùng các từ shlwapi.dll, shell32.dll tới msi.dll cho dân đen nhìn thấy mà sợ thì chỉ là trò làm cho bạn gái lác mắt mà thôi. Ta không phải thuộc loại đó.

Dù sao ta cũng đưa ra 1 ý tưởng, và có code đàng hoàng. Còn hơn viết 1 loạt bài chỉ ở mức ăn tục nói phét, chưa đưa ra được 1 dòng code, thì đừng lên mặt dạy người khác nhé.
 
Upvote 0
Hì hì, bác này thù dai thù vặt ghê nhỉ. Nội cái vụ BOM mà nói tới nói lui hoài.
Cái tôi muốn select multi foler cuối cùng là cái này nè bác. Nhưng tôi tìm chưa ra, dù đã đào tùm lum các dll của Windows. Nó là undocument function API.
Ý tôi muốn là chỉ cần tìm, dùng được API này thì mọi chuyện sẽ đơn giản. Vì các giải pháp, code hiện tại của khongtu19bk, của bác, hay cách hook GetOpenFileName tôi đưa ra đều không chọn được multi folder cùng lúc trong nhiều thư mục khác nhau, ổ đĩa khác nhau.
Nên tôi nói đơn giản nhất là loop, chọn từng thư mục bất kỳ, không chọn nữa thì Cancel. Chả cần form fiec, code kiết gì cả. Đơn giản nhất.
Và nói luôn là file của bác tôi chả cần download mà xem, vì biết cũng chỉ nhiêu đó, không có cái gì hay ho hay mới mẽ cả. Ba cái userform với VBA này thì bác chỉ khè được các anh chị dân tin học VP, làm VP ở đây thôi, dân newbie, amatuer VBA, chứ với dân coder chuyên nghiệp, nó là trò con nít.
Tôi nói không cần thiết vì mục đích của chủ thớt ban đầu là xử lý txt file, chọn multi folder chỉ là phụ. Có cũng được không có cũng chả sao.
Chả cần phải làm cái form, mang 1 đống code vào để chỉ làm mục đích chọn multi folder. Cái chính chủ thớt muốn là xử lý file txt thôi. Hết. Cái này bạn khongtubk19 đã làm rồi.
 

File đính kèm

  • 1.png
    1.png
    19.1 KB · Đọc: 26
Upvote 0
úi ra xem cái hình có check check thế kia là mê tê cứng ròi ... có code VBA úp cho mạnh học với thì tuyệt vời ông mặt trời Or Delphi thì cũng mầm tạm chút ... còn code C thì chỉ dòm xong đoán mò được vài từ hay vài dòng thui ( Nói chung là tịt )
 
Upvote 0
Mới coi xong cảm giác như Chim sẻ nhảy vào vườn rậm ấy ===\.-0-0-0-
...
cái này có phải VBA không ạ. hicccc em xem mà không hiểu gì cả ạ. Mong bác kieu manh giúp em với
Cảm ơn bác nhiều!
Hai bạn tìm cái anh chàng chiên diên Xê Cọng Cọng đề nghị dạy 200 đô la mẽo một tiết ấy.
Mượn anh ta giải thích giùm cho. Có lẽ anh ta cũng không từ chối chút tiền lẻ vô nhớt xe mát da.

(tiếc quá, không ai viết code COBOL cho mình có dịp phét)
 
Upvote 0
Trên Delphi, C++, .NET thì thư viện không có sẳn control nào như thế, nhưng ngoài thị trường thì hằng hà sa số các cty, cá nhân viết bán hoặc free các custom control, class dạng này. Nhiều không đếm xuể...
Trên Delphi, bạn Mạnh thử TFileOpenDialog với options fdoPickFolders Or fdoAllowMultiSelect thử xem sao. Do máy cùi bắp vp của tui không có cài RAD Studio nên không thử được.
Còn custom component làm sẵn thì bạn Mạnh tham khảo vài cái ở đây thử:
1. http://www.gtro.com/delphi/gtrocheckshelltreeview_e.php
2. https://www.ssware.com/articles/shb...bout-the-windows-folder-browser-component.htm
3. https://www.jam-software.com/shellbrowser_delphi/
....
Nếu muốn dùng cho VBA thì phải build DLL cho VBA gọi thôi, không còn cách nào khác, hay viết OCX.
 
Upvote 0
Trên Delphi, C++, .NET thì thư viện không có sẳn control nào như thế, nhưng ngoài thị trường thì hằng hà sa số các cty, cá nhân viết bán hoặc free các custom control, class dạng này. Nhiều không đếm xuể...
Trên Delphi, bạn Mạnh thử TFileOpenDialog với options fdoPickFolders Or fdoAllowMultiSelect thử xem sao. Do máy cùi bắp vp của tui không có cài RAD Studio nên không thử được.
Còn custom component làm sẵn thì bạn Mạnh tham khảo vài cái ở đây thử:
1. http://www.gtro.com/delphi/gtrocheckshelltreeview_e.php
2. https://www.ssware.com/articles/shb...bout-the-windows-folder-browser-component.htm
3. https://www.jam-software.com/shellbrowser_delphi/
....
Nếu muốn dùng cho VBA thì phải build DLL cho VBA gọi thôi, không còn cách nào khác, hay viết OCX.
1/ Thử build DLL úp lên cho Mạnh thử quậy chút xem sao .... nếu tốt Mạnh xài ké nhét vào cái DLL vb6 của Mạnh xài khi cần thiết ( Add Resoure VB6 )

2/ Nếu nó là DLL API thì thử trên VBA xem sao ?!

3/ Cũng đang tính khi nào rãnh Úp bài hỏi cách Add Resource trên Delphi cách nó làm như thế nào và lấy ra như thế nào ??? VB6 thì mạnh biết .... còn Delphi thì tịt .... có link nào hay code gì chỉ dùm !?

Cảm ơn
 
Upvote 0
Hì hì, bác này thù dai thù vặt ghê nhỉ. Nội cái vụ BOM mà nói tới nói lui hoài.
Không phải thù dai. Tranh luận đúng sai là chuyện thường, nhưng tôi không thích kiểu tranh luận cù nhầy.
Cái tôi muốn select multi foler cuối cùng là cái này nè bác. Nhưng tôi tìm chưa ra, dù đã đào tùm lum các dll của Windows. Nó là undocument function API.
Ý tôi muốn là chỉ cần tìm, dùng được API này thì mọi chuyện sẽ đơn giản. Vì các giải pháp, code hiện tại của khongtu19bk, của bác, hay cách hook GetOpenFileName tôi đưa ra đều không chọn được multi folder cùng lúc trong nhiều thư mục khác nhau, ổ đĩa khác nhau.
Nên tôi nói đơn giản nhất là loop, chọn từng thư mục bất kỳ, không chọn nữa thì Cancel. Chả cần form fiec, code kiết gì cả. Đơn giản nhất.
Và nói luôn là file của bác tôi chả cần download mà xem, vì biết cũng chỉ nhiêu đó, không có cái gì hay ho hay mới mẽ cả. Ba cái userform với VBA này thì bác chỉ khè được các anh chị dân tin học VP, làm VP ở đây thôi, dân newbie, amatuer VBA, chứ với dân coder chuyên nghiệp, nó là trò con nít.
Tôi nói không cần thiết vì mục đích của chủ thớt ban đầu là xử lý txt file, chọn multi folder chỉ là phụ. Có cũng được không có cũng chả sao.
Chả cần phải làm cái form, mang 1 đống code vào để chỉ làm mục đích chọn multi folder. Cái chính chủ thớt muốn là xử lý file txt thôi. Hết. Cái này bạn khongtubk19 đã làm rồi.
Nếu ở bài #72 bạn viết thế này thì tôi sẽ chẳng trả lời bạn gì cả. Vì thực chất tôi không trả lời cho chủ chủ đề, cho bạn hay bất cứ ai khác ngoài kieu manh. Và tôi cho là hiểu ý kieu manh như thế. Chỉ có kieu manh mới có quyền giải thích cụ thể hơn cho tôi về yêu cầu của mình. Viết bài trong một chủ đề nào đó không có nghĩa là trả lời cho vấn đề của chủ chủ đề. Đôi khi là sự trao đổi với người khác trong số những người đọc chủ đề. Tôi không quan tâm bạn muốn gì nên bạn không cần phải giải thích cho tôi.

Trong bài #72 bạn có thể thông báo các mong đợi của mình cho mọi người. Nhưng bạn chọn cách chê bai, nói khóe bài của tôi. Ai là người thù dai đây bạn. Bạn không cần trả lời vì đây là câu hỏi tu từ. Và tôi cũng không cần câu trả lời. Khi viết trả lời cho kieu manh thậm chí tôi không đọc tất cả các bài, không biết tới sự tồn tại của ý tưởng của khongtu19bk. Bài của tôi không có ý là nên dùng thay cho bất cứ cái gì. Nó chỉ nhằm mục đích chỉ ra là: có thể tự viết code để lấy về nhiều thư mục, và có đặc điểm giống như ta thao tác chọn nhiều thư mục con trong Explorer, và code đó hoàn toàn có thể ngắn gọn và dễ hiểu. Chỉ ra khả năng, và sự đơn giản của nó. Thế thôi. Tôi không nói là dùng nó để thay thế cái gì.

Tôi nhắc lại là tôi đã không quan tâm bạn muốn gì. Tôi trả lời cho mỗi kieu manh thôi. Những thằng chả đưa ra một code cụ thể nào mà chỉ ngồi nói phét thì tôi khinhh. Giỏi thì đưa ra code của mình cho mọi người học tập. Cho mọi người thấy cái thiên tài của mình. Cho mọi người ngưỡng mộ. Còn nếu không đưa ra được code thì ngồi im nghe người khác nói. Nếu thay vì code chỉ phun ra những từ "kêu to" thì quá tầm thường. Chỉ hù họa được bọn không biết gì, các bé mới lớn mà thôi. Quá tầm thường.

Nhắc lại: Nếu giỏi thì tung code ra cho mọi người ngưỡng mộ. Còn không thì đừng chê bai, nói khóe. Ghét nhất những bọn ăn tục nói phét, cù nhầy, lý sự cùn.
 
Upvote 0
Tui đã nói là code C++/MFC tui đã có từ lâu lắc rồi mà không tin. Chả ai rảnh đâu mà nói xạo.
Vấn đề là tui thấy không cần thiết phải 1 viết thêm 1 cái DLL wrap cái code này lại, để export 1 hàm ra cho chọn multi folder.
Cái tôi muốn là tìm ra API có sẵn trong đống DLL của Windows mà MS coder đã viết để dùng cho khỏe. Làm được như cái hình tui post ở trên. Thế thôi.
File đính kèm là EXE tui đã build release mode, code = Visual C++, dùng MFC. Bà con có thể test thử.
List các files, folder mà bà con đã chọn lưu trong HKEY_CURRENT_USER\Software\ThangCuAnh, bà con có thể test xong thì vào đó xóa cho sạch máy.
Code C++/MFC tui không đính kèm vì post lên bà con cũng không hiểu, như Kieumanh nói như "Chim sẻ nhảy vào vườn rậm" ấy, và nó dù code của tui, nhưng sở hữu của cty tôi đang làm, dùng trong nhiều sản phẩm, không open source được.
File Exe bảo đảm sạch, bà con an tâm
 

File đính kèm

Upvote 0
Sao không thấy có Check box chọn nhiều Folder nhỉ
Capture.JPG
 
Upvote 0
Code này chỉ test thôi bạn, không có phần modify style của TreeView của SHBrowseForFolder để bật tính năng checkbox.
Bấm cái mũi tên -> để add thư mục cần chọn vào 1 list
 
Upvote 0
Sao không thấy có Check box chọn nhiều Folder nhỉ
Tôi hiểu cái nỗi khổ của bạn.

Nếu mắt không nhìn thấy, mũi không ngửi thấy thì lòng thanh thản. Còn nếu người ta chỉ nhử nhử cái đùi gà trước mặt nhưng không cho, trong tầm tay mà không với tới được, thì ................ không có cái khổ nào như cái khổ này. :D

Bạn đã nói là chỉ cần chút gợi ý ABC thôi để bạn từ đó phát triển lên. Vậy tôi cho bạn ABC. Trước hết hãy chạy EXE xem đúng ý chưa. Tất nhiên chỉ ABC còn tôi không còn hứng phát triển lên. Vd. viết phục vụ Unicode. Tôi chỉ dùng Delphi 5 thôi. Tất nhiên có những bộ controls unicode cho Delphi 5 nhưng hồi xưa tôi cài để vọc chứ bây giờ không dùng. Nói chung mấy trò API này khoảng hơn 20 năm trước tôi chơi hàng ngày. Bây giờ già rồi không chơi nữa. Vì chơi về system, API thì chơi hết rồi.

Chú ý:
- muốn chọn thư mục nào thì click vào nó. Muốn bỏ chọn do chọn nhầm thì click lần nữa vào nó. Nhưng không click ngay được sau khi chọn nhầm để bỏ chọn. Phải click thư mục khác mà mình muốn chọn rồi sau đó click thư mục chọn nhầm. CheckBox sẽ được đánh dấu nếu thư mục được chọn.
- chỉ click tên thư mục chứ không click checkbox. Code tự đánh dấu checkbox. Mà thậm chí click checkbox thì kết quả sẽ sai do code tự đánh dấu.
- khi nhấn OK mà có các thư mục được chọn thì chúng sẽ được nạp vào Memo.
- chương trình không phục vụ Unicode vì tôi viết trong Delphi 5.
- đã chạy thử trên XP Home + Excel 2010 32 bit, và Windows 10 64 bit + Excel 2007 32 bit.

Nếu vừa ý thì tôi sẽ gửi cho code viết trong Delphi 5.
 

File đính kèm

Upvote 0
Tôi hiểu cái nỗi khổ của bạn.

Nếu mắt không nhìn thấy, mũi không ngửi thấy thì lòng thanh thản. Còn nếu người ta chỉ nhử nhử cái đùi gà trước mặt nhưng không cho, trong tầm tay mà không với tới được, thì ................ không có cái khổ nào như cái khổ này. :D

Bạn đã nói là chỉ cần chút gợi ý ABC thôi để bạn từ đó phát triển lên. Vậy tôi cho bạn ABC. Trước hết hãy chạy EXE xem đúng ý chưa. Tất nhiên chỉ ABC còn tôi không còn hứng phát triển lên. Vd. viết phục vụ Unicode. Tôi chỉ dùng Delphi 5 thôi. Tất nhiên có những bộ controls unicode cho Delphi 5 nhưng hồi xưa tôi cài để vọc chứ bây giờ không dùng. Nói chung mấy trò API này khoảng hơn 20 năm trước tôi chơi hàng ngày. Bây giờ già rồi không chơi nữa. Vì chơi về system, API thì chơi hết rồi.

Chú ý:
- muốn chọn thư mục nào thì click vào nó. Muốn bỏ chọn do chọn nhầm thì click lần nữa vào nó. Nhưng không click ngay được sau khi chọn nhầm để bỏ chọn. Phải click thư mục khác mà mình muốn chọn rồi sau đó click thư mục chọn nhầm. CheckBox sẽ được đánh dấu nếu thư mục được chọn.
- chỉ click tên thư mục chứ không click checkbox. Code tự đánh dấu checkbox. Mà thậm chí click checkbox thì kết quả sẽ sai do code tự đánh dấu.
- khi nhấn OK mà có các thư mục được chọn thì chúng sẽ được nạp vào Memo.
- chương trình không phục vụ Unicode vì tôi viết trong Delphi 5.
- đã chạy thử trên XP Home + Excel 2010 32 bit, và Windows 10 64 bit + Excel 2007 32 bit.

Nếu vừa ý thì tôi sẽ gửi cho code viết trong Delphi 5.
Cảm ơn Anh ... đó mới là tuyệt vời Ông Mặt trời ... Anh cho em xin code nghiên cứu
Nếu được Anh viết dùm Em code .... Em cho Cái Form vào DLL Dephi xong em gọi hàm thì quá tuyệt !
Em chạy Trên Office 2016x32 và Windows10x64
Máy Em cài Delphi 10.2.3
221756
 
Upvote 0
Cảm ơn Anh ... đó mới là tuyệt vời Ông Mặt trời ... Anh cho em xin code nghiên cứu
Nếu được Anh viết dùm Em code .... Em cho Cái Form vào DLL Dephi xong em gọi hàm thì quá tuyệt !
Em chạy Trên Office 2016x32 và Windows10x64
Máy Em cài Delphi 10.2.3
Thôi thôi. Bạn muốn ABC để nghiên cứu nên tôi bỏ công ra cho ABC. Bạn tự làm tiếp thôi.

Tất cả các hàm API mà tôi dùng thì bạn cũng từng đọc, từng dùng rồi. Chả có hàm nào lạ với bạn cả. Còn 2 macro TreeView_*** (Nếu thích bạn có thể thay bằng SendMessage - hãy đọc help trong Delphi để biết) cũng có luôn trong Delphi 5, và như vậy chắc cũng có trong Delphi mới hơn. Chả có hàm nào bạn chưa dùng cả. Mấu chốt chỉ là ý tưởng mà thôi. Code cũng ngắn cũn cỡn nên chắc là không làm bạn mệt.
Bài đã được tự động gộp:

À trong code chỉ có 1 chỗ duy nhất là
Mã:
if A and B > 0 then
Tôi nghĩ là nên thay bằng
Mã:
if A and B = B then
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Thôi thôi. Bạn muốn ABC để nghiên cứu nên tôi bỏ công ra cho ABC. Bạn tự làm tiếp thôi.

Tất cả các hàm API mà tôi dùng thì bạn cũng từng đọc, từng dùng rồi. Chả có hàm nào lạ với bạn cả. Còn 2 macro TreeView_*** (Nếu thích bạn có thể thay bằng SendMessage - hãy đọc help trong Delphi để biết) cũng có luôn trong Delphi 5, và như vậy chắc cũng có trong Delphi mới hơn. Chả có hàm nào bạn chưa dùng cả. Mấu chốt chỉ là ý tưởng mà thôi. Code cũng ngắn cũn cỡn nên chắc là không làm bạn mệt.
Bài đã được tự động gộp:

À trong code chỉ có 1 chỗ duy nhất là
Mã:
if A and B > 0 then
Tôi nghĩ là nên thay bằng
Mã:
if A and B = B then
Em mới thử code xong BrowseFolder rất đẹp và tiện ích ... nếu Anh điều chỉnh lại code cho nó khi chọn vào Checkbox hay folder thì nó hiểu như nhau nữa thì hoàn hảo
Em mở trên Delphi 10.2.3 mà code ko báo lỗi ( code đó anh viết trên Delphi 5 )

Hai hàm đó Em bổ sung vào thư viện Hàm API của em thật tuyệt

sao em tìm ko thấy dòng code sau ? hay anh mới viết thêm
Mã:
if A and B > 0 then
Capture.JPG
 
Lần chỉnh sửa cuối:
Upvote 0

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

Back
Top Bottom