ExtJSにはEditorGridPanelというものがあるのですが、エクセルのような表をフォームとして扱えるウィジェットです。これをSharePointのフォームとして扱えれば、データシートビューのようなフォームが作れてしまいます。基本的にはLists.asmxのUpdateListItemsを使っているのですが、まとめて更新、新規作成なんかができちゃうので、ちゃんと作りこめばかなり便利なものになるかと思いますよ。
いかにサンプルソースを載せておきます。簡単ではありますが、ソースにコメントを残しておきました。ご自身の環境に合わせてパスなどを書き換えてみてください。また、このサンプルソースをそのまま使う場合はSharePoint側でライブラリ(カスタムリストかな)を作る際のフィールド名などもあわせてください。(ソースに記述しておきました。)
<link rel="stylesheet" type="text/css" href="<yourSitePath>/ext/resources/css/ext-all.css" />
<script type="text/javascript" src="<yourSitePath>/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="<yourSitePath>/ext/ext-all.js"></script>
<script type="text/javascript">
function getHttpReq(){
return window.XMLHttpRequest ? new XMLHttpRequest() : ( function() {
try { return new ActiveXObject( "Msxml2.XMLHTTP" ); }
catch( e ) { return new ActiveXObject( "Microsoft.XMLHTTP" ); }
}());
}
function getFieldItems()
{
var dataAry = new Array();
var libName = '<yourLibName>'
// SharePointでのフィールド定義
var targetFields =
'<FieldRef Name="ID" />' + // デフォルト
'<FieldRef Name="Title" />' + // デフォルト
'<FieldRef Name="selectClmn" />' + // 選択肢フィールドを"selectClmn"で作成しておく
'<FieldRef Name="numField" />' + // 数値フィールドを"numField"で作成しておく
'<FieldRef Name="dateField" />'; // 日付フィールドを"dateField"で作成しておく
var httpInst = getHttpReq();
httpInst.open( "POST", "<yourSitePath>/_vti_bin/Lists.asmx", false );
httpInst.setRequestHeader( 'Content-Type','text/xml; charset=utf-8' );
httpInst.setRequestHeader( 'SOAPAction','http://schemas.microsoft.com/sharepoint/soap/GetListItems' );
var postBody = '<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body><GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/"><listName>' + libName + '</listName><viewName></viewName><query></query><viewFields><ViewFields>' + targetFields + '</ViewFields></viewFields><rowLimit></rowLimit><queryOptions><QueryOptions/></queryOptions><webID></webID></GetListItems></soap12:Body></soap12:Envelope>';
httpInst.onreadystatechange = function()
{
if ( httpInst.readyState == 4 ){
xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" );
xmlDoc.async = false;
xmlDoc.loadXML( httpInst.responseText );
var rowsItem = xmlDoc.selectNodes( '/soap:Envelope/soap:Body/GetListItemsResponse/GetListItemsResult/listitems/rs:data/z:row' );
for( idx = 0; idx < rowsItem.length; idx++ ){
var fieldDataList = new Array();
// 日付フィールドは "2008-04-07 13:00:00"で返ってくるので
// "2008/04/07"にフォーマットを変換しておく。
var dateRow = rowsItem[ idx ].getAttribute( "ows_dateField" ).replace( /-/g, "/" );
dateRow = dateRow.substring( 0, dateRow.lastIndexOf( " " ) );
// 数値フィールドは 0.0000000・・・で返ってくるのでroundする。
var numRow = Math.round( rowsItem[ idx ].getAttribute( "ows_numField" ) );
fieldDataList.push( rowsItem[ idx ].getAttribute( "ows_ID" ) );
fieldDataList.push( rowsItem[ idx ].getAttribute( "ows_Title" ) );
fieldDataList.push( rowsItem[ idx ].getAttribute( "ows_selectClmn" ) );
fieldDataList.push( numRow );
fieldDataList.push( dateRow );
dataAry.push( fieldDataList );
}
}
}
httpInst.send( postBody );
return dataAry;
}
function updateListItems( paramXML )
{
var httpInst = getHttpReq();
var libName = '<yourLibName>';
httpInst.open( "POST", "<yourSitePath>/_vti_bin/Lists.asmx", false );
httpInst.setRequestHeader( 'Content-Type','text/xml; charset=utf-8' );
httpInst.setRequestHeader( 'SOAPAction','http://schemas.microsoft.com/sharepoint/soap/UpdateListItems' );
var postBody = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><UpdateListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/"><listName>' + libName + '</listName><updates>' + paramXML + '</updates></UpdateListItems></soap:Body></soap:Envelope>';
/*
httpInst.onreadystatechange = function()
{
// エラーハンドリングはここで行う。
if ( httpInst.readyState == 4 ){
}
}
*/
httpInst.send( postBody );
alert( "更新しました" );
}
Ext.onReady( function(){
var changeList = new Array();
var headAry = [
{ name : 'ID' },
{ name : 'Title' },
{ name : 'selectClmn' },
{ name : 'numField' },
{ name : 'dateField', type:'date', dateFormat: 'Y/m/d' }
];
var clmn = new Ext.grid.ColumnModel([
{
id : 'ID',
header: "ID",
dataIndex: 'ID',
width: 50
},
{
header: "タイトル",
dataIndex: 'Title',
width: 100,
editor: new Ext.form.TextField(
{
allowBlank: false
})
},
{
// 選択肢フィールド定義はHTML下部のid:ddfieldより取得する。
header: "選択肢フィールド",
dataIndex: 'selectClmn',
width: 100,
editor: new Ext.form.ComboBox({
typeAhead: true,
triggerAction: 'all',
transform:'ddfield',
lazyRender:true
})
},
{
header: "数値フィールド",
dataIndex: 'numField',
width: 100,
align: 'right',
editor: new Ext.form.NumberField()
},
{
header: "日付フィールド",
dataIndex: 'dateField',
width: 120,
renderer: Ext.util.Format.dateRenderer( 'Y/m/d' ),
editor: new Ext.form.DateField( { format: 'Y/m/d' } )
}
]);
clmn.defaultSortable = true;
var MyForm = Ext.data.Record.create( headAry );
var reader = new Ext.data.ArrayReader( {}, headAry );
var store = new Ext.data.Store({
reader: reader,
data: getFieldItems(),
sortInfo:{ field:'ID', direction:'DESC' }
});
var grid = new Ext.grid.EditorGridPanel({
store: store,
cm: clmn,
renderTo: 'editor-grid',
width:640,
height:300,
title:'Form',
frame:true,
clicksToEdit:1,
stripeRows:true,
// リスナー登録。
listeners:{
// gridセルに対する編集が加わった際のイベントを取得する。
'afteredit': function( evt ) {
var curChange = grid.getStore().getAt( evt.row ).get( 'ID' );
// 編集が加わったIDを参照して、空の場合は新規作成とする
if( curChange == '' ) return;
// 既存のアイテムで編集されたIDをためておく。
for( var idx = 0; idx < changeList.length; idx++ ){
if( changeList[ idx ] == curChange ){
return;
}
}
changeList.push( curChange );
}
},
// ツールバー。「新規作成」と「送信」
tbar: [{
text: '新規作成',
handler : function(){
var newForm = new MyForm({
ID:'',
Title: '',
selectClmn: '',
numField: 0,
dateField: ( new Date() ).clearTime()
});
grid.stopEditing();
store.insert( 0, newForm );
grid.startEditing( 0, 0 );
}
},
{
text: '送信',
handler : function(){
var idx = 0;
var methodCnt = 1;
var batchXML = '';
var curStore = grid.getStore();
curStore.each( function(){
// 新規作成はIDが空
if( curStore.getAt( idx ).get( 'ID' ) == '' ){
var fmtDate = Ext.util.Format.date( curStore.getAt( idx ).get( 'dateField' ), 'Y-m-d' );
batchXML = batchXML +
'<Method ID="' + methodCnt + '" Cmd="New">' +
'<Field Name="Title">' + curStore.getAt( idx ).get( 'Title' ) + '</Field>' +
'<Field Name="selectClmn">' + curStore.getAt( idx ).get( 'selectClmn' ) + '</Field>' +
'<Field Name="numField">' + curStore.getAt( idx ).get( 'numField' ) + '</Field>' +
'<Field Name="dateField">' + fmtDate + '</Field>' +
'</Method>'
methodCnt++;
}
// 既存のアイテムを変更した場合、
// aftereditイベントでためたIDを参照してXMLを構築する。
else {
for( var sdx = 0; sdx < changeList.length; sdx++ ){
if( curStore.getAt( idx ).get( 'ID' ) == changeList[ sdx ] ){
// SharePointの日付フォーマットに直す。"2008/04/07" → "2008-04-07"
var fmtDate = Ext.util.Format.date( curStore.getAt( idx ).get( 'dateField' ), 'Y-m-d' );
batchXML = batchXML +
'<Method ID="' + methodCnt + '" Cmd="Update">' +
'<Field Name="ID">' + curStore.getAt( idx ).get( 'ID' ) + '</Field>' +
'<Field Name="Title">' + curStore.getAt( idx ).get( 'Title' ) + '</Field>' +
'<Field Name="selectClmn">' + curStore.getAt( idx ).get( 'selectClmn' ) + '</Field>' +
'<Field Name="numField">' + curStore.getAt( idx ).get( 'numField' ) + '</Field>' +
'<Field Name="dateField">' + fmtDate + '</Field>' +
'</Method>'
methodCnt++;
}
}
}
idx++;
});
// 新規作成や、更新があった場合はmethodCntが1以上
if( methodCnt > 1 ){
// XMLを渡して更新する。
updateListItems( '<Batch>' + batchXML + '</Batch>' );
// リロードしてgridフォームを読み直すと更新されてます。
// location.reload();
}
else {
alert( "フォームの更新がされていません" );
}
}
}]
});
});
</script>
</head>
<body>
<div style="margin: 12px 12px">
<div id="editor-grid"></div>
<select name="ddfield" id="ddfield" style="display: none;">
<option value="hoge">hoge</option>
<option value="moge">moge</option>
<option value="fuga">fuga</option>
</select>
</div>
</body>



