2020年2月20日木曜日

表内での文字列置換の不具合を回避したこと

※以下のコードは Notes 9.0.1 FP8 と Notes 11.0.0 で確認したものです
※[2020/8/7 追記] Notes 11.0.1 FP1 では本エントリで報告した不具合が解消していることを確認しました。なお、回避する方法についても、そのまま 11.0.1 FP1 適用後にそのまま使用して問題ないことを確認しました

リッチテキストフィールドに次のような 3 行 x 3 列の表だけあります。セル内にはテキストだけあり、テキストに文字の装飾は無い(ひとつのセルにひとつのテキストランがある)ものとします。

test (1)test (2)test (3)
test (4)test (5)test (6)
test (7)test (8)test (9)

この表には 9 つのセルがありますが、この表の特定のセルにある文字列を対象に、文字を置換します。

特定のセルは1つとは限らず、複数のセルに跨る場合もあります。複数のセルの場合、それらは連続しているものとします。

といった、非常に特殊な件に対応するため、ヘルプにある SetPositionAtEnd メソッドと SetEnd メソッドのサンプルコードを参考にしながら次のコードを書きました。

Dim ss As NotesSession
Dim doc As NotesDocument
Dim body As NotesRichTextItem
Dim nav As NotesRichTextNavigator
Dim range As NotesRichTextRange
Const elm = RTELEM_TYPE_TEXTRUN
Const firstRun = 3
Const lastRun = 6
Const findString = "test"
Const replString = "prod"
Sub Initialize
 Set ss = New NotesSession
 Set doc = ss.Currentdatabase.Unprocesseddocuments.Getfirstdocument()
 Set body = doc.Getfirstitem( "Body" )
 Set nav = body.Createnavigator
 
 If nav.Findnthelement( elm , firstRun ) Then
  Set range = body.Createrange()
  Call range.Setbegin( nav )
  If nav.Findnthelement( elm, lastRun ) Then
   Call nav.SetPositionAtEnd( nav )
   Call range.Setend( nav )
  End If
  Call range.FindAndReplace( findString, replString, RT_REPL_ALL + RT_FIND_CASEINSENSITIVE)
  Call body.Update
 End If
 Call doc.save( True, False )
End Sub

ビューでフォーカスしている文書に対してこのコードを実行してみたところ、テキストランの範囲(今回の条件下では、テキストランの位置はセルの位置と等しいため、3 ~ 6 番目のセルを指すことと同じです)にある 3 ~ 5 番目のセルにある値が FindAndReplace メソッドによって正しく置換されるのですが、最後の(6 番目の)セルの値が削除されてしまうことに気付きました。

test (1)test (2)prod (3)
prod (4)prod (5)
test (7)test (8)test (9)

この問題をサポートへ問い合わせたところ、不具合であると報告がありました。※TSAOBLXCQL で追跡できます
※[2020/8/7 追記] この不具合は Notes 11.0.1 FP1 で解消されたことを確認しました

またこのコードの 21 行目にある Call nav.SetPositionAtEnd( nav ) の行を削除することで、範囲の最後にあるセルの値が削除される問題がなくなることを、併せて教えていただきました。

ところが、21行目を削除してみたのですが、指定する範囲を 3 ~ 6 とした場合、FindAndReplace で置換される範囲は 3 ~5 番目が対象となり、範囲の最後にあるセルの値が置換されずにそのまま残ります。範囲がセル 1 つ分少なくなったようです。

SetPositionAtEnd を削除したからでしょうか。理由はともかく範囲の最後に 1 を加えてみることにしました。

次のようにコードを書き替えました。※Initialize 以外の部分は同じなので省略

Sub Initialize
 Set ss = New NotesSession
 Set doc = ss.Currentdatabase.Unprocesseddocuments.Getfirstdocument()
 Set body = doc.Getfirstitem( "Body" )
 Set nav = body.Createnavigator
 
 If nav.Findnthelement( elm , firstRun ) Then
  Set range = body.Createrange()
  Call range.Setbegin( nav )
  If nav.Findnthelement( elm, lastRun + 1 ) Then
   Call range.Setend( nav )
  End If
  Call range.FindAndReplace( findString, replString, RT_REPL_ALL + RT_FIND_CASEINSENSITIVE)
  Call body.Update
 End If
 Call doc.save( True, False )
End Sub

こうして指定したセルの範囲にある文字をすべて置換できるようになりました。

test (1)test (2)prod (3)
prod (4)prod (5)prod (6)
test (7)test (8)test (9)

ちなみに、今回の条件の下では定数 elm の値を RTELEM_TYPE_TEXTPARAGRAPH (テキスト段落)に変えても同様の結果が得られました。

2020年2月19日水曜日

サマリーフィールドの制限を緩和するには

サマリーフィールドの制限をご存知でしょうか。

ややこしいのですが、サマリーフィールドの制限は2種類あります。

文書にあるサマリーフィールドのサイズの合計

バージョン 9.0.1 FP8 で、文書内にあるサマリーフィールドのサイズの合計が、これまでの 64K から 16M に拡張されました。
こちらは御代様のブログに詳細に書かれていますので、ここでは省略します。


サマリーフィールドひとつあたりのサイズ

バージョン 10 で、ひとつのサマリーフィールドのサイズの制限が、これまでの 32K から 64K へ拡張されました。※この資料の34ページで紹介されています



以下、後者の制限が拡張されたことについて書きます。
なお、今回私が試した環境は バージョン11のベータ2です。製品版ではありません。


ひとつのサマリーフィールドのサイズを 64K へ拡張する場合、対象のデータベースに対して -LargeSummary on オプションを付けて圧縮タスクを実行します。
この -LargeSummary on オプションは、9.0.1 FP8 以降でサマリーフィールドの合計サイズを拡張したい場合に指定するものでしたが、単一のサマリーフィールドのサイズを拡張したい場合にも使用します。

もし、データベースの ODS バージョンが 53 でない場合、 notes.ini に CREATE_R10_DATABASES=1 を追加してコピー圧縮も実行します。
※実は ODS 52 でも -LargeSummary オプションを有効にすると 64K まで使えるっぽいのですが...サポートしてくれるのかしら...

そして圧縮タスクを実行したデータベースで、フォームにあるテキストフィールドで半角英数字をタイプしていくと 32762 文字目をタイプしたところで次のメッセージが表示されました。
Field is too large (32K) or View's column & selection formulas are too large

上のメッセージを閉じた後、Ctrl + S で文書を保存しようとすると、次のメッセージが表示されました。
Field 'xxx' contains too many characters (nn over 32767 maximum). Field will be saved but will not be displayed in views.

また、タイプした文字列が制限を超えている状態で保存した文書を、再びフォームで開くと、制限を超えた部分?の内容が崩れたような表示になりました。試してみると、正しく表示されるのは 32000 文字までで、32001文字目をタイプして保存した文書を開きなおすと崩れていました。
表示が崩れた部分で文字数が増加。それらもカウントされて32001文字ではなくなった...

他にも、テキストエディタで編集した、32K 以上 64K 未満の文字列をクリップボード経由で貼り付けようとすると、こんなメッセージが表示されました。
Text on clipboard must be less than 64K bytes in order to be pasted

どうやらフォームを使って編集する場合、まだ 32K の制限が有効のままのようです。※しつこいようですがこの環境は製品版ではありません

それでは LotusScript のエージェントでバックグラウンド系のクラスを使えば、文書が作成できるのか見ていきます。

NotesDocument.AppendItemValue メソッドで 32K を超える 62000 文字をセットしたところ、文字が崩れることもなく保存できていました。保存した文書のプロパティから、アイテムに SUMMARY フラグがあることと、 Data Length が 62000 であることが確認できます。
フィールドフラグに SUMMARY、Data Length に 32K を超える値がある

これだけ見れば、確かに 32K の制限は緩和され 64K まで拡張されているようです。


最後に、先のエージェントを修正して AppendItemValue で 64K 以上の文字列をセットしてみます。

エージェントを実行したところ AppendItemValue の行で次のようなメッセージが表示されました。

Memory allocation request exceeded 65,000 bytes
64K の制限が機能していることを確認できました。


今回 LargeSummary オプションについて分かったことは、御代さんもブログの中でご指摘されてるとおり LargeSummary オプションが有効かどうかを簡単に確認する方法は現状ありませんが、この問題は SPR SWASBLWJ39 として報告されているとのこと。

実は LargeSummary オプションを有効にしたデータベースの icon note には、$LargeSummary アイテムの値に "1" がセットされるようですので、LotusScript 等を使えば確認できないわけではなさそうです。
※icon note の取得方法はこちらが参考になるかと。

なお、LargeSummary を有効にしたデータベースに対して、再度 -LargeSummary on を指定して Compact を実行すると「LargeSummary is already enabled in database xxx.nsf.」と表示されます。

それならば、いったん有効にするコマンドを投入してみて、already enabled と表示されなかったら有効ってことで、そうでなければ無効に戻せばいいよね?と安易に考えて、有効にしたデータベースに対して Compact のオプションに -LargeSummary off と指定してみたところ「Invalid command line argument」と叱られてしまいました。off というオプションは存在しないようです。仮に無効にできたとしても 64K 超えの値を含む文書が失われたりして...やらないけど。

あ、-i とともに -R または -r を付けて Compact タスクを実行して ODS バージョンを戻せば無効にできるかも...やらないけど。

2020年2月14日金曜日

読者/作成者とフィールド

昨日は会社帰りに「のの会」に参加しました。

毎月恒例のアベさんの@関数講座は、@DbColumn と @DbLookup の最終回でした。値を取得する列の番号の数値についての考察が大変興味深かったです。

今回私はある方から「読者/作成者と、関連するフィールド」というお題をいただきまして、下のスライドを使ってお話させていただきました。

資料の前半は、マニュアル的な退屈な内容です.。後半は読者/作成者フィールドにまつわる「よくある話」をまとめました。



Notesアプリの開発者には「文書を作成した本人が文書を編集できない...なんで?」といったようなつまづきがあります。私はときどきこのような特性を忘れてしまい、その都度簡単なデータベースを作成して確認することがありますが、この資料を今後は備忘録として活用することになりそうです。

Notes アプリ開発で、読者フィールドや作成者フィールドに初めて触れる方や学び直したい方にご一読いただけると幸いです。

2020年2月7日金曜日

HCL Nomad の GPS についてまとめました

昨夜は「テクてくLotus技術者夜会」に参加しました。

今回の夜会のテーマは、開発者ではないユーザー向けの Domino アプリ開発ツール「Domino Volt」と、HCL Master によるライトニングトークということで、私も発表の機会をいただきました。

既に本ブログでも2つのエントリでご紹介しましたが、発表のテーマを「HCL Nomad と GPS」として、ブログの内容はなるべく省略しつつ、実際に使ってみてわかったことや、サポートへ問い合わせて得たことを加えました。

発表で使用したスライドを SlideShare に共有しました。※下のスライドです

ヘルプに記載が無いことも紹介していますので、これから GPS を使った Notes (Nomad) アプリを開発したいと考えているユーザーの参考になれば嬉しいです。