Xử lý Chuỗi, tách số ra khỏi chuỗi (1 người xem)

Liên hệ QC

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

TuanPV2803

Thành viên mới
Tham gia
27/7/18
Bài viết
13
Được thích
2
Dear các anh chị!
Em có một bảng tính gồm rất nhiều mã hàng như sau:
CP950x2150mt
cox1230x900
Ctp560x1830tl
.....
Em muốn viết code tách riêng các chuỗi số ra 2 cột khác nhau ví dụ:


CP950x2150mt

950

2150

Nhưng thật sự em đã tìm kiếm rất nhiều và chỉ thấy tách ra thành 9502150
Vậy rất mong các anh chị em trong diễn đàn giúp đỡ em với!
Em xin chân thành cảm ơn!
Em gửi file đính kèm mong các anh chị em giúp em với ạ!
 

File đính kèm

Dear các anh chị!
Em có một bảng tính gồm rất nhiều mã hàng như sau:
CP950x2150mt
cox1230x900
Ctp560x1830tl
.....
Em muốn viết code tách riêng các chuỗi số ra 2 cột khác nhau ví dụ:

CP950x2150mt

950

2150

Nhưng thật sự em đã tìm kiếm rất nhiều và chỉ thấy tách ra thành 9502150
Vậy rất mong các anh chị em trong diễn đàn giúp đỡ em với!
Em xin chân thành cảm ơn!
Em gửi file đính kèm mong các anh chị em giúp em với ạ!
Chuyện này "hình như" dùng VBA cũng có khả năng giải quyết.
Nhưng "Sử lý" và "Dear" dò tự điển chưa ra nên khó mà xem tiếp.
 
Upvote 0
Dear các anh chị!
Em có một bảng tính gồm rất nhiều mã hàng như sau:
CP950x2150mt
cox1230x900
Ctp560x1830tl
.....
Em muốn viết code tách riêng các chuỗi số ra 2 cột khác nhau ví dụ:

CP950x2150mt

950

2150

Nhưng thật sự em đã tìm kiếm rất nhiều và chỉ thấy tách ra thành 9502150
Vậy rất mong các anh chị em trong diễn đàn giúp đỡ em với!
Em xin chân thành cảm ơn!
Em gửi file đính kèm mong các anh chị em giúp em với ạ!

Nếu dòng nào cũng có chữ "x" thì trong thời gian chờ đợi nên tách ra 2 cột (trước chữ x và sau chữ x). Sau đó dùng vba tách số và chữ ra là xong. Còn không thì chờ Anh/Em khác giúp cho code tách luôn.
 

File đính kèm

Upvote 0
Chuyện này "hình như" dùng VBA cũng có khả năng giải quyết.
Nhưng "Sử lý" và "Dear" dò tự điển chưa ra nên khó mà xem tiếp.
Dạ em cảm ơn sự chỉ bảo của anh về chính tả! lần sau em sẽ chú ý nhiều hơn ạ!
Bài đã được tự động gộp:

Nếu dòng nào cũng có chữ "x" thì trong thời gian chờ đợi nên tách ra 2 cột (trước chữ x và sau chữ x). Sau đó dùng vba tách số và chữ ra là xong. Còn không thì chờ Anh/Em khác giúp cho code tách luôn.
Em cảm ơn anh nhiều cách của anh cũng rất hay để em làm trước theo cách này, có gì nhờ các anh em trong diễn đàn giúp viết giùm code tách luôn không cần bước tách nhỏ ra 2 cột ạ. thật sự em rất muốn học để làm như vậy!
 
Upvote 0
Từ khóa cho bạn nè "CtoNPlus", bạn search trên GPE sẽ ra.
 
Upvote 0
Nếu dòng nào cũng có chữ "x" thì trong thời gian chờ đợi nên tách ra 2 cột (trước chữ x và sau chữ x). Sau đó dùng vba tách số và chữ ra là xong. Còn không thì chờ Anh/Em khác giúp cho code tách luôn.
Hổng ăn nỗi với dữ liệu chẳng có quy luật nào:
Bx1000x450RF -------->dòng 11
B250x324-S1 ---------->dòng 69
........................................
 
Upvote 0
CP950x2150mt
cox1230x900
Ctp560x1830tl
.....
Em muốn viết code tách riêng các chuỗi số ra 2 cột khác nhau ví dụ:

CP950x2150mt

950

2150


Chào bạn, bạn có thể xem qua code của tôi
Bạn có thể copy code sau vào Code của Worksheet chứa dữ liệu của bạn.
Giải thích một tí:
Code này sử dụng Regular expression
Nếu bạn Chọn một Cells mà có chứa dữ liệu mẫu thì nó sẽ cho kết quả ra đằng sau
Kể cả một mảng duyệt theo cột

Để giới hạng vùng chọn để Code thực hiện:
PHP:
If Intersect(Target, Range("A:A, D:D")) Is Nothing Then Exit Sub

PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  On Error GoTo EndS
  Dim ref As Object, isRefs As Boolean
  For Each ref In Application.VBE.ActiveVBProject.References
    If ref.Name = "VBScript_RegExp_55" Then isRefs = True
  Next ref
  If Not isRefs Then _
    ThisWorkbook.VBProject.References.AddFromFile "C:\Windows\system32\vbscript.dll\3"
  Dim iRegex As New VBScript_RegExp_55.RegExp
  Dim isArr As Boolean
  If IsArray(Selection.Value) Then
    If UBound(Selection.Value, 2) = 1 Then
      isArr = True
      Dim Arr: Arr = Selection.Value
      Dim aRow&: aRow = Selection.Row
      Dim aCol&: aCol = Selection.Column
    Else
      Exit Sub
    End If
  Else
    isArr = False
    Dim Text$: Text = Selection.Value
    If Text = "" Then Exit Sub
  End If

  With iRegex
    .Global = True
    .Pattern = "\d+[xX]\d+"
      If isArr Then
        Dim i
        For i = LBound(Arr) To UBound(Arr)
          If Arr(i, 1) <> "" And .Test(Arr(i, 1)) Then
            Arr(i, 1) = Replace(Arr(i, 1), "X", "x")
            Cells(aRow + i - 1, aCol + 1).Value = Split(.Execute(Arr(i, 1))(0), "x")(0)
            Cells(aRow + i - 1, aCol + 2).Value = Split(.Execute(Arr(i, 1))(0), "x")(1)
          End If
        Next i
      Else
        If .Test(Text) Then
          Selection(1, 2) = Split(.Execute(Text)(0), "x")(0)
          Selection(1, 3) = Split(.Execute(Text)(0), "x")(1)
        End If
      End If

  End With
EndS:
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Dear các anh chị!
Em có một bảng tính gồm rất nhiều mã hàng như sau:
CP950x2150mt
cox1230x900
Ctp560x1830tl
.....
Em muốn viết code tách riêng các chuỗi số ra 2 cột khác nhau ví dụ:

CP950x2150mt

950

2150

Nhưng thật sự em đã tìm kiếm rất nhiều và chỉ thấy tách ra thành 9502150
Vậy rất mong các anh chị em trong diễn đàn giúp đỡ em với!
Em xin chân thành cảm ơn!
Em gửi file đính kèm mong các anh chị em giúp em với ạ!
Dùng hàm nhé!
 

File đính kèm

Upvote 0
Chào bạn, bạn có thể xem qua code của tôi
Bạn có thể copy code sau vào Code của Worksheet chứa dữ liệu của bạn.
Giải thích một tí:
Code này sử dụng Regular expression
Nếu bạn Chọn một Cells mà có chứa dữ liệu mẫu thì nó sẽ cho kết quả ra đằng sau
Kể cả một mảng duyệt theo cột

Để giới hạng vùng chọn:
PHP:
If Intersect(Target, Range("A:A, D:D")) Is Nothing Then Exit Sub

PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  On Error GoTo EndS
  Dim ref As Object, isRefs As Boolean
  For Each ref In Application.VBE.ActiveVBProject.References
    If ref.Name = "VBScript_RegExp_55" Then isRefs = True
  Next ref
  If Not isRefs Then _
    ThisWorkbook.VBProject.References.AddFromFile "C:\Windows\system32\vbscript.dll\3"
  Dim iRegex As New VBScript_RegExp_55.RegExp
  Dim isArr As Boolean
  If IsArray(Selection.Value) Then
    If UBound(Selection.Value, 2) = 1 Then
      isArr = True
      Dim Arr: Arr = Selection.Value
      Dim aRow&: aRow = Selection.Row
      Dim aCol&: aCol = Selection.Column
    End If
  Else
    isArr = False
    Dim Text$: Text = Selection.Value
    If Text = "" Then Exit Sub
  End If

  With iRegex
    .Global = True
    .Pattern = "\d+[xX]\d+"
      If isArr Then
        Dim i
        For i = LBound(Arr) To UBound(Arr)
          If Arr(i, 1) <> "" And .Test(Arr(i, 1)) Then
            Arr(i, 1) = Replace(Arr(i, 1), "X", "x")
            Cells(aRow + i - 1, aCol + 1).Value = Split(.Execute(Arr(i, 1))(0), "x")(0)
            Cells(aRow + i - 1, aCol + 2).Value = Split(.Execute(Arr(i, 1))(0), "x")(1)
          End If
        Next i
      Else
        If .Test(Text) Then
          Selection(1, 2) = Split(.Execute(Text)(0), "x")(0)
          Selection(1, 3) = Split(.Execute(Text)(0), "x")(1)
        End If
      End If

  End With
EndS:
End Sub
Dạ em cảm ơn anh nhiều nhưng thật sự em mới bắt đầu tập tành nên rất dốt. em đã copy Code của anh và pase vào trong module nhưng không biết sử dụng sao được nhờ anh hướng dẫn giúp
 
Upvote 0
Dạ em cảm ơn anh nhiều nhưng thật sự em mới bắt đầu tập tành nên rất dốt. em đã copy Code của anh và pase vào trong module nhưng không biết sử dụng sao được nhờ anh hướng dẫn giúp
Bạn đọc kĩ bài hướng dẫn chứ "copy code sau vào Code của Worksheet chứa dữ liệu của bạn"

Capture.PNG
 
Upvote 0
Dạ em cảm ơn anh nhiều nhưng thật sự em mới bắt đầu tập tành nên rất dốt. em đã copy Code của anh và pase vào trong module nhưng không biết sử dụng sao được nhờ anh hướng dẫn giúp
Hướng dẫn là Copy vào VBE của sheet chứ đâu phải vào Module, chọn ô nào trong sheet code cũng chạy ???
Dùng hàm tự tạo như bài #8 xem sao.
 
Upvote 0
chọn ô nào trong sheet code cũng chạy ???
Em sợ chủ Topic có dữ liệu nhiều cột nên cho Code chạy tự do.
Nên Em đã thêm một đoạn code giới hạn vùng Code chạy. Không biết bạn này biết sử dụng không.
Nếu bạn ấy muốn viết thành Hàm thì chuyển sang Hàm. Thấy dùng hàm sẽ không hay. Phải đánh công thức vào Ô
 
Upvote 0
Dear các anh chị!
Em có một bảng tính gồm rất nhiều mã hàng như sau:
CP950x2150mt
cox1230x900
Ctp560x1830tl
.....
Em muốn viết code tách riêng các chuỗi số ra 2 cột khác nhau ví dụ:

CP950x2150mt

950

2150

Nhưng thật sự em đã tìm kiếm rất nhiều và chỉ thấy tách ra thành 9502150
Vậy rất mong các anh chị em trong diễn đàn giúp đỡ em với!
Em xin chân thành cảm ơn!
Em gửi file đính kèm mong các anh chị em giúp em với ạ!
Dùng hàm tự tạo
Mã:
Function TachSo(iStr As String, iD As Byte)
  Dim S, tmp As String
  Dim j As Byte, n As Byte
  S = Split(StrReverse(iStr), "x")
  If iD = 1 Then tmp = S(1) Else tmp = StrReverse(S(0))
    n = Len(tmp)
    For j = 1 To n
      If IsNumeric(Mid(tmp, j, 1)) = False Then
        tmp = Mid(tmp, 1, j - 1)
        Exit For
      End If
    Next j
  If iD = 1 Then TachSo = CLng(StrReverse(tmp)) Else TachSo = CLng(tmp)
End Function
 

File đính kèm

Upvote 0
Bạn đọc kĩ bài hướng dẫn chứ "copy code sau vào Code của Worksheet chứa dữ liệu của bạn"

View attachment 209988
1545787636553.png
Anh ơi nhờ anh kiểm tra lại giúp với em coppy vào sheet1 sau đó chạy thì nó báo lỗi như hình ảnh!
Em cảm ơn anh nhiều!
Bài đã được tự động gộp:

Dùng hàm tự tạo
Mã:
Function TachSo(iStr As String, iD As Byte)
  Dim S, tmp As String
  Dim j As Byte, n As Byte
  S = Split(StrReverse(iStr), "x")
  If iD = 1 Then tmp = S(1) Else tmp = StrReverse(S(0))
    n = Len(tmp)
    For j = 1 To n
      If IsNumeric(Mid(tmp, j, 1)) = False Then
        tmp = Mid(tmp, 1, j - 1)
        Exit For
      End If
    Next j
  If iD = 1 Then TachSo = CLng(StrReverse(tmp)) Else TachSo = CLng(tmp)
End Function
Cảm ơn sự giúp đỡ của anh! đây đúng là code em đang cần! anh có thể giải thích đôi chút về code này để em cùng các anh em có thể học hỏi được không!
Em cảm ơn anh nhiều!
 
Upvote 0
View attachment 209999
Anh ơi nhờ anh kiểm tra lại giúp với em coppy vào sheet1 sau đó chạy thì nó báo lỗi như hình ảnh!
Code đó không chạy được đâu.

Giả sử trước khi chạy code bạn không tự tay thêm references "Microsoft VBScript Regular Expressions ..."

Tất nhiên code (hàm ý của người viết) sẽ thêm reference. Nhưng muốn code thêm reference thì nó phải được chạy. Nhưng trước khi được chạy thì code sẽ bị kiểm tra, vd. xem cú pháp có sai không, sau đó code phải được thông dịch. Mà trong quá trình này thì sẽ lòi cái lỗi "User-defined type not defined". Vì đã có reference tới "Microsoft VBScript Regular Expressions ..." đâu để mà biết VBScript_RegExp_55.RegExp nó là cái gì.

Lỗi tại dòng iRegex As New VBScript_RegExp_55.RegExp là đương nhiên.

Quá trình kiểm tra và thông dịch luôn được thực hiện trước khi chạy code. Không thể dùng bất cứ thứ gì trong thư viện mà "hiện thời" vẫn chưa có, cái chỉ có sau khi chạy code.

Bạn có 2 lựa chọn:
1. Trước khi chạy code thì tự tay thêm reference tới "Microsoft VBScript Regular Expressions ...". Trong trường hợp này code sau là thừa
Mã:
For Each ref In Application.VBE.ActiveVBProject.References
    If ref.Name = "VBScript_RegExp_55" Then isRefs = True
  Next ref
  If Not isRefs Then _
    ThisWorkbook.VBProject.References.AddFromFile "C:\Windows\system32\vbscript.dll\3"

2. Dùng kết nối chậm. Trong trường hợp này thì code trên cũng thừa. và phải sửa khai báo thành
Mã:
Dim iRegex As Object
Sau đó trước khi dùng đối tượng iRegex thì phải tạo nó
Mã:
Set iRegex = CreateObject("VBScript.RegExp")
 
Upvote 0
Code đó không chạy được đâu.

Giả sử trước khi chạy code bạn không tự tay thêm references "Microsoft VBScript Regular Expressions ..."

Tất nhiên code (hàm ý của người viết) sẽ thêm reference. Nhưng muốn code thêm reference thì nó phải được chạy. Nhưng trước khi được chạy thì code sẽ bị kiểm tra, vd. xem cú pháp có sai không, sau đó code phải được thông dịch. Mà trong quá trình này thì sẽ lòi cái lỗi "User-defined type not defined". Vì đã có reference tới "Microsoft VBScript Regular Expressions ..." đâu để mà biết VBScript_RegExp_55.RegExp nó là cái gì.

Lỗi tại dòng iRegex As New VBScript_RegExp_55.RegExp là đương nhiên.

Quá trình kiểm tra và thông dịch luôn được thực hiện trước khi chạy code. Không thể dùng bất cứ thứ gì trong thư viện mà "hiện thời" vẫn chưa có, cái chỉ có sau khi chạy code.

Bạn có 2 lựa chọn:
1. Trước khi chạy code thì tự tay thêm reference tới "Microsoft VBScript Regular Expressions ...". Trong trường hợp này code sau là thừa
Mã:
For Each ref In Application.VBE.ActiveVBProject.References
    If ref.Name = "VBScript_RegExp_55" Then isRefs = True
  Next ref
  If Not isRefs Then _
    ThisWorkbook.VBProject.References.AddFromFile "C:\Windows\system32\vbscript.dll\3"

2. Dùng kết nối chậm. Trong trường hợp này thì code trên cũng thừa. và phải sửa khai báo thành
Mã:
Dim iRegex As Object
Sau đó trước khi dùng đối tượng iRegex thì phải tạo nó
Mã:
Set iRegex = CreateObject("VBScript.RegExp")
Em cảm ơn anh! để xíu về em thử chạy theo anh nói hi cảm ơn sự giúp đỡ nhiệt tình của các anh!
 
Upvote 0
Dear các anh chị!
Em có một bảng tính gồm rất nhiều mã hàng như sau:
CP950x2150mt
cox1230x900
Ctp560x1830tl
.....
Em muốn viết code tách riêng các chuỗi số ra 2 cột khác nhau ví dụ:

CP950x2150mt

950

2150

Nhưng thật sự em đã tìm kiếm rất nhiều và chỉ thấy tách ra thành 9502150
Vậy rất mong các anh chị em trong diễn đàn giúp đỡ em với!
Em xin chân thành cảm ơn!
Em gửi file đính kèm mong các anh chị em giúp em với ạ!
Dùng được công thức, chỉ tiếc là không áp dụng được cho dòng dữ liệu đầu tiên (dòng 11)
Bạn thử công thức sau:
Cột C
PHP:
C12=LOOKUP(10^10,--MID(LEFT(SUBSTITUTE($B12,"x",REPT(" ",20)),20),AGGREGATE(15,6,SEARCH({0,1,2,3,4,5,6,7,8,9},LEFT(SUBSTITUTE($B12,"x",REPT(" ",20)),20)),1),ROW($A$1:$A$20)))
Cột D
PHP:
D12=LOOKUP(10^10,--MID(RIGHT(SUBSTITUTE($B12,"x",REPT(" ",20)),20),AGGREGATE(15,6,SEARCH({0,1,2,3,4,5,6,7,8,9},RIGHT(SUBSTITUTE($B12,"x",REPT(" ",20)),20)),1),ROW($A$1:$A$20)))
Cả 2 đều Enter, Fill xuống
 
Upvote 0
Anh ơi nhờ anh kiểm tra lại giúp với em coppy vào sheet1 sau đó chạy thì nó báo lỗi như hình ảnh!
Em cảm ơn anh nhiều!
Code trên vì nghĩ bạn chưa biết Add References nên dùng những câu lệnh Check , nếu References chưa được add thì Add vào.
Không ngờ là bạn không biết thật.
Nếu bạn add References Microsoft Regular expression 1.0 - > 5.5 bằng tay thì không cần Nhưng câu lệnh này
Khai báo New thì không sử dụng thêm Microsoft Scripting Runtime
Bạn cũng có thể sửa là: Dim iRegex As New RegExp
còn không thì phải add Microsoft Scripting Runtime, Microsoft Regular expression 1.0 - > 5.5

Đơn giản là: cửa sổ VBA -> Tools -> References... tìm và Tick
Đã muốn biết và học VBA thì bạn cần biết xử lý và sử dụng các WIN API

Lúc này :
Dim iRegex As Object
Set iRegex = CreateObject("VBScript.RegExp")

Lợi thế của Regular expression là xử lý chuỗi, cũng như tìm kiếm chuỗi rất mạnh.

Đã học VBA không nhất thiết bạn phải dựa vào một Code nào tốt nhất. Vì mỗi cái đều có lợi thế riêng
 
Lần chỉnh sửa cuối:
Upvote 0
View attachment 209999
Anh ơi nhờ anh kiểm tra lại giúp với em coppy vào sheet1 sau đó chạy thì nó báo lỗi như hình ảnh!
Em cảm ơn anh nhiều!
Bài đã được tự động gộp:


Cảm ơn sự giúp đỡ của anh! đây đúng là code em đang cần! anh có thể giải thích đôi chút về code này để em cùng các anh em có thể học hỏi được không!
Em cảm ơn anh nhiều!
Chỉnh lại code dể hiểu hơn và nhanh hơn một chút
Mã:
Function TachSo(iStr As String, iD As Byte)
  Dim S, tmp As String
  Dim j As Byte, n As Byte
  S = Split(iStr, "x")
  If iD = 1 Then tmp = StrReverse(S(UBound(S) - 1)) Else tmp = S(UBound(S))
    n = Len(tmp)
    For j = 1 To n
      If IsNumeric(Mid(tmp, j, 1)) = False Then
        tmp = Mid(tmp, 1, j - 1)
        Exit For
      End If
    Next j
  If iD = 1 Then TachSo = CLng(StrReverse(tmp)) Else TachSo = CLng(tmp)
End Function
Dữ liệu có dạng: Bz1000x450RF
Các ký tự chuỗi cuối cùng là chữ In: S = Split(iStr, "x") tách chuổi ngăn cách bằng ký tự "x" thành mảng S, với giá trị cuối S(ubound(S))= "450RF" chứa số thứ 2, và giá trị kế cuối S(ubound(S)-1)= "Bz1000" chứa số thứ 1
If iD = 1 Then tmp = StrReverse(S(UBound(S) - 1)) Else tmp = S(UBound(S))
StrReverse(S(UBound(S) - 1))="0001zB" đảo ngược của chuổi chứa số thứ 1 "Bz1000", để cả 2 thành phần đều có dạng số trước chuỗi sau,
Sau đó dò từng ký tự nếu không phải là số, là đã lấy hết các số
Mid(tmp, j, 1)="0001" : lấy 1 ký tự thú j
If IsNumeric(Mid(tmp, j, 1)) = False Then : Nếu ký tự thứ j không phải là số thì lấy kết quả là các ký tự từ 1 tới j-1
tmp = Mid(tmp, 1, j - 1)
Do chuổi số thứ 1 đã bị đảo ngược nên kết quả phải đảo ngược lại
If iD = 1 Then TachSo = CLng(StrReverse(tmp)) Else TachSo = CLng(tmp)
Hàm Clng chuyển chuỗi thành số nguyên
 
Upvote 0
Dùng được công thức, chỉ tiếc là không áp dụng được cho dòng dữ liệu đầu tiên (dòng 11)
Không cần phải tiếc em! :p
Dùng công thức mảng như sau:
Mã:
C11=LOOKUP(10^10, --MID("|"&$B11,SMALL(IF(FREQUENCY(-ROW($1:$50),ISERR(--MID("|"&$B11,ROW($1:$50),1))*-ROW($1:$50))>2,ROW($1:$50)),COLUMN(A11))+1,{3,4}))
Kết thúc bằng Ctrl+Shift+Enter, fill qua phải 1 cột, rồi fill cả hai cột C: D xuống dưới.

Chúc em ngày vui.
/-*+//-*+//-*+/
 

File đính kèm

Upvote 0
Web KT

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

Back
Top Bottom