2016-04-19 4 views
0

Я экспериментировал с чтением метаданных столбцов SharePoint 2013 сайта из C# VSTO на уровне приложений Word 2010.Чтение/запись поля пользователя SharePoint [Word 2010 VSTO]

Для тестирования я установил столбцы сайта для каждого типа, который использует SharePoint, а затем создал тип содержимого документа, который связывается со всеми ними - таким образом, все эти столбцы встроены в документ Word (выглядит как хранимый в customXml в файле документа).

Посредством чтения из свойства _Document.ContentTypeProperties в коде VSTO я могу получить доступ ко всем типам, но мне трудно получить доступ к данным столбца сайта Person или Group - я получаю COM-исключения, пытающиеся читать или писать к объекту .Value.

Глядя на схеме XSD в customXml, я могу видеть одинарное значение столбец пользователя состоит из трех значений: DisplayName (типа string), AccountType (типа string) и AccountId (типа UserId) - однако я не видят способ чтения/записи из/в это в VSTO? Многозначные столбцы пользователя выглядят совершенно разными и состоят из двух значений string: идентификатор (как представляется, идентификатор пользователя SharePoint) и строковый идентификатор (или, по крайней мере, это то, что, по-моему, i:0#.w|domain\userid, в любом случае).

Word само может редактировать как одно-, так и многозначные данные столбцов пользователя через панель документов, но только если Word в настоящее время подключен к SharePoint - в противном случае функциональность отключена. Я бы предположить то же самое будет справедливо и для VSTO, если я мог бы получить доступ к значениям на всех ...

Мои два вопроса:

  1. Есть ли способ для чтения/записи одно- и многозначные поля пользователя из кода VSTO (даже если это не через свойство _Document.ContentTypeProperties)?

  2. Есть ли способ сделать Q1, если он не подключен к SharePoint (если, скажем, значения известны коду)?

(я был несколько излишне многословен в случае мои разработки до сих пор полезны для кого-то еще, даже если я не получаю ответы, как представляется, не будет большой объем информации об этом в любом месте)

ответ

0

С некоторыми оговорками, я считаю, что вы можете читать или обновлять эти поля с помощью VSTO - хотя я фактически не создал рабочий пример с использованием VSTO, те же объекты, что и в Word VBA, доступно - фрагменты кода ниже являются VBA.

Значения person/group, отображаемые в DIP, хранятся в пользовательской части XML, даже если сервер SharePoint недоступен. Таким образом, проблема не изменяет значения - это, по сути, операция CRUD - но зная, какие значения вы можете использовать, особенно в многозначном случае. Если вы знаете, как создавать допустимые значения (допустим, у вас есть независимый список адресов электронной почты), вы можете внести изменения локально. Лично я не знаю, как я построил бы допустимое значение для многозначного случая, поэтому мне бы в основном пришлось обратиться к серверу.

Так если у вас есть данные, которые нужно обновить локально ...

Когда SharePoint служит документ Word, он вставляет/обновляет несколько пользовательских частей XML. Один содержит набор схем (как вы обнаружили). Другой содержит данные. Все, что вам действительно нужно сделать, это получить доступ к правильной пользовательской части XML, найти XML-элемент, соответствующий столбцу пользователя/группы SharePoint, а затем это 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 столбца person/group. Это может быть то же самое, что и внешнее имя (тот, который вы видите в списке SharePoint), но если, например, кто-то назвал столбец Sharepoint «группа лиц», имя элемента будет «person_x0020_group». Если имя не изменится, вы можете получить его из XML схемы как одноразовую задачу. Или может быть легко создать правильное имя элемента из любого имени SharePoint.В противном случае, вы можете получить его динамически из схемы XML, который вы можете получить (в виде строки) с помощью

theDoc.ContentTypeProperties.SchemaXML 

Что вам нужно сделать, это найти элемент с атрибутом ма: 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]") 

Или вы можете найти это предпочтительнее, чтобы получить URI пространства имен из элементов в этом Пользовательские XML-части и использовать, чтобы помочь вам найти правильный узел. Имя - длинная шестнадцатеричная строка, назначенная SharePoint. Вы можете получить его из XML схемы, используя, например,

//xsd:schema[1]/@targetNamespace 

После того, как у вас есть узел, можно использовать известные структуры (то есть те, которые вы нашли в Schemas), чтобы получить/изменить/создать дочерние узлы по мере необходимости.

+0

Я думал, что мне, возможно, придется напрямую модифицировать данные customXml - я надеялся, что мне не нужно просто для одного типа. Я посмотрю на это - спасибо! – Reznikk

+0

Да, AFAICS нет интерфейса, который предоставляет внутреннюю структуру объекта ContentTypeProperty для этого типа Property. –

+0

Огромное спасибо за ваши усилия - и хотя это, безусловно, похоже на единственный доступный вариант, я бы хотел оставить короткое обозначение «правильным», если появится другое потенциальное решение (вы никогда не знаете с вещами VSTO ...). – Reznikk

0

, конечно, вы можете. Вы должны использовать объектную модель SharePoint Client (CSOM) для управления данными SharePoint из местоположения вдали от сервера. Единственное, что вам понадобится, это URL вашего сайта SharePoint.

Вы можете подключить через 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(); 

Для установки значения вы можете использовать этот формат строки:

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

Смежные вопросы