有些字符会在vba宏中丢失格式,而有些则不会 [英] some characters lose formatting in vba macro others don't

查看:91
本文介绍了有些字符会在vba宏中丢失格式,而有些则不会的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有许多在Unicode以前时代编写的文档,其中包含各种语言的转录本,每种都有自己的字体. 我做了一个宏,用另一个字符(从多个旧的转录字体转换为unicode字体)替换了文档中的每个字符. (有关这些字体之一,请参见下面的宏代码)

由于某种原因,宏会保留某些字符(而不是其他字符)的格式(在我的情况下,大多数是斜体).这给我留下了很多单词,其中有些字母是斜体的,而其他字母不是斜体的,例如.

al-Malik al-Mu ǧā hidḫu ba

丢失格式的字符都是带有变音符号的字符,但并非所有带有变音符号的字符都失去了格式(例如,示例中的ḫ). 并非所有保持格式的字符在原始字体中都具有与unicode字体相同的代码点(例如,示例中的has在原始字体中具有unicode号U + 23,在unicode字体中具有U + 1E2B). /p>

您是否知道为什么保留某些字符而不保留其他字符的格式?或者我该如何解决这个问题?

或者,我可以在该过程中添加另一个宏,该宏将把至少包含一个斜体字母的所有单词格式化为斜体(但是如何做到这一点是另一个问题:

首先,作为一个建议,如果将数组设置为:-

Dim ValueMap(270)  As String
Dim AryTemp()      As String
ValueMap(0) = "&H30|&H30"

For i = 0 To 270
    AryTemp = Split(ValueMap(i),"|")
    'AryTemp(0) = The Old
    'AryTemp(1) = The New
Next

关于您的问题的答案.我不知道如何阻止它失去斜体,我怀疑这可能是因为通过样式而不是格式将其设置为斜体,反之亦然,但是这种深度的调查不适用于此环境(问与答)我不认为.

作为一种解决方案,您可以按照

(此代码未经测试且构成示例性解决方案)

I have a number of documents that are made in the pre-Unicode era, and contain transcriptions of various languages, each with their own fonts. I made a macro that replaces every character in a document with another character (from multiple old transcription fonts into a unicode font). (see code below of the macro for one of these fonts)

For some reason, the macro keeps the formatting (in my case, mostly italics) for some characters, not for others. This leaves me with a lot of words in which some letters are italicized, and other letters aren't, e.g.

al-Malik al-Muǧāhid ḫuba

The characters that lose the formatting are all characters with diacritics, but not all characters with diacritics lose their formatting (e.g., the ḫ in the example). Not all characters that keep their formatting have the same code point in the original font as in the unicode font (e.g., the ḫ in the example has unicode number U+23 in the original font and U+1E2B in the unicode font).

Do you have an idea why the formatting is kept for some characters, and not for others? Or how I could solve this problem?

Alternatively, I could add another macro to the procedure that would format all words that contain at least one letter in italics into italics (but how to do that is another question: MS Word macro to correct partially formatted words).

Sub BatchReplaceAOTimes()

'Replace the font AO Times New Roman in the body and footnotes
'of the active document

Debug.Print "Replacing AO Times New Roman font"
Dim old_values(270) As String
Dim unicode_values(270) As Long

old_values(0) = &H30
old_values(1) = &H31
(...)
old_values(263) = &HFD
old_values(264) = &HDD
old_values(265) = &H178
old_values(266) = &HFF
old_values(267) = &H5A
old_values(268) = &H7A
old_values(269) = &H2C
old_values(270) = &H9

unicode_values(0) = &H30
unicode_values(1) = &H31
(...)
unicode_values(263) = &H2BE
unicode_values(264) = &H2BF
unicode_values(265) = &H1E6E
unicode_values(267) = &H5A
unicode_values(268) = &H7A
unicode_values(269) = &H2C
unicode_values(270) = &H9

Selection.HomeKey Unit:=wdStory

Dim ThisRng As Range

'do body text
Set ThisRng = ActiveDocument.StoryRanges(wdMainTextStory)
For i = 0 To 270
    Debug.Print i

    ThisRng.Find.ClearFormatting
    ThisRng.Find.Replacement.ClearFormatting

    With ThisRng.Find
        .Font.Name = "AO Times New Roman"
        .Text = ChrW(old_values(i))
        .Replacement.Font.Name = "Arial Unicode MS"
        .Replacement.Text = ChrW(unicode_values(i))
        .Forward = True
        .Wrap = wdFindContinue
        .Format = True
        .MatchCase = True
        .MatchWholeWord = False
        .MatchKashida = False
        .MatchDiacritics = False
        .MatchAlefHamza = False
        .MatchControl = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    ThisRng.Find.Execute Replace:=wdReplaceAll
    Next i

   (...: do the same for the footnotes)

    End Sub

解决方案

Firstly, just as a suggestion, you could have a smaller code base if you set the array as: -

Dim ValueMap(270)  As String
Dim AryTemp()      As String
ValueMap(0) = "&H30|&H30"

For i = 0 To 270
    AryTemp = Split(ValueMap(i),"|")
    'AryTemp(0) = The Old
    'AryTemp(1) = The New
Next

As to an answer to your question. I am unaware of how to stop it losing the italic, I suspect this could be caused by it being set to italic via a style instead of formatting or vice versa, but that depth of investigation would not fit in this environment (Q&A) I don't think.

As for a solution, there are many ways to do what you need to, as solutioned in your other question, I don't think this can be done in a blanket manner (i.e. there is no way to set all those that were italic back to italic in one go) as the information is not retained after the find and replace is executed. So it would have to be done at the point the character is swapped, meaning it can only do one find and replace at a time which will have a performance impact.

In the below example I have also used the shorter array method described above.

Public Sub Sample()
Dim BlnWasItalic        As Boolean
Dim AryValueMap(270)    As String
Dim AryTemp()           As String
Dim LngLocation         As Long
Dim LngValueID          As Long
Dim WdDoc               As Word.Document
Dim WdFnd               As Word.Find
Dim WdRng               As Word.Range
Dim WdSlct              As Word.Selection

AryValueMap(0) = "&H30|&H30"
AryValueMap(1) = "&H31|&H31"
'...
AryValueMap(269) = "&H2C|H2C"
AryValueMap(270) = "&H9|&H9"

Set WdDoc = ThisDocument
    For Each WdRng In WdDoc.StoryRanges
        For LngValueID = 0 To 270
            WdRng.Select
            Set WdSlct = Selection
                WdSlct.SetRange 0, 0
                Set WdFnd = WdSlct.Find

                    'Clear any previous find settings
                    If LngValueID = 0 Then
                        WdFnd.ClearAllFuzzyOptions
                        WdFnd.ClearFormatting
                        WdFnd.ClearHitHighlight

                        .Font.Name = "AO Times New Roman"

                    End If

                    AryTemp = Split(AryValueMap(LngValueID), "|")

                    'Look for any italic character
                    Do Until Not WdFnd.Execute(FindText:=ChrW(AryTemp(0)), MatchCase:=True, _
                                                MatchWholeWord:=False, MatchWildcards:=False, _
                                                MatchSoundsLike:=False, MatchAllWordForms:=False, _
                                                Forward:=True, Wrap:=wdFindStop, Format:=True, _
                                                ReplaceWith:="", Replace:=wdReplaceNone, _
                                                MatchKashida:=False, MatchDiacritics:=False, _
                                                MatchAlefHamza:=False, MatchControl:=False)

                        'Take note if it was italic
                        BlnWasItalic = WdSlct.Font.Italic

                        'Make the replacement
                        WdSlct = ChrW(AryTemp(1))

                        'Remember the location (in case there are due to be more than
                        'one change in one word
                        LngLocation = WdSlct.End

                        'Expand the selection to the whole word
                        WdSlct.Expand wdWord

                        'Set the font
                        WdSlct.Font.Name = "Arial Unicode MS"

                        'Set the word to be italic if it was meant to be
                        WdSlct.Font.Italic = BlnWasItalic

                        'Move past the word
                        WdSlct.SetRange LngLocation, LngLocation
                    Loop
                Set WdFnd = Nothing
            Set WdSlct = Nothing
            DoEvents
        Next
        DoEvents
    Next
Set WdDoc = Nothing
End Sub

(This code is untested and formed to exemplify a solution)

这篇关于有些字符会在vba宏中丢失格式,而有些则不会的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆