Tuần 2 · Ngày 6 · Bài mới · 4 giờ
Mục tiêu
- Hiểu Power Query và cơ chế Applied Steps
- Nhận diện vấn đề chất lượng dữ liệu bằng Column quality / distribution / profile
- Loại bỏ dòng tiêu đề rác, dòng trống, dòng lặp tiêu đề, dòng tổng, dòng trùng
- Đổi kiểu dữ liệu đúng, kể cả với định dạng Việt Nam (Locale)
Dữ liệu cần tải
Ngày 1: Power Query Editor, làm sạch dữ liệu cơ bản
Kế hoạch 4 giờ
| Thời gian | Nội dung |
|---|---|
| Giờ 1 | Phần 1 - 3: Power Query là gì, giao diện, khám phá file bẩn |
| Giờ 2 - 3 | Phần 4: làm sạch từng bước |
| Giờ 4 | Bài tập, trong đó có 2 “cái bẫy” kinh điển |
1. Bối cảnh
Phòng kinh doanh gửi bạn file DonHang_Q1_2025_XuatTuPhanMem.xlsx, xuất từ phần mềm bán hàng của công ty. Mở bằng Excel, bạn sẽ thấy:
- 3 dòng tiêu đề công ty, ngày xuất, 1 dòng trống, rồi mới đến dòng tên cột.
- Cứ khoảng 400 dòng, phần mềm lại chèn 1 dòng trống và lặp lại dòng tên cột (do phân trang khi in).
- Cuối file có dòng Tổng cộng.
- Ngày đặt là văn bản kiểu
07/01/2025. Đơn giá là văn bản kiểu168.000. CK là5%hoặc để trống. - Tên cửa hàng có khoảng trắng thừa. Kênh viết lộn xộn (
GT,gt,GT,Mt…). - Một số dòng bị trùng do phần mềm xuất lỗi.
Nếu sửa tay trong Excel, tháng sau bạn lại phải sửa tay từ đầu. Với Power Query, bạn làm một lần. Tháng sau chỉ cần thay file và bấm Refresh.
2. Power Query là gì?
Power Query là “dây chuyền xử lý dữ liệu” có sẵn trong Power BI (và cả trong Excel, ở tab Data > Get Data).
- Mỗi thao tác bạn làm (xóa dòng, đổi kiểu, tách cột…) được ghi lại thành một bước (Applied Step).
- Mỗi lần Refresh, Power Query chạy lại toàn bộ các bước theo thứ tự trên dữ liệu mới nhất.
- File gốc không bao giờ bị sửa.
- Đằng sau mỗi bước là một dòng code bằng ngôn ngữ M. Bạn chưa cần viết M, nhưng sẽ học đọc dần từ hôm nay (học kỹ ở tuần 4).
3. Giao diện Power Query Editor
| Số | Vùng | Dùng để |
|---|---|---|
| 1 | Ribbon | Các tab Home, Transform, Add Column, View |
| 2 | Queries | Danh sách các query (mỗi query thường cho ra 1 bảng) |
| 3 | Formula bar | Code M của bước đang chọn. Nếu không thấy: View > bật Formula Bar |
| 4 | Column quality | Tỷ lệ Valid / Error / Empty của từng cột |
| 5 | Xem trước | Dữ liệu tại bước đang chọn. Chỉ là bản xem trước, tối đa khoảng 1.000 dòng đầu |
| 6 | Applied Steps | Danh sách các bước. Bấm vào một bước để xem dữ liệu tại thời điểm đó |
| 7 | Thanh trạng thái | Số cột, số dòng; phạm vi profiling |
Hai điểm khác biệt quan trọng giữa Transform và Add Column:
- Tab Transform: biến đổi ngay trên cột đang có.
- Tab Add Column: tạo cột mới, giữ nguyên cột cũ.
4. Thực hành: làm sạch từng bước
4.1 Mở file trong Power Query
- Tạo file Power BI mới, lưu thành
SaoMai_PQ_Tuan2.pbix. - Home > Get data > Excel workbook > chọn
DonHang_Q1_2025_XuatTuPhanMem.xlsx. - Trong Navigator, tick Sheet1 > bấm Transform Data (không bấm Load).
- Cửa sổ Power Query Editor mở ra. Ở pane Query Settings, đổi Name thành
DonHang.
4.2 Bật công cụ soi dữ liệu
View > tick Column quality, Column distribution, Column profile.
Ở thanh trạng thái phía dưới, bấm vào chữ Column profiling based on top 1000 rows, chọn Column profiling based on entire data set để thống kê toàn bộ dữ liệu thay vì 1.000 dòng đầu.
4.3 Xem Power Query đã tự làm gì
Nhìn Applied Steps. Có thể Power Query đã tự thêm vài bước: Source, Navigation, có khi thêm Promoted Headers và Changed Type.
- Bấm vào bước Promoted Headers (nếu có). Tên cột đang là “CÔNG TY CP HÀNG TIÊU DÙNG SAO MAI”, “Column2”… Power Query đã lấy nhầm dòng tiêu đề công ty làm tên cột.
- Xóa 2 bước tự động này: bấm dấu X bên trái tên bước Changed Type, rồi đến Promoted Headers. Xóa từ dưới lên.
Giờ dữ liệu có các cột Column1 … Column12, dòng 1 là “CÔNG TY CP…”.
4.4 Bỏ dòng rác phía trên và lấy tên cột
- Home > Remove Rows > Remove Top Rows > nhập 4 > OK. Đã bỏ 3 dòng tiêu đề và 1 dòng trống.
- Home > Use First Row as Headers. Dòng “Mã đơn hàng, Ngày đặt…” trở thành tên cột.
- Power Query lại tự thêm bước Changed Type. Xóa bước này đi. Ta sẽ đổi kiểu ở cuối.
4.5 Bỏ dòng trống
Home > Remove Rows > Remove Blank Rows. Bước này xóa các dòng mà mọi ô đều trống.
4.6 Bỏ dòng lặp tên cột và dòng Tổng cộng
- Bấm mũi tên lọc ở tiêu đề cột Mã đơn hàng.
- Bỏ tick 2 giá trị Mã đơn hàng và Tổng cộng. Nếu danh sách quá dài, gõ vào ô tìm kiếm.
- Nếu Power Query báo List may be incomplete, bấm Load more.
Có thể làm chắc chắn hơn: mũi tên lọc > Text Filters > Does Not Equal > Mã đơn hàng > And > Does Not Equal > Tổng cộng.
Xem code M của bước vừa tạo trên Formula bar:
= Table.SelectRows(#"Removed Blank Rows", each ([Mã đơn hàng] <> "Mã đơn hàng" and [Mã đơn hàng] <> "Tổng cộng"))
Đọc như câu tiếng Việt: “Từ bảng ở bước Removed Blank Rows, chọn các dòng mà mỗi dòng có Mã đơn hàng khác ‘Mã đơn hàng’ và khác ‘Tổng cộng’.”
4.7 Bỏ cột không cần
Chuột phải tiêu đề cột Ghi chú > Remove.
4.8 Cắt khoảng trắng thừa
- Chọn các cột văn bản: Tên cửa hàng, Kênh, Vùng, Tên sản phẩm (Ctrl + click).
- Transform > Format > Trim. Bỏ khoảng trắng ở đầu và cuối chuỗi.
- Tiếp tục Transform > Format > Clean. Bỏ các ký tự điều khiển ẩn, ví dụ ký tự xuống dòng.
4.9 Bỏ dòng trùng
- Bấm vào ô góc trên trái của bảng (biểu tượng bảng nhỏ) > Remove Duplicates.
- Hoặc chọn tất cả các cột (Ctrl + A khi đang chọn một tiêu đề cột) > Home > Remove Rows > Remove Duplicates.
- Bước này giữ lại một dòng cho mỗi nhóm dòng giống hệt nhau trên mọi cột đang chọn.
4.10 Đổi kiểu dữ liệu, kể cả định dạng Việt Nam
Bấm biểu tượng kiểu dữ liệu ở bên trái tên cột (ABC, 123, lịch…) để đổi kiểu.
| Cột | Giá trị mẫu | Kiểu đích | Cách đổi |
|---|---|---|---|
| Mã đơn hàng, Mã CH, Tên cửa hàng, Kênh, Vùng, Mã SKU, Tên sản phẩm | Văn bản | Text | Bình thường |
| SL (thùng) | 2 (vài dòng là văn bản "2") | Whole Number | Bình thường |
| CK | 5% | Percentage | Bình thường |
| Ngày đặt | 07/01/2025 (ngày 7 tháng 1) | Date | Using Locale |
| Đơn giá | 168.000 (một trăm sáu mươi tám nghìn) | Whole Number | Using Locale |
Đổi kiểu bằng Locale:
- Chuột phải cột Ngày đặt > Change Type > Using Locale…
- Data Type = Date, Locale = Vietnamese (Vietnam) > OK.
- Làm tương tự với Đơn giá: Data Type = Whole Number, Locale = Vietnamese (Vietnam).
Ảnh chụp màn hình sẽ được bổ sung
Hộp thoại “Change Type with Locale”: Data Type = Date, Locale = Vietnamese (Vietnam), phần xem trước bên dưới.
Vì sao cần Locale?
- Theo kiểu Mỹ (en-US),
07/01/2025là ngày 1 tháng 7, và168.000là 168 phẩy 000, tức 168. - Theo kiểu Việt Nam (vi-VN),
07/01/2025là ngày 7 tháng 1, và168.000là một trăm sáu mươi tám nghìn.
Power Query mặc định dùng cài đặt vùng của file .pbix, xem ở File > Options and settings > Options > Current File > Regional Settings. Máy bạn đặt kiểu gì thì Power Query hiểu kiểu đó. Using Locale giúp kết quả đúng trên mọi máy.
4.11 Kiểm tra và nạp
- Nhìn Column quality: mọi cột phải Valid 100%, Error 0%. CK có thể Empty khoảng 53%, vì nhiều dòng không có chiết khấu.
- Thanh trạng thái: 12 → 11 COLUMNS, số dòng: xem bài tập 1.
- Home > Close & Apply. Dữ liệu được nạp vào Power BI.
4.12 Đọc lại toàn bộ code
Home > Advanced Editor. Bạn sẽ thấy toàn bộ các bước dưới dạng code M, đại ý như sau (đường dẫn file và tên bước có thể khác):
let
Source = Excel.Workbook(File.Contents("C:\KhoaHoc\data\tuan-02\DonHang_Q1_2025_XuatTuPhanMem.xlsx"), null, true),
Sheet1_Sheet = Source{[Item="Sheet1",Kind="Sheet"]}[Data],
#"Removed Top Rows" = Table.Skip(Sheet1_Sheet, 4),
#"Promoted Headers" = Table.PromoteHeaders(#"Removed Top Rows", [PromoteAllScalars=true]),
#"Removed Blank Rows" = Table.SelectRows(#"Promoted Headers", each not List.IsEmpty(List.RemoveMatchingItems(Record.FieldValues(_), {"", null}))),
#"Filtered Rows" = Table.SelectRows(#"Removed Blank Rows", each ([Mã đơn hàng] <> "Mã đơn hàng" and [Mã đơn hàng] <> "Tổng cộng")),
#"Removed Columns" = Table.RemoveColumns(#"Filtered Rows", {"Ghi chú"}),
#"Trimmed Text" = Table.TransformColumns(#"Removed Columns", {{"Tên cửa hàng", Text.Trim, type text}, {"Kênh", Text.Trim, type text}, {"Vùng", Text.Trim, type text}, {"Tên sản phẩm", Text.Trim, type text}}),
#"Cleaned Text" = Table.TransformColumns(#"Trimmed Text", {{"Tên cửa hàng", Text.Clean, type text}, {"Kênh", Text.Clean, type text}, {"Vùng", Text.Clean, type text}, {"Tên sản phẩm", Text.Clean, type text}}),
#"Removed Duplicates" = Table.Distinct(#"Cleaned Text"),
#"Changed Type with Locale" = Table.TransformColumnTypes(#"Removed Duplicates", {{"Ngày đặt", type date}, {"Đơn giá", Int64.Type}}, "vi-VN"),
#"Changed Type" = Table.TransformColumnTypes(#"Changed Type with Locale", {{"Mã đơn hàng", type text}, {"Mã CH", type text}, {"Mã SKU", type text}, {"SL (thùng)", Int64.Type}, {"CK", Percentage.Type}})
in
#"Changed Type"
Chưa cần hiểu hết. Chỉ cần nhận ra 3 điều:
- Mỗi dòng giữa
letvàinlà một bước trong Applied Steps. - Mỗi bước dùng kết quả của bước ngay trước nó, ví dụ
#"Removed Columns"dùng#"Filtered Rows". - Dòng sau
inlà kết quả cuối cùng.
5. Bài tập tự làm
Kiểm tra kết quả làm sạch. Sau khi làm xong phần 4:
- Bảng
DonHangcó bao nhiêu dòng? Xem ở Table view, hoặc tạo card Count of Mã đơn hàng. - Tổng SL (thùng) là bao nhiêu?
- Dòng Tổng cộng trong file gốc ghi tổng SL là bao nhiêu? Vì sao khác với con số của bạn?
- 10.543 dòng.
- Tổng SL = 32.448 thùng.
- Dòng Tổng cộng trong file ghi 32.552. Chênh lệch 104 thùng đến từ 37 dòng trùng mà phần mềm xuất thừa: dòng tổng của phần mềm đã cộng cả các dòng trùng. Số của bạn mới đúng.
Hành trình số dòng (bấm từng bước trong Applied Steps và xem thanh trạng thái):
| Bước | Số dòng |
|---|---|
| Sheet gốc | 10.639 |
| Sau Remove Top Rows 4 + Use First Row as Headers | 10.634 |
| Sau Remove Blank Rows | 10.607 (bỏ 27 dòng trống) |
| Sau lọc “Mã đơn hàng” và “Tổng cộng” | 10.580 (bỏ 26 dòng lặp tên cột và 1 dòng tổng) |
| Sau Trim/Clean + Remove Duplicates | 10.543 (bỏ 37 dòng trùng) |
Lưu ý: thanh trạng thái có thể hiện “999+ ROWS”. Để xem số chính xác, hãy chọn một cột > Transform > Count Rows (nhớ xóa bước này sau khi xem), hoặc xem sau khi Close & Apply.
Cái bẫy số 1: thứ tự bước. Trong Applied Steps, kéo bước Removed Duplicates lên trước bước Trimmed Text (kéo thả để đổi thứ tự).
- Số dòng cuối cùng bây giờ là bao nhiêu?
- Vì sao?
- Kéo về đúng thứ tự cũ.
- 10.555 dòng, thừa 12 dòng.
- Trong 37 dòng trùng, 12 dòng chỉ khác dòng gốc ở khoảng trắng cuối Tên cửa hàng. Trước khi Trim, máy coi đó là 2 giá trị khác nhau, nên Remove Duplicates không xóa. Sau khi Trim, chúng giống hệt nhau và mới bị xóa.
Bài học: chuẩn hóa văn bản (Trim, Clean, chữ hoa/thường) trước khi khử trùng.
Cảnh báo: kéo thả bước có thể làm hỏng các bước sau nếu chúng tham chiếu đến cột đã bị đổi tên hay bị xóa. Power Query sẽ báo lỗi màu vàng. Khi đó, hãy kéo về thứ tự cũ.
Cái bẫy số 2: Locale. Tạo một bản sao query: chuột phải DonHang trong pane Queries > Duplicate, đặt tên DonHang_ThuLocale. Trong bản sao:
- Xóa bước Changed Type with Locale.
- Đổi kiểu Ngày đặt sang Date và Đơn giá sang Whole Number bằng Using Locale, nhưng chọn Locale = English (United States).
- Quan sát: dòng có Ngày đặt gốc
07/01/2025thành ngày nào? Dòng có ngày13/01/2025thì sao? Đơn giá168.000thành bao nhiêu? - Xóa query thử nghiệm này.
Với Locale English (United States):
| Giá trị gốc | Kết quả | Vấn đề |
|---|---|---|
07/01/2025 | 01/07/2025 (1 tháng 7) | Sai lặng lẽ, không báo lỗi. Nguy hiểm nhất |
13/01/2025 | Error (không có tháng 13) | Ít nhất còn thấy được |
168.000 | 168 hoặc Error, tùy phiên bản | Vì Mỹ dùng dấu chấm làm dấu thập phân |
Bài học: dữ liệu Việt Nam (ngày dd/mm/yyyy, số có dấu chấm ngăn hàng nghìn) luôn đổi kiểu bằng Using Locale = Vietnamese (Vietnam).
Kiểm tra nhanh: sau khi đổi kiểu ngày, xem Column profile của cột ngày. Dữ liệu Q1/2025 thì ngày nhỏ nhất là 02/01/2025, ngày lớn nhất là 31/03/2025. Nếu thấy tháng 4 - 12, chắc chắn đã sai Locale.
Đọc Column profile. Với bảng DonHang đã sạch (profiling trên entire data set):
- Cột CK có bao nhiêu % Empty? Ý nghĩa kinh doanh của ô trống ở cột này là gì?
- Cột Kênh có bao nhiêu giá trị khác nhau (distinct)? Vì sao không phải 2?
- Cột Vùng có bao nhiêu giá trị khác nhau?
- CK: khoảng 53% Empty (5.621 / 10.543 dòng). Ô trống nghĩa là không có chiết khấu: không thuộc chương trình khuyến mãi và là kênh GT. Khi tính doanh thu, cần thay trống bằng 0. Nếu không, phép nhân với null sẽ ra null (bài ngày mai).
- Kênh: 6 giá trị:
GT,gt,Gt,MT,mt,Mt. Sau Trim, các biến thể có khoảng trắng (GT,MT) đã gộp lại, nhưng chữ hoa/thường vẫn khác nhau, vì Power Query so sánh văn bản có phân biệt hoa thường. Ngày mai sẽ dùng Uppercase để chuẩn hóa. - Vùng: 9 giá trị. Mỗi vùng có 3 cách viết:
Miền Bắc,MIỀN BẮC,miền bắc…
Mô phỏng tháng sau. Đây là phép thử quan trọng nhất của Power Query.
- Mở file Excel gốc, xóa khoảng 2.000 dòng dữ liệu bất kỳ ở giữa, lưu thành tên khác (để giữ bản gốc), ví dụ
DonHang_Thang_Sau.xlsx. - Trong Power Query, chọn bước Source > bấm biểu tượng bánh răng ⚙ > đổi đường dẫn sang file mới > OK.
- Bấm Home > Refresh Preview. Mọi bước có chạy không lỗi không? Số dòng thay đổi ra sao?
- Đổi lại về file gốc.
Nếu các bước được làm đúng, query chạy không lỗi và số dòng giảm tương ứng. Đây chính là giá trị của Power Query: làm một lần, dùng mãi.
Các lỗi có thể gặp và nguyên nhân:
| Lỗi | Nguyên nhân |
|---|---|
| Lỗi ở bước lọc dòng | Bạn đã lọc bằng cách tick/bỏ tick danh sách, và danh sách đó bị “đông cứng” theo dữ liệu cũ. Kiểu lọc <> (Does Not Equal) an toàn hơn |
| Lỗi The column ‘Ghi chú’ wasn’t found | File mới không có cột Ghi chú. Dùng Remove Other Columns sẽ an toàn hơn |
| Lỗi ở bước Source | Đường dẫn file sai. Tuần 3 sẽ học Parameter để đổi đường dẫn dễ dàng |
6. Tự đánh giá
- Tôi giải thích được Applied Steps hoạt động thế nào khi Refresh
- Tôi biết xóa bước tự động Promoted Headers / Changed Type khi cần
- Tôi làm được: Remove Top Rows, Use First Row as Headers, Remove Blank Rows, lọc dòng rác, Trim/Clean, Remove Duplicates
- Tôi biết vì sao phải Trim trước Remove Duplicates
- Tôi đổi kiểu được bằng Using Locale = Vietnamese (Vietnam)
- Bảng DonHang của tôi có đúng 10.543 dòng