文字列の中の必要な部分にだけ書式設定をする
指定した文字の書式だけを変更する
記入見本作り
記入例を作りたかったんだが、日付の欄は、
こんな感じで、「月」と「日」と「(」、「)」をあらかじめ入れておいて、月・日・曜日だけを書いてもらうようにしている。
んで、記入者に書いてもらう部分だけを手書き風のフォントに変えて記入例を作ろうと思った。
しかし、ちょっと考えたら分かると思うが、これはめんどくさい。
たとえば、
7月23日(日)
という記入例を作ろうと思ったら、
「7」と「23」と「日」(曜日の方)だけを選択してフォントを変える
というしちめんどくさいことになる。
まあ、ちまちまと時間をかけて努力するのが好きな人ならそれほど苦痛ではないだろうが、私にとっては端的に苦痛ですw
んで、WordVBAの練習も兼ねてやってみた。
必要な部分だけ書式を変更するマクロ
Wordのオブジェクト構造がイマイチよく分かっとらんので、かなり行き当たりばったりのコードだと思うが、恥ずかしげもなく載せる。
リスト1
Option Explicit Public Const FONT_TO_USE As String = "HG正楷書体-PRO" '……(1)' Public Sub setFontNameAndItalic() Dim chr As String '……(2)' Dim i As Integer Dim numOfChar As Integer Dim flg As Boolean numOfChar = Selection.Range.Characters.Count '……(3)' For i = 1 To numOfChar chr = Selection.Range.Characters(i) '……(4)' If flg = True And chr <> ")" Then '……(5)' With Selection.Range.Characters(i).Font '……(*)' .Name = FONT_TO_USE .Italic = True End With End If If chr = "月" Or chr = "日" Or _ chr = "(" Or chr = ")" Then '……(6)' If chr = "(" Then flg = True '……(7)' If chr = ")" Then flg = False '……(8)' Else With Selection.Range.Characters(i).Font .Name = FONT_TO_USE .Italic = True End With End If Next End Sub
改めて見直すと、ブサイクなコードです。。。(´・ω・`)ショボーン
まずは、(*)のところ。実はこれがメインの処理だったりする。
With Selection.Range.Characters(i).Font '……(*)' .Name = FONT_TO_USE .Italic = True End With
まず、Withでまとめている
Selection.Range.Characters(i).Font
では、選択箇所のRangeオブジェクトの中にある文字列Charactersコレクションのi番目の文字のFontプロパティを呼び出して、Fontオブジェクトを取得している。
んでもって、次の2行、
.Name = FONT_TO_USE .Italic = True
でフォントの種類と斜体を設定する。
この処理を、それぞれの文字に対して実行するかどうかを切り替える、というやり方をしている。
ちなみに、「FONT_TO_USE」というのは定数で、リスト1の(1)で
Public Const FONT_TO_USE As String = "HG正楷書体-PRO"
と指定している。
(2)からの4行は、変数の宣言。
chr
Charactersコレクションから取得した1文字を入れる。(*)の処理を施すかどうかの条件判定に使用。別になくても良いが、コードを短くするために使っている。
i
おなじみループカウンタ。
numOfChar
選択中の文字数を格納する。Forループの上限値として使用。
flg
(*)の処理を行うかどうかを切り替えるためのフラグ。
(3)の
numOfChar = Selection.Range.Characters.Count
では、CharactersコレクションのCountプロパティを用いて文字数を取得し、変数numOfCharに格納。
ここからがForループの中身。
まず、(4)の
chr = Selection.Range.Characters(i)
で1文字を変数chrに格納。
(5)の
If flg = True And chr <> ")" Then
という条件分岐により、この段階でflgがTrueになっていたら、「)」でない限り(*)の処理を実行してしまう。
(7)のところで、「(」に出会ったらflgをTrueにするようにしているので、「(」に出会った直後のループでは、(*)を実行する。ただし、その直後はflgがTrueのままなので、放っておいたら「)」にまで(*)を実行してしまう。
それを防ぐための条件設定。うーーーむ、ブサイクすぎる。。。
(6)の
If chr = "月" Or chr = "日" Or chr = "(" Or chr = ")" Then
は、一番初歩的な条件設定。
「月」、「日」、「(」、「)」だったら何もしない、ということ。
ただし、めんどくさいのは、(*)の処理を施したい対象の中にも「月」、「日」という文字があること。言うまでもなく曜日を表す方の「月」、「日」だ。
幸い、曜日を表す方の「月」、「日」には、
「()」で括られている
という特徴があるので、
「(」に出会ったらスイッチオン、「)」に出会ったらスイッチオフ
というやり方にした。
……と書いているうちに、
カッコで括られているのは1文字って決まってるんだから、「(」に出会って次の1字に(*)の処理を施したら即flgをFalseにしたらいいんじゃね???
と思いついたというのは内緒だw
(7)、(8)の
If chr = "(" Then flg = True If chr = ")" Then flg = False
がスイッチ切り替え。
「(」に出会ったらスイッチオン、「)」に出会ったらスイッチオフ、というイメージ。
実行結果
こんなふうに、日付欄を選択して実行すると、
この通り、意図したとおりの結果となった。
おわりに
ツッコミどころ満載のコードだということは認めます。
正直、Wordのオブジェクト構造がイマイチ理解できていないので、アホみたいなコードになっていると思います。これを機に勉強しようとは思うものの、ホントにやるかどうかは分かりませんw
ただ、ちょい書きでこのぐらいできたら、しちめんどくさい作業をせずに済む(しかも、コードを書くのは楽しいので、しょうもないはずの作業が楽しくなる)ので、まあええかな、と。