這是一個演算法,是我在做熱敏印表機列印小票時解決的一個問題,想了想還是分享給大家,或許多大家有些許協助。
在列印小票時,可能遇到一些字串長度過長的問題,但是你不能直接截取,所以需要自動換行來顯示全部名稱。經過分析,其實是這麼一個問題:需要把字串分行,使得每行不得超過最大長度,最後一行長度為指定的最小長度,長度不夠,用空格補齊。
先給出一個簡單的效果樣本圖:
具體的演算法源碼:
#Region "把字串按指定最大長度分行,使得最後一行長度為指定的最低長度" ''' <summary> ''' 處理字串自動換行問題。最短為intLenMin,最長為intLenMax,最後一行用空格補齊到intLenMin長度。 ''' </summary> ''' <param name="strOldText">原字串</param> ''' <param name="intLenMin">最短位元組長度</param> ''' <param name="intLenMax">最長位元組長度</param> ''' <returns>string</returns> ''' <remarks></remarks> Public Function AutomaticLine(ByVal strOldText As String, ByVal intLenMin As Integer, ByVal intLenMax As Integer) As String Dim intLength As Integer Dim strResult As String = "" '擷取原字串的位元組長度 intLength = System.Text.Encoding.GetEncoding("gb2312").GetByteCount(strOldText) If intLength > intLenMax Then '總位元組數> 最長截取的最長位元組數, '則截取最長位元組數, 然後對剩餘字串再處理 '擷取字串的UCS2碼 Dim bytes As Byte() = System.Text.Encoding.Unicode.GetBytes(strOldText) '擷取字元的實際截取位置 Dim intCutPos = RealCutPos(bytes, intLenMax) '採用遞迴調用 strResult = System.Text.Encoding.Unicode.GetString(bytes, 0, intCutPos * 2) + vbCrLf + AutomaticLine(Mid(strOldText, intCutPos + 1), intLenMin, intLenMax) ElseIf intLength > intLenMin Then '如果 最長位元組數 >總位元組數 > 最短位元組數,則 換行,並補齊空格到最短位元組數位置 strResult = strOldText + vbCrLf + Space(intLenMin) Else '如果 總位元組數 < 最短位元組數,則直接補齊空格到最短位元組數的位置 strResult = strOldText + Space(intLenMin - intLength) End If Return strResult End Function ''' <summary> ''' 返回字元的實際截取位置 ''' </summary> ''' <param name="bytes">UCS2碼</param> ''' <param name="intLength">要截取的位元組長度</param> ''' <returns></returns> ''' <remarks></remarks> Public Function RealCutPos(ByVal bytes As Byte(), ByVal intLength As Integer) As Integer '擷取UCS2編碼 Dim intCountB As Integer = 0 ' 統計當前的位元組數 Dim intCutPos As Integer = 0 '記錄要截取位元組的位置 While (intCutPos < bytes.GetLength(0) AndAlso intCountB < intLength) ' 偶數位置,如0、2、4等,為UCS2編碼中兩個位元組的第一個位元組 If intCutPos Mod 2 = 0 Then ' 在UCS2第一個位元組時,位元組數加1 intCountB += 1 Else ' 當UCS2編碼的第二個位元組大於0時,該UCS2字元為漢字,一個漢字算兩個位元組 If bytes(intCutPos) > 0 Then intCountB += 1 End If End If intCutPos += 1 End While ' 如果intCutPos為奇數時,處理成偶數 If intCutPos Mod 2 = 1 Then ' 該UCS2字元是漢字時,去掉這個截一半的漢字 If bytes(intCutPos) > 0 Then intCutPos = intCutPos - 1 Else ' 該UCS2字元是字母或數字,則保留該字元 intCutPos = intCutPos + 1 End If End If Return intCutPos / 2 End Function#End Region
由於該演算法是按照位元組處理的,所以可以處理中英文、數字及各種字元的混排,當截取的最後一位正好是漢字,則會自動處理到前一個字元,不會出現截取錯誤而導致亂碼。