Excelの置換は、、置換後は必ず1文字目のフォントが、文字列すべてに適用される仕様になっている。
それだと、不便なことがあったので、文字列のフォントをきちんと保存して、置換後に元に戻すマクロを作成。
参考にしたのは、
・以前作ったイテレータもどき
CFontCollector
Option Explicit
Dim m_collection As VBA.Collection ‘このオブジェクトがコレクターのキモ
Private Sub Class_Initialize()
Set m_collection = New VBA.Collection
End SubPrivate Sub Class_Terminate()
Set m_collection = Nothing
End SubPublic Sub Add(ByVal Data As CFontData)
Call m_collection.Add(Data)
End SubPublic Sub Remove(ByVal index As Long)
Call m_collection.Remove(index)
End SubPublic Property Get Count() As Long
Count = m_collection.Count
End PropertyPublic Property Get Item(ByVal index As Long) As CFontData
Set Item = m_collection.Item(index)
End PropertyPublic Property Get FontDatas() As Collection
Set FontDatas = m_collection
End Property
CFontData
Option Explicit
Public start As Long
Public Length As Long
Public ColorIndex As Long
Public Bold As Boolean
Public Italic As Boolean
Public UnderLine As Variant
Public Strikethrough As Boolean
Public FontStyle As String
Public Name As String
Public Size As VariantPrivate Sub Class_Initialize()
Me.start = 0
Me.Length = 0
Me.ColorIndex = 0
Me.Bold = False
Me.Italic = False
Me.Strikethrough = False
Me.FontStyle = ""
Me.Name = ""
Me.UnderLine = Empty
Me.Size = Empty
End SubPrivate Sub Class_Terminate()
End Sub
Public Sub Copy(ByRef F As Font)
With F
Me.Name = .Name
Me.ColorIndex = .ColorIndex
Me.FontStyle = .FontStyle
Me.UnderLine = .UnderLine
Me.Italic = .Italic
Me.Strikethrough = .Strikethrough
Me.Size = .Size
End With
End SubPublic Sub SetFont(ByRef F As Font)
With F
.Name = Me.Name
.ColorIndex = Me.ColorIndex
.FontStyle = Me.FontStyle
.UnderLine = Me.UnderLine
.Italic = Me.Italic
.Strikethrough = Me.Strikethrough
.Size = Me.Size
End With
End SubPublic Function Diff(ByRef F As Font) As Boolean
Diff = False
‘フォントに変化があった場合
If ((Me.FontStyle <> F.FontStyle) Or _
(Me.ColorIndex <> F.ColorIndex) Or _
(Me.UnderLine <> F.UnderLine) Or _
(Me.Italic <> F.Italic) Or _
(Me.Strikethrough <> F.Strikethrough) Or _
(Me.Size <> F.Size) Or _
(Me.Bold <> F.Bold) Or _
(Me.Name <> F.Name)) Then
Diff = True
End If
End Function
Sheet1
Option Explicit
Sub test()
Call FullReplace("B3", "test", "abcd")End Sub
‘フォントも含めた置換を行う(置換前後の文字数が同一であることが条件)
Sub FullReplace(ByVal RangeArea As String, ByVal What As String, ByVal Replacement As String)
Dim FontCollector As CFontCollector
Set FontCollector = New CFontCollector
Dim MyRange As Range
Set MyRange = ActiveSheet.Range(RangeArea)
Dim i, Length As Long
Dim Data As CFontData
Dim F As FontLength = Len(MyRange.Value)
‘ セルの文字数だけループする
For i = 1 To Length
Set F = MyRange.Characters(i, 1).Font
If i = 1 Then ‘初回、フォントデータコピー
Set Data = New CFontData
Data.start = 1
Call Data.Copy(F)
ElseIf i = Length Then ‘最後 フォント情報の収集完了、コレクターに格納
Data.Length = i – Data.start + 1
Call FontCollector.Add(Data)
Set Data = Nothing
Else
‘保存していたフォントと異なる(変化が出た)場合、その位置から再保存
If Data.Diff(F) = True Then
‘ここまででフォント情報の収集が完了するので、コレクターに格納
Data.Length = i – Data.start
Call FontCollector.Add(Data)
‘次に、新規フォント情報を保存
Set Data = Nothing
Set Data = New CFontData
Data.start = i
Call Data.Copy(F)
End If
End If
Next
‘置換
Call MyRange.Replace(What, Replacement)
‘フォントの復元
For Each Data In FontCollector.FontDatas
Set F = MyRange.Characters(Data.start, Data.Length).Font
Call Data.SetFont(F)
Set Data = Nothing
Next Data
Set FontCollector = Nothing
End Sub
今の作りだと、置換前後の文字数は同じであることが前提の作りになっているので、次は置換前後の文字数が異なっても対応できる作りが必要だ。
コメント