Chèn kí tự xuống dòng tại vị trí nhất định trong 1 cell (1 người xem)

Liên hệ QC

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

giaosucan

Thành viên hoạt động
Tham gia
6/7/12
Bài viết
117
Được thích
1
Hi các bác , em đã phải xử lý vấn đề này ạ
e có 1 file nhiều cell mỗi cell chứa 1 chuỗi kí tự như thế này

FF FF FF FF FF FF 02 00 00 31 1A 1E 08 00 45 00 01 48 00 24 00 00 80 11 39 82 00 00 00 00 FF FF FF FF 00 44 00 43 01 34 4C B0 01 01 06 00 59 6A 88 DA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 31 1A 1E 00 00 00 00 00 00 00 00 00

Các số cách nhau bằng khoảng trắng em muốn chia chuỗi này thành nhiều dòng bằng cách chèn chuỗi kí tự xuống dòng tại vị trí xác định (Chẳng hạn cứ 16 khoảng trắng chèn 1 dấu xuống dòng) Kiểu thế này ạ

FF FF FF FF FF FF 02 00 00 31 1A 1E 08
00 45 00 01 48 00 24 00 00 80 11 39 82
00 00 00 00 FF FF FF FF 00 44 00 43 01

....

Các bác có cách nào ko ạ
 
Lần chỉnh sửa cuối:
Hi các bác , em đã phải xử lý vấn đề này ạ
e có 1 file nhiều cell mỗi cell chứa 1 chuỗi kí tự như thế này
FF FF FF FF FF FF 02 00 00 31 1A 1E 08 00 45 00 01 48 00 24 00 00 80 11 39 82 00 00 00 00 FF FF FF FF 00 44 00 43 01 34 4C B0 01 01 06 00 59 6A 88 DA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 31 1A 1E 00 00 00 00 00 00 00 00 00

Các số cách nhau bằng khoảng trắng em chi chuỗi này thành nhiều dòng bằng cách chèn chuỗi kí tự xuống dòng tại vị trí xác định (Chẳng hạn cứ 16 khoảng trắng chèn 1 dấu xuống dòng) Kiểu thế này ạ

FF FF FF FF FF FF 02 00 00 31 1A 1E 08
00 45 00 01 48 00 24 00 00 80 11 39 82
00 00 00 00 FF FF FF FF 00 44 00 43 01

....

Các bác có cách nào ko ạ

Chào bạn!
Không hiểu ý bạn lắm. Tốt nhất bạn gửi file lên và ghi kết quả bạn muốn vào đấy mọi người sẽ giúp bạn nhanh hơn.
 
Với bài này mình thử code như sau:
PHP:
Function TachDong(S As String, Length As Long) As String
    Dim i As Long
    For i = 1 To Len(S) \ (Length * 3) + 1
        TachDong = TachDong & vbCr & Trim(Mid(S, (i - 1) * 3 * Length + 1, Length * 3))
    Next
End Function
Khi chạy thử sub Test:
PHP:
Sub Test()
    MsgBox TachDong(Sheet1.[A1], 13)
End Sub
thì được kết quả như hộp thoại, có vẻ giống ý tác giả, mặc dù dư 1 dấu xuống dòng ở đầu, nhưng cái này dễ khắc phục.
Còn khi gõ trực tiếp công thức trên sheet thì chuỗi thu được là một dây thiệt dài, chẳng thấy xuống hàng đâu cả.
(xin xem hình)
Test_zps763d4fd8.png


Vậy, xin hỏi mọi người: Nguyên nhân là gì và cách khắc phục như thế nào để có thể sử dụng hàm TachDong trực tiếp trên sheet?
 
Với bài này mình thử code như sau:
PHP:
Function TachDong(S As String, Length As Long) As String
    Dim i As Long
    For i = 1 To Len(S) \ (Length * 3) + 1
        TachDong = TachDong & vbCr & Trim(Mid(S, (i - 1) * 3 * Length + 1, Length * 3))
    Next
End Function
Khi chạy thử sub Test:
PHP:
Sub Test()
    MsgBox TachDong(Sheet1.[A1], 13)
End Sub
thì được kết quả như hộp thoại, có vẻ giống ý tác giả, mặc dù dư 1 dấu xuống dòng ở đầu, nhưng cái này dễ khắc phục.
Còn khi gõ trực tiếp công thức trên sheet thì chuỗi thu được là một dây thiệt dài, chẳng thấy xuống hàng đâu cả.
(xin xem hình)


Vậy, xin hỏi mọi người: Nguyên nhân là gì và cách khắc phục như thế nào để có thể sử dụng hàm TachDong trực tiếp trên sheet?
Nhìn sơ cũng biết là nó chẳng thể xuống dòng được rồi.
vbCr = Chr(13) trong khi ký tự xuống dòng trên bảng tính là Chr(10), tức vbLf ---> Cũng chính là tổ hợp phím Alt + Enter ---> Khác xa 1 trời 1 vực rồi
 
Nhìn sơ cũng biết là nó chẳng thể xuống dòng được rồi.
vbCr = Chr(13) trong khi ký tự xuống dòng trên bảng tính là Chr(10), tức vbLf ---> Cũng chính là tổ hợp phím Alt + Enter ---> Khác xa 1 trời 1 vực rồi

như vậy chỉ cần thay vbcr = vbcrlf là ok
vbcrlf = chr(13) +chr(10)
 
Lần chỉnh sửa cuối:
như vậy chỉ cần thay vbcr = vbcrlf là ok vbcrlf = chr(13) +chr(10)

Được nhưng mà.. thừa (thừa thằng em chr(13)...)
Ký tự vbCrLf thường dùng với các text nằm trong file txt. Ký tự ngắt dòng của của nó khi ấy sẽ là vbCrLf
Bài này chỉ cần vbLf hoặc Chr(10) là đủ
 
Nhìn sơ cũng biết là nó chẳng thể xuống dòng được rồi.
vbCr = Chr(13) trong khi ký tự xuống dòng trên bảng tính là Chr(10), tức vbLf ---> Cũng chính là tổ hợp phím Alt + Enter ---> Khác xa 1 trời 1 vực rồi
Thực ra thì lúc viết code, em đã thử Chr(10) đầu tiên rồi, nhưng mà không được nên mới dùng đến vbCr (hổng biết có cái anh chàng vbLf này).

Và cho đến bây giờ, em đã thử đủ kiểu: vbCr, vbLf, vbCrLf, Chr(10), Chr(13), và tất cả đều có cùng 1 kết quả như nhau (ít ra thì nhìn bằng mắt thường nó như vậy), đó là: Trên hộp thoại Msgbox thì nó hiển thị đúng như yêu cầu (hết 13 cặp ký tự thì xuống dòng), còn trên sheet thì nó vẫn là một chuỗi liên tục mà không hề có ký tự xuống dòng.

Rất mong được các anh chị và các bạn hướng dẫn thêm.
Xin cảm ơn mọi người.
 
Và cho đến bây giờ, em đã thử đủ kiểu: vbCr, vbLf, vbCrLf, Chr(10), Chr(13), và tất cả đều có cùng 1 kết quả như nhau (ít ra thì nhìn bằng mắt thường nó như vậy), đó là: Trên hộp thoại Msgbox thì nó hiển thị đúng như yêu cầu (hết 13 cặp ký tự thì xuống dòng), còn trên sheet thì nó vẫn là một chuỗi liên tục mà không hề có ký tự xuống dòng.

Rất mong được các anh chị và các bạn hướng dẫn thêm.
Xin cảm ơn mọi người.
Anh chỉ cần dùng vbLf và định dạng ô kết quả là Wrap text là OK ngay
Bình thường trên Sheet anh dùng công thức ="A"&char(10)&"B" nó cũng chỉ hiển thị AB nếu chưa định dang Wrap text mà!
 
Anh chỉ cần dùng vbLf và định dạng ô kết quả là Wrap text là OK ngay
Bình thường trên Sheet anh dùng công thức ="A"&char(10)&"B" nó cũng chỉ hiển thị AB nếu chưa định dang Wrap text mà!
Mình cũng đã thử Wrap text, nhưng vấn đề là nó xuống dòng không như ý. Ví dụ: Gõ vào ô công thức ="ABC" &CHAR(10)&"DEF" và định dạng Wrap text thì cho dù ô rộng hơn chiều dài "ABCDEF" thì 3 chữ "DEF" cũng tự động xuống dòng, còn với bài toán này thì lại không như vậy, cách hiển thị dữ liệu trong ô hoàn toàn giống với việc định dạng khi trong chuỗi không có các ký tự vbLf. Bạn thử nghiệm xem.
 
Mình cũng đã thử Wrap text, nhưng vấn đề là nó xuống dòng không như ý. Ví dụ: Gõ vào ô công thức ="ABC" &CHAR(10)&"DEF" và định dạng Wrap text thì cho dù ô rộng hơn chiều dài "ABCDEF" thì 3 chữ "DEF" cũng tự động xuống dòng, còn với bài toán này thì lại không như vậy, cách hiển thị dữ liệu trong ô hoàn toàn giống với việc định dạng khi trong chuỗi không có các ký tự vbLf. Bạn thử nghiệm xem.
Em thử nghiệm theo file đính kèm, và mở trên máy em thì vẫn ổn
 

File đính kèm

Em thử nghiệm theo file đính kèm, và mở trên máy em thì vẫn ổn
Hic, chẳng biết nó là thế nào nữa. Từ hôm qua đến giờ, mình thử đủ kiểu mà vẫn không được.
Bây giờ thử lại thì lại OK...
Sau khi xóa dấu ngắt dòng thừa ở đầu thì nó thế này:
[GPECODE=vb]Function TachDong(S As String, Length As Long) As String
Dim i As Long
For i = 1 To Len(S) \ (Length * 3) + 1
TachDong = TachDong & vbLf & Trim(Mid(S, (i - 1) * 3 * Length + 1, Length * 3))
Next
TachDong = Right(TachDong, Len(TachDong) - 1)
End Function[/GPECODE]

Cảm ơn bạn đã chỉ dẫn!
 
Baì này dùng RegExp cũng rất hay
Mã:
Function tach(S As String, Length As Long) As String
With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "(\w+\s){" & Length & "}"
    For Each Match In .Execute(S)
        tach = tach & Trim(Match) & ChrW(10)
    Next
End With
End Function
 
Baì này dùng RegExp cũng rất hay
Mã:
Function tach(S As String, Length As Long) As String
With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "(\w+\s){" & Length & "}"
    For Each Match In .Execute(S)
        tach = tach & Trim(Match) & ChrW(10)
    Next
End With
End Function
Kết quả bị mất đâu mất một số ký tự phía sau (mất 7 cặp số 00 ở cuối trong dữ liệu mẫu). Phải sửa lại code như thế nào vậy dhn46? (cái món RegExp này thì mình mù tịt)
 
Kết quả bị mất đâu mất một số ký tự phía sau (mất 7 cặp số 00 ở cuối trong dữ liệu mẫu). Phải sửa lại code như thế nào vậy dhn46? (cái món RegExp này thì mình mù tịt)
Cái này sửa 1 chút như thế này anh ah
Mã:
Function tach1(S As String, Length As Long) As String
Dim i As Integer
With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "(\w+\s){" & Length & "}"
    For Each Match In .Execute(S)
        tach1 = tach1 & Match & ChrW(10)
        i = i + Len(Match) 'lay so ky tu chrw(10)
    Next
End With
    tach1 = tach1 & Trim(Mid(S, i, Len(S) - i))
End Function

-Em không chú ý tới trường hợ chuỗi cuối cùng có độ dài lớn hơn Length.
RegExp quan trọng nhất là Pattern
-Với .Pattern = "(\w+\s){" & Length & "}" => có thể hiểu là: đánh dấu toàn bộ 1 chuỗi mà chúng bắt đàu bời 1 ký tự khác dấu cách sau đo tới 1 dấu cách nữa (\w+\s) ví dụ như (FF ). Length để trong dấu {} là ý chuỗi đầu lặp lại đúng length lần
=> Ta sẽ có các đoạn match dạng (FF ) lặp lại Length lần
-Dùng vòng lặp để duyệt qua các đoạn Match và thêm dấu xuống dòng sẽ cho kết quả
 
Lần chỉnh sửa cuối:
Mày mò với RegExp Dhn46 thấy, chỉ cần dùng RegExp không cần Right hay Mid cũng có thể đáp ứng được yêu cầu
Mã:
Function tach(S As String, Length As Long) As String
With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "(\w+\s){0," & Length & "}"
    For Each Match In .Execute(S)
        tach = tach & Trim(Match) & ChrW(10)
    Next
End With
End Function
 
Mày mò với RegExp Dhn46 thấy, chỉ cần dùng RegExp không cần Right hay Mid cũng có thể đáp ứng được yêu cầu
Mã:
Function tach(S As String, Length As Long) As String
With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "(\w+\s){0," & Length & "}"
    For Each Match In .Execute(S)
        tach = tach & Trim(Match) & ChrW(10)
    Next
End With
End Function

Chú ý là nếu ta có dạng pattern là "((\w+\s){" & Length & "})"
Thì nếu tôi không lầm thì $1 = "((\w+\s){" & Length & "})" <--- cả dòng tìm thấy, và $2 = (\w+\s) với (\w+\s) cho cụm cuối, tức với dòng đầu tiên là FF FF FF FF FF FF 02 00 00 31 1A 1E 08 thì $2 = "08 ". Các dòng tiếp theo tương tự
-------------
Mọi người thử code sau xem sao:
Mã:
Function tach(S As String, Length As Long) As String
    With CreateObject("vbscript.regexp")
        .Global = True
        .Pattern = "((\w+\s){" & Length & "})"
        tach = .Replace(S, Trim("$1") & Chr(10))
    End With
End Function
 
Lần chỉnh sửa cuối:
Chú ý là nếu ta có dạng pattern là ((\w+\s){0," & Length & "})
Thì nếu tôi không lầm thì $1 = ((\w+\s){0," & Length & "}) <--- cả dòng tìm thấy, và $2 = (\w+\s) với (\w+\s) cho cụm cuối, tức với dòng đầu tiên là FF FF FF FF FF FF 02 00 00 31 1A 1E 08 thì $2 = "08 ". Các dòng tiếp theo tương tự
-------------
Mọi người thử code sau xem sao:
Mã:
Function tach(S As String, Length As Long) As String
    With CreateObject("vbscript.regexp")
        .Global = True
        .Pattern = "((\w+\s){0," & Length & "})"
        tach = .Replace(S, Trim("$1") & Chr(10))
    End With
End Function
Dạ chuẩn quá rồi, nhờ sự giải thích của bác SiwTom dhn46 lại thấy 1 vấn đề là: có thể đơn giản Pattern 1 chút nữa giống bài #13 và vận dụng .Repalce. Cảm ơn bác Siwtom mong bác chỉ giáo nhiều nhiều nữa!
 
Dạ chuẩn quá rồi, nhờ sự giải thích của bác SiwTom dhn46 lại thấy 1 vấn đề là: có thể đơn giản Pattern 1 chút nữa giống bài #13 và vận dụng .Repalce. Cảm ơn bác Siwtom mong bác chỉ giáo nhiều nhiều nữa!

Mà pattern của bạn sai rồi. Bị mất "00" ở cuối

Trước đó tôi tin tưởng pattern của bạn nhưng thử nhìn kỹ thì thấy sai.
Bởi nếu dòng cuối ngắn, vd "ab fa cd ef" thì theo pattern nó chỉ tìm thấy "ab fa cd " - do phải kết thúc bằng " " nên bạn bị mất "ef"

Hoặc bạn có thể thêm " " vào cuối S trước khi xử lý
 
Lần chỉnh sửa cuối:
Mày mò với RegExp Dhn46 thấy, chỉ cần dùng RegExp không cần Right hay Mid cũng có thể đáp ứng được yêu cầu
Mã:
Function tach(S As String, Length As Long) As String
With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "(\w+\s){0," & Length & "}"
    For Each Match In .Execute(S)
        tach = tach & Trim(Match) & ChrW(10)
    Next
End With
End Function

Nếu như không cần đến vòng lập thì dùng RegExp mới đáng đồng tiền, bằng ngược lại thì... bạn nghĩ xem: Chỉ mỗi chuyện cỏn con mà lại mượn nguyên thư viện của người ta
Nếu là tôi thì tôi làm vầy:
Mã:
Function BreakLines(ByVal Text As String, BlankPos As Long) As String
  Dim sTmp As String, n As Long, Arr()
  On Error Resume Next
  sTmp = Text
  Do
    n = n + 1
    ReDim Preserve Arr(1 To n)
    Arr(n) = Trim(Mid(sTmp, (n - 1) * BlankPos * 3 + 1, BlankPos * 3))
  Loop Until n * BlankPos * 3 >= Len(sTmp)
  BreakLines = Join(Arr, vbLf)
End Function
Bảo đảm vòng lập tối ưu, cắt 10 dòng thì vòng lập cũng duyệt đúng 10 lần (chứ không duyệt theo Len của chuổi)
 
Nếu như không cần đến vòng lập thì dùng RegExp mới đáng đồng tiền, bằng ngược lại thì... bạn nghĩ xem: Chỉ mỗi chuyện cỏn con mà lại mượn nguyên thư viện của người ta
Nếu là tôi thì tôi làm vầy:
Mã:
Function BreakLines(ByVal Text As String, BlankPos As Long) As String
  Dim sTmp As String, n As Long, Arr()
  On Error Resume Next
  sTmp = Text
  Do
    n = n + 1
    ReDim Preserve Arr(1 To n)
    Arr(n) = Trim(Mid(sTmp, (n - 1) * BlankPos * 3 + 1, BlankPos * 3))
  Loop Until n * BlankPos * 3 >= Len(sTmp)
  BreakLines = Join(Arr, vbLf)
End Function
Bảo đảm vòng lập tối ưu, cắt 10 dòng thì vòng lập cũng duyệt đúng 10 lần (chứ không duyệt theo Len của chuổi)

Thực ra tôi vẫn nghĩ không phải bao giờ cũng nên giết gà bằng dao mổ trâu. Ngoài ra trong nhiều th dùng RegExp lại lâu hơn.
 
Thực ra tôi vẫn nghĩ không phải bao giờ cũng nên giết gà bằng dao mổ trâu. Ngoài ra trong nhiều th dùng RegExp lại lâu hơn.

Ah không! Riêng code ở bài 17 của anh hoàn toàn không dùng vòng lập thì em đồng ý. Ít ra nó cũng phải có gì đó khác biệt so với cách thông thường dùng vòng lập (nếu không thì dùng làm quái gì.. Ẹc... Ẹc...)
Chậm hay nhanh em chưa bàn tới, ít ra là học được giải thuật hay (dùng cho những trường hợp khác)
 

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

Back
Top Bottom