いいね!数

0

閲覧数
117

リッチテキストに文字の装飾や画像や表などがあります。

この構成要素内の文字列置換を行う要件があるのですが FindAndReplace で「位置が正しくありません」とエラーになります。

どのような修正が必要でしょうか?

※文字装飾(色など)や表などの文字以外の要素は維持する必要があります。

	Dim rtnav As NotesRichTextNavigator
	Dim rtrange As NotesRichTextRange
	Dim msg As String
	
	Set body = doc.GetFirstItem("Body")
	Set rtnav = body.CreateNavigator
	
	If rtnav.FindFirstElement(RTELEM_TYPE_TEXTRUN) Then
		Set rtrange = body.CreateRange
		Do
			Call rtrange.SetBegin(rtnav)
			msg = rtrange.TextRun
			Msgbox "[" & msg & "]"
			
			'実際にはここに文字列を加工する処理が入ります
			
			Call rtrange.FindAndReplace( msg, "(置換文字列)", RT_REPL_ALL + RT_FIND_CASEINSENSITIVE )
			
		Loop While rtnav.FindNextElement(RTELEM_TYPE_TEXTRUN)
	End If
サーバー情報: | クライアント情報: | 
カテゴリ:Notes - 使い方 | タグ:
  | 質問日時:Feb 14, 2020, 6:17:51 PM

回答・コメント

いいね!数

0

findandreplace の直後に body.update をコールしてもダメでしょうか…

回答日時:Feb 14, 2020, 6:55:02 PM

いいね!数

0

素早いアドバイスありがとうございます。

FindAndReplaceの所でエラーになるのでそこまで行けないですね…

多分、使い方が間違ってる気がするのですが^^;

回答日時:Feb 14, 2020, 7:06:24 PM

いいね!数

0

ループを1回も回ることなく止まるのですね。ろくに確認もせずにとんちんかんな回答してしまいすみません。以下はコメントです。

改めてバージョン 11 のベータ2 を使い、そのままのコードで試したところエラーが再現しました。

コードを見て、テキストランにあるすべての文字列 msg を置換したいのかな、と想像しました。

このコードは、最後に示すコードと同様に、一度きりの実行で body フィールドにあるすべての文字列から msg の部分を探し置換してしまうのではないかと思います。RT_REPL_ALL が指定されているため、もし bodyフィールド内に msg の文字列が複数出現する場合、すべて置換されてしまうように思います。

FindandReplace を実行すると NotesRichTextRange クラスのオブジェクトの内容(テキストラン等)が空っぽになることがデバッグモードで確認できますが、(ヘルプによると)同時にリッチテキストアイテムのナビゲーションマークが無効になります。ひょっとするとループ処理の中では FindandReplace は使いづらいかもしれません。

なお私の環境では、テキストレンジの範囲をテキストランの番号を指定することで設定した後、FindandReplace で置換すると、最後のエレメントが表のセルの場合にセル内の文字列が削除されてしまうという不具合に遭遇してしまいました。信頼性に欠けるような気がしますので私からの回答は控えたいと思います。

ご使用のバージョンが書かれていませんが 10.0.1 は FindandReplace メソッドに不具合があるようです。ご参考まで。

https://alichtenberg.cz/ibm-notes-domino-10-0-1-fix-pack-1-preliminary-release-notice/

Set body = doc.GetFirstItem( "Body" )
Set nav = body.Createnavigator
Set range = body.Createrange()
If range.FindAndReplace( searchString, replaceString, RT_REPL_ALL + RT_FIND_CASEINSENSITIVE ) Then
	Call body.Update
End If
Call doc.Save(True, True)
回答日時:Feb 16, 2020, 8:28:02 AM

いいね!数

0

自己解決(といってよいのかわかりませんが)しました。

1度目のループでテキストランの情報取得のみを行って配列に格納し、その後作成した配列をもとにFinfAndReplaceを実行することでやりたいことは問題なく実行できました。(RT_REPL_ALLの指定は止めて取得したテキストラン1つづつ処理)

 

回答日時:Feb 18, 2020, 10:49:58 AM

いいね!数

0

自己解決されたとのことですので完全に蛇足ですが、私も不具合を回避する方法がみつかりましたので、改めて回答したいと思います。

Set body = doc.GetFirstItem( "Body" )
Set nav = body.Createnavigator
n = 1
if nav.Findnthelement( elm, n ) Then
    Do
        Set range = body.CreateRange
        Call range.Setbegin(nav)
        Call nav.Findnthelement( elm, n + 1 )
        Call range.Setend(nav)
        msg = range.Textrun
        'ここで文字列の処理
        Call range.FindAndReplace( msg, "<置換する文字列>", RT_REPL_ALL + RT_FIND_CASEINSENSITIVE)
        Call body.Update()
        Set range = Nothing
        n = n + 1
    Loop While nav.Findnthelement( elm, n )
End If

Call doc.Save(True, True)

元のコードとの違いですが、次の2つです。

  • テキストランを番号で順に指定する
  • SetBegin/SetEnd でレンジを明確にする

テキストランの範囲を「n 番目から n + 1 番目」としていますが、実際のところ FindandReplace の対象となるのは n 番目だけです。

ちなみに上のコードでは削除していますが、ヘルプにあるサンプルに従って SetPositionAtEnd を SetEnd の直前で実行したところ不具合に遭遇しました。

なお、文字と文字の間に小さいイメージをペーストしたような場合、range.Textrun はペーストした画像を除く前後の文字列をセットしますが、これをFindandReplace で置換することができませんでした。リッチテキストはなかなか難しいですね。

回答日時:Feb 20, 2020, 5:29:26 PM

いいね!数

0

1回のループで処理できる正しい手順を示してくださってありがとうございます。

>なお、文字と文字の間に小さいイメージをペーストしたような場合、range.Textrun はペーストした画像を除く前後の文字列をセットしますが、これをFindandReplace で置換することができませんでした。

これには気づきませんでした。

リッチテキストは難しい、というかノーツは文献が少なすぎる・・・

回答日時:Feb 21, 2020, 9:16:17 AM