【问题标题】:Read/Write SharePoint User Field [Word 2010 VSTO]读/写 SharePoint 用户字段 [Word 2010 VSTO]
【发布时间】:2016-04-19 13:00:00
【问题描述】:

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

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

通过读取 VSTO 代码中的 _Document.ContentTypeProperties 属性,我可以访问大多数类型,但是我在访问“个人或组”站点列的数据时遇到了困难——我收到 COM 异常尝试读取或写入项目的.Value 属性。

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

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

我的两个问题是:

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

  2. 如果未连接到 SharePoint(例如,如果代码已知这些值),是否有办法执行 Q1?

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

【问题讨论】:

    标签: c# sharepoint ms-word vsto sharepoint-2013


    【解决方案1】:

    有了一些附加条件,我相信您可以使用 VSTO 读取/更新这些字段 - 虽然我实际上并没有使用 VSTO 创建一个工作示例,但我在 Word VBA 中使用的相同对象是可用的 - 代码 sn -ps 下面是 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 名称生成正确的元素名称可能很容易。否则,您可以从 Schema XML 中动态获取它,您可以使用(作为字符串)获取它

    theDoc.ContentTypeProperties.SchemaXML
    

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

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

    应该返回“person_x0020_group”

    然后您可以获取数据的元素节点,例如类似于

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

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

    //xsd:schema[1]/@targetNamespace
    

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

    【讨论】:

    • 我在想我可能必须直接修改 customXml 数据——不过我希望我不需要只针对一种类型。我会看看这个 - 谢谢!
    • 是的,AFAICS 没有为此类 Property 公开 ContentTypeProperty 对象内部结构的接口。
    • 非常感谢您的努力 - 虽然这看起来确实是唯一可用的选项,但我想暂时将其标记为“正确”,以防出现另一个潜在的解决方案(您永远不会了解 VSTO 的东西...)。
    【解决方案2】:

    当然可以。您应该使用 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();
    

    希望对你有帮助

    【讨论】:

    • 感谢您的回答,但是您的方法是直接更改 SharePoint 上的数据,而不是 Word 文档中包含的数据 - 因此,当将文档保存回 SharePoint 时,它肯定会覆盖使用您的方法进行了哪些更改?
    • 好吧抱歉,我看错了你的问题。然后我只能说,在你所说的“基于字符串的 id”中,这实际上是一个声明编码的用户名。前缀 'i:0#.w|'告诉 SharePoint 它是用户还是组(i 或 c)以及使用哪种类型的身份验证(w:windows auth,f:formsbased)
    猜你喜欢
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多