Tách 1 chuỗi thành 2 chuỗi dài tương đương nhau (độ dài chênh lệch nhau ít nhất) ?

Liên hệ QC

jialink

Thành viên mới
Tham gia
16/11/08
Bài viết
17
Được thích
1
Mình có 1 đề bài yêu cầu thế này.
Giả sử mình có 1 chuỗi: "a bc def ghij klmno pqrstu"
Mình muốn tách chuỗi trên thành 2 chuỗi có độ dài tương đương nhau (độ dài chênh lệch nhau ít nhất)
Ví dụ sau khi tách được 2 chuỗi:
Chuỗi 1: a bc def ghij
Chuỗi 2: klmno pqrstu
Mong các cao thủ giaiphapexcel.com trả lời giúp!
many thanks!
 
1. Điểm cắt là một khoản trống hay ký tự nào cũng được.
2. Nếu độ dài 2 chuỗi sau khi tách không bằng nhau thì cái nào ưu tiên dài hơn (phần đầu hay phần sau)
 
Mình có 1 đề bài yêu cầu thế này.
Giả sử mình có 1 chuỗi: "a bc def ghij klmno pqrstu"
Mình muốn tách chuỗi trên thành 2 chuỗi có độ dài tương đương nhau (độ dài chênh lệch nhau ít nhất)
Ví dụ sau khi tách được 2 chuỗi:
Chuỗi 1: a bc def ghij
Chuỗi 2: klmno pqrstu
Mong các cao thủ giaiphapexcel.com trả lời giúp!
many thanks!
Nếu chỉ tách đôi đơn thuần, vị trí nào cũng được thì ví dụ ô A1 là dữ liệu thì
chuỗi đầu:
Mã:
=LEFT(A1,INT(LEN(A1)/2))
Chuỗi đuôi
Mã:
=RIGHT(A1,LEN(A1)-INT(LEN(A1)/2))
(chênh lệch nhiều nhất là 1 ký tự)
 
1. Điểm cắt là một khoản trống hay ký tự nào cũng được.
2. Nếu độ dài 2 chuỗi sau khi tách không bằng nhau thì cái nào ưu tiên dài hơn (phần đầu hay phần sau)

Mình xin trả lời:
1. Điểm cắt là khoảng trống
2. Độ dài 2 chuỗi sau khi tách thường không bằng nhau, mình chỉ muốn chênh lệch số ký tự giữa 2 chuỗi sau khi tách là MIN, không quan trọng phần đâu hay phần sau dài hơn
Cảm ơn đã quan tâm nhé!
 
Nếu chỉ tách đôi đơn thuần, vị trí nào cũng được thì ví dụ ô A1 là dữ liệu thì
chuỗi đầu:
Mã:
=LEFT(A1,INT(LEN(A1)/2))
Chuỗi đuôi
Mã:
=RIGHT(A1,LEN(A1)-INT(LEN(A1)/2))
(chênh lệch nhiều nhất là 1 ký tự)
Cảm ơn đã quan tâm!
Mình nghĩ nếu tách kiểu này sợ sẽ có trường hợp bị chia đôi ở giữa 1 từ. Mình muốn tách ở vị trí 1 khoảng trống thành 2 chuỗi có chênh lệch số ký tự trong chuỗi là MIN.
 
Làm bằng công thức thì tôi không biết.

Nếu muốn code VBA thì giải thuật như vầy:

Giải thuật 1:
- Dùng hàm Application.Trim để chuẩn hoá các khoảng trống.
- Dùng hàm split để đổi chuỗi thành array các từ.
- Dùng vòng lặp, nối các từ thành 2 chuỗi. Chuỗi 1 nối từ bên trái, chuỗi 2 nối từ bên phải. Cứ chuõi nào dài nhơn hì tạm ngưng đợi chuỗi kia. Bao giờ 2 chuỗi chạm nhau thì ngưng vòng lặp.

Gíải thuật 2:
- Dùng hàm Application.Trim để chuẩn hoá các khoảng trống.
- Chọn ngay điểm giữa chuỗi. Đếm từng ký tự về phía trái và phải, gặp khoảng trắng thì dừng. Cắt chuỗi ở đó.
 
Làm bằng công thức thì tôi không biết.

Nếu muốn code VBA thì giải thuật như vầy:

Giải thuật 1:
- Dùng hàm Application.Trim để chuẩn hoá các khoảng trống.
- Dùng hàm split để đổi chuỗi thành array các từ.
- Dùng vòng lặp, nối các từ thành 2 chuỗi. Chuỗi 1 nối từ bên trái, chuỗi 2 nối từ bên phải. Cứ chuõi nào dài nhơn hì tạm ngưng đợi chuỗi kia. Bao giờ 2 chuỗi chạm nhau thì ngưng vòng lặp.

Gíải thuật 2:
- Dùng hàm Application.Trim để chuẩn hoá các khoảng trống.
- Chọn ngay điểm giữa chuỗi. Đếm từng ký tự về phía trái và phải, gặp khoảng trắng thì dừng. Cắt chuỗi ở đó.

Cảm ơn đã quan tâm!
Mình cũng nghĩ dùng công thức excel thì khó.
Chắc phải dùng đến VBA để giải quyết. VBA thì mình chỉ biết chút ít nên khó quá :D
Mong được các cao thủ VBA giúp đỡ.
 
Bạn thử kiểm tra hàm tự tạo sau trên trang tính excel nha

Mình xin trả lời:
1. Điểm cắt là khoảng trống
2. Độ dài 2 chuỗi sau khi tách thường không bằng nhau, mình chỉ muốn chênh lệch số ký tự giữa 2 chuỗi sau khi tách là MIN, không quan trọng phần đâu hay phần sau dài hơn
Cảm ơn đã quan tâm nhé!

PHP:
Option Explicit
Function ChiaDoi(StrC As String, Optional Dau As Boolean = True) As String
 Dim J As Integer, VT0 As Byte, Tmp As Byte
  
 VT0 = Len(StrC) \ 2
 If Mid(StrC, VT0, 1) = " " Then
    ChiaDoi = GPE(StrC, VT0, Dau)
 ElseIf Mid(StrC, VT0 + 1, 1) = " " Then
    ChiaDoi = GPE(StrC, 1 + VT0, Dau)
 Else
    For J = 1 To Len(StrC)
        If Mid(StrC, VT0 - J, 1) = " " Then
            ChiaDoi = GPE(StrC, VT0 - J, Dau)
            Exit Function
        ElseIf Mid(StrC, VT0 + J, 1) = " " Then
            ChiaDoi = GPE(StrC, VT0 + J, Dau)
            Exit Function
        End If
    Next J
 End If
End Function
Mã:
[B]Function GPE(StrC As String, VTr As Byte, Optional Dau As Boolean = True)[/B]
 If Dau Then
    GPE = Left(StrC, VTr - 1)
 Else
    GPE = Mid(StrC, VTr + 1, Len(StrC))
 End If
[B]End Function[/B]
 
Cảm ơn đã quan tâm!
Mình cũng nghĩ dùng công thức excel thì khó.
Chắc phải dùng đến VBA để giải quyết. VBA thì mình chỉ biết chút ít nên khó quá :D
Mong được các cao thủ VBA giúp đỡ.
Nếu bạn muốn công thức thì có thể dùng như sau:
Ví dụ chuỗi tại ô A1 (giả sử trong chuỗi không chứa ký tự #)
Đặt các Name
Ref:
Mã:
=TRIM(A1)
Lstring
Mã:
=SUBSTITUTE(LEFT(Ref,INT(LEN(Ref)/2))," ","#")
Rstring
Mã:
=SUBSTITUTE(RIGHT(Ref,LEN(Ref)-INT(LEN(Ref)/2))," ",REPT(" ",LEN(Ref)))
Kết quả chuỗi lấy từ bên trái
Mã:
=SUBSTITUTE(TRIM(LEFT(Lstring & Rstring,INT(LEN(Ref)/2)+LEN(Ref))),"#"," ")
Chuỗi lấy còn lại
Mã:
=RIGHT(Ref,LEN(Ref)-LEN(D4))
Tham khảo thêm đính kèm
 

File đính kèm

  • Tach chuoi.xls
    17 KB · Đọc: 14
Tham khảo thêm đính kèm
Nếu chuỗi ban đầu là ab c d thì phải tách ra thành abc d mới đúng chứ. Công thức của bạn tách ra thành ab cd
Cảm ơn đã quan tâm!
Mình cũng nghĩ dùng công thức excel thì khó.
Chắc phải dùng đến VBA để giải quyết. VBA thì mình chỉ biết chút ít nên khó quá :D
Mong được các cao thủ VBA giúp đỡ.
Nếu bạn muốn dùng công thức thì xem file đính kèm thử xem.
 
Lần chỉnh sửa cuối:
Nếu chuỗi ban đầu là ab c d thì phải tách ra thành abc d mới đúng chứ. Công thức của bạn tách ra thành ab cd

Nếu bạn muốn dùng công thức thì xem file đính kèm thử xem.
Có thể vụng chèo khéo chống như sau:
Công thức của tôi cho phép tìm chuỗi từ bên trái, giờ làm thêm công thức lấy chuỗi từ bên phải, so sánh 2 chuỗi này cái nào ngắn hơn thì chọn, ẹc ẹc.
 
Nếu bạn muốn công thức thì có thể dùng như sau:
Ví dụ chuỗi tại ô A1 (giả sử trong chuỗi không chứa ký tự #)
Đặt các Name
Ref:
Mã:
=TRIM(A1)
Lstring
Mã:
=SUBSTITUTE(LEFT(Ref,INT(LEN(Ref)/2))," ","#")
Rstring
Mã:
=SUBSTITUTE(RIGHT(Ref,LEN(Ref)-INT(LEN(Ref)/2))," ",REPT(" ",LEN(Ref)))
Kết quả chuỗi lấy từ bên trái
Mã:
=SUBSTITUTE(TRIM(LEFT(Lstring & Rstring,INT(LEN(Ref)/2)+LEN(Ref))),"#"," ")
Chuỗi lấy còn lại
Mã:
=RIGHT(Ref,LEN(Ref)-LEN(D4))
Tham khảo thêm đính kèm

Cảm ơn đã quan tâm.
Công thức của bạn đã tách được nhưng chưa thỏa mãn yêu cầu chênh lệch số ký tự trong 2 chuỗi là MIN, hì
 
Nếu chuỗi ban đầu là ab c d thì phải tách ra thành abc d mới đúng chứ. Công thức của bạn tách ra thành ab cd

Nếu bạn muốn dùng công thức thì xem file đính kèm thử xem.

Công thức mảng cậu dùng là gì vậy?
máy tính tớ cứ báo virus và hiện {=#VALUE! }
Cậu thử ghi ra để tớ thử xem nhé. Thanks
 
PHP:
Option Explicit
Function ChiaDoi(StrC As String, Optional Dau As Boolean = True) As String
 Dim J As Integer, VT0 As Byte, Tmp As Byte
  
 VT0 = Len(StrC) \ 2
 If Mid(StrC, VT0, 1) = " " Then
    ChiaDoi = GPE(StrC, VT0, Dau)
 ElseIf Mid(StrC, VT0 + 1, 1) = " " Then
    ChiaDoi = GPE(StrC, 1 + VT0, Dau)
 Else
    For J = 1 To Len(StrC)
        If Mid(StrC, VT0 - J, 1) = " " Then
            ChiaDoi = GPE(StrC, VT0 - J, Dau)
            Exit Function
        ElseIf Mid(StrC, VT0 + J, 1) = " " Then
            ChiaDoi = GPE(StrC, VT0 + J, Dau)
            Exit Function
        End If
    Next J
 End If
End Function
Mã:
[B]Function GPE(StrC As String, VTr As Byte, Optional Dau As Boolean = True)[/B]
 If Dau Then
    GPE = Left(StrC, VTr - 1)
 Else
    GPE = Mid(StrC, VTr + 1, Len(StrC))
 End If
[B]End Function[/B]
Cảm ơn bạn rất nhiều!
Mình vừa kiểm tra lại rồi, đúng chính xác.
Cảm ơn tất cả mọi người!
 
Cảm ơn đã quan tâm.
Công thức của bạn đã tách được nhưng chưa thỏa mãn yêu cầu chênh lệch số ký tự trong 2 chuỗi là MIN, hì
Như tôi có nói thêm, chế biến lại 1 chút là được
thêm 1 name điều kiện so sánh
Delta
Mã:
=IF(LEN(TRIM(RIGHT(SUBSTITUTE(Lstring,"#",REPT(" ",LEN(Ref))),LEN(Ref))))<FIND(" ",Rstring),-LEN(TRIM(RIGHT(SUBSTITUTE(Lstring,"#",REPT(" ",LEN(Ref))),LEN(Ref)))),LEN(Ref))
1 chuỗi bên trái lấy ra với công thức là:
Mã:
=SUBSTITUTE(TRIM(LEFT(Lstring & Rstring,INT(LEN(Ref)/2)+Delta)),"#"," ")
Xem thêm theo đính kèm.
 

File đính kèm

  • Tach chuoi.xls
    17.5 KB · Đọc: 12

File đính kèm

  • Tach chuoi.xlsx
    8 KB · Đọc: 20
Như tôi có nói thêm, chế biến lại 1 chút là được
thêm 1 name điều kiện so sánh
Delta
Mã:
=IF(LEN(TRIM(RIGHT(SUBSTITUTE(Lstring,"#",REPT(" ",LEN(Ref))),LEN(Ref))))<FIND(" ",Rstring),-LEN(TRIM(RIGHT(SUBSTITUTE(Lstring,"#",REPT(" ",LEN(Ref))),LEN(Ref)))),LEN(Ref))
1 chuỗi bên trái lấy ra với công thức là:
Mã:
=SUBSTITUTE(TRIM(LEFT(Lstring & Rstring,INT(LEN(Ref)/2)+Delta)),"#"," ")
Xem thêm theo đính kèm.

Cảm ơn bạn.
Giờ thì ngon lành rồi đấy ạ!
 
PHP:
Option Explicit
Function ChiaDoi(StrC As String, Optional Dau As Boolean = True) As String
 Dim J As Integer, VT0 As Byte, Tmp As Byte
  
 VT0 = Len(StrC) \ 2
 If Mid(StrC, VT0, 1) = " " Then
    ChiaDoi = GPE(StrC, VT0, Dau)
 ElseIf Mid(StrC, VT0 + 1, 1) = " " Then
    ChiaDoi = GPE(StrC, 1 + VT0, Dau)
 Else
    For J = 1 To Len(StrC)
        If Mid(StrC, VT0 - J, 1) = " " Then
            ChiaDoi = GPE(StrC, VT0 - J, Dau)
            Exit Function
        ElseIf Mid(StrC, VT0 + J, 1) = " " Then
            ChiaDoi = GPE(StrC, VT0 + J, Dau)
            Exit Function
        End If
    Next J
 End If
End Function
Mã:
[B]Function GPE(StrC As String, VTr As Byte, Optional Dau As Boolean = True)[/B]
 If Dau Then
    GPE = Left(StrC, VTr - 1)
 Else
    GPE = Mid(StrC, VTr + 1, Len(StrC))
 End If
[B]End Function[/B]

Code này không chạy đúng. Nếu chuỗi là "a bb cc" thì nó cắt ra "a" và "bb cc" (1:5). Đáng lẽ phải cắt thành "a bb" và "cc" (4:2)

Mã:
Function CheChuoi(ByVal s As String) As Variant
[COLOR=#006400]' Hàm cắt chuỗi làm 2
' Trả về một mảng 2 phần tử.
' Khi dùng, chọn 2 ô liên tiếp và ghi theo công thức mảng (ctrl+shift+enter)[/COLOR]
Dim a(1 To 2) As String
Dim d1 As Integer, dd As Integer
dd = Len(s)
For d1 = dd \ 2 + 1 To dd[COLOR=#006400] ' bắt đầu từ giữa chuỗi[/COLOR]
    If Mid(s, d1, 1) = " " Then Exit For[COLOR=#006400] ' thử nới chuỗi 1[/COLOR]
    If Mid(s, dd - d1 + 1, 1) = " " Then[COLOR=#006400] ' thử nới chuỗi 2[/COLOR]
        d1 = dd - d1 + 1
        Exit For
    End If
Next d1
a(1) = Left(s, d1 - 1)
a(2) = Mid(s, d1 + 1, dd)
CheChuoi = a
End Function
 
Code này không chạy đúng. Nếu chuỗi là "a bb cc" thì nó cắt ra "a" và "bb cc" (1:5). Đáng lẽ phải cắt thành "a bb" và "cc" (4:2)

Mã:
Function CheChuoi(ByVal s As String) As Variant
[COLOR=#006400]' Hàm cắt chuỗi làm 2
' Trả về một mảng 2 phần tử.
' Khi dùng, chọn 2 ô liên tiếp và ghi theo công thức mảng (ctrl+shift+enter)[/COLOR]
Dim a(1 To 2) As String
Dim d1 As Integer, dd As Integer
dd = Len(s)
For d1 = dd \ 2 + 1 To dd[COLOR=#006400] ' bắt đầu từ giữa chuỗi[/COLOR]
    If Mid(s, d1, 1) = " " Then Exit For[COLOR=#006400] ' thử nới chuỗi 1[/COLOR]
    If Mid(s, dd - d1 + 1, 1) = " " Then[COLOR=#006400] ' thử nới chuỗi 2[/COLOR]
        d1 = dd - d1 + 1
        Exit For
    End If
Next d1
a(1) = Left(s, d1 - 1)
a(2) = Mid(s, d1 + 1, dd)
CheChuoi = a
End Function

Bài này mình nghĩ đâu cần vòng lặp làm gì. Chỉ cần 1 cái If Else là xong thôi
 
Web KT
Back
Top Bottom