<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:itunes="http://www.itunes.com/DTDs/Podcast-1.0.dtd">
  <channel>
    <title>yamachan's Notes/Domino メモ</title>
    <link>http://hannover.sblo.jp/</link>
    <description>Lotus Notes/Domino 開発のメモ</description>
    <language>ja</language>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <itunes:subtitle></itunes:subtitle>
    <itunes:summary>Lotus Notes/Domino 開発のメモ</itunes:summary>
    <itunes:keywords>Lotus Notes Domino LotusScript</itunes:keywords>
    
    <itunes:author>yamachan</itunes:author>
    <itunes:owner>    
       <itunes:name></itunes:name>
       <itunes:email></itunes:email>
    </itunes:owner>
        <itunes:explicit>no</itunes:explicit>
        <item>
      <link>http://hannover.sblo.jp/article/54662400.html</link>
      <title>Notesアイコン用パレット for GIMP</title>
      <pubDate>Wed, 28 Mar 2012 11:28:01 +0900</pubDate>
      <description>久しぶりにLotus Notesのアイコンを作成することになったのでメモ。以下の内容を NotesIcon.gpl のファイル名でGIMPのpalettesフォルダに保存。GIMP PaletteName: Notes Icon##       by yamachan 2012/03/28#  0   0   0	K255 255 255	W255   0   0	R  0 255   0	G  0   0 255	B255   0 255	M255 255   0	Y  0..</description>
            <content:encoded><![CDATA[
久しぶりにLotus Notesのアイコンを作成することになったのでメモ。以下の内容を NotesIcon.gpl のファイル名でGIMPのpalettesフォルダに保存。<br /><br />GIMP Palette<br />Name: Notes Icon<br />#<br />#       by yamachan 2012/03/28<br />#<br />  0   0   0	K<br />255 255 255	W<br />255   0   0	R<br />  0 255   0	G<br />  0   0 255	B<br />255   0 255	M<br />255 255   0	Y<br />  0 255 255	C<br />128   0   0	1<br />  0 128   0	2<br />  0   0 128	3<br />128   0 128	4<br />128 128   0	5<br />  0 128 128	6<br />128 128 128	7<br />192 192 192	8<br /><br />添付ファイルにしておくので、自由にご利用ください:<a href="http://yamachan.sakura.ne.jp/sblo_files/hannover/image/NotesIcon.gpl">NotesIcon.gpl</a><a name="more"></a>

]]><![CDATA[
]]></content:encoded>
            <category>メモ</category>
      <author>yamachan</author>
                  <enclosure url="http://yamachan.sakura.ne.jp/sblo_files/hannover/image/NotesIcon.gpl" length="289" type="text/plain" />
                      </item>
        <item>
      <link>http://hannover.sblo.jp/article/3803330.html</link>
      <title>ロード後にイメージを表示</title>
      <pubDate>Sun, 15 Apr 2007 08:26:21 +0900</pubDate>
      <description>いつのころからか、データベースのプロパティに 「ロード後にイメージを表示」 というオプションがついています。先日、担当した Notes DB にはこのオプションが設定されていて、ちょっと苦労しましたので、簡単にご報告します。これまで、リッチテキストに画像を貼り付けると、リッチテキストの一部として扱われていました。ですので、サイズの大きなものがあるとリッチテキストのサイズが膨らみ、処理に時間がかかってしまいます。例えば遅いネットワーク越しで、大きな画像が貼り付けられた文書を開く..</description>
            <content:encoded><![CDATA[
いつのころからか、データベースのプロパティに 「ロード後にイメージを表示」 というオプションがついています。<br /><br /><img src="//rinco.jp/blog/memo/20070415_loadimage.gif" width="200" height="68" alt="ロード後にイメージを表示"/><br /><br />先日、担当した Notes DB にはこのオプションが設定されていて、ちょっと苦労しましたので、簡単にご報告します。<br /><br />これまで、リッチテキストに画像を貼り付けると、リッチテキストの一部として扱われていました。ですので、サイズの大きなものがあるとリッチテキストのサイズが膨らみ、処理に時間がかかってしまいます。<br /><br />例えば遅いネットワーク越しで、大きな画像が貼り付けられた文書を開くと、なかなか開きませんよね。<br /><br />このオプションを使うと、読み込んだ画像を、添付ファイルのように格納するようです。 文書を開くとすぐに本文が表示され、画像部分は後から読み込まれる動作になります。 いいですね。<br /><br />さて、詳しくみていきましょう。<br /><br />文書を調べてみると、画像の数だけ、$FILE が増えているのがわかります。 通常の添付ファイルは Type が ATTACHMENT (1084) なのですが、画像は 1085 になっていて、少し違います。<br /><br />ちなみに添付ファイルの場合は、1084, 1085 両方の $FILE アイテムが作成されます。 添付アイコンも画像として処理されているのですね。<br /><br />さて、ちょっと苦労した点なのですが...。<br /><br />画像、もしくは添付ファイルのあるリッチテキスト・アイテムを別文書にコピーしたところ、以下のようなエラーが発生していました。<br /><br /><img src="//rinco.jp/blog/memo/20070415_itemerror.gif" width="227" height="114" alt="文書アイテムが見つかりません。" /><br /><a name="more"></a> <br />調べてみると、Type 1085 の $FILE アイテムをコピーし忘れている雰囲気なんですよね。 手元の R6, R7 Notes client の両方で問題が発生したので、一時的なバグでもない模様。<br /><br />そこで Type 1085 アイテムを明示的に CopyItem しようとしたのですが、エラーになりました。<br /><br /><img src="//rinco.jp/blog/memo/20070415_copyerror.gif" width="437" height="114" alt="ATTACHMENT か OTHEROBJECT の種類のアイテムはコピーできません。" /><br /><br />CopyAllItems ならちゃんとコピーされるようす。 またこれもバグっぽいのですが、リッチテキストを RemoveItem しても消えない様子。<br /><br />しょうがないので、これらの特徴を利用して、以下の関数をクイックハックしてみました。<br /><br /><pre class="myLotusScript">Sub fixIconProblem(sDoc As NotesDocument, tDoc As NotesDocument)<br />  Dim tmpDoc As NotesDocument<br /> <br />  If sDoc Is Nothing Or tDoc Is Nothing Then<br />    Exit Sub<br />  End If<br /> <br />  Set tmpDoc = tDoc.ParentDatabase.CreateDocument<br /> <br />  Call sDoc.CopyAllItems(tmpDoc)<br /> <br />  Forall i In sDoc.Items<br />    Set item = i<br />    If Not(item.Type = 1084 Or item.Type = 1085) Then<br />      tmpDoc.RemoveItem(item.Name)<br />    End If			<br />  End Forall<br /> <br />  Call tmpDoc.CopyAllItems(tDoc)<br />End Sub<br /></pre><br />リッチテキストをコピーした後に呼び出せば、とりあえず Type 1085 アイテムをコピーしてくれます。 まとめてコピー処理してしまうので、複数のリッチテキストがある場合には注意が必要です。<br /><br />CopyItem/RemoveItem がちゃんと Type 1085 に対応してくれれば、このコードは無効化される (Forall の中で全 item が削除される) はず。 理論的には、ですが...。

]]><![CDATA[
]]></content:encoded>
            <category>雑談</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1685050.html</link>
      <title>DocumentDiffer クラス (6)</title>
      <pubDate>Wed, 08 Nov 2006 23:00:00 +0900</pubDate>
      <description>これまでご紹介した DocumentDifferクラス を 20061108_DocumentDiffer_v100.txt にまとめました。おまけとして toStringWithLabel()関数 を追加しています。 toString()関数 ではフィールド名(アイテム名)をそのまま使うため、出力結果は開発者にしかわからないものでした。 こちらはフィールド名に対応した表示名を指定するラベルを渡すことにより、よりわかりやすい出力になっています。更新ログをユーザーも参照すること..</description>
            <content:encoded><![CDATA[
これまでご紹介した <strong>DocumentDifferクラス</strong> を <a href="http://yamachan.sakura.ne.jp/sblo_files/hannover/image/20061108_DocumentDiffer_v100.txt" alt="20061108_DocumentDiffer_v100.txt">20061108_DocumentDiffer_v100.txt</a> にまとめました。<br /><br />おまけとして <strong>toStringWithLabel()関数</strong> を追加しています。 <strong>toString()関数</strong> ではフィールド名(アイテム名)をそのまま使うため、出力結果は開発者にしかわからないものでした。 こちらはフィールド名に対応した表示名を指定するラベルを渡すことにより、よりわかりやすい出力になっています。<br /><br />更新ログをユーザーも参照することがある場合、こちらの使用をお勧めします。 またこちらは、ラベル登録したもの以外は出力しない仕様になっていますので、いちいち removeItem() しなくてすむので、その意味でも使いやすいです。<br /><br />使い方の例はこちら。<br /><pre class="myLotusScript">Sub Postsave(Source As Notesuidocument)<br />  Call  aDocumentDiffer.process(Source.Document)<br /> <br />  Dim targetList$ List <br />  targetList$("Title") = "タイトル"<br />  targetList$("Description") = "概要"<br /> <br />  Msgbox aDocumentDiffer.toStringWithLabel(targetList$)<br />End Sub<br /></pre><br /><a name="more"></a>実際のコードは以下のようになっています。<br /><pre class="myLotusScript">Function toStringWithLabel(labelList$ List) As String<br />  toStringWithLabel = ""<br />  If Me.diffDoc Is Nothing Then<br />    Exit Function<br />  End If<br /> <br />  Forall item In Me.diffDoc.Items<br />    If Iselement(labelList(item.Name)) = True Then<br />      toStringWithLabel = toStringWithLabel<br />          & labelList(item.Name) & ": "<br />          & Me.getOldValue(item.Name)<br />          & " -> "<br />          & item.Text & Chr(10)<br />    End If<br />  End Forall<br />End Function<br /></pre><br />このサイトで紹介されているコードの利用は自由です。 DocumentDifferクラスはまだ使用回数が少なく、実装も練れているとは言えません。 もし使っていただく機会がありましたら、お気づきの点をお知らせいただければ助かります～

]]><![CDATA[
]]></content:encoded>
            <category>my設計パターン</category>
      <author>yamachan</author>
                  <enclosure url="http://yamachan.sakura.ne.jp/sblo_files/hannover/image/20061108_DocumentDiffer_v100.txt" length="2739" type="text/plain" />
                      </item>
        <item>
      <link>http://hannover.sblo.jp/article/1636294.html</link>
      <title>DocumentDiffer クラス (5)</title>
      <pubDate>Thu, 02 Nov 2006 01:16:02 +0900</pubDate>
      <description>DocumentDiffer クラス (4) に引き続き、今回はお遊びコードをご紹介します。ネタ元は LotusScript に対する不満？(2) Variant の名前でクラスを扱う、というあたり。カッコ良く言えば レイト・バインディング(late binding) を利用した実装ですね。 たぶんね。DocumentDiffer クラスに、以下のような workWith() メソッドを追加します。 引数としては Variant を指定しています。 指定したオブジェクトと適切..</description>
            <content:encoded><![CDATA[
<a href="/article/1330919.html">DocumentDiffer クラス (4)</a> に引き続き、今回はお遊びコードをご紹介します。
<br/><br/>
ネタ元は <a href="/article/1235144.html">LotusScript に対する不満？(2) Variant</a> の名前でクラスを扱う、というあたり。カッコ良く言えば レイト・バインディング(late binding) を利用した実装ですね。 たぶんね。
<br/><br/>
DocumentDiffer クラスに、以下のような workWith() メソッドを追加します。 引数としては Variant を指定しています。 指定したオブジェクトと適切に連動する、という仕様書に書くと怒られるようなアバウトな仕様。
<br/><br/>
今回のコードでは、以前にご紹介した <a href="/article/1148871.html">ログ生成用クラス</a> との連携を実装してみます。 ログに変更点を書き出してくれるという目論見です。
<pre class="myLotusScript">
Sub workWith(coWoker As Variant)
  If coWoker Isa "CoreLog" Then
    Call coWoker.logText(toString())
  End If
End Sub
</pre>
が、このコードは僕の環境では動作しませんでした。 謎です。 なにせ、次のコードは動作するのですから...。<br/><a name="more"></a><pre class="myLotusScript">
Sub workWith(coWoker As Variant)
  If Typename(coWoker) = "CORELOG" Then
    Call coWoker.logText(toString())
  End If
End Sub
</pre>
ちなみに、定義したときのクラス名 "CoreLog" だと動きませんでした。 以前から LotusScript は大文字小文字の区別がゆるい (Case sensitive ではない) とは感じていましたが、内部では大文字で格納しているっぽいですねぇ。
<pre class="myLotusScript">
Sub workWith(coWoker As Variant)
  If Typename(coWoker) = "CoreLog" Then
    Call coWoker.logText(toString())
  End If
End Sub
</pre>
気になって試したところ、Variant で受けると Isa が利かなくなってしまうみたいですね。
<br/><br/>
<table border="1" bgcolor="white">
        <tr valign="top">
                <td></td>
                <td>
                        coWoker<br/>as CoreLog
                </td>
                <td>
                        coWoker<br/>as Variant
                </td>
        </tr>
        <tr valign="top">
                <td>
                        coWoker Isa &quot;CoreLog&quot;
                </td>
                <td>
                        <div align="center">
                                True
                        </div>
                </td>
                <td>
                        <div align="center">
                                False
                        </div>
                </td>
        </tr>
        <tr valign="top">
                <td>
                        coWoker Isa &quot;CORELOG&quot;
                </td>
                <td>
                        <div align="center">
                                True
                        </div>
                </td>
                <td>
                        <div align="center">
                                False
                        </div>
                </td>
        </tr>
        <tr valign="top">
                <td>
                        Typename(coWoker) = &quot;CoreLog&quot;
                </td>
                <td>
                        <div align="center">
                                False
                        </div>
                </td>
                <td>
                        <div align="center">
                                False
                        </div>
                </td>
        </tr>
        <tr valign="top">
                <td>
                        Typename(coWoker) = &quot;CORELOG&quot;
                </td>
                <td>
                        <div align="center">
                                True
                        </div>
                </td>
                <td>
                        <div align="center">
                                True
                        </div>
                </td>
        </tr>
</table>
<br/>
というわけで、ちょっと遊びっぽい実装をご紹介しました。 (^-^;
<br/><br/>
でもこの WorkWith の実装例、意外に使えるかもしれませんよ。 CoreLog と連携する機能を実装して、かつ CoreLog が無くとも動作するクラスの作成トカ。
<br/><br/>
え？そんな変態的なクラス作るヒマがあったら、シンプルなアダプタクラスを提供しろって？ まぁ、それが王道ですかね...。

]]><![CDATA[
]]></content:encoded>
            <category>my設計パターン</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1330919.html</link>
      <title>DocumentDiffer クラス (4)</title>
      <pubDate>Tue, 26 Sep 2006 23:51:32 +0900</pubDate>
      <description>DocumentDiffer クラス (3) に引き続き、コードをご紹介します。まずはベタですが、チェック対象のフィールドを追加したり外したりする add/removeItem() 関数。 例えば更新履歴のフィールドなど、removeItem(&quot;updateHistory&quot;) などと外しておくのがお勧めデス。Sub addItem(doc As NotesDocument, itemName$)  Dim tmpItem As NotesItem    Set tmpItem..</description>
            <content:encoded><![CDATA[
<a href="/article/1307409.html">DocumentDiffer クラス (3)</a> に引き続き、コードをご紹介します。<br /><br />まずはベタですが、チェック対象のフィールドを追加したり外したりする <strong>add/removeItem()</strong> 関数。 例えば更新履歴のフィールドなど、removeItem("updateHistory") などと外しておくのがお勧めデス。<br /><pre class="myLotusScript">Sub addItem(doc As NotesDocument, itemName$)<br />  Dim tmpItem As NotesItem <br /> <br />  Set tmpItem = doc.getFirstItem(itemName$)<br />  If Not(tmpItem Is Nothing) Then <br />    Call tmpItem.CopyItemToDocument(Me.oldDoc, itemName$) <br />  End If<br />End Sub<br /> <br />Sub removeItem(itemName$)<br />  Call Me.oldDoc.removeItem(itemName$)<br />End Sub<br /></pre><br />続きましては、更新されたフィールドの以前の値を得るための <strong>getOldValue()</strong> 関数です。 あると意外と便利なのと、内部の仕組みをあるていど隠蔽するために実装してみたり。<br /><a name="more"></a><pre class="myLotusScript">Function getOldValue(itemName$) As String<br />  Dim tmpItem As NotesItem<br /> <br />  Set tmpItem = Me.oldDoc.getFirstItem(itemName$)<br />  If Not(tmpItem Is Nothing) Then<br />    getOldValue = tmpItem.Text<br />  End If<br />End Function<br /></pre><br />そしてデバッグに便利な <strong>toString()</strong> 関数です。<br /><pre class="myLotusScript">Function toString() As String<br />  toString = ""<br />  If Me.diffDoc Is Nothing Then<br />    Exit Function<br />  End If<br /> <br />  Forall item In Me.diffDoc.Items<br />    toString = toString & item.Name & ": " &<br />      Me.getOldValue(item.Name) & " -> " &<br />      item.Text & Chr(10)<br />  End Forall<br />End Function<br /></pre><br />とりあえずこれで最低限のコードはご紹介しました。 次回はお遊びコードを追加してみましょう。<br />

]]><![CDATA[
]]></content:encoded>
            <category>my設計パターン</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1307409.html</link>
      <title>DocumentDiffer クラス (3)</title>
      <pubDate>Thu, 21 Sep 2006 09:44:45 +0900</pubDate>
      <description>超操縦メカMG にハマって更新が止まっている今日この頃。 僕らの世代を狙い撃ちのゲームだとおもうんですが、意外に売れてないみたいですね...。さて今回も DocumentDiffer クラス (2) に引き続き、コードをご紹介します。今回は、実際に差分を作成する process関数 です。 process関数の引数は、更新後のNotes文書 (NotesDocument) です。実際に処理をおこなっているのは、Forall の部分です。 New で必要なフィールドのみ old..</description>
            <content:encoded><![CDATA[
<a href="http://www.nintendo.co.jp/ds/aigj/">超操縦メカMG</a> にハマって更新が止まっている今日この頃。 僕らの世代を狙い撃ちのゲームだとおもうんですが、意外に売れてないみたいですね...。<br /><br />さて今回も <a href="/article/1300949.html">DocumentDiffer クラス (2)</a> に引き続き、コードをご紹介します。<br /><br />今回は、実際に差分を作成する <strong>process関数</strong> です。 process関数の引数は、更新後のNotes文書 (NotesDocument) です。<br /><br />実際に処理をおこなっているのは、<strong>Forall</strong> の部分です。 New で必要なフィールドのみ oldDoc にコピーしているので、今度はそれを1つずつ、更新後の文書の同名フィールドと比べているわけです。<br /><a name="more"></a><pre class="myLotusScript">  ' ---- Public methods ----<br /> <br />  Function process(doc As NotesDocument) As NotesDocument<br />    Dim session As New NotesSession <br />    Dim tmpItem As NotesItem<br /> <br />    ' 差分文書が残っている場合は再作成<br />    If Not(Me.diffDoc Is Nothing) Then<br />      Delete Me.diffDoc<br />    End If<br />    Set Me.diffDoc = session.CurrentDatabase.CreateDocument<br /> <br />    ' アイテムごとに更新を確認<br />    Forall item In Me.oldDoc.Items<br />      If doc.HasItem(item.Name) Then<br />        Set tmpItem = doc.GetFirstItem(item.Name)<br />        If tmpItem.Text <> item.Text Then<br />          Call item.CopyItemToDocument(Me.diffDoc, item.Name)<br />        End If<br />      End If<br />    End Forall<br /> <br />    Set process = Me.diffDoc<br />  End Function<br /></pre><br />ちなみにアイテムの比較は単に <strong>.Text</strong> を使用していますが、これは少し手抜きです。 例えば複数値の格納された .Text の結果が、単数の結果と一致することがあるかもしれません。<br /><br />process関数は作成した差分文書を戻り値として返します。 もし差分をNotes文書で残す必要がある場合、この文書に適切な Form (入力フォームそのままでもいいかも) や、作成者フィールド他を設定して保存すればOKです。<br /><br />さて次回は、toString 関数などの便利系関数のコードを見てみましょう。<br />

]]><![CDATA[
]]></content:encoded>
            <category>my設計パターン</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1300949.html</link>
      <title>DocumentDiffer クラス (2)</title>
      <pubDate>Wed, 20 Sep 2006 00:57:37 +0900</pubDate>
      <description>DocumentDiffer クラス (1) に引き続き、コードをご紹介します。今回はコンストラクタ部分です。 コンストラクタは、対象のNotes文書を引数にします。DocumentDiffer はインスタンス生成の際、後の差分作成(process 関数)の実行に備え、必要なフィールドを全て保持しようとします。 具体的には、内部にテンポラリ文書を作成し、必要なフィールド(NotesItem)をコピーしておきます。保持しておくフィールドは、とりあえず 日付・名前・数値・テキスト..</description>
            <content:encoded><![CDATA[
<a href="/article/1244754.html">DocumentDiffer クラス (1)</a> に引き続き、コードをご紹介します。<br /><br />今回はコンストラクタ部分です。 コンストラクタは、対象のNotes文書を引数にします。<br /><br />DocumentDiffer はインスタンス生成の際、後の差分作成(process 関数)の実行に備え、必要なフィールドを全て保持しようとします。 具体的には、内部にテンポラリ文書を作成し、必要なフィールド(NotesItem)をコピーしておきます。<br /><br />保持しておくフィールドは、とりあえず 日付・名前・数値・テキストに限定しています。 また '$' 文字で始まるフィールドは、システムで利用するフィールドが多いので、保持する対象からはずしています。<br /><br />さて、実際のコードをみてみましょう。<br /><a name="more"></a><pre class="myLotusScript">Public Class DocumentDiffer<br />  Private oldDoc As NotesDocument<br />  Private diffDoc As NotesDocument<br /> <br />  ' ---- Constractor/Destractor methods ----<br /> <br />  Sub New(doc As NotesDocument)<br />    Dim session As New NotesSession <br />    Set Me.oldDoc = session.CurrentDatabase.CreateDocument<br /> <br />    Forall item In doc.Items<br />      If item.Type = DATETIMES Or item.Type = NAMES Or<br />            item.Type = NUMBERS Or item.Type = TEXT Then<br />        If Left$(item.Name, 1) <> "$" Then<br />          Call item.CopyItemToDocument(Me.oldDoc, item.Name)<br />        End If<br />      End If <br />    End Forall <br />  End Sub<br /> <br />  Sub Delete<br />    Delete Me.oldDoc<br />    If Not(Me.diffDoc Is Nothing) Then<br />      Delete Me.diffDoc<br />    End If<br />  End Sub<br />End Class<br /></pre><br />New の部分をみますと、条件に合うフィールドをコピーするだけの、わりあい単純な仕組みであることがわかるとおもいます。<br /><br />Delete はいつもながら、生成したインスタンスを削除するだけの最低限のものです。<br /><br />さて次回は、実際に差分を作成する process() 関数の定義をみていきましょう～

]]><![CDATA[
]]></content:encoded>
            <category>my設計パターン</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1244754.html</link>
      <title>DocumentDiffer クラス (1)</title>
      <pubDate>Sat, 09 Sep 2006 21:40:49 +0900</pubDate>
      <description>先日、職場のヒトが ソックス の話をしていたので、ニーソックス や 絶対領域 に関する熱い話題 を期待して近づいていったら、J-SOX 法に関する話題でした... orzなんちて。最近、J-SOX だの 内部統制 だのの流れで、システムの要件に厳密な権限管理や、詳細ログの保存等が盛り込まれることが多いようです。知り合いも既存の Notes DB に、文書の変更ログ機能 を追加するよう言われていました。 変更のあったフィールドを、基本的にはすべてログする必要があるとのことです。..</description>
            <content:encoded><![CDATA[
先日、職場のヒトが <strong>ソックス</strong> の話をしていたので、<a href="http://ja.wikipedia.org/wiki/%E3%83%8B%E3%83%BC%E3%82%BD%E3%83%83%E3%82%AF%E3%82%B9">ニーソックス</a> や <a href="http://ja.wikipedia.org/wiki/%E7%B5%B6%E5%AF%BE%E9%A0%98%E5%9F%9F">絶対領域</a> に関する熱い話題 を期待して近づいていったら、J-SOX 法に関する話題でした... orz<br /><br />なんちて。<br /><br />最近、<strong>J-SOX</strong> だの <strong>内部統制</strong> だのの流れで、システムの要件に厳密な権限管理や、詳細ログの保存等が盛り込まれることが多いようです。<br /><br />知り合いも既存の Notes DB に、<strong>文書の変更ログ機能</strong> を追加するよう言われていました。 変更のあったフィールドを、基本的にはすべてログする必要があるとのことです。 フィールドの数が多いので眩暈がすると嘆いていました。<br /><br />いい機会ですので、(頭の隅の)倉庫に眠っていた <strong>DocumentDiffer</strong> クラスをご紹介します。<br /><a name="more"></a> <br />まずは恒例の使い方から。<br /><br />まずはフォームの (Globals) の (Declaration) で大域変数を宣言しておきます。<br /><pre class="myLotusScript">Dim aDocumentDiffer As DocumentDiffer<br /></pre><br />後は以下のように利用します。<br /><pre class="myLotusScript">Sub Postmodechange(Source As Notesuidocument)<br />  ' 文書の変更前の状態をバックアップ<br />  If Source.EditMode = True Then<br />    Set aDocumentDiffer = New DocumentDiffer(Source.Document)<br />  End If<br />End Sub<br /> <br />Sub Postsave(Source As Notesuidocument)<br />  ' 変更前との差分を作成<br />  Call  aDocumentDiffer.process(Source.Document)<br />  ' 今回の例では単にポップアップ表示するだけ<br />  Msgbox aDocumentDiffer.toString<br />End Sub<br /></pre><br />文書を更新すると、更新したフィールドの名前と、変更前後の値がポップアップ表示されるようになるはずです。<br /><br />次回はコンストラクタあたりから、実際のコードをご紹介しましょう。

]]><![CDATA[
]]></content:encoded>
            <category>my設計パターン</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1235144.html</link>
      <title>LotusScript に対する不満？(2) Variant</title>
      <pubDate>Fri, 08 Sep 2006 00:24:13 +0900</pubDate>
      <description>さて Variant型 に関する不満(？)です。 いや嫌いじゃないんですけどね。使うたびに頭の中で 三石琴乃さん (マリュー・ラミアス大尉)の、「ヴァリアント、てー！」という声が響くんですよね～ というのは嘘で。どうも馴染めないのは、あまりに柔軟すぎるから、だとおもいます。 Variant を利用すると途端に、静的な事前チェックがほとんどできなくなる気がします。Variant 型にもクラスのインスタンスを代入できます。 代入されたのがどのクラスかは IsA 演算子 で確認でき..</description>
            <content:encoded><![CDATA[
さて <strong>Variant型</strong> に関する不満(？)です。 いや嫌いじゃないんですけどね。<br /><br />使うたびに頭の中で <a href="http://ja.wikipedia.org/wiki/%E4%B8%89%E7%9F%B3%E7%90%B4%E4%B9%83">三石琴乃さん</a> (<a href="http://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%BB%E3%83%A9%E3%83%9F%E3%82%A2%E3%82%B9">マリュー・ラミアス大尉</a>)の、「ヴァリアント、てー！」という声が響くんですよね～ というのは嘘で。<br /><br />どうも馴染めないのは、あまりに柔軟すぎるから、だとおもいます。 Variant を利用すると途端に、静的な事前チェックがほとんどできなくなる気がします。<br /><br />Variant 型にもクラスのインスタンスを代入できます。 代入されたのがどのクラスかは <strong>IsA 演算子</strong> で確認できますが、なんと！ クラスそのものではなく、クラス名(文字列)と比較しているような気が。 あらビックリ。<br /><a name="more"></a> <br />この面白さが伝わるかどうか不明ですが、サンプルを見てみてください。 まず、適当にアクションボタンでも作成して、(Declarations) セクションに2つの適当な(ありがちな！)クラスを定義します。<br /><pre class="myLotusScript">Class Cat<br />  Sub test<br />    Msgbox |nya-|<br />  End Sub<br />End Class<br /> <br />Class Dog<br />  Sub test<br />    Msgbox |bow!|<br />  End Sub <br />End Class<br /></pre><br />以下のように実行部分を記述して、クラスの動作を確かめてみましょう。 ま、動かなかったら困りますね。<br /><pre class="myLotusScript">Sub Click(Source As Button)<br />  Dim aCat As New Cat<br />  Dim aDog As New Dog<br /> <br />  Call aCat.test<br />  Call aDog.test <br />End Sub<br /></pre><br />さて、これからが面白い(たぶん)ところです。 以下のような Function を追加してみます。 Panda クラスという、どこにも定義していないクラスを利用していますが、特にエラーにはなりません。<br /><pre class="myLotusScript">Sub doTest(target As Variant) <br />  If target Isa "Panda" Then<br />    Call target.test <br />    Call target.testPanda <br />  Elseif target Isa "Cat" Or target Isa "Dog" Then<br />    Call target.test<br />  End If<br />End Sub<br /></pre><br />念のため、以下のように実行部分を書き換えて実行すると、何事もなかったように動きます。<br /><pre class="myLotusScript">Sub Click(Source As Button)<br />  Dim aCat As Variant<br />  Dim aDog As Variant<br /> <br />  Set aCat = New Cat<br />  Set aDog = New Dog<br /> <br />  Call doTest(aCat)<br />  Call doTest(aDog)<br />End Sub<br /></pre><br />なんといいますか、Variant が入ることで、事前の静的なチェックがされなくなってるような。メソッド実行が単に実行時に 名前で 処理されているような、アバウトな雰囲気を感じるんですよね。<br /><br />その反面、Java のように Interface を用意しなくても、名前さえあわせておけば、全然関係ないクラスのメソッドを自由に呼び出せたりしそうで、ニヤニヤしてしまいます。 かなーり変態的なコードが書けそうなニオイがするというか。<br /><br />んー、楽しそう。<br /><br />ちなみに、僕は普段 "Option Declare" を指定せずに、宣言しない変数を使った LotusScript を書いたりしてます。 Variant がどうこうなどと、あまり偉そうなことは言えない立場なのかも？ (^-^;

]]><![CDATA[
]]></content:encoded>
            <category>雑談</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1231323.html</link>
      <title>LotusScript に対する不満？(1) オーバーロード</title>
      <pubDate>Wed, 06 Sep 2006 23:36:07 +0900</pubDate>
      <description>最初に書きましたが、僕はもともとは Java な人でした。 LotusScript を使い始めたとき、まず調べたのはクラスの定義方法。 で、その制限の多さには少し驚きました。 極論するとこれ、オブジェクト指向というよりも、、、単に継承＆カプセル化が利用できるようになった、便利なデータ型なのではないかと。 (言葉悪くて、スイマセン...)まず最初に困ったのは、メソッド(クラス Function) に オーバーロード が無いことです。 簡単に言えば、引数の異なる同じ名前のメソッド..</description>
            <content:encoded><![CDATA[
最初に書きましたが、僕はもともとは Java な人でした。 LotusScript を使い始めたとき、まず調べたのはクラスの定義方法。 で、その制限の多さには少し驚きました。 <br /><br />極論するとこれ、オブジェクト指向というよりも、、、単に継承＆カプセル化が利用できるようになった、便利なデータ型なのではないかと。 (言葉悪くて、スイマセン...)<br /><br />まず最初に困ったのは、メソッド(クラス Function) に <strong>オーバーロード</strong> が無いことです。 簡単に言えば、引数の異なる同じ名前のメソッドを定義できる、というものです。<br /><a name="more"></a> <br />例えば、以前にご紹介した <a href="/article/1128810.html">CoreLog クラス</a> ですが、オブジェクトを初期化する New 部分は、以下のような感じで複数用意したかったのです。 でもこれを実装しようとすると2個目以降の New の定義が「以前に宣言した名前です。」 と怒られちゃいますよね。<br /><pre class="myLotusScript">Public Class CoreLog<br />  Sub New()<br />    Call New(Nothing, 2, "default log")<br />  End Sub <br /> <br />  Sub New(logType$)<br />    Call New(Nothing, 2, logType$)<br />  End Sub<br /> <br />  Sub New(doc As NotesDocument, level%, logType$)<br />    ....<br />  End Sub<br />End Class<br /></pre><br />多態性を利用すると、例えば、作成したコードを気軽に利用できるようになります。 引数によく使うデフォルト値がある場合、僕はよく、引数の有る/無しで複数のメソッドを定義します。<br /><br />引数を指定する必要が無いときは、単に最低限の引数で呼び出すと、お任せで動作する。 それが僕の好みです。 細かく制御したくなったら、はじめてマニュアル等を調べて、引数を追加してもらえば良いわけです。 オートマでもマニュアルでも運転できる車、と言ったら大げさですが、そんなイメージかなぁ。<br /><br />逃げ道としては、古典的ですが、引数の違いを名前に反映させることでしょうか。 例えば数値を追加する場合には "addNumber(value%)" を使用し、文字列を追加する場合には "addString(value$)" を利用する、といった実装です。 LotusScript で用意されているクラスにはこのパターンが多い気がします。<br /><br />この場合、New などの名前が変えられないものは、デフォルト処理のみを実行するしかないですね。 後で setXXXX などのセッターや、setupXXXX などのメソッドで、必要な値をセットするカタチになります。<br /><br />まったく別の手法として、引数に Variant 型を指定する方法もあるとは思います。 が、僕は Variant にはどうも馴染めず... って、これは次回のネタにしましょう。(^-^;<br />

]]><![CDATA[
]]></content:encoded>
            <category>雑談</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1208984.html</link>
      <title>あっという間に3週間</title>
      <pubDate>Thu, 31 Aug 2006 23:59:00 +0900</pubDate>
      <description>8月のアクセス統計というのを見たところ、訪問者数 437 ページビュー 6186 でした。 アクセスしていただいた皆さん、ありがとうございました。夏休み期間が終わってしまったので、更新頻度は不定期になるとおもいますが、地道に更新していきたいナ、と考えています。こんごともよろしくお願いいたします。 (_o_)</description>
            <content:encoded><![CDATA[
8月のアクセス統計というのを見たところ、訪問者数 437 ページビュー <br />6186 でした。 アクセスしていただいた皆さん、ありがとうございました。<br /><br />夏休み期間が終わってしまったので、更新頻度は不定期になるとおもいますが、地道に更新していきたいナ、と考えています。<br /><br />こんごともよろしくお願いいたします。 (_o_)<br /><a name="more"></a> <br />ところで、よくわからない英語のトラックバックがあるのですが、これが噂の <strong>トラックバックSPAM</strong> ってやつですかね。<br /><br />こんな地味な小さなサイトにも、もう来るぐらいですから、きっと皆、大変なんだろうなぁ...。<br /><br />禁止 URL に指定しようにも、ランダム数値を混ぜてるっぽいので難しいですね。ん、ランダム URL で何の価値があるんだ？<br /><br />とりあえずblogマニュアル見て、防ぐ手段を探してみよう、とか思ってます。

]]><![CDATA[
]]></content:encoded>
            <category>日記</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1198465.html</link>
      <title>ありえないSELECT文</title>
      <pubDate>Mon, 28 Aug 2006 21:57:44 +0900</pubDate>
      <description>アリエナイ設計、というカテゴリを追加してみました。これは僕が見た Notes/Domino アプリで驚いた、いえ正直に言えば呆れた書き方をしたものの記録です。 知ってて当然、という感じであまり説明されない、基本的な事柄が中心になるとおもいます。さて今日のびっくりは、ありえないSELECT文です。ある日、とあるアプリのスケジュールエージェントが動作しないという相談がありました。 テスト環境では動くのですが、本番に配置すると何故か動作しない、そうで。動作しない、と簡単に言われても..</description>
            <content:encoded><![CDATA[
アリエナイ設計、というカテゴリを追加してみました。<br /><br />これは僕が見た Notes/Domino アプリで驚いた、いえ正直に言えば<strong>呆れた</strong>書き方をしたものの記録です。 知ってて当然、という感じであまり説明されない、基本的な事柄が中心になるとおもいます。<br /><br />さて今日のびっくりは、<strong>ありえないSELECT文</strong>です。<br /><br />ある日、とあるアプリのスケジュールエージェントが動作しないという相談がありました。 テスト環境では動くのですが、本番に配置すると何故か動作しない、そうで。<br /><br />動作しない、と簡単に言われても、ちゃんとした動作ログが無いのでよくわかりません(これもアリエナーイ)。 そこで、以前にご紹介した <a href="/article/1128810.html">ログ生成クラス</a> をさっくり組み込んで動作を確認し、問題に対応しました。 で、ログ機能は今後のために残しておくことになりました。<br /><br />さて数日後、アプリの担当者から連絡がありました。 「謎の文書が表示されている」 という怪現象が発生しているそうで。 しかも日に日に増えているとか。 こ、これは考えるまでもありません、原因はアレです。<br /><a name="more"></a> <br />案の定、該当ビューの SELECT文は、以下のようになっていました。 眩暈がします。<br /><pre class="myLotusScript">SELECT FORM!="A Form" & FORM!="B Form" & FORM!="C Form"<br /></pre><br />よっぽどの理由がない限り、「選択式」はその名のとおり<strong>選択する条件</strong>を記載しましょう。 けっして<strong>例外条件を列挙</strong>してはいけません。<br /><br />何か変更がある場合、関係のある部分をチェックするのは普通です。が、この設計だと、関係のない部分を全部チェックしないと安心できないですよね。 アリエナーイ、とは思いませんか？<br /><br />ビューだけではなく、NotesDatabase クラスの Search メソッドなども要注意。 <br /><br />まぁ、時間がなかったとはいえ、アプリ全体の確認をしなかった僕も悪いのですがネ...。

]]><![CDATA[
]]></content:encoded>
            <category>アリエナイ設計</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1179472.html</link>
      <title>NotesColor の240色って？</title>
      <pubDate>Wed, 23 Aug 2006 23:11:25 +0900</pubDate>
      <description>NotesColor (NotesColorObjectクラス) では240色が利用できますが、アイコンと違い、デザイナーズヘルプには全色は載っていないようです。 なので簡単な表を作成してみました。</description>
            <content:encoded><![CDATA[
<script type="text/javaScript" src="http://rinco.jp/sblo_files/hannover/image/20060823_NotesColor.js"></script>

NotesColor (NotesColorObjectクラス) では240色が利用できますが、アイコンと違い、デザイナーズヘルプには全色は載っていないようです。 なので簡単な表を作成してみました。
<br />
<br />

<script language="JavaScript1.2" type="text/javascript">
<!--
  writeNCTable(0, 50);
-->
</script><a name="more"></a><script language="JavaScript1.2" type="text/javascript">
<!--
  writeNCTable(50, 240);
-->
</script>

<br />
表は
<a href="http://rinco.jp/sblo_files/hannover/image/20060823_NotesColor.js" alt="20060823_NotesColor.js">20060823_NotesColor.js</a>
 という JavaScript で生成しています。 JavaScript のデータ部分は、以下のような LotusScript で生成したものを利用しています。
<br />
<br />
※ JavaScript のほうは特に、かなーり適当に書いてあるので、あまり参考にしないほーが良いかも
<br />
<br />
ある処理系で、別の処理系のコードを生成する、なんてトリッキーに感じるかもしれませんが、なかなか便利です。
<br />
<br />
<pre class="myLotusScript">
Sub Initialize
  Dim session As New NotesSession
  Dim ws As New NotesUIWorkspace
  Dim doc As NotesDocument
  Dim rti As NotesRichTextItem
  Dim color As NotesColorObject
 
  Set doc = ws.CurrentDocument.Document	
  Set color = session.CreateColorObject
  Call doc.RemoveItem("Body")
  Set rti = doc.CreateRichTextItem("Body")
 
  For i = 0 To 240
    color.NotesColor = i
    Call rti.AppendText(|c[| & Cstr(i) & |] = "#|)
    Call rti.AppendText(Right$("00" & Hex$(color.Red), 2))
    Call rti.AppendText(Right$("00" & Hex$(color.Green), 2))
    Call rti.AppendText(Right$("00" & Hex$(color.Blue), 2))
    Call rti.AppendText(|";|)		
    Call rti.AddNewLine(1)
  Next
  Call doc.Save(True, True)
End Sub
</pre>

※ 適当なフォームのアクションに貼り付けて実行すると、いきなり Body フィールドを書き換えてしまうという荒い作りです (デザイナーズヘルプの例を改造して遊んだコードなので、単にその名残りデス)


]]><![CDATA[
]]></content:encoded>
            <category>雑談</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1148871.html</link>
      <title>ログ生成用クラス (6)</title>
      <pubDate>Tue, 22 Aug 2006 00:10:33 +0900</pubDate>
      <description>三回に分けて掲載した LotusScript コードを 20060822_CoreLog_v100.txt にまとめました。 使用する時は適当なスクリプトライブラリの Declarations セクションにでも貼りつけてください。CoreLog クラスは最低限の機能しか実装していないため、誰が書いても似たようなコードになると考えます。 著作権等を主張することはありませんので、自由にご利用ください。なにか不具合を発見された方、より良いコードを書かれた方、フィードバックいただけれ..</description>
            <content:encoded><![CDATA[
三回に分けて掲載した LotusScript コードを <a href="http://rinco.jp/sblo_files/hannover/image/20060822_CoreLog_v100.txt" alt="CoreLog クラス v100">20060822_CoreLog_v100.txt</a> にまとめました。 使用する時は適当なスクリプトライブラリの <strong>Declarations</strong> セクションにでも貼りつけてください。<br /><br /><strong>CoreLog</strong> クラスは最低限の機能しか実装していないため、誰が書いても似たようなコードになると考えます。 著作権等を主張することはありませんので、自由にご利用ください。<br /><br />なにか不具合を発見された方、より良いコードを書かれた方、フィードバックいただければ嬉しいです。<a name="more"></a> <br />もし現在の実装で、物足りなく思える方、現在のクラスを継承して拡張してみるのがお勧めです。<br /><br />CoreLog クラス自体を書き換えてしまってもかまいませんが、その場合は、クラス全体をテストする必要があります。 継承を使えば、安定した実装をベースに、自分の拡張部分のみをテストすればOKです。<br /><br />例えば以下は、ログ文書に読者フィールドを設定するメソッド <strong>setReader()</strong> を追加した例になります。<br /><pre class="myLotusScript">Public Class MyCoreLog As CoreLog<br /> <br />  Public Sub setReader(fieldName$, value$)<br />    Dim item As NotesItem<br /> <br />    Set item = Me.logDoc.ReplaceItemValue(fieldName$, value$)<br />    item.IsReaders = True<br />  End Sub<br /> <br />  Sub New(doc As NotesDocument, level%, logType$)<br />  End Sub <br />End Class<br /></pre>CoreLog は引数付きのコンストラクタを使用しているため、継承した <strong>MyCoreLog</strong> クラスでもコンストラクタの定義が必要なことに注意してください。<br /><br />また以下は、10行以上のログ出力がある場合、いったんログ文書を保存する拡張例になります。<br /><pre class="myLotusScript">Public Class MyCoreLog As CoreLog<br />  Private saveCounter As Integer<br /> <br />  Public Sub logText(message$)<br />    CoreLog..logText(message$)<br /> <br />    Me.saveCounter = Me.saveCounter + 1<br />    If Me.saveCounter > 10 Then<br />      Call saveLog()<br />      Me.saveCounter = 0<br />    End If<br />  End Sub<br /> <br />  Sub New(doc As NotesDocument, level%, logType$)<br />  End Sub<br />End Class <br /></pre>この例では、CoreLog の <strong>logText()</strong> メソッドを上書き(オーバーライド)しているのがポイントです。 元の CoreLog クラスの logText() メソッドをまず実行したうえで、独自の処理を追加しているのがわかるとおもいます。<br /><br />他にもいろいろ拡張方法は考えられます。 何か良いコードがありましたら、ぜひお知らせください。 便利そうなものは、CoreLog クラスにマージさせて共有していきたいと考えています。<br />

]]><![CDATA[
]]></content:encoded>
            <category>my設計パターン</category>
      <author>yamachan</author>
          </item>
        <item>
      <link>http://hannover.sblo.jp/article/1148523.html</link>
      <title>ログ生成用クラス (5)</title>
      <pubDate>Mon, 21 Aug 2006 22:48:30 +0900</pubDate>
      <description>ログ生成用クラス (4) に引き続き、CoreLog クラスの残りの実装をみていきましょう。 まずは処理のメインとなる2つのメソッドです。  ' ---- Public methods ----   Public Sub logText(message$)    Me.getLog().AppendText(message$)    Call Me.getLog().AddNewLine(1)  End Sub   Public Sub traceText(message$,..</description>
            <content:encoded><![CDATA[
<a href="/article/1142595.html">ログ生成用クラス (4)</a> に引き続き、CoreLog クラスの残りの実装をみていきましょう。 まずは処理のメインとなる2つのメソッドです。<br /><pre class="myLotusScript">  ' ---- Public methods ----<br /> <br />  Public Sub logText(message$)<br />    Me.getLog().AppendText(message$)<br />    Call Me.getLog().AddNewLine(1)<br />  End Sub<br /> <br />  Public Sub traceText(message$, level%)<br />    If level% <= Me.getTraceLevel() Then<br />      Me.getTrace().AppendText(message$)<br />      Call Me.getTrace().AddNewLine(1)<br />    End If<br />  End Sub<br /></pre><a name="more"></a>期待して待っていた方には多し訳ないのですが、ま、えてして重要な部分っていうのはシンプル作りなのです。(^-^;<br /><br />で、残りはログをクローズする部分になります。<br /><pre class="myLotusScript">  Public Sub saveLog()<br />    Call Me.logDoc.Save(True, True)<br />  End Sub<br /> <br />  Public Sub closeLog()<br />    Dim timeComplete As NotesDateTime<br /> <br />    Me.logDoc.Status = "ok"		<br />    Set timeComplete = New NotesDateTime(Now())	<br />    Me.logDoc.End = timeComplete.LSLocalTime<br />    Me.logDoc.Elapsed =<br />     timeComplete.TimeDifference(Me.timeStart)<br /> <br />    Call saveLog()		<br />    Delete timeComplete<br />  End Sub<br /></pre><br />これで実装部分は終わりです。 次回は最終回として、全コードをまとめ、拡張の例をお見せします。

]]><![CDATA[
]]></content:encoded>
            <category>my設計パターン</category>
      <author>yamachan</author>
          </item>
      </channel>
</rss>
