Excel-儲存格內部分文字屬性操作

Excel-儲存格內部分文字屬性操作

一、緣起:

最近一個專案,是關於以Excel資料作為圖文整合來源其中之一,不過中文有一些眉角是挺麻煩的,比如:

1、私書名號:

 

image image

 

2、注音(含破音字)字體

image image

這些東西尤其是針對小學生的讀物中,出現比例頗高,如何讓InDesign在圖文整合過程,認得那些字是要上私書名號、那些是要上注音字體,需有三方要素配合。

clip_image004[7]

原先寄望Excel的搜尋取代功能,不過後來發現,Excel與Word不同,Excel可以處理儲存格內所有文字的屬性,卻不能處理部分文字的屬性,而且使用者後來還反映一個問題就是搜尋取代功能,會使被取代後面的文字屬性跑掉。

舉個簡單的例子,想把儲存格內分行符號,取代成『//』字串。

clip_image004[5]

 

 

 

 

 

在幾經思考之後,必須使用最原始的處理方式,也就是針對逐個儲存格內的文字,逐字檢查其屬性,比如檢查到美國兩個有底線屬性時,便加以處理。

此處理模式,慢歸慢,但機器做總比人做來的好吧!

 

二、程式碼

底線文字,前面加上 『~@C001-』,後面加上『@~』

刪除線文字,前面加上 『~@C002-』,後面加上『@~』

特定字體,前面加上 『~@CXXX-』,後面加上『@~』

『~@』指示InDesign Server在處理到這時,要注意開始套用特定樣式了。

『@~』指示InDesign Server套用作業到此結束。

『C001』表示在InDesign版型中對應的樣式名稱,C開頭表示字元樣式,P開頭表示段落樣式。

『-』區隔樣式代碼與文字內容。

image

公用變數


    Dim firstSym As String = "~@" '共通符 前符
    Dim lastSym As String = "@~" '共通符 尾符
    Dim sepSym As String = "-" ''共通符 區別符
    Dim theNameStyleCode As String = "C001" '私名號樣式碼
    Dim theBookStyleCode As String = "C002" '書名號樣式碼

    Dim thePhone1 As String = "C101" '華康寬注音(標楷W5)
    Dim thePhone2 As String = "C102" '華康寬破音一(標楷W5)
    Dim thePhone3 As String = "C103" '華康寬破音二(標楷W5)
    Dim thePhone4 As String = "C104" '華康寬破音三(標楷W5)
    Dim thePhone5 As String = "C105" '華康寬破音四(標楷W5)
    Dim thePhone6 As String = "C106" '華康寬破音五(標楷W5)

    Dim thePhone1_Name As String = "華康寬注音(標楷W5)"
    Dim thePhone2_Name As String = "華康寬破音一(標楷W5)"
    Dim thePhone3_Name As String = "華康寬破音二(標楷W5)"
    Dim thePhone4_Name As String = "華康寬破音三(標楷W5)"
    Dim thePhone5_Name As String = "華康寬破音四(標楷W5)"
    Dim thePhone6_Name As String = "華康寬破音五(標楷W5)"

底線文字處理


        Dim totalCount As Integer = 0 '計量
        Dim charsCount As Integer = 0 '收集字數
        Dim prevLineCode As String = "" '前字 線代號

        For v1 As Integer = sCell.Characters.Count To 1 Step -1
            Dim nowChars As Excel.Characters = sCell.Characters(v1, 1) '目前進行到的文字
            If nowChars.Font.Underline.ToString() <> prevLineCode Or v1 = 1 Then '目前文字底線代碼與上次紀錄的線型代碼不同
                '將該字前之連續字串位置及字數送入加工
                Dim preCharUnderLine As String = sCell.Characters(v1 + 1, 1).Font.Underline.ToString() '取得上一個字的底線代號
                If preCharUnderLine = "2" Then ' 如果底線代號為 2 ( 單底線 )
                    Dim startLocation As Integer = v1 + 1 '原則上開始的位置應該是目前字的前一個字
                    '如果是在儲存格內第一個字
                    If v1 = 1 Then '
                        startLocation = startLocation - 1 '則開始位置是目前這個字,不是前一個字,故開始位置要減1
                        charsCount += 1 '本字即時納入,不然會錯過
                    End If
                    '判斷代碼
                    Dim firstChar As Excel.Characters = sCell.Characters(startLocation, 1) '確定第一個是哪種線型
                    Dim rangeChars As Excel.Characters = sCell.Characters(startLocation, charsCount) '全字串
                    totalCount += rangeInsert(rangeChars, theNameStyleCode)
                End If
                charsCount = 1 '字數歸零 本字納入
                prevLineCode = nowChars.Font.Underline.ToString() '更新線碼
            Else '有接續
                charsCount += 1
            End If
            prevLineCode = sCell.Characters(v1, 1).Font.Underline.ToString() '紀錄線代號
        Next

刪除線文字處理


        Dim totalCount As Integer = 0 '計量
        Dim charsCount As Integer = 0 '集字數
        Dim prevStrikeStatus As String = "" '前字 刪除線狀態

        For v1 As Integer = sCell.Characters.Count To 1 Step -1
            Dim nowChars As Excel.Characters = sCell.Characters(v1, 1)
            If nowChars.Font.Strikethrough.ToString() <> prevStrikeStatus.ToString() Or v1 = 1 Then
                '該字前之連續字串位置及字數送入加工
                If prevStrikeStatus = "True" Then
                    Dim startLocation As Integer = v1 + 1
                    '儲存格內第一個字()
                    If v1 = 1 Then
                        startLocation = startLocation - 1 '起始位置是目前這個字,不是前一個字,故開始位置要減1
                        charsCount += 1 '本字即時納入
                    End If

                    '判斷代碼
                    Dim rangeChars As Excel.Characters = sCell.Characters(startLocation, charsCount) '全字串
                    totalCount += rangeInsert(rangeChars, theBookStyleCode)
                End If
                charsCount = 1 '字數歸零 本字納入
                prevStrikeStatus = nowChars.Font.Strikethrough.ToString() '更新狀態
            Else '有接續
                charsCount += 1
            End If
            prevStrikeStatus = sCell.Characters(v1, 1).Font.Strikethrough.ToString() '紀錄線代號
        Next

套用指定字體文字處理


        Dim totalCount As Integer = 0 '計量
        Dim charsCount As Integer = 0 '集字數
        Dim prevFontName As String = "" '前字 字體名稱

        For v1 As Integer = sCell.Characters.Count To 1 Step -1 '由後往前推
            Dim nowChars As Excel.Characters = sCell.Characters(v1, 1) '目前字元
            If nowChars.Font.Name.ToString() <> prevFontName Or v1 = 1 Then '目前字體名稱不等於前一個字體名稱
                '該字前之連續字串位置及字數送入加工
                Dim preCharFontName As String = sCell.Characters(v1 + 1, 1).Font.Name.ToString() '上一個字的字體名稱
                Dim startLocation As Integer = v1 + 1
                '如果是在儲存格內第一個字
                If v1 = 1 Then
                    startLocation = startLocation - 1 '起始位置是目前這個字,不是前一個字,故開始位置要減1
                    charsCount += 1 '本字即時納入
                End If
                '判斷代碼
                Dim firstChar As Excel.Characters = sCell.Characters(startLocation, 1) '第一個字要確定是哪種字體
                Dim rangeChars As Excel.Characters = sCell.Characters(startLocation, charsCount) '全字串

                Select Case firstChar.Font.Name.ToString()
                    Case thePhone1_Name
                        totalCount += rangeInsert(rangeChars, thePhone1)
                    Case thePhone2_Name
                        totalCount += rangeInsert(rangeChars, thePhone2)
                    Case thePhone3_Name
                        totalCount += rangeInsert(rangeChars, thePhone3)
                    Case thePhone4_Name
                        totalCount += rangeInsert(rangeChars, thePhone4)
                    Case thePhone5_Name
                        totalCount += rangeInsert(rangeChars, thePhone5)
                    Case thePhone6_Name
                        totalCount += rangeInsert(rangeChars, thePhone6)
                End Select
                'End If
                charsCount = 1 '字數歸零 本字納入
                prevFontName = nowChars.Font.Name.ToString() '更新線碼
            Else '有接續
                charsCount += 1
            End If
            prevFontName = sCell.Characters(v1, 1).Font.Name.ToString() '重記
        Next

指定文字串插文


    Function rangeInsert(ByVal rangeChars As Excel.Characters, ByVal styleName As String) As Integer
        If Trim(rangeChars.Text) = "" Then
            Return 0
        End If
        rangeChars.Insert(firstSym & styleName & sepSym & rangeChars.Text.ToString() & lastSym)
        Return 1
    End Function