[Notes/Domino] @UserNamesList を LotusScript でシミュレートする
@UserNamesList はとっても便利な関数ですが、ログインしているユーザーしか対象にできないという難点があります。他のユーザーの権限を確認したい場合は、ACLの「有効なアクセス権」機能で確認はできるものの、リスト欄が小さくて見づらかったり、リストを書き出すことができなかったりと、ちょっと不便なところがあります。
今回、これらの問題を解消すべく、@UserNamesList と同じ(と思われる)値を返す LotusScript の処理を作ってみました。ログインしているユーザー以外のユーザーも対象にできますので、参考にしてみてください。
UserNamesList 関数
| 説明 | @UserNamesList と同じ(と思われる)結果を返す |
|---|---|
| 構文 | UserNamesList(dbTgt As NotesDatabase, Byval strId As String) As Variant |
| 引数 | [in,---]dbTgt ... 調査対象のDB [in,---]strId ... 調査対象のノーツID(階層付き) |
| 戻り値 | グループなどのリスト(エラー時はEmpty) |
ソースコード
Function UserNamesList(dbTgt As NotesDatabase, Byval strId As String) As Variant
Dim dbNab As New NotesDatabase("", "")
Dim vwNab As NotesView
Dim nm As NotesName
Dim varRetAry As Variant
Dim varRoleAry As Variant
Dim strRetAry() As String
UserNamesList = varRetAry
'エラーチェック
If dbTgt Is Nothing Then
Exit Function
End If
If dbTgt.Server = "" Then
Exit Function
End If
If dbNab.Open(dbTgt.Server, "names.nsf") = False Then
Exit Function
End If
'ビュー取得
Set vwNab = dbNab.GetView("($ServerAccess)")
'基準書式で検索
Set nm = New NotesName(strId)
strId = nm.Canonical
Call GetGroupList(vwNab, strId, strRetAry)
'OU~Cまで検索
Do Until Instr(strId, "/") = 0
strId = "*/" & Strright(strId, "/")
Call GetGroupList(vwNab, strId, strRetAry)
strId = Strright(strId, "/")
Loop
'*で検索
Call GetGroupList(vwNab, "*", strRetAry)
'CNで検索
Call GetGroupList(vwNab, nm.Common, strRetAry)
'ソートなど
varRetAry = Arrayunique(strRetAry) '念のため
varRetAry = ArySort(varRetAry) 'ソートが必要なければ、この行は不要
'ロールがあれば追加
varRoleAry = dbTgt.QueryAccessRoles(nm.Canonical)
If varRoleAry(0) <> "" Then
varRetAry = Arrayappend(varRetAry, varRoleAry)
End If
UserNamesList = varRetAry
End Function
Sub GetGroupList(vwDir As NotesView, Byval strKey As String, strRetAry() As String)
Dim nav As NotesViewNavigator
Dim entry As NotesViewEntry
Dim strVal As String
Call AryPush(strRetAry, strKey)
Set nav = vwDir.CreateViewNavFromCategory(Lcase(strKey))
If nav.Count > 0 Then
Set entry = nav.GetFirst()
Do Until entry Is Nothing
strVal = Cstr(entry.ColumnValues(1))
If Isnull(Arraygetindex(strRetAry, strVal)) = True Then
Call AryPush(strRetAry, strVal)
Call GetGroupList(vwDir, strVal, strRetAry) '再帰
End If
Set entry = nav.GetNext(entry)
Loop
End If
End Sub
Sub AryPush(varAry As Variant, varVal As Variant)
Dim intMax As Integer
If Isarray(varAry) = False Then
Exit Sub
End If
On Error Goto ERR_INIT
intMax = Ubound(varAry) + 1
On Error Goto 0
Redim Preserve varAry(intMax)
varAry(intMax) = varVal
Exit Sub
ERR_INIT:
intMax = 0
Redim varAry(0)
Resume Next
End Sub
Function ArySort(varAry As Variant) As Variant
Const COMBGAP = 1.3
Dim varRetAry As Variant
Dim varTmp As Variant
Dim lngMin As Long
Dim lngMax As Long
Dim i As Long
Dim j As Long
Dim lngGap As Long
Dim blnEnd As Boolean
varRetAry = varAry
lngMin = Lbound(varRetAry)
lngMax = Ubound(varRetAry)
lngGap = lngMax - lngMin
blnEnd = False
Do While lngGap > 1 Or blnEnd = False
lngGap = Int(lngGap / COMBGAP)
If lngGap = 9 Or lngGap = 10 Then lngGap = 11
If lngGap < 1 Then lngGap = 1
blnEnd = True
For i = lngMin To lngMax - lngGap
j = i + lngGap
If varRetAry(i) > varRetAry(j) Then
varTmp = varRetAry(i)
varRetAry(i) = varRetAry(j)
varRetAry(j) = varTmp
blnEnd = False
End If
Next
Loop
ArySort = varRetAry
End Function
例文
v = UserNamesList(db, "Test01 User/TEST")
If Isempty(v) Then
Msgbox ""
Else
Msgbox Join(v, Chr(10))
End If
使用上の注意事項
- この関数の処理は @UserNamesList をシミュレートしますが、あくまで管理人が @UserNamesList の処理を推測して作ったものであり、100% 同じ結果になるかどうかは保証いたしかねます。
- @UserNamesList はキャッシュ機能があるためローカルでも動作させることは可能ですが、この関数ではそのようなことはできないので、調査対象のDBがローカルの場合、Emptyを返します。
- グループが多い環境では、ユーザーが所属するグループの数に比例して、処理速度が遅くなります。グループが多い環境では、権限チェックなどに使わないでください。(どうしても使いたい場合は、結果をどこかにキャッシュしておくなど、工夫してみてください。)
- グループのメンバに共通名や「*」などを使わない規約がある場合は、これらの処理を削除すると速度が多少速くなります。また、ロールが必要ない場合は、引数の dbTgt は要らないです。パフォーマンスが最適になるよう、適当に改変してみてください。

コメント
コメントはありません
※コメントは承認制となっております。管理者が承認するまで表示されません。申し訳ありませんが、投稿が表示されるまでしばらくお待ちください。