打印小票时自动换行算法,可处理各种字符混排

       这是一个算法,是我在做热敏打印机打印小票时解决的一个问题,想了想还是分享给大家,或许多大家有些许帮助。

       在打印小票时,可能遇到一些字符串长度过长的问题,但是你不能直接截取,所以需要自动换行来显示全部名称。经过分析,其实是这么一个问题:需要把字符串分行,使得每行不得超过最大长度,最后一行长度为指定的最小长度,长度不够,用空格补齐。

先给出一个简单的效果示例图:

《打印小票时自动换行算法,可处理各种字符混排》

具体的算法源码:

#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

 

       由于该算法是按照字节处理的,所以可以处理中英文、数字及各种字符的混排,当截取的最后一位正好是汉字,则会自动处理到前一个字符,不会出现截取错误而导致乱码。

    原文作者:银行家问题
    原文地址: https://blog.csdn.net/xiaoxian8023/article/details/7276220
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞