Tổng hợp (gộp) nhiều sheet của 1 file Excel, nhiều file trong folder bằng Power Query nâng cao
I. Tổng hợp (gộp) nhiều sheet trong 1 file
Thông thường và với trình độ căn bản, khi muốn gộp (tổng hợp) nhiều sheet trên cùng 1 file Excel bằng Power query, các bạn tạo mỗi sheet 1 query con, sau đó Append chúng lại với nhau.
Như vậy sẽ có nhiều query con mất công quản lý chúng.
Các cách làm sau đây là chỉ tạo 1 query duy nhất.
Giả sử ta có file Data4Sheet.xlsx nằm ở thư mục D:MyPhamMY BOOKMCode-PowerQuery, trong đó có 4 sheet HCM, HN, DN, AG có cùng cấu trúc dữ liệu chuẩn, cùng số cột, thứ tự cột, tên cột, và bắt đầu từ dòng 1, không hề có merge cell, không có dữ liệu bên ngoài cột thừa, dòng thừa. Dữ liệu được định dạng Table sẵn. File đính kèm bên dưới
Cách 1: Dùng câu lệnh hàm M Table.Combine
let
FName= "D:MyPhamMY BOOKMCode-PowerQueryData4Sheet.xlsx",
Source = Table.Combine({Table.PromoteHeaders(Excel.Workbook(File.Contents(FName), null, true){[Item="HCM",Kind="Sheet"]}[Data]),
Table.PromoteHeaders(Excel.Workbook(File.Contents(FName), null, true) {[Item="HN",Kind="Sheet"]}[Data]),
Table.PromoteHeaders(Excel.Workbook(File.Contents(FName), null, true){[Item="AG",Kind="Sheet"]}[Data]),
Table.PromoteHeaders(Excel.Workbook(File.Contents(FName), null, true){[Item="DN",Kind="Sheet"]}[Data])})
in Source
Câu lệnh combine nối 4 query con nhưng mỗi query con được tạo ra ngay trong query tổng này, Mỗi sheet được lấy ra và gán dòng đầu làm tiêu đề trong 1 câu lệnh. Trong file MultiSheet đính kèm là Sheet Combine.
Cách này phải biết được trong file có bao nhiêu sheet, và tên mỗi sheet mới tạo được. Khi đổi tên sheet sẽ bị lỗi, khi thêm sheet phải sửa code của query thêm 1 dòng tạo query con.
Cách 2: Dùng câu lệnh Table.ExpandColumn từ 1 bảng các Table con
let
FName="D:MyPhamMY BOOKMCode-PowerQueryData4Sheet.xlsx",
Source = Table.SelectRows(Excel.Workbook(File.Contents(FName), null, true),each ([Kind] = "Table"))[Data],
List1 = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
ListColumns = Table.ColumnNames(List1{2}[Column1]),
Ketqua = Table.ExpandTableColumn(List1,"Column1",ListColumns)
in
Ketqua
Từ kết quả đầu tiên lấy từ workbook, lọc lấy list (Source) các Dữ liệu dạng Table, chỉ lấy cột có tên , chuyển thành table (List1)
Liệt kê tên cột dữ liệu thành 1 list (ListColumns) từ 1 record của List1 bằng hàm Table.ColumnNames.
Không cần biết List1 có bao nhiêu tên cột, và tên gì, dùng nó trong hàm able.ExpandTableColumn để ra kết quả cuối.
Cách này có ưu điểm là không cần biết file dữ liệu có bao nhiêu sheet, không cần biết tên sheet, cũng không cần biết tên các cột. MultiSheet đính kèm là Sheet MultiSheet. Ngoài ra, khi file dữ liệu gốc có thêm sheet, thì file chứa query tổng hợp chỉ cần refresh, sheet mới tự động thêm vào cuối bảng kết quả. SỬa tên sheet gốc thì query tổng hợp tự cập nhật mà không cần sửa code M. Cách 1 không làm được điều này
Cách 2 có thêm cột: Dùng cấu trúc vòng lặp của M-Code để thêm 1 cột chứa tên sheet.
let
FName="D:MyPhamMY BOOKMCode-PowerQueryData4Sheet.xlsx",
Source = Table.SelectRows(Excel.Workbook(File.Contents(FName), null, true),each ([Kind] = "Sheet")),
SourceData=Source[Data],
SheetName=Source[Item],
SheetNum={0..List.Count(SheetName)-1},
DataN= List.Transform(SheetNum, (i) =>
let
Data0 = Source[Data]{i},
Datai = Table.AddColumn(Table.PromoteHeaders(Data0), "Tỉnh thành", each SheetName{i})
in Datai),
List1 = Table.FromList(DataN, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
ListColumns = Table.ColumnNames(List1{0}[Column1]),
Ketqua = Table.ExpandTableColumn(List1,"Column1",ListColumns)
in
Ketqua
Dùng hàm List.Count để đếm số dòng của list SheetName, cho biết số sheet lấy được.
Dùng số sheet để tạo vòng lặp n lần tương ứng n sheet. Mỗi vòng lặp lấy 1 table con trong SourceData làm 2 việc:
– Do giả định sheet dữ liệu không định dạng table nên phải lấy Data dạng sheet, và phải dùng hàm PromoteHeaders để lấy dòng 1 làm tiêu đề,
– thêm 1 cột có tên "Tỉnh thành". nội dung là tên sheet tương ứng với table trong vòng lặp, tên sheet lấy từ list SheetName
Ghi chú
Vòng lặp tạo ra bởi hàm List.Transform, bắt đầu từ dòng DataN, chứa 1 cấu trúc let .. in và kết thúc sau in. Trong file đính kèm ở sheet MultiSheetWIthShName
Xem 2 file đính kèm, tải về ở thư mục nào thì sửa đường dẫn trong dòng đầu FName bằng đường dẫn thư mục tải về. Chỉ sửa duy nhất 1 chỗ và duy nhất 1 lần.
Tôi góp ý một tý:
Cách 1: nên đưa source excel vào một biến rồi khi combine gọi, như vậy code sẽ ngắn và chỉ connect lần duy nhất, cách của bạn nó đang connect tới 4 lần
Cách 2: Sau bước source là có thể expandcolumn rồi không cần tạo List, có thể thêm bước filter để lấy sheet hay table thôi
2186
Cám ơn bạn đã gợi ý. Cách 1 là cách tôi làm kiểu record macro của VBA rồi chỉnh sửa, chưa có đầu tư suy nghĩ nhiều. Sau đó khi rảnh rỗi mới nghĩ ra cách 2 và 2+. Phải nói rằng nhờ hướng dẫn về vòng lặp của bạn và @Hau151978 trong chủ đề giải thích [URL='www.giaiphapexcel.com/diendan/threads/ch%E1%BB%A7-%C4%91%E1%BB%81-power-query-m-code-t%E1%BB%95ng-h%E1%BB%A3p.153230/post-1004773']vòng lặp mà tôi làm được việc thêm cột trong 2+. Quá trình làm file trên là cả 1 quá trình mày mò đúng/ sai/ sửa nên chưa tối ưu.
Làm theo gợi ý của @excel_lv1.5
Cách 2
let
FName="D:MyPhamMY BOOKMCode-PowerQueryData4Sheet.xlsx",
Source = Table.SelectRows(Excel.Workbook(File.Contents(FName), null, true),each ([Kind] = "Table")),
ListColumns = Table.ColumnNames(Source{2}[Data]),
Table.ExpandTableColumn(Table.SelectColumns(Source,"Data"),"Data",ListColumns)
in
Ketqua
Cách 1 có hạn chế nên không sửa
www.giaiphapexcel.com/diendan/threads/t%E1%BB%95ng-h%E1%BB%A3p-g%E1%BB%99p-nhi%E1%BB%81u-sheet-c%E1%BB%A7a-1-file-excel-nhi%E1%BB%81u-file-trong-folder-b%E1%BA%B1ng-power-query-n%C3%A2ng-cao.156830/
Khóa học Power PI – Ứng dung trong Nhân sự
TỔNG QUAN KHÓA HỌC: POWER BI CHO NGÀNH NHÂN SỰ Khóa học Power BI cho Nhân sự được thiết kế dành riêng cho các...
Xem khóa học
Tôi hiểu gợi ý của @excel_lv1.5 về dùng biến là tạo 1 biến connect toàn bộ file và sửa như sau:
Theo tôi nhận xét thì chỉ connect 1 lần. Có lẽ nó khớp được cái mà bạn gọi là reference, hay bạn có ý khác?
II. TỔNG HỢP TỪ 1 FOLDER NHIỀU FILE, MỖI FILE NHIỀU SHEET
Dùng 2 vòng lặp lồng nhau, lấy hết các file trong folder, mỗi file lấy hết sheet. Điều kiện là tất cả sheet trong tất cả file là dữ liệu đúng chuẩn.
Có thể thêm bớt file, thêm bớt sheet, đổi tên file, đổi tên sheet tuỳ ý
Có thể thư mục bất kỳ với dữ liệu bất kỳ.
Giải nén thư mục Data, lấy đường dẫn thư mục sửa vào dòng 1 của query.
Thứ nhất: Folder nhiều file nhưng không cần mở file, thứ hai file nhiều sheet không cần tên sheet, thứ ba Sheet bao nhiêu cột, cột tên gì không cần biết.
Quan trọng hơn hết: Nếu tổng số dòng của tất cả file, tất cả sheet mà vượt quá số dòng của excel cũng làm được và lưu trữ để phân tích được. Về điểm này thì VBA, ADO cũng không làm được, còn công thức chỉ cần quá 10 ngàn dòng, 5 cột là hết chạy nổi.
Dùng M-Code hay bất kỳ phương pháp tổng hợp không mở file nào, cũng đòi hỏi cấu trúc dữ liệu chuẩn: Mỗi sheet chỉ 1 bảng dữ liệu, tiêu chuẩn về tiêu đề dữ liệu (không merge, tên cột không trùng, đồng nhất số lượng cột và tên cột của tất cả sheets cần tổng hợp trong tất cả cac files, ngay cả đồng nhất về chỉ số dòng chứa tiêu đề).
Nếu đạt tiêu chuẩn đó, và các sheet cần tổng hợp có tên theo 1 điểm chung nào đó, thì vẫn làm được. Ví dụ mỗi file đều có 1 (hoặc nhiều) sheet cần tổng hợp, tên của chúng là "Nhom Thao", "Nhom Ha", "Nhom Suong", "Nhom Vanaccex", … nghĩa là bắt đầu bằng cùng 1 nhóm ký tự, hoặc kết thúc bằng cùng 1 nhóm ký tự, hoặc ví dụ tên sheet cần lấy là "Th1", "Th2", … thì hoàn toàn có thể làm được.
Hãy tưởng tượng câu lệnh If(Left(Tên sheet, …)) = "abc" Then
Nếu có thể dùng If như vậy mà đạt, tức là làm được. If các kiểu mà không ra thì sẽ không được.
Ví dụ chủ đề này: [URL='www.giaiphapexcel.com/diendan/threads/t%E1%BB%95ng-h%E1%BB%A3p-nhi%E1%BB%81u-file-th%C3%A0nh-1-file-b%E1%BA%B1ng-power-query.156768/post-1040037']Tổng hợp nhiều file thành 1 file, mỗi file có nhiều sheet nhưng chỉ lấy 1 sheet "Nhom – Hà"
2189
Chẳng qua Function bạn viết gọn hơn và viết tách ra ngoài, còn tôi viết Function trực tiếp bên trong Code. Với lại tôi viết để không cần biết tên cột luôn.
Khi đó 1 bộ code M này dùng cho folder bất kỳ, file bất kỳ, sheet bất kỳ, và table cấu trúc bất kỳ.
Điều kiện tiên quyết để sử dụng Powe query là dữ liệu phải chuẩn và cùng cấu trúc ở tất cả file, tất cả sheet. Dữ liệu của bạn vi phạm 1 đống quy tắc:
– Dữ liệu merge cell (tốn công xóa dòng trống)
– File này bắt đầu dòng 12, file kia bắt đầu dòng 13, không đồng nhất
– Có dòng tổng cộng.
Bạn phải sửa ít nhất là 2 mục 2 và 3 rồi sử dụng code:
12 hay 13 thì thêm 1 cái if được. Còn dòng cộng thì bạn tự xóa bằng tay.
Cuối cùng, theo tôi nghĩ nếu chỉ 2 file thì làm combine bằng tay cho rồi. Code này chuyên trị dữ liệu chuẩn, không chơi dữ liệu không chuẩn. Vì dữ liệu không chuẩn khiến cho phải sửa tan nát code.
Thay
Bằng
Hoặc
Bạn hãy đọc phần căn bản trong tài liệu [URL='www.giaiphapexcel.com/diendan/threads/qu%C3%A0-t%E1%BA%B7ng-t%E1%BB%AB-smod-ptm0412-t%C3%A0i-li%E1%BB%87u-v%E1%BB%81-powerpivot-nh%C3%A2n-sinh-nh%E1%BA%ADt-gpe13.143641/post-927216']Power Pivot- Power query là biết cách làm từng bước. Code trong các bài trong chủ đề này thì copy paste thẳng vào query editor.