Generování Word dokumentu pomoci Open XML SDK, část 1

Jan Holan       14.02.2012       Office       13403 zobrazení

V minulosti jsme si na tomto blogu ukázali, jak .NET kódem vytvářet Excel nebo PDF dokumenty. Dnes si ukážeme jak vytvářet Microsoft Word docx dokumenty.

Nejprve malý výčet, jaké vlastně možnosti co se týče tvorby Word dokumentů v .NETu máme:

  • Word application COM object model
    Jedná se o volání Word aplikace pomoci COM rozhraní (ActiveX), které se z .NET volá pomoci interop knihovny. Výhodou jsou velké možnosti tohoto API (podstatě cokoli co umí samotný Word) a také možnost zpracovávat i jiné formáty než docx. Dále je zde ale řada nevýhod, nejhlavnější je to, že Word musí být na počítači nainstalován nebo že volání COM není výkonnostně optimální. Toto řešení dnes není již moc podporováno, na serverové aplikace (generování na Webovém serveru) je přímo i Microsoftem nedoporučováno. (Více také zde.)
  • Microsoft Office Open XML SDK
    Open XML SDK  2.0 poskytuje sadu managed .NET tříd postavených nad .NET System.IO.Packaging API, které umožňují tvorbu Open XML Office dokumentů. Na základě Open XML standardu je umožněn pomoci XML přístup do obsahu souborů v package dokumentu (nejen tedy k obsahu vlastního package). SDK kromě podpory pro zpracování Word dokumentů (Word processing – schéma WordprocessingML) obsahuje také podporu pro Excel (SpreadsheetML schéma) a PowerPoint (PresentationML schéma). Nevýhoda knihovny je (jak si ukážeme) to, že její API je podle mě moc na nízké úrovni tj. až příliš obecné, je tak možné vytvořit nevalidní dokumenty.
  • SharePoint 2010 Word Automation Services
    Word Automation Services je komponenta běžící pod SharePoint Server 2010. Jedná se o placenou variantu od  Microsoftu, která umožňuje vývojářům manipulovat a aktualizovat obsah Word dokumentů, dále navíc umožňuje konverze do jiných formátů (např. PDF). Některé scénáře lze pomoci této knihovny provádět jednodušeji než pomoci Open XML SDK, nebo lze oba způsoby bez problému přímo kombinovat. Toto řešení je zaměřené výhradně pro server-side scénáře. (Více také zde)
  • Placené knihovny třetích stran
    Dále existují jiné placené knihovny od dodavatelů třetích stran, které umožňují pomoci .NET API tvorbu Word dokumentů (například Aspose.Words for .NET).

Já jsem pro svojí webovou/Silverlight aplikaci použil způsob pomoci Open XML SDK. Toto SDK ve verzi 2.0 je volně ke stažení zde (verze 1.0 již není podporovaná). Soubor OpenXMLSDKv2.msi obsahuje instalaci .NET assembly DocumentFormat.OpenXml.dll, ve které jsou všechny třídy umístěné. Dále je zde ke stažení OpenXMLSDKTool.msi, ten obsahuje dokumentaci a pomocný nástroj Open XML SDK 2.0 Productivity Tool (*).

Pozn.: Samotná assembly DocumentFormat.OpenXml.dll je napsaná pro .NET FW 3.5 SP1 ale není vůbec žádný problém jí použít ve FW 4.0 projektech.

A nyní si už rovnou ukážeme vytvoření jednoduchého Word dokumentu. Do VS projektu ještě přidáme reference na assemby DocumentFormat.OpenXml.dll a také WindowsBase.dll assemby (obsahuje IO.Packaging). Také budeme využívat následující namespace:

using System.IO;
using System.IO.Packaging;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

Vlastní kód pro generování dokumentu bude vypadat takto:

public byte[] Generate()
{
    using (var ms = new MemoryStream())
    {
        //Create a new Word document. 
        using (var wordDocument = WordprocessingDocument.Create(ms, WordprocessingDocumentType.Document))
        {
            //Add a new main document part. 
            var mainPart = wordDocument.AddMainDocumentPart();
            //Create the Document DOM. 
            mainPart.Document = new Document();
            //Create a new Body and add it to the document
            mainPart.Document.Append(new Body());

            //Create text for first paragraph
            var run = new Run(new Text("Hello World"));

            //Apply font formatting to a Run using RunProperties object
            var runProperties = new RunProperties();
            runProperties.AppendChild(new RunFonts() { Ascii = "Arial" });
            runProperties.AppendChild(new Bold());
            runProperties.AppendChild(new FontSize() { Val = "50" });
            runProperties.AppendChild(new Color() { Val = "red" });

            run.PrependChild(runProperties);    //Add to beginning of run

            mainPart.Document.Body.AppendChild(new Paragraph(run));

            //Create and append second paragraph with some text (with Word's default font)
            mainPart.Document.Body.AppendChild(
                    new Paragraph(
                        new Run(
                            new Text("Created using Microsoft Office Open XML SDK 2.0"))));

            //Save the results
            mainPart.Document.Save();
        }

        return ms.ToArray();
    }
}

Jak jste asi z kódu sami poznali, metoda Generate vrací nově vytvořený docx dokument s nadpisem Hello World a dalším textem v druhém odstavci. Dokument je vrácen jako pole bajtů, odkud lze uložit do souboru nebo rovnou použít jako výstup např. z HttpHandleru.

Práce s objekty knihovny je velice podobná jako tvoření XML dokumentu pomoc System.Xml.Linq.XElement (ono to ve skutečnosti také nic jiného než tvoření XML není). Objekty tedy můžeme libovolně vkládat pomoci metod AppendChildPrependChild, InsertAfter, InsertAfterSelf, InsertBefore apod. Například při vkládání formátovacího objektu RunProperties, který je nutné umístit před vlastní text, je použita metoda PrependChild pro vložení na začátek elementu. Vnořování objektů je dále také možné provádět přímo v konstruktoru objektů, vytvoření prvního odstavce v příkladu by bylo tedy možné zapsat i tímto způsobem:

mainPart.Document.Body.AppendChild(
        new Paragraph(
            new Run(
                new RunProperties(
                    new RunFonts() { Ascii = "Arial" },
                    new Bold(),
                    new FontSize() { Val = "50" },
                    new Color() { Val = "red" }),
                new Text("Hello World"))));

A jak to celé funguje? Každý objekt odpovídá XML elementu definovaném ve schématu Open XML formátu. Jak už jsem tedy naznačil, výsledkem není nic jiného, než XML soubory podle této specifikace. Konkrétně pro uvedený příklad nám v package docx souboru (můžete ho přejmenovat na zip a přesvědčit se sami) vznikne následující XML soubor document.xml ve složce word. Jeho struktura XML elementů by vám měla připomínat objekty v uvedeném kódu (např. w:p je objekt Paragraph, w:rPr je RunProperties atd.):

<?xml version="1.0" encoding="utf-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:body>
    <w:p>
      <w:r>
        <w:rPr>
          <w:rFonts w:ascii="Arial" />
          <w:b />
          <w:sz w:val="50" />
          <w:color w:val="red" />
        </w:rPr>
        <w:t>Hello World</w:t>
      </w:r>
    </w:p>
    <w:p>
      <w:r>
        <w:t>Created using Microsoft Office Open XML SDK 2.0</w:t>
      </w:r>
    </w:p>
  </w:body>
</w:document>

Tento programový interface, který umožňuje objekty libovolně do sebe vnořovat je na jednu stranu velice pěkný (při tvoření klasického XML dokumentu pomoci XElement bych si už ani jiný způsob neuměl představit). Je zde ale velká nevýhoda v tom, že v interface není podchyceno to, že dokument má přesně specifikovanou strukturu, např. že Run musí být v Paragraph, že Paragraph musí být Body atd. Velice často se vám tedy při generování dokumentu může stát, že knihovnou vytvoříte nevalidní Word dokument. Stačí k tomu opravdu málo, zkuste např. pozměnit kód druhého odstavce na:

mainPart.Document.Body.AppendChild(
        new Run(
            new Text("Created using Microsoft Office Open XML SDK 2.0")));

A výsledek:

WordDocumentError

Mnohdy tedy skončíte u toho, že budete volat validaci dokumentu (např. pomoci XML SDK 2.0 Productivity Tool (*) nebo programově ) nebo budeme ručně kontrolovat XML elementy výsledného dokumentu (a nebo studovat Open XML specifikaci). Druhá nevýhoda je také to, že Open XML je poměrně “ukecaný” formát a tak někdy je potřeba vytvořit pro danou věc docela dost elementů, schválně se podívejte např. na kód pro vložení obrázku do dokumentu.

Příště se podíváme jak vytvořit Word šablonu a tu pomoci Open XML SDK použít pro generování dokumentu.


(*) Nástroj Open XML SDK 2.0 Productivity Tool obsahuje některé funkce, které mohou pomoci při vývoji kódu, který generuje Open XML dokument. Jsou to funkce pro zobrazení C# kódu, který by generoval daný existující dokument, porovnání XML dvou dokumentů a volání validace dokumentu.

 

hodnocení článku

0 bodů / 1 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback