Read/Write SharePoint 用户字段 [Word 2010 VSTO]
Read/Write SharePoint User Field [Word 2010 VSTO]
我一直在尝试从 Word 2010 应用程序级 C# VSTO 中读取 SharePoint 2013 网站栏元数据。
为了测试,我为 SharePoint 使用的每种类型设置了网站栏,然后创建了一个与它们相关联的文档内容类型——因此所有这些栏都嵌入到 Word 文档中(看起来存储在文档文件中的 customXml 中)。
通过读取 VSTO 代码中的 _Document.ContentTypeProperties
属性,我可以访问大多数类型,但我很难访问 'Person or Group' 网站栏的数据 -- 我m 获取试图读取或写入项目的 .Value
属性.
的 COM 异常
通过查看 customXml 中的 XSD 架构,我可以看到单值用户列由三个值组成:DisplayName
(类型 string
)、AccountType
(键入 string
)和 AccountId
(键入 UserId
)——但是我在 VSTO 中看不到 read/write from/to 的方法?多值用户列似乎完全不同,由两个 string
值组成:一个 ID(似乎是 SharePoint 用户的 ID)和一个基于字符串的 ID(或者至少我认为i:0#.w|domain\userid
是,无论如何)。
Word 本身可以通过文档面板编辑单值和多值用户列数据,但前提是 Word 当前已连接到 SharePoint——否则该功能将被禁用。我会 假设 对于 VSTO 也是如此,如果我完全可以访问这些值...
我的两个问题是:
有没有办法从 VSTO 代码中 read/write 单值和多值用户字段(即使不是通过 _Document.ContentTypeProperties
属性) ?
如果未连接到 SharePoint(如果代码已知这些值),是否有办法执行 Q1?
(我有点过于冗长了,以防我到目前为止的工作对其他人有用,即使我没有得到答案;似乎没有大量关于这个的信息任何地方)
当然可以。您应该使用 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();
希望对您有所帮助
有一些附带条件,我相信您可以使用 VSTO read/update 这些字段 - 虽然我实际上还没有使用 VSTO 创建一个工作示例,但我在 Word 中使用的对象相同 VBA 可用 - 下面的代码片段是 VBA.
DIP 中显示的 person/group 值存储在自定义 XML 部分中,即使 SharePoint 服务器不可用也是如此。所以问题不在于修改值——它本质上是一个 CRUD 操作——而是知道你可以使用什么值,特别是在多值的情况下。如果您知道如何构建有效值(假设您有一个独立的电子邮件地址列表),那么您可以在本地进行修改。就个人而言,我不知道如何为多值案例构建有效值,所以我基本上必须联系服务器。
所以假设您有需要在本地更新的数据...
当 SharePoint 提供 Word 文档时,它 inserts/updates 几个自定义 XML 部分。一个包含一组模式(正如您所发现的)。另一个包含数据。您真正需要做的就是访问正确的自定义 XML 部分,找到与您的 SharePoint user/group 列对应的 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)
此时你需要知道person/group列的XML元素名称。它可能与外部名称(您可以在 SharePoint 列表中看到的名称)相同,但如果有人将 Sharepoint 列称为 "person group",则元素名称将为 "person_x0020_group"。如果名称不会改变,您可以从模式 XML 中获取它作为一次性任务。或者,从任何给定的 SharePoint 名称生成正确的元素名称可能很容易。否则,您可以从架构 XML 中动态获取它,您可以使用
获取(作为字符串)
theDoc.ContentTypeProperties.SchemaXML
然后您需要做的是找到具有属性 ma:displayName="the external name" 的元素并获取 name 属性的值。我认为使用 c#、合适的 XML 对象和一些 XPath 会非常简单,比如
//xsd:element[@ma:displayName='person group'][1]/@name
应该return'person_x0020_group'
然后您可以获取数据的元素节点,例如类似
的东西
Dim cxn As Office.CustomXMLNode
Set cxn = cxp.SelectSingleNode("//*[name()='person_x0020_group'][1]")
或者您可能会发现获取此自定义 XML 部分中元素的命名空间 Uri 并使用它来帮助您找到正确的节点会更好。该名称是由 SharePoint 分配的长十六进制字符串。您可以使用 XML 从架构中获取它,例如
//xsd:schema[1]/@targetNamespace
获得节点后,您可以根据需要将已知结构(即您在模式中找到的结构)用于 get/modify/create 个子节点。
我一直在尝试从 Word 2010 应用程序级 C# VSTO 中读取 SharePoint 2013 网站栏元数据。
为了测试,我为 SharePoint 使用的每种类型设置了网站栏,然后创建了一个与它们相关联的文档内容类型——因此所有这些栏都嵌入到 Word 文档中(看起来存储在文档文件中的 customXml 中)。
通过读取 VSTO 代码中的 _Document.ContentTypeProperties
属性,我可以访问大多数类型,但我很难访问 'Person or Group' 网站栏的数据 -- 我m 获取试图读取或写入项目的 .Value
属性.
通过查看 customXml 中的 XSD 架构,我可以看到单值用户列由三个值组成:DisplayName
(类型 string
)、AccountType
(键入 string
)和 AccountId
(键入 UserId
)——但是我在 VSTO 中看不到 read/write from/to 的方法?多值用户列似乎完全不同,由两个 string
值组成:一个 ID(似乎是 SharePoint 用户的 ID)和一个基于字符串的 ID(或者至少我认为i:0#.w|domain\userid
是,无论如何)。
Word 本身可以通过文档面板编辑单值和多值用户列数据,但前提是 Word 当前已连接到 SharePoint——否则该功能将被禁用。我会 假设 对于 VSTO 也是如此,如果我完全可以访问这些值...
我的两个问题是:
有没有办法从 VSTO 代码中 read/write 单值和多值用户字段(即使不是通过
_Document.ContentTypeProperties
属性) ?如果未连接到 SharePoint(如果代码已知这些值),是否有办法执行 Q1?
(我有点过于冗长了,以防我到目前为止的工作对其他人有用,即使我没有得到答案;似乎没有大量关于这个的信息任何地方)
当然可以。您应该使用 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();
希望对您有所帮助
有一些附带条件,我相信您可以使用 VSTO read/update 这些字段 - 虽然我实际上还没有使用 VSTO 创建一个工作示例,但我在 Word 中使用的对象相同 VBA 可用 - 下面的代码片段是 VBA.
DIP 中显示的 person/group 值存储在自定义 XML 部分中,即使 SharePoint 服务器不可用也是如此。所以问题不在于修改值——它本质上是一个 CRUD 操作——而是知道你可以使用什么值,特别是在多值的情况下。如果您知道如何构建有效值(假设您有一个独立的电子邮件地址列表),那么您可以在本地进行修改。就个人而言,我不知道如何为多值案例构建有效值,所以我基本上必须联系服务器。
所以假设您有需要在本地更新的数据...
当 SharePoint 提供 Word 文档时,它 inserts/updates 几个自定义 XML 部分。一个包含一组模式(正如您所发现的)。另一个包含数据。您真正需要做的就是访问正确的自定义 XML 部分,找到与您的 SharePoint user/group 列对应的 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)
此时你需要知道person/group列的XML元素名称。它可能与外部名称(您可以在 SharePoint 列表中看到的名称)相同,但如果有人将 Sharepoint 列称为 "person group",则元素名称将为 "person_x0020_group"。如果名称不会改变,您可以从模式 XML 中获取它作为一次性任务。或者,从任何给定的 SharePoint 名称生成正确的元素名称可能很容易。否则,您可以从架构 XML 中动态获取它,您可以使用
获取(作为字符串)theDoc.ContentTypeProperties.SchemaXML
然后您需要做的是找到具有属性 ma:displayName="the external name" 的元素并获取 name 属性的值。我认为使用 c#、合适的 XML 对象和一些 XPath 会非常简单,比如
//xsd:element[@ma:displayName='person group'][1]/@name
应该return'person_x0020_group'
然后您可以获取数据的元素节点,例如类似
的东西Dim cxn As Office.CustomXMLNode
Set cxn = cxp.SelectSingleNode("//*[name()='person_x0020_group'][1]")
或者您可能会发现获取此自定义 XML 部分中元素的命名空间 Uri 并使用它来帮助您找到正确的节点会更好。该名称是由 SharePoint 分配的长十六进制字符串。您可以使用 XML 从架构中获取它,例如
//xsd:schema[1]/@targetNamespace
获得节点后,您可以根据需要将已知结构(即您在模式中找到的结构)用于 get/modify/create 个子节点。