SSブログ

リストを別サイトに移行する -(2)- [技術情報]

リストを別のサイトに移行する -(1)- で記載したように標準のリストテンプレートでコンテンツを含んだリストテンプレートを作成できないリストが存在します。
下記の例は案件テンプレートを使用したリストです。

なぜだかわかりませんが、このリストをテンプレートとして保存する際に「コンテンツを含む」チェックボックスが選択できないようになっています。

これを回避する方法としてはサーバー側のテンプレート設定XMLファイルを修正することにより回避することができます。ただし、修正前のテンプレートで作成してしまったリストには反映されません。

下記に方法を記載します。

テンプレート設定XMLファイル名:ONET.XML
サーバー側保存場所:C:\Program Files\Common Files\Microsoft Shared\web server extentions\60\TEMPLATE\1041\STS\XML

ONET.XMLのissueに関する記述の中にある DontSaveInTemplate = "TRUE" を削除して保存します。

<ListTemplate Name="issue" DisplayName="Issues" Type="1100" BaseType="5" DontSaveInTemplate="TRUE" OnQuickLaunch="TRUE" SecurityBits="11" Description="Create an issues list when you want to manage a set of issues or problems. You can assign, prioritize, and follow the progress of issues from start to finish."  Image="/_layouts/images/itissue.gif">

</ListTemplate>

 

その後、IISリセットを実行し、案件リストテンプレートを使用してanken3リストを作成します。

この状態でテンプレートとして保存します。このとき「コンテンツを含む」がチェックできるようになっています。

テンプレート保存後に別サイトで「案件3」を指定してリストを作成します。

すると、データも含めて別サイトに案件リストが移行できました。


なぜ案件リストがコンテンツを含めたリストテンプレート作成に対応していないのかは不明ですが上記の手順によりコンテンツを含めたリストテンプレート作成に対応することができます。

本手順はサーバー側の設定ファイルを修正しますのでバックアップを必ずとってから作業するようにしてください。


 


リストを別サイトへ移行する -(1)- [技術情報]

SharePointの世界においてリストは非常に重宝される情報蓄積手段です。

リストには標準でいくつかのテンプレートが用意されています。リンク、お知らせ、連絡先、イベント、ToDo、案件など。それとは別にユーザーが列を自由に作成できるカスタムリスト。

サイトが肥大化したりした場合にサブサイトを作成し、ここに今まで蓄積されたデータを移動したいと考えたとき有効な手段の一つとしてリストをテンプレート化するときにコンテンツを含むをチェックしてサブサイトに移す方法があります。
リストテンプレート化するにはリストの「設定と列の変更」から「リストをテンプレートとして保存」を選択します。

その後でコンテンツを含むにチェックを入れて保存します。

その後、移行したいサブサイトでリストを作成する際に「氏名リスト」テンプレートを選択します。

するとデータも含めた移行が完了します。

ただ、上記方法で移行できないリストも存在します。

次回は標準ではデータを含んだリストテンプレートが作成できない標準リストテンプレートについて書きたいと思います。 


 

 


使用容量計算 [技術情報]

ユーザーがWebUI上で容量の確認をしようと思うと「サイト コレクションの利用状況の概要」でサイトコレクション単位で確認することができます。ただし、サイトコレクション単位でしかデータは存在していません。
しかもそのデータは集計値ではなく累積値になっています。つまり、サイトコレクションにファイルが追加・削除されるたびに加算・減算を行っているようです。

Sitesテーブルに存在する下記のカラムがそう。
 ・DISKUSED … ディスク使用量

そのほかにもこんなカラムがあります。
 ・DISKQUOTA … クォータ設定値
 ・DISKWARNING … 警告メール送信値

それじゃぁつまらないので、できる限り正確なサブサイト単位の容量を計算してみたいと思います。

まず、容量は2つに分かれています。1つがサイトコレクション単位の容量、もう一つがサブサイト単位の容量です。
 サイト単位 … WebPartsテーブル
 サブサイト単位 … Docs, DocVersions, ComMd, Personalization, Lists, UserData

まず、サイト単位の情報を取得します。
-- WebParts
SELECT Sites.FullUrl AS SiteUrl,Sites.id AS SiteId,Sites.DiskUsed AS DiskUsed,
  Sites.DiskQuota AS DiskQuota,Sites.DiskWarning AS DiskWarning,
  Sum(ISNULL(WebParts.tp_Size,0)) AS WebPartsSize FROM Sites
 LEFT OUTER JOIN WebParts ON Sites.id = WebParts.tp_SiteId
 GROUP BY Sites.FullUrl,Sites.id,DiskUsed,DiskQuota,DiskWarning
 ORDER BY Sites.FullUrl

次にサブサイト単位にDocsの情報を集計します。
-- Docs
SELECT Sites.FullUrl AS SiteUrl,  Webs.FullUrl AS SubSiteUrl, Sites.Id AS SiteId,
  Webs.Id AS WebId, ISNULL(SUM(CAST(ISNULL(Docs.Size, 0) AS BIGINT) +
  CAST(ISNULL(Docs.CheckoutSize, 0) AS BIGINT)+
  CAST(ISNULL(Docs.MetaInfoSize, 0) AS BIGINT)),0) AS DocSize
 FROM Sites
 LEFT OUTER JOIN Webs ON Sites.Id = Webs.SiteID
 LEFT OUTER JOIN Docs ON Sites.Id = Docs.SiteId and Webs.id = Docs.webid
 GROUP BY Sites.FullUrl,Webs.FullUrl,Sites.Id,Webs.Id
 ORDER BY Sites.FUllUrl,Webs.FullUrl

次にDocVersions,ComMd,Personalizationを集計します。
-- DocVersions,ComMd,Personalizations,
SELECT Sites.FullUrl AS SiteUrl, Webs.FullUrl AS SubSiteUrl, Sites.Id AS SiteId,
  Webs.Id AS WebId, SUM(CAST((ISNULL(DocVersions.Size, 0)
  + ISNULL(DocVersions.MetaInfoSize, 0)) AS BIGINT)) AS DocVerSize,
  SUM(ISNULL(CONVERT(BIGINT,ComMd.[size]),0)) AS ComMdSize,
  SUM(ISNULL(CONVERT(BIGINT,Personalization.[tp_size]),0)) AS PersonalSize FROM Sites
 LEFT OUTER JOIN Webs ON Sites.Id = Webs.SiteID
 LEFT OUTER JOIN Docs ON Sites.Id = Docs.SiteId and Webs.id = Docs.webid
 LEFT OUTER JOIN DocVersions ON Sites.id = Docversions.siteid and Docs.id = DocVersions.id
 LEFT OUTER JOIN ComMd ON Sites.id = ComMd.siteid and Docs.id = ComMd.docid
 LEFT OUTER JOIN Personalization ON Sites.id = Personalization.tp_siteid
  and Docs.id = Personalization.tp_pageurlid
 GROUP BY Sites.FullUrl,Webs.FullUrl,Sites.Id,Webs.Id ORDER BY Sites.FUllUrl,Webs.FullUrl

次にリストデータの集計をします。
-- Lists,UserData
SELECT Sites.FullUrl AS SiteUrl,  Webs.FullUrl AS SubSiteUrl, Sites.Id AS SiteId,
  Webs.Id AS WebId, SUM(ISNULL(CONVERT(BIGINT,UserData.[tp_Size]), 0)) AS UserDataSize
 FROM Sites
 LEFT OUTER JOIN Webs ON Sites.Id = Webs.SiteID
 LEFT OUTER JOIN Lists ON Webs.Id = Lists.tp_WebId
 LEFT OUTER JOIN UserData ON Sites.id = UserData.tp_siteid and Lists.tp_id = UserData.tp_ListId
 GROUP BY Sites.FullUrl,Webs.FullUrl,Sites.Id,Webs.Id
 ORDER BY Sites.FUllUrl,Webs.FullUrl

上記のDocs, DocVersions, ComMD, Personalization, UserDataの集計値を加算した値に最初で算出したWebPartsの集計値を加算します。

ただし、正式に発表された情報ではないのであくまでも目安としてつかってください。


ほたる鑑賞会 [こーひーぶれいく]

仕事から帰ってきたら回覧板がきていました。

中身を見てびっくり。

「ほたる鑑賞会のご案内」

えっ!この辺にほたるいるの?
町内会の人が案内してくれるそうです。ほーっ、早速参加希望を出そう。

注意事項が書いてある。ふむふむ。

 「 ・民家が近いので、静かに鑑賞しましょう。」

うん、のどかだねぇ。民家の近くでほたるが鑑賞できるなんて。

 「 ・草むらには、マムシが居ますので、十分注意してください。」

えっ、ちょっと待て!この辺ってそんなに田舎だっけ?マムシが居るなんてしらなかった。
地元民のかみさんから狸やイタチが居るってのは聞いたけど。。。

さっそくググってみると。

 「 南西諸島を除く日本の各地に生息する。 」

あら、各地に生息するんだ。そっか、別段田舎ってわけじゃないよね?と勝手に解釈する。

というわけで6月の後半に家族でほたるを見に行こうと思います。
見ることができたら報告しますね。


アップロード時のファイル名自動生成 for SPS2003 [技術情報]

今日はドキュメントライブラリへのアップロード時のファイル名変更について記載します。MOSS2007ではいろいろな方法が提案されていますがもう少し違ったアプローチでSPS2003で実現してみましょう。

今回はデータベーストリガーを使用したアプローチを紹介します。データベーストリガーはデータベースに対してInsert,Delete,Update文発行前後におのおの動作するように指定が可能になっています。これを利用します。

たとえば、「障害レポート」ドキュメントライブラリを作成し、障害発生時にアップロードする運用を考えます。

障害レポートのひな形は「障害報告.xls」。これはひな形をドキュメントライブラリに登録しておきトップページにリンクを張っておきます。

障害発生時に運用担当者がリンクから「障害報告.xls」をローカルPCにダウンロードし、これを記入した後で「障害レポート」ドキュメントライブラリにアップロードします。

この運用の場合、下記の要件が考えられます。
 ・上書きしないようにファイル名を変えてアップロードする。
 ・定められた命名規則に則って変更してアップロードする。
 ・「障害レポート」ドキュメントライブラリのみファイル名を自動生成させる。

これを自動化する運用を考えます。

SQLServerの場合はInsert,Delete,Update文発行時にINSERTED,DELETEDテーブルに更新する値が保持されます。

またドキュメントライブラリにアップロードされたドキュメントはDocsテーブルに保存されます。Docsテーブルには下記の使えそうなColumnが用意されています。

ID          … ドキュメントごとにユニークなID
  LEAFNAME    … ファイル名
  DOCLIBROWID … ドキュメントライブラリごとにユニークなID
DIRNAME    … ファイルのURL

今回の要件の場合はドキュメントライブラリにアップロードされたタイミングで実行されればいいのでDocsテーブルにInsert文が発行された後にトリガーが動くようにトリガーを張ります。

トリガーの中ではDocsテーブルに対してInsertされたデータに対して下記の条件をチェックします。
 ・ドキュメントライブラリに登録された文書か?
 ・「障害レポート」ドキュメントライブラリに対してInsertされたか?

上記条件を満たした場合、ファイル名の前に"[TR-00000x]"のヘッダーを追加するようにします。

【トリガー】
--------------------------------------------------------------------------
/*
ドキュメントライブラリ通番付加ストアドプロシージャ
前提
・サーバーオプション 「nested trigger」 が1になっていること
・WebURLを指定すること
*/
CREATE TRIGGER trigger_DoclibNumbering ON Docs
AFTER INSERT AS
BEGIN
DECLARE @ID UNIQUEIDENTIFIER
DECLARE @LeafName NVARCHAR(255)
DECLARE @DocLibRowID INT
DECLARE @LenRowID INT
-- 更新前データの取得
SELECT
@ID = Id,
@LeafName = LeafName,
@DocLibRowID = DocLibRowID,
@LenRowID = LEN(DocLibRowID)
FROM
INSERTED
WHERE
DIRNAME = 'sites/test/TroubleReport/TR_Report'
-- 見つからない場合は何もしない
IF @LEAFNAME IS NULL
BEGIN
-- 対象外データ
RETURN
END
-- ファイル名の更新
UPDATE Docs
SET LeafName = '[TR-' + STUFF('000000',6 - @LenRowID,@LenRowID + 1,CAST(@doclibrowid AS NVARCHAR) ) + ']' + @LEAFNAME
WHERE Id = @ID
END
--------------------------------------------------------------------------

では、実際に運用してみましょう
まずは障害管理.xlsをダウンロードし、障害内容を記入します。

そして、ドキュメントライブラリにアップロードします。

すると、自動的にファイル名の頭にヘッダー部をつけて登録してくれました。

もうひとつ

今度はエクスプローラビューにドラッグ&ドロップしてみましょう。すると。。。

あら、失敗か? 試しにすべてのドキュメントビューに戻すと。

おおっ、うまく動いているようです。

編集もすべてのビューからは問題なくできます。ただ、エクスプローラビューはそのままだとファイル名が違うので開けません。そこでいったんブラウザを閉じて再度エクスプローラビューにするとファイル名がきちんと表示されて編集が可能になります。


という具合にデータベーストリガーを利用することにより比較的簡単に自動採番を実施できます。
今回は自動採番機能にDocLibIDを使用しましたが日付を使用したり、採番用のストアドを作成する
ことによりいろいろな使い方ができると思います。


カスタムリストの不思議 「前へ」 [技術情報]

今日は1つ、勉強をさせてもらいました。みなさんはすでに承知のことかもしれませんが、自分に対しての備忘録として記録しておきます。
SPS2003ではカスタムリストをWebパーツで表示し、表示アイテム数を指定した場合、次へしか出ないのが当たり前だと思っていましたが、FrontPageでとあることをすると「前へ」も表示されます。

たとえば下記の様にカスタムリスト「テスト」をページに配置し、9件登録した場合

 


表示件数を3件にして4~6件を表示した場合、戻って1~3件目を表示するのにブラウザの「戻る」を使用して表示させていました。

 


しかし、FrontPage2003を使って、このカスタムリストをXSLTデータビューに変換してやると。。。

あら、不思議。「前へ」と「次へ」が両方とも表示されます。
すごい!というか最初からこうしてよって気がしなくもないですが。ちなみにリセットは最初に戻るようです。


 

いやぁ~、初めて画像を入れてみました(笑) いかがでしょう?


DataBase構造について-(1)- [技術情報]

SharePointではデータと言われるものはほとんどSQL Serverデータベースに格納される。
よってSQL Serverのデータベース構造を把握することは重要になる。
この内容は「Microsoft SharePoint 製品とテクノロジ 2003 ソフトウェア開発キット」に記載されている。
主な内容を備忘録としてまとめる。

【コンフィグレーションデータベース】
  Databases … SharePointで使用しているデータベースの一覧
  VirtualServers … 仮想サーバー一覧
  Servers … サーバー一覧

【コンテンツデータベース】
  ComMD … ディスカッションのデータ
  Docs … ドキュメントのデータ
  DocVersions … ドキュメントのVersion管理データ
  Lists … リストに関する情報
  Personalization … 個別に登録されたWebパーツの一覧
  Sites … トップレベルサイトの情報
  UserData … リストのデータ
  UserInfo … サイトコレクションのユーザー情報
  Webs … サブサイトの一覧

  
 


システム移行の苦悩 -(1)- [技術情報]

いやぁー、困りました。
実はお客様よりPloneからSPS2003へのデータ移行の話がありました。
PloneはZopeを基盤としたUnixのOpenSourceです。ただで使えるということで少し前からもてはやされていますが、OpenSourceの宿命でユーザー側にかなりのスキルを要求されます。
今回のお客様もシステムを構築した人が会社を辞めてしまい、内部がわからない状態で困っておられるようです。
データはZope固有の内部DBに格納され、簡単にはデータを取り出せない仕組みになっています。
抽出方法としてはエクスポート機能があるのですが、PloneもしくはZopeへの移行用でサイト全体を1XMLファイルに書き出すもので、内部を解析しないと使えない状態です。
エクスポートのほかにスクリプト言語のPythonが使えるようなのですが、残念ながら今のところ私は使えません。
明日、いや今日か。チーム内で対応方法を検討することになりそうです。


VBプログラマのSharePoint開発-(3)- リストデータの削除 [技術情報]

リストデータを全部削除するプログラムのサンプル

--------------------------------------------------------------
Public Function DelAllListItem(ByVal MyWeb As SPWeb, ByVal ListName As String) As Boolean
'---------------------------------------------------------------
' 概要
' リスト内のすべてのアイテムを削除する
' パラメータ
' ByVal MyWeb as SPWeb SPWebオブジェクト
' ByVal ListName as String リスト名
' 機能
' 1.リストを削除する
' 戻り値
' Boolean
'---------------------------------------------------------------
Try
DelAllListItem = False
Dim MyListItemCollection As SPListItemCollection = MyWeb.Lists(ListName).Items
Dim k As Integer
Dim MyListItem As SPListItem
If MyListItemCollection.Count > 0 Then
For k = 0 To MyListItemCollection.Count - 1
MyListItem = MyListItemCollection(k)
MyListItemCollection.Delete(k)
Next
End If
DelAllListItem = True
Catch ex As Exception

End Try
End Function


VBプログラマのSharePoint開発-(2)- ユーザー追加 [技術情報]

SPS2003で検索を実施するためには各サイトをクロールする必要性があります。
この際にクロールするユーザーアカウントがクロール対象サイトにアクセス権を持っている必要性があります。
しかし、クロールアカウントが入っていないサイトを見つけてアクセス権を登録するのは至難の業です。
そこで今回は特定アカウントを全サイトに登録するコンソールプログラムを作りました。
下記のサンプルはその一部です。パラメータにサイトURLを渡してそのサイト配下の全サブサイトに対して指定のアカウントが存在しなければ追加します。

--------------------------------------------------------------------------
Public Function AdminUserAdd(ByVal SiteUrl As String) As Boolean
Dim GlobalAdmin As New Administration.SPGlobalAdmin
Dim MySPUser As SPUser
Dim MySPWeb As SPWeb
Dim MySPRole As SPRole
Dim tmpLogin As String
Dim admLogin As String = [追加したいユーザーアカウント]
Dim addFlg As Boolean

Try
Dim MyUri As Uri = New Uri(SiteUrl)
Dim MyVirtualServer As Administration.SPVirtualServer = GlobalAdmin.OpenVirtualServer(MyUri)
Dim MySPSite As SPSite = MyVirtualServer.Sites(MyUri.AbsolutePath)

'サイトコレクション内の全サブサイトを調べる
For Each MySPWeb In MySPSite.AllWebs
        '追加フラグ
addFlg = False
Try
'サブサイト内の全ロールを調べる
For Each MySPRole In MySPWeb.Roles
'ロールが管理者か?
If MySPRole.Type = SPRoleType.Administrator Then
'全管理者ユーザーを調べる
For Each MySPUser In MySPRole.Users
'追加したいアカウントが存在するかチェックする。
If MySPUser.LoginName.ToLower = admLogin.ToLower Then
addFlg = True
End If
Next
End If
Next
Catch ex As Exception
System.Console.WriteLine("*** Web Language Not Supported ** " & ex.Message)
System.Console.WriteLine("Site Url = " & MySPWeb.Url)
End Try
'追加したいアカウントが存在しなかった場合、アカウントを追加する。
If addFlg = False Then
MySPRole.AddUser(sUser, sEmail, sShowName, sNotes)
End If
Next
Catch ex As Exception
System.Console.WriteLine(ex.Message)
End Try
End Function


この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。