[Hỏi] Code VBA cho file excel để có thể Merge Word

Liên hệ QC

quansla

Thành viên mới
Tham gia
14/6/11
Bài viết
11
Được thích
0
Chào mọi người, năm mới em chúc cả nhà mạnh khỏe và thành công, tiền vào như nước, tiền ra nhỏ giọt

Đầu xuân em muốn phiền mọi người chút
Em cần Code VBA (viết cho file excel) để làm được điều sau:
Ban đầu: Một thư mục đã có (giả sử chính là thư mục mà giải nén file em gửi) bên trong gồm 2 thư mục con + 1 file Excel (file này là file nguồn cần Merge File Word)
Yêu Cầu:
Code VBA mà khi chạy:
1. Lấy tên + đường dẫn File hiện hành (file excel nguồn)
2. Tìm trong đường dẫn vừa tìm ở bước 1 tất cả các file Word (*.doc*) nằm trong CẢ THƯ MỤC CON (trong ví dụ của em là các file 1.1.doc; 1.2doc; 1.3.doc (trong thư mục 1) và các file 2.1.doc; 2.2.doc; 2.3.doc (trong thư mục 2)
3. Duyệt qua toàn bộ File word tìm được ở bước 2 để thực hiện chức năng Merge File (Trộn thư) của Word với nguồn là Sheet2 (tên Sheet là DATA_CHUYEN_MER) toàn bộ quá trình làm ẩn dưới nền, thoát và lưu file word
4. Kết thúc VBA
Em xin nhờ mọi người giúp đỡ ạ
 

File đính kèm

  • Hoi ve Merge file.rar
    112 KB · Đọc: 37
Chào mọi người, năm mới em chúc cả nhà mạnh khỏe và thành công, tiền vào như nước, tiền ra nhỏ giọt

Đầu xuân em muốn phiền mọi người chút
Em cần Code VBA (viết cho file excel) để làm được điều sau:
Ban đầu: Một thư mục đã có (giả sử chính là thư mục mà giải nén file em gửi) bên trong gồm 2 thư mục con + 1 file Excel (file này là file nguồn cần Merge File Word)
Yêu Cầu:
Code VBA mà khi chạy:
1. Lấy tên + đường dẫn File hiện hành (file excel nguồn)
2. Tìm trong đường dẫn vừa tìm ở bước 1 tất cả các file Word (*.doc*) nằm trong CẢ THƯ MỤC CON (trong ví dụ của em là các file 1.1.doc; 1.2doc; 1.3.doc (trong thư mục 1) và các file 2.1.doc; 2.2.doc; 2.3.doc (trong thư mục 2)
3. Duyệt qua toàn bộ File word tìm được ở bước 2 để thực hiện chức năng Merge File (Trộn thư) của Word với nguồn là Sheet2 (tên Sheet là DATA_CHUYEN_MER) toàn bộ quá trình làm ẩn dưới nền, thoát và lưu file word
4. Kết thúc VBA
Em xin nhờ mọi người giúp đỡ ạ
Góp ý cho bạn:
1/ Sheet DATA nên thiết kế lại để nhập liệu theo chiều dọc (để thuận tiện lấy dữ liệu).
2/ Bạn nên đưa 1 cái mẫu File Word có đầy đủ nội dung để thiết kế 1 mẫu duy nhất trên 1 sheet Excel để sử dụng in hàng loạt thì sẽ thuận tiện hơn và đỡ bị lỗi.
 
Upvote 0
Góp ý cho bạn:
1/ Sheet DATA nên thiết kế lại để nhập liệu theo chiều dọc (để thuận tiện lấy dữ liệu).
2/ Bạn nên đưa 1 cái mẫu File Word có đầy đủ nội dung để thiết kế 1 mẫu duy nhất trên 1 sheet Excel để sử dụng in hàng loạt thì sẽ thuận tiện hơn và đỡ bị lỗi.
Cảm ơn bác, nhưng trong file excel em gửi, file nhập liệu là theo chiều dọc, file DATA_CHUYEN_MER là chuyển thành ngang nhờ công cụ có sẵn của Excel: Copy and Trans-> dọc thành ngang nên cơ bản là vẫn dễ kiểm soát; còn file Word thì toàn bộ các Fiel của file Word Mer em đã chọn chuẩn rồi, file thì nó có dạng như này:
 

File đính kèm

  • 4. Thông báo khởi công.doc
    61.5 KB · Đọc: 30
Upvote 0
Cảm ơn bác, nhưng trong file excel em gửi, file nhập liệu là theo chiều dọc, file DATA_CHUYEN_MER là chuyển thành ngang nhờ công cụ có sẵn của Excel: Copy and Trans-> dọc thành ngang nên cơ bản là vẫn dễ kiểm soát; còn file Word thì toàn bộ các Fiel của file Word Mer em đã chọn chuẩn rồi, file thì nó có dạng như này:
Cách làm của bạn như đề xuất ở bài 1 là chưa hợp lý. Vỉ vậy, để giúp bạn hiểu được vấn đề, bạn có thể tham khảo File trong bài viết sau:

http://www.giaiphapexcel.com/diendan/threads/theo-dõi-và-truy-vấn-đơn-thuốc-nơi-phòng-khám-bệnh.126073/

Code để truy vấn và in hàng loạt trong bài viết sau:

http://www.giaiphapexcel.com/diendan/threads/giúp-tăng-tốc-xử-lý-code-in-hàng-loạt.133354/#post-843369


Như góp ý ở bài 2, bạn nên thiết kế 1 cái mẫu ở 1 sheet nào đó rồi đưa File lên nhờ các thành viên giúp tiếp.
 
Lần chỉnh sửa cuối:
Upvote 0
Cách làm của bạn như đề xuất ở bài 1 là chưa hợp lý. Vỉ vậy, để giúp bạn hiểu được vấn đề, bạn có thể tham khảo File trong bài viết sau:

http://www.giaiphapexcel.com/diendan/threads/theo-dõi-và-truy-vấn-đơn-thuốc-nơi-phòng-khám-bệnh.126073/

Code để truy vấn và in hàng loạt trong bài viết sau:

http://www.giaiphapexcel.com/diendan/threads/giúp-tăng-tốc-xử-lý-code-in-hàng-loạt.133354/#post-843369


Như góp ý ở bài 2, bạn nên thiết kế 1 cái mẫu ở 1 sheet nào đó rồi đưa File lên nhờ các thành viên giúp tiếp.
Xin lỗi anh, nhưng anh đưa lý thuyết tầm cao quá, em chưa đủ đến trình độ đó, em cứ làm tạm theo ý em thôi


Phần code đã làm được
1. Code cho Hàm Function: Lấy danh sách tên File (*.doc*) kể cả trong thư mục con , bắt đầu từ thư mục chứa file nguồn


Mã:
Function show_list(ByVal Myfolder As String)
    Dim HAM_Morong_Scrip, List_Files, f1, sub_folder, List_Folder
    Set HAM_Morong_Scrip = CreateObject("Scripting.FileSystemObject")
    Set List_Files = HAM_Morong_Scrip.GetFolder(Myfolder).Files
   
   
    If HAM_Morong_Scrip.FolderExists(Myfolder) Then
        'Debug.Print "co chua thu muc con"
        For Each f1 In List_Files
            If f1.name Like "*.doc*" Then Debug.Print f1.Path & f1.name
        Next f1
        Set List_Folder = HAM_Morong_Scrip.GetFolder(Myfolder).SubFolders
        For Each sub_folder In List_Folder
            show_list sub_folder.Path
        Next sub_folder
    Else
        'Debug.Print "Khong chua thu muc con"
        For Each f1 In List_Files
            If f1.name Like "*.doc*" Then Debug.Print f1.Path & f1.name
        Next f1
    End If
   
    Set List_Files = Nothing
    Set List_Folder = Nothing
End Function
End Sub
Ví dụ thử nghiệm
Mã:
Sub Vi_du_thu_nghiem()
    show_list ActiveWorkbook.Path
End Sub

Thủ tục cho phép đưa giữ liệu đầu vào là Array (as string) (trong đó các phần tử là tên FullPathName của file doc sau đó ấn định sẽ Merger file
Mã:
Sub danh_sach_thu_nghiem(ByVal li As Variant)
    Dim wd As Object
    Dim wdocSource As Object
    On Error Resume Next
    Set wd = GetObject(, "Word.Application")
    If wd Is Nothing Then
        Set wd = CreateObject("Word.Application")
    End If
    On Error GoTo 0
    Dim str_doc As String, str_nguon_excel As String, str_ten_SHeet As String
    'str_doc = "C:\Users\Admin\Desktop\1_111.doc"
    str_nguon_excel = "C:\Users\Admin\Desktop\QUan lam HS QLCL\Nguon\NguonQuan.xlsm"
    str_ten_SHeet = "DATA_Chuyen_MER"
    For Each name_doc In li
        Set wdocSource = wd.Documents.Open(name_doc)
        wdocSource.MailMerge.OpenDataSource _
            name:=str_nguon_excel, _
            Connection:= _
            "Data Source=" & str_nguon_excel, _
            SQLStatement:="SELECT * FROM `" & str_ten_SHeet & "$`"
            wdocSource.Close SaveChanges:=True
    Next name_doc
  
    Set wdocSource = Nothing
    Set wd = Nothing
End Sub

End Sub



Phần thủ tục, em chưa kiểm tra kỹ, có thể có sai sót, với lại em chưa hiểu vài vấn đề nên còn chưa giải quyết được:


1. Muốn redim hoặc bằng cách nào đó, hạn chế bớt bộ nhớ cho mảng động
2. Muốn đưa kết quả Function trả về dạng mảng để đưa vào Sub ở dưới
3. Kiểm tra cuối

Nhờ anh, (mọi người) kiểm tra, bổ sung giúp em
 
Upvote 0
Tôi thấy hơi lạ.
Bạn có n tập tin Word. Theo tôi hiểu thì các tập tin này khác nhau. Vì nếu y hệt nhau thì sao lại giữ n tập tin y hệt nhau? Và n có thể thay đổi. Vd. bây giờ có n = 5 (5 tập tin), ngày mai có thể n= 7 (7 tập tin). Và có thể không chỉ thêm 2 tập tin mà ngay cả 5 tập tin đầu có thể có nội dung khác. Tức số tập tin và cả nội dung có thể thay đổi. Nếu thế thì không thể thiết kế n Form bên Excel và chỉ dùng code bên Excel để thao tác. Và kiểu đó không tổng quát. Vì khi chạy code mà số lượng và nội dung các tâp tin thay đổi thì các Form thiết kế trước đó vô dụng, còn các Form cho dữ liệu hiện hành thì chưa có.

Nhưng tôi thắc mắc. Bạn có n tập tin. Theo tôi hiểu thì với mỗi tập tin bạn đã làm Mail merge hoàn chỉnh: chọn cơ sở dữ liệu, thêm các trường (insert merge field), lưu tập tin. Chỉ có 1 thao tác cuối cùng là Finish & Merge.

Tại sao không làm thêm bước cuối cùng mà để tới bây giờ lại phải nhọc công? Chỉ là 3 click và chờ chút xíu (cái chờ này thì dùng code vẫn phải chờ). Không hiểu, bó tay.
 
Upvote 0
Bác không hiểu ý em rồi!. Em cần quản lý nhiều công trình: làm nhiều lần, nhưng số lượng các công văn file Word, hợp đồng, thông báo, giấy mời là theo Form đã có, mỗi công trình lại có một Folder để lưu trữ và quản lý, tóm lại Quản lý công trình theo từng Folder

Vậy sẽ nảy sỉnh cách làm như sau:
1. Dùng 1 folder chuẩn làm nơi lưu trữ (bao gồm: file excle nguồn chuẩn, 01 Thư mục: bên trong gồm nhiều thư mục con, mỗi thư mục con lại có nhiều file WORD khác nhau (bộ này lưu cố định tại Support)
2. Khi dùng chỉ cần COPY 01 file nguồn vào thư mục mới, đổi tên cho phù hợp, Nhập giữ liệu cho file nguồn này. Sau đó nhấn vào 1 nút duy nhất
3. Kết quả của công việc này:
VBA, copy+đổi hàng dọc thành ngang từ Sheet nhập liệu sang Sheet chỉ để chuyên Mer Word
VBA, copy thư mục + các file mẫu từ Support vào thư mục mới này
VBA, tự động cập nhật cho TOÀN BỘ file doc nằm trong từng thu mục mới này theo cách: MERGE WORD với cơ sở dữ liệu dùng chung là sheet Data_chuyen_MER (sheet chuyên Mer Word ở trên)
VBA, tự động chọn số lượng bản in, xuất bản in, đổi tên bản in, lưu cùng chỗ với file nguồn ở trên , tự đổng close an Save, tự dổng Rename cho phù hợp
4. Cái khó của em chỉ là code
4.1 tìm danh sách file doc (đã làm được) -> dùng hàm Function tự tạo để kết quả trả về là dạng mảng (chưa làm được)
4.2 Lấy kết quả ở bước 4.1 để dùng hàm FOR EACH duyệt qua toàn bộ và cập nhật cơ sở data Merge Word
4.3 toàn bộ các bước, in ấn, xuất, đổi tên, lưu trữ em có khả năng làm được
5. VẬY em cần là code và tư duy hợp lý, em tập trung vào thẳng vấn đề em cần, em đưa những gì em đã làm được lên cùng trao đổi
6. Nhưng bác lại toàn cho em kiến thức đâu đâu + bác có vẻ (em xin lỗi) nhưng bác không đọc kỹ yêu cầu của em

:((
 
Upvote 0
6. Nhưng bác lại toàn cho em kiến thức đâu đâu + bác có vẻ (em xin lỗi) nhưng bác không đọc kỹ yêu cầu của em
Tôi đọc kỹ. Nhưng tính tôi khác người. Khi tôi muốn giúp ai đấy thì trước tiên tôi phải hiểu họ cần gì. Tiếp theo tôi xét xem yêu cầu của họ thế nào. Nếu thấy hợp lý thì không tiếc thời gian. Mất nhiều hay ít thời gian là do vấn đề. Đã muốn giúp thì dù vấn đề đòi hỏi nhiều hay ít thời gian thì cũng không tiếc. Nhưng nếu tôi cho, tức nhận xét chủ quan, là yêu cầu không hợp lý thì một phút tôi cũng tiếc. Không phải người hỏi muốn gì tôi cũng cung phụng.
Bạn nghi tôi không đọc kỹ bài của bạn. Nhưng bạn be09 cũng đọc, và tôi không dám chắc là có thể làm theo ý bạn. Vì ý tưởng là tạo Form bên Excel với tất cả các trường dữ liệu cần lấy. Nếu có n tập tin Word khác nhau thì phải tạo n Form. Mà tương lai số lượng Form (tập tin Word) có thay đổi không? Nếu thay đổi thì sẽ có lúc chạy code thì thừa nhiều Form và thiếu những Form cần cho các tập tin Word hiện hành. Số lượng và nội dung của các tập tin Word có thay đổi không? Có đọc kỹ thì tôi cũng không biết được vì bạn có nói đâu.

Bài trước của tôi là hướng tới bài đầu tiên của bạn, không đề cập tới những bài sau.

Mà bạn cho là ai cũng thông minh, đọc bài của bạn thì phải hiểu. Nhưng có những người chậm hiểu như tôi, và họ có quyền thắc mắc. Bạn không cho họ cái quyền thắc mắc, quyền được hỏi cho rõ thì họ nghỉ chơi thôi.
Tôi xin dừng ở đây.
 
Upvote 0
Xin lỗi anh, nhưng anh đưa lý thuyết tầm cao quá, em chưa đủ đến trình độ đó, em cứ làm tạm theo ý em thôi


Phần code đã làm được
1. Code cho Hàm Function: Lấy danh sách tên File (*.doc*) kể cả trong thư mục con , bắt đầu từ thư mục chứa file nguồn


Mã:
Function show_list(ByVal Myfolder As String)
    Dim HAM_Morong_Scrip, List_Files, f1, sub_folder, List_Folder
    Set HAM_Morong_Scrip = CreateObject("Scripting.FileSystemObject")
    Set List_Files = HAM_Morong_Scrip.GetFolder(Myfolder).Files
  
  
    If HAM_Morong_Scrip.FolderExists(Myfolder) Then
        'Debug.Print "co chua thu muc con"
        For Each f1 In List_Files
            If f1.name Like "*.doc*" Then Debug.Print f1.Path & f1.name
        Next f1
        Set List_Folder = HAM_Morong_Scrip.GetFolder(Myfolder).SubFolders
        For Each sub_folder In List_Folder
            show_list sub_folder.Path
        Next sub_folder
    Else
        'Debug.Print "Khong chua thu muc con"
        For Each f1 In List_Files
            If f1.name Like "*.doc*" Then Debug.Print f1.Path & f1.name
        Next f1
    End If
  
    Set List_Files = Nothing
    Set List_Folder = Nothing
End Function
End Sub
Ví dụ thử nghiệm
Mã:
Sub Vi_du_thu_nghiem()
    show_list ActiveWorkbook.Path
End Sub

Thủ tục cho phép đưa giữ liệu đầu vào là Array (as string) (trong đó các phần tử là tên FullPathName của file doc sau đó ấn định sẽ Merger file
Mã:
Sub danh_sach_thu_nghiem(ByVal li As Variant)
    Dim wd As Object
    Dim wdocSource As Object
    On Error Resume Next
    Set wd = GetObject(, "Word.Application")
    If wd Is Nothing Then
        Set wd = CreateObject("Word.Application")
    End If
    On Error GoTo 0
    Dim str_doc As String, str_nguon_excel As String, str_ten_SHeet As String
    'str_doc = "C:\Users\Admin\Desktop\1_111.doc"
    str_nguon_excel = "C:\Users\Admin\Desktop\QUan lam HS QLCL\Nguon\NguonQuan.xlsm"
    str_ten_SHeet = "DATA_Chuyen_MER"
    For Each name_doc In li
        Set wdocSource = wd.Documents.Open(name_doc)
        wdocSource.MailMerge.OpenDataSource _
            name:=str_nguon_excel, _
            Connection:= _
            "Data Source=" & str_nguon_excel, _
            SQLStatement:="SELECT * FROM `" & str_ten_SHeet & "$`"
            wdocSource.Close SaveChanges:=True
    Next name_doc
 
    Set wdocSource = Nothing
    Set wd = Nothing
End Sub

End Sub



Phần thủ tục, em chưa kiểm tra kỹ, có thể có sai sót, với lại em chưa hiểu vài vấn đề nên còn chưa giải quyết được:


1. Muốn redim hoặc bằng cách nào đó, hạn chế bớt bộ nhớ cho mảng động
2. Muốn đưa kết quả Function trả về dạng mảng để đưa vào Sub ở dưới
3. Kiểm tra cuối

Nhờ anh, (mọi người) kiểm tra, bổ sung giúp em
mình cũng đang cần cái này, bạn đã hoàn thiện được chưa nhỉ? xin chia sẽ. chân thành cảm ơn!
 
Upvote 0
mình cũng đang cần cái này, bạn đã hoàn thiện được chưa nhỉ? xin chia sẽ. chân thành cảm ơn!
Chỉ ở dạng ý tưởng thôi. Mình cũng đang nhờ mọi người trên diễn đàn. Bạn cứ đặt theo dõi. Nếu được là biết luôn thôi.
Ôi trời. Mình đã trả lời nhầm sang chủ đề khác của mình đang theo dõi rồi.
 
Upvote 0
Tôi đề nghị 1 giải pháp cho bạn:
1. Không dùng Mail Merge mà dùng bookmark cho file Word để lấy chỗ chèn dữ liệu từ file Excel sang
2. Cứ giữ nguyên kết cấu theo chiều dọc như sheet DienGiaidoc (vì không dùng mail merge nên không cần theo chiều ngang)
3. Vì vẫn cần phải lưu dữ liệu đã làm nên khi ấn 1 phát thì ngoài việc "trộn" sang Word thì chép dữ liệu đã trộn sang sheet Data_chuyen_MER nhưng chuyển cột thành dòng.
4. Cần "trộn" lại dữ liệu cũ thì chọn vào cell bất kỳ ở dòng cần trộn ở sheet Data_chuyen_MER rồi chạy lệnh chỉ định để thi hành
 
Upvote 0
Web KT
Back
Top Bottom