2016-04-19 42 views
0

我一直在嘗試從Word 2010應用程序級C#VSTO中讀取SharePoint 2013站點列元數據。讀/寫SharePoint用戶字段[Word 2010 VSTO]

爲了測試,我爲每個SharePoint使用的類型設置了Site Columns,然後創建了一個與它們相關聯的文檔內容類型 - 因此所有這些列都嵌入到Word文檔中(看起來存儲在文檔文件中的customXml)。

通過閱讀VSTO代碼中的_Document.ContentTypeProperties屬性,我可以訪問大多數類型,但是我無法訪問「Person或Group」站點列的數據 - 我正在嘗試讀取或寫入COM異常到物品的.Value屬性。

通過查看在customXml XSD架構,我可以看到一個單值的用戶列由三個值之一:DisplayName(類型string),AccountType(類型string)和AccountId(類型UserId) - 但是我在VSTO中沒有看到讀寫方式?多值用戶列看起來完全不同,並且由兩個值組成:一個ID(看起來是SharePoint用戶的ID)和一個基於字符串的ID(或者至少這就是我認爲i:0#.w|domain\userid是,無論如何)。

Word本身可以通過文檔面板編輯單值和多值用戶列數據,但只有當Word當前連接到SharePoint時 - 否則功能被禁用。我倒是承擔同樣將是真實的VSTO,如果我能在所有訪問值...

我的兩個問題是:

  1. 是否有讀/寫的方式VSTO代碼中的單值和多值用戶字段(即使它不通過_Document.ContentTypeProperties屬性)?

  2. 如果沒有連接到SharePoint(如果這些值已知代碼),是否有辦法執行Q1?

(我一直在有些情況下過於冗長我的工作方式,即使我沒有得到任何答案至今都對別人有用的;似乎沒有能夠成爲信息的這個大量的任何地方)

回答

0

在一些條件下,我相信你可以使用VSTO讀取/更新這些字段 - 雖然我沒有真正創建一個使用VSTO的工作示例,但是我在Word VBA中使用的對象是可用 - 下面的代碼片段是VBA。

即使SharePoint服務器不可用,DIP中顯示的人員/組值也存儲在自定義XML部件中。所以這個問題並沒有修改值 - 本質上這是一個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 group」,則元素名稱將爲「person_x0020_group」。如果名稱不會有所不同,您可以從模式XML中獲取它作爲一次性任務。或者,從任何給定的SharePoint名稱生成正確的元素名稱可能很容易。否則,你可以得到它動態地使用

theDoc.ContentTypeProperties.SchemaXML 

你需要做的是什麼模式的XML,你可以得到(作爲一個字符串)是找到屬性MA元素:顯示名=「外部名稱」並獲取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 

一旦你有你的節點,你可以使用已知結構得到/修改/根據需要創建子節點(即你在架構上發現的)。

+0

我想我可能不得不直接修改customXml數據 - 但我希望我不需要僅僅爲一種類型。我會看看這個 - 謝謝! – Reznikk

+0

是的,AFAICS沒有爲這種類型的Property公開ContentTypeProperty對象的內部結構的接口。 –

+0

非常感謝您的努力 - 儘管這看起來像是唯一可用的選項,但我希望在短時間內將其標記爲「正確」,以防出現另一個潛在的解決方案(您永遠不知道VSTO的東西...... )。 – Reznikk

0

當然可以。您應該使用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(); 

在這裏看到一個例子,創下了單用戶字段:

首先通過確保用戶名

u = context.Web.EnsureUser(UserOrGroupName); 
context.Load(u); 
context.ExecuteQuery(); 
獲得用戶的ID

要設置的值,你可以使用這個字符串格式:

userid;#userloginname;# 

要設置現場使用這樣的:

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

要設置多用戶領域,你可以使用相同的代碼,只需使用;#到Concat的不同的用戶名,如:

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

希望這可以幫助

+0

感謝您的回答,但是您的方法是直接更改SharePoint上的數據,而不是Word文檔中包含的數據 - 因此,在將文檔保存回SharePoint時,它肯定會覆蓋使用您的所做更改進場? – Reznikk

+1

好的,對不起,我誤解了你的問題。然後,我只能說,在你稱之爲'stringbased id'的情況下,這實際上是一個聲明編碼的用戶名。前綴'i:0#.w |'告訴SharePoint是否它的用戶或組(i或c)以及使用了哪種類型的身份驗證(w:windows auth,f:formsbased) – Verthosa

+0

這實際上非常有用,謝謝! – Reznikk