读/写 SharePoint 用户字段 [Word 2010 VSTO]



我一直在尝试从Word 2010应用程序级C#VSTO中读取SharePoint 2013网站栏元数据。

为了进行测试,我为 SharePoint 使用的每种类型设置了网站栏,然后创建了一个与它们相关联的文档内容类型 - 因此所有这些列都嵌入到 Word 文档中(看起来存储在文档文件的自定义 Xml 中(。

通过从 VSTO 代码中的 _Document.ContentTypeProperties 属性读取,我可以访问大多数类型,但我在访问"个人或组"网站栏的数据时遇到困难 - 我在尝试读取或写入项目的 .Value 属性时遇到 COM 异常。

通过查看customXml中的XSD架构,我可以看到单值用户列由三个值组成:DisplayName(类型string(,AccountType(类型string(和AccountId(类型UserId( - 但是我没有看到在VSTO中读取/写入的方法? 多值用户列似乎完全不同,由两个string值组成:ID(似乎是 SharePoint 用户的 ID(和基于字符串的 ID(或者至少我认为i:0#.w|domainuserid是这样,无论如何(。

Word

本身可以通过文档面板编辑单值和多值用户列数据,但前提是 Word 当前已连接到 SharePoint,否则该功能将被禁用。 我假设 VSTO 也是如此,如果我可以访问这些值......

我的两个问题是:

  1. 有没有办法从 VSTO 代码中读取/写入单值和多值用户字段(即使不是通过 _Document.ContentTypeProperties 属性(?

  2. 有没有办法在未连接到 SharePoint 时执行 Q1(例如,如果代码知道值(?

(我有点过于冗长,以防我到目前为止的工作对其他人有用,即使我没有得到答案;任何地方似乎都没有关于这方面的大量信息(

有一些附带条件,我相信您可以使用 VSTO 读取/更新这些字段 - 虽然我实际上还没有使用 VSTO 创建工作示例,但可以使用我在 Word VBA 中使用的相同对象 - 下面的代码片段是 VBA。

DIP 中显示的人员/组值存储在自定义 XML 部件中,即使 SharePoint 服务器不可用也是如此。因此,问题不在于修改值 - 本质上这是一个 CRUD 操作 - 而是知道您可以使用哪些值,尤其是在多值情况下。如果您知道如何构造有效值(假设您有一个独立的电子邮件地址列表(,则可以在本地进行修改。就个人而言,我不知道如何为多值情况构造一个有效值,所以我基本上必须联系服务器。

因此,假设您有需要在本地更新的数据......

当 SharePoint 提供 Word 文档时,它会插入/更新多个自定义 XML 部件。一个包含一组架构(正如您所发现的(。另一个包含数据。您真正需要做的就是访问正确的自定义 XML 部件,找到与您的 SharePoint 用户/组列对应的 XML 元素,然后对该元素的子元素执行 CRUD 操作。

您可以使用适当的命名空间名称找到正确的自定义 XML 部件,例如

Const metaPropDataUri as String = _
  "http://schemas.microsoft.com/office/2006/metadata/properties"
Dim theDoc as Word.Document
Dim cxp as Office.CustomXMLPart 
Dim cxps as Office.CustomXMLParts 
Set theDoc = ActiveDocument
Set cxps = theDoc.CustomXMLParts.SelectByNamespace(metaPropDataUri)

如果有多个部分与该命名空间相关联,我不确定如何选择正确的部分。AFAIK Word/Sharepoint只创建一个,实验表明,如果有另一个,SharePoint将使用第一个。所以我用

Set cxp = cxps(1)

此时,您需要知道人员/组列的 XML 元素名称。它可能与外部名称(您可以在 SharePoint 列表中看到的名称(相同,但如果有人将 SharePoint 列称为"人员组",则元素名称将为"person_x0020_group"。如果名称不会更改,则可以将其作为一次性任务从架构 XML 中获取。或者,从任何给定的 SharePoint 名称生成正确的元素名称可能很容易。否则,您可以从架构 XML 动态获取它,您可以使用

theDoc.ContentTypeProperties.SchemaXML

然后,您需要做的是找到属性为 ma:displayName="外部名称"的元素,并获取 name 属性的值。我想使用c#,一个合适的XML对象和一些XPath非常简单,比如说。

//xsd:element[@ma:displayName='person group'][1]/@name

应该返回"person_x0020_group">

然后,您可以获取数据的 Element 节点,例如

类似
Dim cxn As Office.CustomXMLNode
Set cxn = cxp.SelectSingleNode("//*[name()='person_x0020_group'][1]") 

或者,您可能会发现最好获取此自定义 XML 部件中元素的命名空间 Uri,并使用它来帮助您找到正确的节点。该名称是由 SharePoint 分配的长十六进制字符串。您可以使用以下方法从架构 XML 中获取它:

//xsd:schema[1]/@targetNamespace

拥有节点后,您将使用已知结构(即在架构中找到的结构(根据需要获取/修改/创建子节点。

当然可以。您应该使用 SharePoint 客户端对象模型 (CSOM( 从远离服务器的位置操作 SharePoint 数据。您唯一需要的是您的 SharePoint 网站的 URL。

然后,可以通过 CSOM 进行连接,如下所示:

ClientContext context = new ClientContext("SITEURL");
Site site = context.Site;
Web web = context.Web;
context.Load(site);
context.Load(web);
context.ExecuteQuery();

请参阅此处设置单个用户字段的示例:

首先通过确保用户名来获取用户的ID

u = context.Web.EnsureUser(UserOrGroupName);
context.Load(u);
context.ExecuteQuery();

若要设置值,可以使用以下字符串格式:

userid;#userloginname;#

要设置该字段,请使用以下命令:

item[myusercolumn] = "userid;#userloginname;#";
item.Update();
context.ExecuteQuery();

要设置多用户字段,您可以使用相同的代码,只需使用 ;# 连接不同的用户名,例如:

item[myusercolumn] = "userid1;#userloginname1;#userid2;#userloginname2;#userid3;#userloginname3;#";
item.Update();
context.ExecuteQuery();

希望这有帮助

最新更新