Sunday, November 8, 2009

数据视图案例 – Part 1

这是实际环境中,按用户需求来设置的步骤,不是单一个SharePoint 功能的设置示范。这当中牵涉到多方面,包括:

1. 网页界面中的网页修改

2. SharePoint Designer 2007 (SPD 2007)中的网页修改

3. 数据视图的设置

4. 运用 SPD 2007修改和源码修改数据视图的 XSLT

用户的需求如下:

分公司的文档分散在分公司各自网站的文档库中,总部同事需要资料时候需要进去各个分公司的文档库中打开文档,再制作成集团的报告。希望统一显示在一个页面中

解决方法有很多种,例如:

1. 创建一个SharePoint网页部件页面,加入各个分公司的文档库网页部件,设置视图筛选,显示各自的所需文档

2. 创建一个公用的 EXCEL 档,各分公司同事共享 EXCEL 档,各自填写总部所需的内容

3. 在总部页面创建文档库,各分公司同事登入总部页面,上传自己分公司的文档

4. 创建一个SharePoint的列表,各分公司填入总部所需内容

5. 创建一个数据视图网页部件,显示所有分公司的经筛选后的文档内容

经与部门沟通,也考虑到文档内资料保密、权限等等的考虑,总部部门同事决定用数据视图。


步骤如下:

1. 添加 WebPart

打开 SPD 2007 导航到总部页面,点击准备添加视图的 webpart zone。

clip_image002[4]

在 SPD 2007 的菜单中,选数据视图,点选“插入数据视图”

clip_image004[4]

这时候,在对应的 webpart zone 之中,会出现了一个新的网页部件,DataFormWebPart,这就是数据视图

clip_image006[4]

2. 添加跨网页链接

在 SPD 2007 的右方应该会出现“数据源库”界面

clip_image008[4]

没有的话,点击SPD 2007 菜单 “数据视图>管理数据源”来打开

clip_image010[4]

在之前没有做过数据连接的话,界面中只会有“当前网站”一个分类,现在按界面最下方的“连接到其他库…”来添加连接

clip_image012[4]

点击后会出现“管理库”界面,按“添加”,填上名称和分公司的网页位置

clip_image014[4]

重复以上动作直到所有分公司的网页都连上,比如下图有三家分公司已经添加上,然后按“确定”

clip_image016[4]

成功连接后,此时界面中除了“当前网站”之外,还有刚才加上的三个网页,如下图

clip_image018[4]

3. 添加合并的数据源

展开“当前网站”,在“连接源”下面,按“新建链接源…”,然后会出现“链接数据源向导”界面,把各分公司需要连接的文档库,点选使它高亮只会按“添加(A) > >”,直至三家分公司需要连接的文档库都出现在“选择的数据源”框中,如下图,然后按“下一步(N) > ”

clip_image020[4]

向导会变成以下界面,由于此方案中文档是做合拼显示而不是关联关系的配对,所以选第一项“合并数据源的内容”,然后按完成

clip_image022[4]

此时看到,这个新的数据源,链接类型是“合并”的,喜欢的话,可以在“常规”中修改此数据源的名称

clip_image024[4]

此例子中没有修改名称,系统默认名称为“新数据源”,显示为如下。此时打开新数据源的菜单,点击“显示数据(S)”

clip_image026[4]

点击后,右边这个“数据源库”会变成显示数据界面,在此界面的最下方,选“显示数据”,方便查看。

4. 选取数据视图要显示的栏位

此时,“数据源详细信息”内会出现合并后的各栏位。这里要注意,这是个合并的数据,出现的所有三家分公司选取了文档库的栏位。在agg:source 中就可以看到有三个连接在此数据源内,如下图红框内显示的,按左右可以切换。

当鼠标移动到数据上,SPD 2007 会有提示说明此栏位的内部名称,如下图红色箭头,鼠标指着“名称”栏的“0808-local-pack-hk-v01.xls”时候,出现了提示显示XPath 表达式,如下面箭头所指示。

clip_image028[4]

表达式“/dsQueryResponse/Rows/Row/@FileLeafRef” 中可以看到此栏位在系统中的名称是 FileLeafRef。这些内部的栏位名,系统内建的栏名称是固定的,比如档案名必定是FileLeafRef、路径必定是FileRef。其他用户建的栏位,名称视乎创建栏时候输入的字符。自建栏的名字,在文档库设置内亦可看到,比如下图,“年份”栏的超链接路径最后部分“Field=Year”显示了栏位名是 Year。因为创建此栏时候栏位名取了Year,后来才改为中文“年份”,但是,显示名变了内部名也不会有变化。

clip_image030[4]

这个名称,与合并数据有莫大关系,也是在建设文档库时候需要注意的地方。只有内部名完全相同时候,比如系统栏 FileLeafRef,三个文档库的数据合并时候才会视作一个栏。在SPD 2007 的“数据源详细信息”框在三个连接中切换一下,都可以看到档案名都是出现在 FileLeafRef 栏位中。

但是,在用户自建的栏,一个文档库建立栏位时候填写了名称为中文“年份”,内部名称就会是“_x5e74__x4efd_”,另一个文档库建立栏位时候填写了名称为“年”,内部名称就会是“_x5e74_”,而如上例填了“Year”的话内部名称就是“Year”。

不同的内部名,系统会认为那是不同的栏,情况如下面的示意图:

clip_image032[4]

所以,有些全域共用的栏,比如年份、月份、部门等等,尽量用顶级网站栏来设置,在下级应用,方便管理和数据整合。

如果相信微软所说,把网站管理权开放给下级管理员,甚至开放给一般用户,虽然 IT 人员是减少了工作,但到数据整合时候,这很可能会变成开发员和管理员的噩梦。

5. 组成合并数据源

在数据库详细信息界面中,按CTRL不放然后点击所需要显示的字段,点选了后字段会变成高亮,如下图箭头(2)所示。然后,点击“将选择的域插入为…”点选“多项目视图”,如下图箭头(3)。由于我们要的是三个文档库内文档的列表,所以是多项目视图。

clip_image034[4]

插入成功后,在 SPD 2007 的设计界面会看到效果。

6. 调整显示格式 - 排序

接下去就是要调一下格式,使用户查看使用时候更方便。

点击 SPD 2007 的设计界面中的数据视图网页部件,在视图右边边缘顶部,会有个按钮,按一下可以带出编辑视图菜单,鼠标指着视图按右键带出编辑亦可。在“常用 Data View 任务”中点击“排序和分组”,带出排序和分组窗口,如下图。在左边找出需要排序分组的栏位,按添加。比如这例子中,我们要用分组排序的是“年份”和“月份”,用户要求是分组成“2009-10”、“2009-09”等等。现在选了年份就好了。当年份出现在右边框框中,点击“编辑排序表达式”,如下图。

clip_image036[4]

新带出来的“高级排序”窗口中,右上角的框框内,就可以编辑 XPath 表达式了。要注意,目前XPath 发展的挺快的,在这里不是所有的 XPath 函数都能用。不记得函数名想查看,下面窗框就有了,旁边还有些不清不楚的说明。回到我们的例子,我们就用“年”加“月”来分组,所以就用 concat() 把年月两个字段加在一起来排序,语法见下图。

clip_image038[4]

窗口下面还有预览,让你看看效果。Concat(@_x5e74__x4efd_,@x6708__x4efd_) 后预览就会显示 (YYYYMM) 格式。(此例子在文档库设置了年份填写格式是 YYYY,月份是 MM)

按确定返回排序和分组窗口,把排序方式改为降序,这样年月最新的文件就会显示在顶部,然后选“显示组页眉”,默认展开。如下图。

clip_image040[4]

按确定后在 SPD 2007 设计界面就会看到效果。

7. 调整显示格式 – 超链接

现在看起来不错了,但是整个数据视图只是个纯文字的列表。我们要为档案项目加入超链接,让用户点击档案名可以直接打开档案。

在 SPD 2007 点击档案名,如下图,点击后会看到“xsl:value-of”字样,整个系列同一个字段的值,系统都会标志为粉红色,这样很清晰看到改动所影响的范围。然后点击在右边边缘的按钮,带出任务窗口。把格式化为的文本,改为超链接。

clip_image042[4]

选了超链接之后,“编辑超链接”窗口就会弹出来。现在把“要显示的文字”,改为{@FileLeafRef},因为 FileLeafRef 就是档案名的字段名。

clip_image044[4]

然后在下面“地址”改为 {@FileRef},FileRef 就是档案路径的字段名。然后按确定保存。

clip_image046[4]

这时候,在 SPD 2007 的设计界面,就会出现超链接了。

8. 调整显示格式 – 插入修改者

总部的用户要求要看到档案的最后修改者,可能是看习惯了文档库的视图吧。本来在创建时候加入就可以了,但为是示范,现在才插入。点击月份栏之后按右键带出菜单,选插入右方栏,操作跟Word 的表格差不多。插入后效果如下图。

clip_image048[4]

然后点击新的栏,按右键带出菜单选“插入公式…”,如下图。

clip_image050[4]

带出来的插入公式界面,其实跟编辑排序时候的是一样。在 XPath 表达式直接输入 @Editor,或者在左边双击修改者。然后按确定保存。

clip_image052[4]

细心的你可能已经看到预览那里出来的效果好奇怪,按确定后在SPD 2007设计界面中看到的是一堆带有<tag>东西,而不是单纯一个用户名,其实在 SharePoint 中的用户栏位,都是用 Rich Text 保存的。现在在 SPD 2007 设计界面点击修改者的值,按边缘的按钮带出任务菜单,把格式化改为 RTF 即可还原,如下图。

clip_image054[4]

9. 调整显示格式 – 原文档库路径

三个文档库的文档全堆在一起是不好分辨到底是哪一家分公司的文档,所以在创建时候加入了“路径”栏,为方便总部同事导航到原文档库,所以把路径栏改成超链接。方法与设置文档超链接时候相同,如下图。

clip_image056[4]

跟文档时候的分别,是在 FileDirRef 前要加“/”号。由于此webpart 是在特定网页上,默认的 SiteCollection 就是页面的网站,此实施是跨网站的,所以要加上“/” ,root 标志,连接才会有效。

clip_image058[4]

10. 调整显示格式 – 底色和标题

最后,搞搞颜色,把分组标题颜色改为淡蓝色配合网页的颜色。如下图。

clip_image060[4]

修改一下数据视图的标题。

clip_image062[4]

最后,保存,离开 SPD 2007。

clip_image064[4]

在 SPD 2007 是无法直接改动 webpart 标题的。默认标题名字就是数据源的名字。这可以通过在页面中,编辑修改 webpart。

clip_image066[4]

把它改为“分公司报表”。

clip_image068[4]

下图就是完成品。

17

还有没提到的,就是处理栏位名不同、用XSLT控制显示内容等等用 SPD 2007 处理不了的事情。待续…

Thursday, May 14, 2009

自定义列表模板的运用

自定义列表在SharePoint中有很多机会用到,由于标准的文档库、列表等等不可能满足到企业的所有需要,对于有需要用列表来处理某一种信息时候,就会用上自定义列表。不管是自定义列表还是文档库,操作都是类似的。

首先,需要先弄好一个列表作为模板。比方说银行账户信息,如下图:


这张表在单一网站已经是可以用的了,但是比如在集团公司有好几家分公司,他们都需要统一用此列表填写银行信息,那就可以把此表做成模板,方法如下:

1. 选择列表设置


2. 在设置界面选择“将列表另存为模板”


3. 在以下界面输入需要的信息

  • 第一个是模板文档的名称,它将会以档案的形式出现在列表模板库
  • 第二是模板的名称,可以输入个容易识别的名字
  • 第三是模板说明,在这里输入说明方便将来查看模板库时候方便理解模板用途
  • 最后是选择是否把现在有的资料也保存进去模板,意思是现在这列表有的现有资料,存在模板内,将来应用模板时候资料一拼带出。举例,文件夹等等。

填好就按确定,这样就完成了。

之后在“创建”页面(这有很多方法进入,比如点击“查看所有网站内容”然后选“创建”),找不到的话,创建的页面是 /_layouts/create.aspx。在这页面的“自定义列表栏”就可以看到此模板了,点击即可创建。如下图:


要查看所有的列表模板,可以到顶层网站的模板库。默认的网址是这个:
/_catalogs/lt/Forms/AllItems.aspx

《完》

Wednesday, May 13, 2009

Reporting Services 报表字段消失和乱码 - 语言问题

如果用 Microsoft SQL 的报表服务,写出来的报表一切正常但字段无法显示,我遇到过好几次,一般的原因是语言设置错误。

首先,报表定义档 RDL (report definition language) 是一份 XML 档。打开看到的第一句:
<?xml version="1.0" encoding="utf-8"?>

看看是否 UTF-8 编码。

第二,看看报表的语言是否正确,这在RDL档的最后:
......
  <Language>en-US</Language>

  <TopMargin>2.5cm</TopMargin>

  <PageHeight>29.7cm</PageHeight>

</Report>

看看<Language>是否是你想要的。

第三,看看报表里面没显示的地方,看看属性是否正确,比如我的报表中有个textbox86没有显示出来的话,在报表设计软件(比如Business Intelligent Studio)切换到“配置”界面,点击textbox86带出它的属性:

看看这里的属性是否你想要的。
  • Calendar 是指资料是日期的时候,你想用的历法,一般选Default即可
  • Language 是指语言,我一般出问题都在这里,Default 就用了整张报表定义的,见上面第二点。比如你特别这一个文字框是显示日语的,需要在这里调
  • WritingMode 指书写的方向,有编程经验的应该熟悉了,lr-tb 是指 Left to Right - Top to Bottom

最后是 font, 如果我这textbox86是显示简体中文的,字体却选了Times New Roman,选错了当然出来乱码了。
《完》

Tuesday, May 5, 2009

Tag Cloud JS 代码

有点丢脸,我看一会,想来想去才知道 log()在以下代码中的作用。以下是我在这个 Blog 中用的 Tag Cloud,我改动了一点点。没什么注释的了,也没什么好说的了,很简单。

log()是用作algorithmic interpolation(对数插值)。不知道是什么的话,自行查阅初中的数学书。要用是因为没有log()的话,linear interpolation(直线插值)在tag数量不平均时候算出的字体大小不合理。

<script type='text/javascript'>

// Label Cloud User Variables
var cloudMin = 0;
var maxFontSize = 20;
var maxColor = [85,136,170];
var minFontSize = 8;
var minColor = [0,0,0];
var lcShowCount = false;

// Cloud function s() ripped from del.icio.us
function s(a,b,i,x)
{
if(a>b)
{
var m=(a-b)/Math.log(x), v=a-Math.floor(Math.log(i)*m)
}
else
{
var m=(b-a)/Math.log(x), v=Math.floor(Math.log(i)*m+a)
}
return v
}

var c=[];
var labelCount = new Array();
var ts = new Object;

<b:loop values='data:labels' var='label'>
var theName = "<data:label.name/>";
ts[theName] = <data:label.count/>;
</b:loop>

for (t in ts)
{
if (!labelCount[ts[t]])
{
labelCount[ts[t]] = new Array(ts[t])
}
}

var ta=cloudMin-1;
tz = labelCount.length - cloudMin;
lc2 = document.getElementById('labelCloud');
ul = document.createElement('ul');
ul.className = 'label-cloud';

for(var t in ts)
{
if(ts[t] < cloudMin)
{
continue;
}
for (var i=0;3 > i;i++)
{
c[i]=s(minColor[i],maxColor[i],ts[t]-ta,tz)
}

var fs = s(minFontSize,maxFontSize,ts[t]-ta,tz);
li = document.createElement('li');
li.style.fontSize = fs+'px';
li.style.lineHeight = '1';
a = document.createElement('a');
a.title = ts[t]+' Posts in '+t;
a.style.color = 'rgb('+c[0]+','+c[1]+','+c[2]+')';
a.href = '/search/label/'+encodeURIComponent(t);

if (lcShowCount)
{
span = document.createElement('span');
span.innerHTML = '('+ts[t]+') ';
span.className = 'label-count';
a.appendChild(document.createTextNode(t));
li.appendChild(a);
li.appendChild(span);
}
else
{
a.appendChild(document.createTextNode(t));
li.appendChild(a);
}

ul.appendChild(li);
abnk = document.createTextNode(' ');
ul.appendChild(abnk);
}
lc2.appendChild(ul);
</script>

首先从<b:loop>取得data:labels的数组,然后用for loop把data:labels数据用s()公式算出字体大小,颜色控制亦是如此,同时准备html的a标志、资料和字体格式写入gadget内,就是这样了。其他还有些除错和个性化的处理,例如lcShowCount,自己看吧。

Saturday, May 2, 2009

SharePoint SDK updated to 1.5

微软的SharePoint Server 2007 SDK 1.5版本在 2009年4月底推出了,同时间WSS3.0的SDK 亦更新到 1.5版本。需要的赶快去下一份啦。

这是发放的通告:SharePoint SDK 1.5 (April 2009) Released

  • 这是MOSS 2007 SDK的下载页面:MOSS 2007 SDK 1.5
  • 这是WSS 3.0 SDK的下载页面:WSS 3.0 SDK 1.5
  • 在线看MSDN的可以到以下地址:

  • MSDN MOSS 2007 SDK
  • MSDN WSS 3.0 SDK
  • Friday, May 1, 2009

    XSL 条件格式化

    前言
    在下的公司用Microsoft的SharePoint作为协作平台,各部门对系统的要求层出不穷,但大都可以归类为Record Management和搜索两方面。搜索方面我用得最多的是数据视图,而数据视图的数据是XML,显示格式化用的是XSLT。

    SharePoint Designer (SPD)是可以处理的,Microsoft官方说明看起来你不用懂XSLT亦可以,在SPD点这点那,拖放一下就搞定。但是,当我用SPD来处理比较复杂的数据视图时候,经常出错,它生成的XSLT源码其实并不可靠,而且冗长。最理想的是,连好数据,带出需要字段后,所有的格式化手工处理。本文是有关条件格式化,不限于应用在SharePoint的数据视图,是可以应用于所有XSL。

    实现
    XSL 条件格式化,用<xsl:choose>可以实现。

    Choose 是 XSL 的flow control 之一,按逻辑测试结果来执行特定代码,需要与 when 和 otherwise 一起使用,格式如下:
    <xsl:choose>
      <xsl:when test="expression">
        ......
      </xsl:when>
      <xsl:otherwise>
        ......
      </xsl:otherwise>
    </xsl:choose>

    expression 是逻辑测试条件。<xsl:choose>与其他编程语言的switch很相似,choose内可以包含多个<xsl:when>,处理多个逻辑分支,而<xsl:otherwise>就处理各个when都不符合的情况,类似其他编程语言switch中的default。这是它与<xsl:if>的最大分别。

    例子
    以下是要显示的XML。连到一张名为new.xsl的XSL档。
    <?xml version="1.0"?>
    <?xml:stylesheet type="text/xsl" href="new.xsl"?>
    <EMPDETAILS>
      <EMP EMPID="E001">
        <ENAME>Karen</ENAME>
        <DESG>MANAGER</DESG>
        <DEPT>SALES</DEPT>
        <SALARY>250</SALARY>
        <HP>http://www.baidu.com/</HP>
      </EMP>
      <EMP EMPID="E002">
        <ENAME>Lepton</ENAME>
        <DESG>Executive</DESG>
        <DEPT>MIS</DEPT>
        <SALARY>300</SALARY>
        <HP>http://leptonation.blogspot.com/</HP>
      </EMP>
    </EMPDETAILS>


    以下是new.xsl的源码,注意看<xsl:choose>部分:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="EMPDETAILS">
    <html>
    <body>
    <table border="1" cellspacing="0">
    <tr><td>EMPID</td><td>NAME</td><td>DESF</td><td>DEPT</td><td>SALARY</td><td>HP</td></tr>
    <xsl:for-each select="EMP">

      <xsl:choose>
        <xsl:when test="SALARY &gt; 260">
          <tr style="color:red">
            <td><xsl:value-of select="@EMPID"/></td>
            <td><xsl:value-of select="ENAME"/></td>
            <td><xsl:value-of select="DESG"/></td>
            <td><xsl:value-of select="DEPT"/></td>
            <td><xsl:value-of select="SALARY"/></td>
          </tr>
        </xsl:when>

        <xsl:otherwise>
          <tr style="color:green">
            <td><xsl:value-of select="@EMPID"/></td>
            <td><xsl:value-of select="ENAME"/></td>
            <td><xsl:value-of select="DESG"/></td>
            <td><xsl:value-of select="DEPT"/></td>
            <td><xsl:value-of select="SALARY"/></td>
          </tr>
        </xsl:otherwise>
      </xsl:choose>

    </xsl:for-each>
    </table>
    </body>
    </html>
    </xsl:template>
    </xsl:stylesheet>


    说明
    1. <xsl:choose>的摆放位置,是在for-each之内,这是理所当然的,因为我这例子每个EMP我都要进行条件格式化
    2. <xsl:when test="SALARY &gt; 260">这里,"SALARY &gt; 260"是条件,「>」符号要 html encode为「&gt;」,这里我设的条件是「SALARY大于260」
    3. <xsl:when>与<xsl:otherwise>两组代码的唯一分别是<tr>的style,SALARY大于260的显示整行为红色,否则的话就显示整行为绿色
    4. 用choose可以实现无限的可能,你要符合条件的单单更改SALARY元素的颜色亦可,你要把SALARY显示为超链接亦可,如下:
    tr 的style不要,单单更改 SALARY的td...

    <td style="color:red"><xsl:value-of select="SALARY"/></td>

    或者把SALARY的值显示为超链接...

    <td><a href="{HP}"><xsl:value-of select="SALARY"/></a></td>


    《完》