Sergey Belskiy Technical Blog

All about SharePoint

Open XML для работы с Office документами Sharepoint 2010

Задача создание механизма слияния документов Word. Допустим у нас есть источник данных и шаблон документа. Вот при выполнении некой операции происходит автоматическое создание документа Word по указанному шаблону с автоматически заполненными данными, которые беруться из нашего источника.

Долго думал и придумал. Источником будет у нас служить обычный список с определёнными колонками, которые нужно потом подставлять для созданного документа. Шаблоны будут храниться в  библиотеке документов. А операция слияния будет запускаться при создании записи в источнике данных.

Этот механизм я покажу чуток позже в своём новом видео касте. А в посте хочу рассказать о механизмах работы с офисными документами в Sharepoint 2010.

Все знают, какие классы существуют для работы с документами.

Указываем пространство имён using Microsoft.Office.Interop.Word;

Application ap = new Application();try{

SPFolder oFolder = oWebsite.GetFolder(“DocsTemplate”);       

SPFileCollection collFile = oFolder.Files;

string path = oWebsite.Url + “/” + “Docs” + “/” + oFile.Name.ToString();

    Document doc = ap.Documents.Open( path, ReadOnly: false, Visible: false );    doc.Activate();

    Selection sel =  ap.Selection;

    if ( sel != null )

    {

        switch ( sel.Type )

        {

            case WdSelectionType.wdSelectionIP:

                sel.TypeText( DateTime.Now.ToString() );

                sel.TypeParagraph();

                break;

            default:

                Console.WriteLine( “Selection type not handled; no writing done” );

                break;

        }

        // Remove all meta data.

        doc.RemoveDocumentInformation( WdRemoveDocInfoType.wdRDIAll );

        ap.Documents.Save( NoPrompt: true, OriginalFormat: true );

    }

    else

    {

        Console.WriteLine( “Unable to acquire Selection…no writing to document done..” );

    }

    ap.Documents.Close( SaveChanges: false, OriginalFormat: false, RouteDocument: false );

}

catch ( Exception ex )

{

    Console.WriteLine( “Exception Caught: ” + ex.Message ); }

finally

{

    ( (_Application)ap ).Quit( SaveChanges: false, OriginalFormat: false, RouteDocument: false );

    System.Runtime.InteropServices.Marshal.ReleaseComObject( ap );

}

Но тут не всё так просто. Всё прекрасно работает на платформе Net FrameWork 4.0. А Sharepoint 2010 работает только с 3.5. Чтобы обойти это, нужно использовать тулзу под названием Open XML

Это специальная тулза для работы с Office документами. Скачать её можно здесь – http://www.microsoft.com/downloads/details.aspx?FamilyId=C6E744E5-36E9-45F5-8D8C-331DF206E0D0&displaylang=en

Open XML является открытым стандартом для обработки текстов документов, презентаций и электронных таблиц. Open XML предназначен работы с документами Office.

Традиционно для производства приложений для работы с Microsoft Office и для автоматизации обработки документов разработчики используют Visual Studio и Visual Basic for Applications (VBA). Часто такие задачи как обработка файлов Office осуществлялась с помощью макросов и скриптов внутри клиентских приложений. По ряду причин такая работа не является оптимальной, и вторая версия Open XML SDK позволяет решить эту проблему.

Open XML SDK 2.0 улучшает возможности обработки документов Microsoft Office: процессы автоматизации документооборота больше не нуждаются в клиентской среде, что позволяет иметь прямой доступ к данным в документе. Таким образом, значительно упрощается разработка решений, связанных с извлечением, анализом или изменением содержимого документов.

Microsoft Open XML SDK содержит набор управляемых библиотек для создания и программной обработки XML-файлов. Версия 1.0 была выпущена 10 июня 2008, она включила в себя изменения, внесенные в спецификацию стандарта Open XML, сделанные в ходе процесса стандартизации ISO / IEC. Версия Open XML SDK 2.0 поддерживает валидацию XML-документов в соответствии со схемой стандарта XML, а также поиск в документах этого формата.

Файл Open XML хранится в ZIP-архиве, что необходимо для упаковки и сжатия данных. Структуру любого файла Open XML можно просмотреть с помощью средства просмотра ZIP-файлов. Документ Open XML состоит из нескольких частей документа. Связи между частями хранятся в частях документа. Формат ZIP поддерживает произвольный доступ к каждой части. Например, приложение может переместить слайд из одной презентации в другую без обработки содержимого слайда. Аналогично, приложение может удалить все комментарии из текстового документа без обработки его содержимого.

Части документа в пакете Open XML создаются в виде разметки XML. Так как XML — это структурированный текст, содержимое части документа можно просматривать с помощью средств просмотра текста или анализировать его с помощью таких процессов, как XPath.

Структурно документ Open XML — это пакет OPC. Как было сказано ранее, пакет состоит из коллекции частей документа. У каждой части есть имя, состоящее из последовательности сегментов или пути, таких как “/word/theme/theme1.xml.” Пакет содержит часть [Content_Types].xml, которая позволяет определить тип содержимого всех частей документа в пакете. Набор явных отношений исходного пакета или части хранится в части отношений (с расширением RELS).

Документ WordprocessingML состоит из коллекции следующих статей.

  • Основной документ (единственная обязательная статья)

  • Глоссарий

  • Заголовок и нижний колонтитул

  • Комментарии

  • Текстовое поле

  • Сноска и концевая сноска

Презентации описываются разметкой PresentationML. Пакеты презентаций могут содержать следующие части документа.

  • Образец слайдов

  • Образец примечаний

  • Образец выдач

  • Макет слайда

  • Примечания

Книги электронных таблиц описываются разметкой SpreadsheetML. Пакеты книг могут содержать следующие части.

  • Часть книги (обязательная часть)

  • Один или несколько листов

  • Диаграммы

  • Таблицы

  • Пользовательский XML-код

Пакет Open XML SDK версии 2.0 для Microsoft Office расширяет поддержку строго типизированных классов, начиная от классов частей, которые представлены в пакете версии 1.0, и заканчивая содержимым XML каждой части. Все функции, доступные в версии 1.0 также поддерживаются. Теперь в версии 2.0 можно программировать содержимое XML внутри каждой части. Данный пакет SDK поддерживает программирование в стиле LINQ to XML, что значительно облегчает программирование XML содержимого по сравнению с обычной моделью программирования W3C XML DOM.

Пакет SDK поддерживает следующие стандартные задачи и сценарии.

  • Строго типизированные классы и объекты. Вместо использования универсальных функций XML для обработки кода XML, для чего требуется знание элементов, атрибутов, значений и пространств имен, можно применять пакет Open XML SDK, управляя объектами, которые представляют элементы, атрибуты и значения. Все типы схем представлены строго типизированными классами среды CLR и значениями атрибутов в виде перечислений.

  • Формирование и поиск содержимого, а также управление им. Технология LINQ встроена непосредственно в пакет SDK. В результате можно выполнять запросы функциональных конструкций и лямбда-выражений непосредственно для объектов, представляющих элементы Open XML. Кроме того пакет SDK позволяет легко объединять содержимое и управлять им, предоставляя поддержку коллекций объектов, таких как таблицы и параграфы.

  • Проверка. Пакет Open XML SDK 2.0 для Microsoft Office предоставляет функции проверки, с помощью которых можно проверять документы Open XML на соответствие различным вариантам формата Open XML.

Помимо пакетов и разделов пакет SDK включает иерархию типов, таких как Paragraph. Для успешного использования SDK важно знать, что эти классы всего лишь представляют элементы XML и действуют так же, но с несколько большей интеграцией с типами.

В корне иерархии располагается (абстрактный) класс OpenXMLElement. Класс OpenXMLElement программно представляет любой старый элемент, фигурирующий в файле Open XML. Имя его довольно ясно представляет элемент XML. Предоставленные методы и свойства также соответствуют ожиданиям в отношении элементов XML: .FirstChild, .InnerText, .NextSibling(), Append(OpenXMLElement) и т.д.

Класс OpenXMLElement сам по себе предоставляет некоторые функции (как все хорошие базовые классы), которые мы рассмотрим ниже, но производные от него классы представляют больший интерес. Для каждого элемента, указанного в спецификации Open XML, существует соответствующий класс в SDK, производный (опосредовано) от класса OpenXMLElement. Во-первых, существует еще два абстрактных класса, предназначенных для того, чтобы отличать элементы, которые могут иметь другие элементы в качестве дочерних и те, которые не могут, — это классы OpenXMLCompositeElement и OpenXMLLeafElement.

Класс Paragraph, например, является производным от класса OpenXMLCompositeElement. “Ну и что?” — спросите вы. Хорошо, начнем с простого. Если вам приходилось писать код, управляющий объектами XmlElement, вы знаете, как трудно постоянно сверять имя и пространство имен, чтобы определить, с каким элементом вы в данный момент работаете. Благодаря иерархии типов, представляющей элементы, вы всегда получаете наиболее производный тип для элемента из методов Open XML SDK, возвращающих объекты OpenXMLElement. Например, свойство Body.FirstChild возвращает экземпляр класса Paragraph, если первый дочерний элемент элемента w:body в считываемом документе действительно является элементом w:p. В противном случае возвращается какой-либо другой тип. Так, вместо проверки имени и пространства имен элемента можно проверить его тип, например:

Paragraph p = child as Paragraph;

if (p != null)

{

// Do something …

}

Вот предоставлю пример работы этой тулзы. Как можно отредактировать некий документ Word на Sharepoint 2010.

Нужно выполнить следующие шаги.

  1. Запустить Microsoft Visual Studio 2010.

  2. Открыть пункт меню New, и создать новые проект.

  3. Выбрать шаблон Sharepoint Empty project.

  4. После открыть свойства нашего проекта.

  5. Выбрать по умолчанию .NET Framework 3.5.

  6. Зайти в меню Build и выбрать Any CPU

После нужно открыть reference и добавить следующее

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Text;

using System.Threading;

using Microsoft.SharePoint;

using DocumentFormat.OpenXml.Packaging;

using DocumentFormat.OpenXml.Wordprocessing;

class Program

{

static void Main(string[] args)

{

string siteUrl = “http://localhost”;

using (SPSite spSite = new SPSite(siteUrl))

{

Console.WriteLine(“Querying for Test.docx”);

SPList list = spSite.RootWeb.Lists[“Shared Documents”];

SPQuery query = new SPQuery();

query.ViewFields = @”<FieldRef Name=’FileLeafRef’ />”;

query.Query =

@”<Where>

<Eq>

<FieldRef Name=’FileLeafRef’ />

<Value Type=’Text’>Test.docx</Value>

</Eq>

</Where>”;

SPListItemCollection collection = list.GetItems(query);

if (collection.Count != 1)

{

Console.WriteLine(“Test.docx not found”);

Environment.Exit(0);

}

Console.WriteLine(“Opening”);

SPFile file = collection[0].File;

byte[] byteArray = file.OpenBinary();

using (MemoryStream memStr = new MemoryStream())

{

memStr.Write(byteArray, 0, byteArray.Length);

using (WordprocessingDocument wordDoc =

WordprocessingDocument.Open(memStr, true))

{

Document document = wordDoc.MainDocumentPart.Document;

Paragraph firstParagraph = document.Body.Elements<Paragraph>()

.FirstOrDefault();

if (firstParagraph != null)

{

Paragraph testParagraph = new Paragraph(

new Run(

new Text(“Test”)));

firstParagraph.Parent.InsertBefore(testParagraph,

firstParagraph);

}

}

Console.WriteLine(“Saving”);

string linkFileName = file.Item[“LinkFilename”] as string;

file.ParentFolder.Files.Add(linkFileName, memStr, true);

}

}

}

}