HeSanbi
Nam Nhân✨Hiếu Lễ Nghĩa Trí Tín✨
- Tham gia
- 24/2/13
- Bài viết
- 2,729
- Được thích
- 4,302
- Giới tính
- Nam
Bài viết này sẽ hướng dẫn cho các bạn hiểu biết thêm về biểu thức chính quy (Regular Expression) trong VBA.
Giúp các bạn dễ dàng thực hiện tìm kiếm chuỗi phức tạp hơn rất nhiều so với các cách tìm kiếm thông thường.
Các bạn hãy xem, nếu như bạn có một tập dữ liệu văn bản trộn lẫn các kiểu dữ liệu như Email, số điện thoại, ... nằm lẫn lộn với nhau, để tách chúng ra thành dữ liệu có cấu trúc để làm việc với chúng. Thì các cách tách dữ liệu bằng hàm trong Excel và phương thức tìm và thay thế hỗ trợ không đủ khả năng để tách những dạng dữ liệu phức tạp khác nhau. Chính vì vậy biểu thức chính quy sẽ giúp thực hiện điều đó dễ dàng hơn. Sau đây là hướng dẫn chi tiết để các bạn có thể thực hiện cho công việc của mình.
Đồng thời, hiện tại Excel 365 đã hỗ trợ hàm thay thế sử dụng biểu thức chính quy là REGEXREPLACE, dựa vào bài hướng dẫn này các bạn cũng có thể ứng dụng vào hàm dễ dàng.
Hướng dẫn cú pháp cơ bản để đặt biểu thức chính quy
Các lỗi thường gặp
Hướng dẫn lưu trữ biểu thức tự tạo
Các bạn cần ghi nhớ và lưu trữ các biểu thức do bạn sáng tạo, hoặc tìm được qua mạng, để dễ nhớ và truy cập lại nhanh chóng.
Hãy lưu trữ biểu thức vào bảng Excel, mỗi biểu thức thực hiện với một chuỗi có cấu trúc nào đó đều có tên, chính vì vậy hãy đặt tên để dễ nhớ cho biểu thức. Mỗi mẫu tìm kiếm đều cần có các ví dụ cụ thể nhiều trường hợp xảy ra, cần có phép thử đúng sai và kết quả cuối cùng.
Có thể tạo bảng lưu trữ như sau:
Các phương thức trong lớp Biểu thức chính quy dành cho VBA
Nếu khởi tạo một đối tượng đại diện chính của lớp là RE như sau:
Đặt tùy chọn để xác định cách tìm kiếm dữ liệu:
Các phương thức của lớp
Phần thực hành với biểu thức chính quy
Sau khi tìm hiểu xong phần cơ bản ở trên thì các bạn có thể bước vào phần thực hành này một cách dễ dàng để hiểu được các mã ví dụ về cách tìm kiếm, thay thế với các văn bản phức tạp mà bạn biết.
Trước hết, các bạn nên biết về cách khởi tạo lớp Regular Expression trong VBA
Khi viết mã trong VBA, có 2 cách khởi tạo lớp thư viện cho dự án
Tạo vài hàm tìm kiếm cơ bản chung hay dùng
Hàm khởi tạo lớp:
Hàm tìm kiếm:
Hàm thay thế:
Hướng dẫn thực hành tại các bài viết bên dưới:
----------------------------------------------------------
Add-in dưới link này của tôi có hỗ trợ sử dụng biểu thức chính quy để tìm và thay thế trong Excel rất linh hoạt, các bạn có thể tham khảo thêm để học và sử dụng biểu thức chính quy.
https://giaiphapexcel.com/diendan/threads/165337/
Giúp các bạn dễ dàng thực hiện tìm kiếm chuỗi phức tạp hơn rất nhiều so với các cách tìm kiếm thông thường.
Các bạn hãy xem, nếu như bạn có một tập dữ liệu văn bản trộn lẫn các kiểu dữ liệu như Email, số điện thoại, ... nằm lẫn lộn với nhau, để tách chúng ra thành dữ liệu có cấu trúc để làm việc với chúng. Thì các cách tách dữ liệu bằng hàm trong Excel và phương thức tìm và thay thế hỗ trợ không đủ khả năng để tách những dạng dữ liệu phức tạp khác nhau. Chính vì vậy biểu thức chính quy sẽ giúp thực hiện điều đó dễ dàng hơn. Sau đây là hướng dẫn chi tiết để các bạn có thể thực hiện cho công việc của mình.
Đồng thời, hiện tại Excel 365 đã hỗ trợ hàm thay thế sử dụng biểu thức chính quy là REGEXREPLACE, dựa vào bài hướng dẫn này các bạn cũng có thể ứng dụng vào hàm dễ dàng.
Hướng dẫn cú pháp cơ bản để đặt biểu thức chính quy
Ký hiệu định nghĩa cơ bản
\ là một ký tự bắt đầu cú pháp khi theo sau là: r, n, t, s, S, w, W, b, B, f, x## (định nghĩa Ascii 00-FF), uXXXX (định nghĩa ký tự unicode 0000-FFFF).
\ xóa bỏ định nghĩa của cú pháp khi theo sau thành chuỗi, gồm: \, $, ^, |, ., ?, +, *, ... và các ký tự bất kỳ nhưng không phải là ký tự như ở định nghĩa 1.
Ví dụ: \\ là xóa cú pháp chính nó, \|, \., \?, ...
\ Khi đi với một số và trước nó có mẫu là nhóm có chỉ định vị trí thì cú pháp đó hiểu là kế thứa.
Ví dụ: (abc)xx\1 là một mẫu có cú pháp kế thừa \1 kế thừa lại giá trị tìm được trong nhóm 1.
| Thanh dọc hiểu là mẫu điều kiện "hoặc", mỗi mẫu của 1 điều kiện bao gồm tất cả cú pháp liên tục ngang hàng, các cú pháp nhóm sẽ giới hạn mẫu điều kiện nằm trong chúng.
Ví dụ: hello|hi lấy chuỗi kí tự hello hoặc chuỗi hi.
Ví dụ: abc(hello|hi)ef lấy chuỗi abc và nhóm (hello hoặc hi) và chuỗi ef.
Cú pháp định nghĩa xác định ký tự
. Dấu chấm hiểu là chụp 1 ký tự bất kỳ không bao gồm ký tự xuống dòng
[ ] Đối sánh bất kỳ ký tự đơn nào giữa các dấu ngoặc [ ]. Ví dụ: [AaSs] chụp 1 ký tự là A hoặc a, S, s
Nếu muốn nhập chính ký hiệu này vào trong nó thì nhập là [[] tìm [ , nhập là [][] thì tìm dấu [ hoặc ], hoặc [\[]
[^ ] Chụp 1 ký tự không chứa các ký tự. Ví dụ: [^AaSs] chụp 1 ký tự khác A và a, S, s
[-] Chụp từ ký tự cho đến ký tự. Ví dụ: [A-Za-z0-9]+ chụp các ký tự A đến Z, a đến z, 0 đến 9 với một hoặc nhiều lần.
Nếu muốn nhập chính ký hiệu gạch ngang (-) thì đặt sau cùng, ví dụ [A-] thì tìm ký tự A hoặc dấu -
\s Chụp 1 ký tự khoảng trắng bao gồm các ký tự: cách, trở về dòng trên, xuống dòng, tab, tab đứng và feed
\S Chụp 1 ký tự không phải ký tự khoảng trắng.
\w Chụp 1 ký tự và số và dấu gạch dưới.
\W Chụp 1 Ký tự không phải Ký tự chữ và số và dấu gạch dưới.
\d Chụp 1 ký tự là số.
\D Chụp 1 ký tự không thuộc số.
\t Chụp 1 ký tự Tab.
\r Chụp 1 ký tự trở lại dòng trên (Charcode: 13).
\n Chụp 1 ký tự xuống dòng (Charcode: 10).
\f feed - ký tự nguồn cấp dữ liệu.
\uXXXX Chụp 1 ký tự Unicode (định nghĩa ký tự unicode hexadecimal từ 0000-FFFF).
Ví dụ: \u1EA5 lấy ký tự "ấ", lấy ký tự từ Z đến ấ thì biểu thức là [Z-\u1EA5].
\xXX Chụp 1 ký tự ASCII (định nghĩa Ascii từ hexadecimal 00-FF). Ví dụ: \x41 ký tự A.
Cú pháp định nghĩa xác định không gian liền kề giữa các kiểu ký tự
Ký tự bao gồm có chữ số, ký tự chữ, ký tự dấu, ký tự phân tách, \b và \B hiểu là định nghĩa ràng buộc liền kề của một ký tự.
\b Đến ký tự phân tách. Ví dụ: a\b hiểu là chụp ký tự a nếu theo sau a ký tự phân tách.
\B Không đến ký tự phân tách, hiểu là ngược lại ở trên.
Ký hiệu chỉ định số lượng
Cú pháp chỉ định số lượng của mẫu, luôn luôn nằm sau mẫu.
? Không hoặc lấy một lần của cú pháp.
Nếu dấu ? nằm sau một ký hiệu xác định nhiều số lượng, thì bắt buộc theo sau nó phải có mẫu, thì hiểu là chỉ tìm đến khi gặp 1 khớp mẫu phía sau thì dừng tìm.
Ví dụ: .+?b , tìm ký các tự bất kỳ cho đến khi gặp khớp mẫu là b.
Nếu không có dấu ? thì tìm bỏ qua các vị trí khớp mẫu b, cho đến khi tìm thấy khớp mẫu b cuối cùng thì dừng.
+ Khả năng khớp mẫu là một hoặc nhiều lần nhất có thể, kết hợp với dấu ? thì hiểu là tìm cho đến khi gặp mẫu liền sau thì dừng lại.
* Như cú pháp + nhưng khả năng khớp mẫu bắt đầu từ 0.
{9} Giới hạn số lượng khớp mẫu là 9 lần. Ví dụ: a{9} lấy 9 ký tự a liên tục.
{2,9} Khả năng khớp mẫu từ 2 đến 9 lần. Ví dụ: a{2,4} lấy 2 đến 4 ký tự a liên tục.
{3,} Khả năng khớp mẫu từ 3 lần trở lên. Ví dụ: a{4,} lấy a từ 4 ký tự trở lên.
{0,12} Khả năng khớp mẫu từ 0 đến 12 lần. Ví dụ: a{0,12}.
Ký hiệu buộc phải tìm khớp từ đầu hoặc ở cuối văn bản
^ Bắt đầu phải là chuỗi khớp với biểu thức. Ví dụ: ^hello.* bắt đầu bằng hello và chuỗi bất kỳ.
$ Kết thúc phải là chuỗi trước nó. Ví dụ: .+a$ chụp bất kỳ chuỗi nào cuối phải là các ký tự a.
Nhóm trong biểu thức chính quy:
Nhóm được định nghĩa là biểu thức nằm trong cặp ngoặc tròn ( và ).
Trong lớp Scipting.RegExp chỉ hỗ trợ 4 dạng nhóm sau đây:
1. ( ) Nhóm: chụp khớp biểu thức có chỉ định vị trí thứ tự nhóm.
Ví dụ: chụp ký tự a và b thì biểu thức nhóm là (a)(b) thì hiểu a nằm trong là nhóm 1, b nằm trong nhóm 2
Vị trí của nhóm có 2 chức năng:
+ Dùng để thay thế nhưng giữ lại nhóm đó, sử dụng ký tự đô-la là $ và 1 số để chỉ định vị trí nhóm trong chuỗi thay thế:
Ví dụ: trong chuỗi "abce" tìm "(a)bc" thay thế thành rỗng, nhưng giữ lại nhóm 1, thì chuỗi thay thế là "$1"
+ Dùng để kế thừa, sử dụng dấu \ và số trong biểu thức:
Ví dụ: trong chuỗi "abbce" tìm "(a)(?=b\1c)" hiểu là tìm ký tự a và theo sau phải là b và kế thừa \1 (a là nhóm 1) và ký tự c.
2. (?: ) Nhóm: Chụp nhưng không chỉ định vị trí của nhóm.
Ví dụ: (a)(?:b)(c) chụp ký tự a và b và c, hiểu a là nhóm 1, c là nhóm 2
3. (?= ) Nhóm: Nhóm liền kề sau nhưng không chụp. Luôn luôn cần có mẫu phía trước nó.
Ví dụ: a(?=b) chụp ký tự a, nếu theo sau a là ký tự b.
4. (?! ) Nhóm: Nhóm tìm không khớp không chỉ định vị trí nhóm.
Ví dụ: (?!hello) hiểu là chụp 5 ký tự bất kỳ nhưng phải khác chuỗi ký tự hello
Ký hiệu kế thừa \ và 1 số
Ký hiệu kế thừa bắt buộc trước nó phải có mẫu là nhóm có chỉ định vị trí, kế thừa có nghĩa là khi mẫu nhóm đó đã xác định được giá trị, thì sẽ kế thừa lại giá trị đó (không phải là kế thừa lại cả mẫu nhóm đó).
Ví dụ: với mẫu (\wx)(?=b\1c) Nếu nhóm 1 tìm được ký tự bất kỳ ở đây cho là d và x
thì theo sau phải là bdxc dx là kế thừa từ nhóm 1. thì chuỗi tìm kiếm bắt buộc chứa giá trị là dxbdxc
Cách xác định vị trí nhóm khi lòng các cú pháp nhóm vào nhau hiểu như sau:
Nhóm nào nằm ngoài cùng thì có thứ tự ưu tiên, nếu nhóm có các nhóm lòng trong nhau, thì ưu tiên đếm trước.
Rồi mới đếm các nhóm ngang hàng.
Ví dụ mẫu là: ((a(b)c)(?:d(e)f)(g))
Vì có cặp ngoặc ngoài cùng nên hiểu cả biểu thức là nhóm 1
Trong nhóm có nhóm thì đếm theo thứ tự + thêm 1, nên abc thuộc nhóm 2.
Trong nhóm 2 có nhóm con là b thì b này thuộc vị trí thứ 3. Trong nhóm 3 không còn. Thì trở ra khỏi nhóm để đếm tiếp tục.
Vì nhóm của def có cú pháp ?: không xem là có vị trí nên không đếm. Nhưng trong nhóm của def có nhóm con, nên e là thuộc nhóm thứ 4.
Và g là nhóm thứ 5 cuối cùng.
Thay thế linh hoạt:
Ký hiệu $ và số chỉ định vị trí nhóm trong chuỗi cần thay thế để giữ nhóm đó sau khi thay thế chuỗi mới.
(Có một số ngôn ngữ và trình soạn thảo mã như Notepad++ thì dấu \ sẽ chỉ định vị trí thay cho $)
Dựa vào ví dụ trên ta thay thế giữ nhóm và dịch vị trí như sau: đưa nhóm 1 đến vị trí thứ 2, đưa vị trí thứ 2 đến vị trí thứ 3 và vị trí thứ 3 về đầu, đồng thời chèn ký tự bất kì xen giữ, thì ta có mẫu thay thế là: "$3xxx$1xxx$2", mã VBA sẽ là:
Re.Pattern = "((a(b)c)(?:d(e)f)(g))"
Text = RE.Replace("abcdefg","$3xxx$1xxx$2")
Trong Excel365:
=REGEXREPLACE("Chuỗi","((a(b)c)(?:d(e)f)(g))","$3xxx$1xxx$2")
Phần biểu thức chính quy có trong các ngôn ngữ hiện đại, không hỗ trợ trong VBA
Các cú pháp biểu thức chính quy có trong các ngôn ngữ như: Python, PHP, java, javascript, perl, R, Rupy, C#, C/C++, ...
(?<= ) tìm xét biểu thức phía trước có khớp với mẫu, hiểu là cú pháp này nằm ở phía trước của mẫu.
(?<! ) tìm xét biểu thức phía trước phải không khớp với mẫu, hiểu là cú pháp này nằm ở phía trước của mẫu.
(?R) hoặc (?0) Đệ quy trong biểu thức chính quy. Đệ quy có nghĩa là tìm mẫu lòng trong mẫu đó nhiều lần
Ví dụ: chuỗi "Sum(Sum(Sum(Sum()))+Sum(Sum(Sum())))", các bạn sẽ thấy các cặp ngoặc nằm trong nhau, để tìm được các cặp lòng trong nhiều và nhiều lần nữa, thì cần đến Đệ quy.
(?(điều kiện)else|then)
(?P<tên> ) Đặt tên cho mẫu, sau khi tìm được mẫu, thì mẫu đó được gán theo tên. Để truy cập lại.
Các lỗi thường gặp
1. Nhập ký tự cú pháp như [, (, ), \, ?, +, * đơn lẻ để hiểu chúng là ký tự thường là sai, hãy thêm dấu \ phía trước chúng để hiểu chúng là ký tự thường, còn không phải nhập đúng cú pháp biểu thức.
2. Dễ nhầm ký tự xuống dòng newLine, vì vậy nên luôn luôn cần sử dụng \r?\n
3. Gây ra vòng lặp tính toán vô tận không thoát ra được khi sử dụng cú pháp số lượng nhiều lần như + và * không hợp lý.
Ví dụ: (((.*?)*?)*?)*?
Hướng dẫn lưu trữ biểu thức tự tạo
Các bạn cần ghi nhớ và lưu trữ các biểu thức do bạn sáng tạo, hoặc tìm được qua mạng, để dễ nhớ và truy cập lại nhanh chóng.
Hãy lưu trữ biểu thức vào bảng Excel, mỗi biểu thức thực hiện với một chuỗi có cấu trúc nào đó đều có tên, chính vì vậy hãy đặt tên để dễ nhớ cho biểu thức. Mỗi mẫu tìm kiếm đều cần có các ví dụ cụ thể nhiều trường hợp xảy ra, cần có phép thử đúng sai và kết quả cuối cùng.
Có thể tạo bảng lưu trữ như sau:
Chủ đề | Kiểu dữ liệu | Biểu thức | Ví dụ | Phép thử | Kết quả | Thay thế |
---|---|---|---|---|---|---|
Tìm số | Số | [-+]?\d+(?:\.\d+)? | ABC -2004 | TRUE | -2004 | Trống |
Tìm chuỗi | Ký tự | \w+ | Hello 2024 | TRUE | Hello | Trống |
Các phương thức trong lớp Biểu thức chính quy dành cho VBA
Nếu khởi tạo một đối tượng đại diện chính của lớp là RE như sau:
Set RE = CreateObject("VBScript.RegExp")
Đặt tùy chọn để xác định cách tìm kiếm dữ liệu:
RE.Global = TRUE | Lấy 1 hoặc tất cả khớp mẫu xảy ra. |
RE.MultiLine = TRUE | Khớp mẫu xảy ra trên các ngắt dòng. |
RE.IgnoreCase = TRUE | Bỏ phân biệt Hoa Thường |
RE.Pattern = "biểu thức" | Phương thức nhận mẫu sẽ sử dụng để đối sánh với chuỗi |
Các phương thức của lớp
bool = RE.test("chuỗi") | Kiểm tra thử xem có khớp mẫu không |
Text = RE.Replace("Chuỗi tìm kiếm","chuỗi thay thế") | Thay thế khớp mẫu thành chuỗi mới |
Text = RE.Replace("Chuỗi","$1") | Thay thế giữ nhóm bằng $ và số thứ tự nhóm |
Set Matches = RE.Execute("chuỗi") | Lấy các khớp mẫu (Matches) |
Matches(0) | Lấy 1 Item của Matches |
Matches.Count | Đếm item trong Matches |
Matches(0).FirstIndex | Vị trí bắt đầu của khớp mẫu |
Matches(0).Length | Độ dài của khớp mẫu |
Matches(0).SubMatches | Các nhóm trong mỗi khớp mẫu |
Matches(0).SubMatches.Count | Đếm item trong SubMatches |
Matches(0).SubMatches(0) | Xuất 1 giá trị của SubMatches |
Phần thực hành với biểu thức chính quy
Sau khi tìm hiểu xong phần cơ bản ở trên thì các bạn có thể bước vào phần thực hành này một cách dễ dàng để hiểu được các mã ví dụ về cách tìm kiếm, thay thế với các văn bản phức tạp mà bạn biết.
Trước hết, các bạn nên biết về cách khởi tạo lớp Regular Expression trong VBA
Khi viết mã trong VBA, có 2 cách khởi tạo lớp thư viện cho dự án
1. Chọn thư viện trong danh sách các thư viện đang chạy mặc định trong máy tính. có tên sau:
Microsoft VBScript Regular Expressions 5.5
2. Khởi tạo thư viện với phương thức CreateObject, mà không cần tham chiếu sớm thư viện.
Set RE = CreateObject("VBScript.RegExp")
Tạo vài hàm tìm kiếm cơ bản chung hay dùng
Hàm khởi tạo lớp:
JavaScript:
Private Function glbRegex(Optional bGlobal As Boolean = True, Optional ignoreCase As Boolean = True, Optional Multiline As Boolean = True) As Object
Set glbRegex = CreateObject("VBScript.RegExp")
With glbRegex: .Global = bGlobal: .ignoreCase = ignoreCase: .Multiline = Multiline: End With
End Function
Hàm tìm kiếm:
JavaScript:
Function TestRE(ByVal Expression$, Optional compare As Boolean) As String
On Error Resume Next
With CreateObject("VBScript.RegExp")
.Global = True: .IgnoreCase = compare: .MultiLine = False
.pattern = Find
TestRE = .test(Expression)
End With
Err.Clear
End Function
JavaScript:
Function RegExReplace(ByVal Expression$, ByVal Find$, ByVal Replace As String, Optional IgnoreCase As Boolean) As String
On Error Resume Next
With CreateObject("VBScript.RegExp")
.Global = True: .IgnoreCase = IgnoreCase: .MultiLine = False
.pattern = Find
RegExReplace = .Replace(Expression, Replace)
End With
Err.Clear
End Function
Hướng dẫn thực hành tại các bài viết bên dưới:
----------------------------------------------------------
Add-in dưới link này của tôi có hỗ trợ sử dụng biểu thức chính quy để tìm và thay thế trong Excel rất linh hoạt, các bạn có thể tham khảo thêm để học và sử dụng biểu thức chính quy.
https://giaiphapexcel.com/diendan/threads/165337/
(Sẽ còn tiếp cập nhật các đoạn mã ví dụ để học tập từ cơ bản đến nâng cao)
File đính kèm
Lần chỉnh sửa cuối: