Tag Archives: Office

Amikor az Outlook 2013-ból eltűnnek a mappák

Sajnos az Office 2013 szeptemberi frissítésébe kis hiba csúszott, amit úgy vesz észre az ember, hogy Outlook 2013-ban üres a folder pane:

outlook-2013-folder-pane

Nem kell megijedni, a mappák megmaradnak, az üres helyet lehet minimalizálni, sőt a folder pane minimalizált működése továbbra is megvan. Tehát az Outlook használható marad, csak éppen használhatatlanul kényelmetlen.

A Microsoft elismerte a hibát és gőzerővel dolgoznak a javítás javításán: Outlook 2013 Folder Pane Disappears After Installing September 2013 Public Update

Addig is a megoldás a KB2817630 frissítés eltávolítása a Programs and Features ablakban. Vigyázat, trükkös! Kétszer jelenik meg a listában és mindkettőt el kell távolítani:

KB2817630

A másik trükk, hogy eltávolítás után a frissítés lelkesen visszamászik a következő frissítésnél, tehát a WSUS szervereken érdemes Decline-ra tenni ezt az update-et.

 

Technorati-címkék: ,,

Office kontra Visual Studio telepítő

Az utóbbi időben a Visual Studioból és az Office-ból is megjelent új változat. Mindkettő szép és jó, de mivel vannak közös komponenseik (például a Web Authoring Component), az eltávolítás, telepítés, frissítés bizony okozhat meglepetéseket.

A leggyakoribb probléma, hogy az Office 2010 telepítése után a Visual Studio 2008 web dizájner komponense lefagy, vagy már be sem töltődik. A problémát az okozza, hogy a VS és az Office is használja a 32-bites MSXML5 komponenst, ami az Office frissítésekor eltűnik, pedig a Visual Studionak még szüksége lenne rá. (Rémlik egy régen hallott fogalom, a “DLL Hell”, nem ezt kellene a Windows Installernek orvosolnia?)

A megoldás egy repair install, a különböző esetekre az alábbi cikkek szolgálnak képes útmutatóval:

Visual Web Developer Team Blog: Upgrade or Uninstall of Office 2007 might cause VS 2008 Web designer to hang

Rinat Abdullin: Visual Studio 2008 Locks or Freezes in ASPX

Martin Hishelwood: Office 2010 gotcha 2: Visual Studio 2008 Locks

Az Office telepítővel amúgy is érdemes vigyázni, a 32/64 bit választás nem is olyan egyszerű:

Office 2010 x64 setup error

Nehéz idők ezek 🙂

Kiegészítés: KB2022915: Upgrade from Office 2007 to Office 2010 on a 64-bit OS Causes Visual Studio 2008 and Visual Web Developer 2008 Express Design View to Hang

 

Technorati-címkék: ,,

Az Excel 2007 adatbányászati bővítményeinek használata – screencast

Az Excel 2007-hez ingyenesen letölthető Data Mining Add-ins for Microsoft Office 2007 nevű kiegészítés segítségével a felhasználók az SQL Server Analysis Services mélyebb ismerete nélkül, varázslók támogatásával, a megszokott Excel környezetben oldhatnak meg adatbányászati feladatokat.

Első lépések

A bővítmény valójában két Excel és egy Visio kiegészítést tartalmaz. A Data Mining Client for Excel a szalagon jeleníti meg a Data Mining fület, melyen a Business Intelligence Development Studiohoz hasonló műveleteket végezhetünk el. Bár szinte minden gomb egy-egy varázslót indít el, ezek használatához célszerű ismerni az adatbányászat fogalmait.

A bővítmény másik komponense a jóval egyszerűbb Table Analysis Tools, amely az Excel tábla objektumait okosítja fel. A telepítés után, ha bármelyik táblára kattintunk, megjelenik a Table Tools csoportban egy Analyze fül és a hozzá tartozó szalagon számos adatbányászati funkció.

Jó tudni

Bármelyik szalag funkcióit használjuk, ne felejtsük el, hogy a háttérben szükség van az SQL Server Analysis Servicesre és azon belül egy adatbázisra, melyben a felhasználónak jogosultnak kell lennie objektumok létrehozására. A szükséges kiszolgáló paraméterek beállítását és munka adatbázis létrehozását a bővítmény telepítő könyvtárában található Microsoft.SqlServer.DataMining.Office.ServerConfiguration.exe alkalmazás segítségével tudjuk könnyen elvégezni.

Demó

A demóban bemutatjuk, hogyan használhatóak az Excel 2007 adatbányászati bővítményei kampányelemzési feladatok megoldására. A videó a képre kattintva megtekinthető böngészőben vagy a kép alatti linkre kattintva letölthető:

Az Excel 2007 adatbányászati bővítményeinek használata - screencast

Letöltés: Excel_2007_adatbanyaszati_bovitmenyeinek_hasznalata_(Balassy_Gyorgy).wmv (25:29, 152 976 KB)

További információk

 

A lényeg kiemelése

A Word 2003-ban volt egy Autosummarize funkció, amely nevéhez hűen kiemelte a lényeget egy dokumentumból. A Word 2007-ben is elérhető ez a szolgáltatás, azonban alapértelmezés szerint nincs kint a szalagon, nekünk kell kitenni:

Word Options: AutoSummary

Ezek után az alábbi opciókat tudjuk beállítani és a funkció kiválóan működik angol szövegre:

AutoSummarize beállítások

Mivel én személy szerint jobban kedvelem a képes megoldásokat, ezért némi keresgélés után sikerült rátalálnom a Wordle weboldalra, ahol a lényeg kiemelése a tag-cloud megoldáshoz hasonlóan méret-, elrendezés- és szín variációkkal történik. Lehet tippelni, hogy Szalkáry Károly barátom miről írta a diplomamunkáját:

Wordle: Diploma

Ez pedig én lennék, rövid angol CV alapján, tömören:

Wordle: Balássy György CV

Mikor jutunk el odáig, hogy a keresőmotorok találatai nem egy csupasz listában, hanem átláthatóan rendezve jelennek meg?

Technorati Tags:

Office 2007 ribbon ikonok

Korábban a SiteSource add-in fejlesztésekor futottam bele abba a problémába, hogy kellene egy jól mutató ikon az add-inhoz tartozó szalagra. Kedvenc ikonunkat kétféle képpen lehet megjeleníteni és a Visual Studioba beépített Ribbon Designer mindkettőre ad is lehetőséget:

Visual Studio Ribbon Designer

  1. Ha valamilyen saját képet szeretnénk használni, adjuk meg azt az Image tulajdonságban.
  2. Ha szeretnénk igazodni az Office 2007 dizájnjához, akkor pedig használhatjuk az OfficeImageId tulajdonságot.

Mivel a legminimálisabb dizájner vér sem csörgedezik az ereimben, ezért úgy döntöttem, hogy az Office beépített ikonjai közül fogok választani. Adott tehát a feladat, ki kell választani egy ikont és megadni annak az azonosítóját az OfficeImageId tulajdonságban.

A képek közötti válogatásban sokat segíthet a 2007 Office System Add-In: Icons Gallery, ami letölthető a Microsoft oldaláról. A neve teljesen félrevezető, miután letöltöttük és kicsomagoltuk, kapunk egy Office2007IconsGallery.xlsm fájlt, ami ahogy a neve is mutatja egy makrót tartalmazó Excel dokumentum. Ennek használatához először is az Excel Options ablakban kapcsoljuk be a Show Developer tab in the Ribbon opciót:

Excel: Show DeveloperTab

Majd nyissuk meg a letöltött fájlt és engedélyezzük a makrók futását, ami után a Developer tabon új ikonokat fogunk látni:

Ribbon Image Gallery

A kilenc galéria bármelyikét kinyitva rengeteg ikon közül válogathatunk, a nevüket pedig úgy tudhatjuk meg, ha föléjük visszük az egeret, vagy rájuk kattintunk:

Ribbon Image Gallery: HappyFace

A kicsomagolt Excel fájl közvetlenül letölthető innen is.

 

Technorati Tags: ,,,

Word dokumentum generálása adatkötéssel – 6. rész: Végjáték

Az előző részekben megszerzett tudásunkat felhasználhatjuk arra, hogy kibővítsük a SharePoint lista elemekkel kapcsolatos szolgáltatásait. A WSS listák beépített funkciói közé tartozik, hogy kiválóan integrálódnak Excellel, Outlookkal és Access-szel, de a Word kimaradt a sorból. Pedig milyen szép is lenne, ha egy névjegyalbum valamelyik eleméből egy kattintással megcímzett levelet generálhatnánk! Nem is olyan nehéz…

Mivel a névjegyalbum típusú lista mezői ismertek, valamint azt is tudjuk, hogy hogyan néz ki nálunk egy levél címzése, ezért gyárthatunk egy Word sablont, meg némi extra kódot, ami a Word sablonba beírja a mezők értékeit. A kód egy ASPX oldalban fog futni, amit a _layouts mappába fogunk tenni és a felhasználó a névjegyalbum listában az egyes elemek helyi menüjéből tudja elérni.

Először tehát a korábbiak alapján készítsük el a Word dokumentumot, legyen benne minden olyan mező, amit egy levél címzésénél használni szoktunk: vezetéknév, keresztnév, város, irányítószám, utca és házszám, sőt még egy cég nevet is beletehetünk, mert olyan mező is van a névjegyalbumban. Akár így:

Sablon dokumentum

Második lépésként használjuk a korábban megismert Word 2007 Content Control Toolkitet, hogy hozzákapcsoljuk a tartalomvezérlőinket például az alábbi szerkezetű XML fájlhoz, ami a DOCX fájlon belül lesz elérhető:

    <?xml version="1.0" encoding="utf-8"?>
    <Contact xmlns="http://www.msdnkk.hu/samples/Contact">
        <FirstName>György</FirstName>
        <LastName>Balássy</LastName>
        <Company>MSDN Kompetencia Központ</Company>
        <City>Budapest</City>
        <Zip>1117</Zip>
        <Address>Magyar Tudósok krt. 2.</Address>
    </Contact>

Következő lépésben készítsünk egy ASPX oldalt, ahova a felhasználó el fog navigálni, amikor egy névjegyalbum listaelem szerkesztő menüjére kattint. Mivel az oldal a _layouts mappában fog lakni és application page lesz, származtassuk a LayoutsPageBase ősosztályból. Az oldal query string paraméterként meg fogja kapni a lista és a lista elem azonosítóját, amiből ki kell bogarászni egy SPListItem típusú objektumot, valahogy így (persze hibakezeléssel):

    private SPListItem GetListItem()
    {
        string listparam = this.Request.QueryString[ "listid" ];
        string itemparam = this.Request.QueryString[ "itemid" ];

        Guid listGuid = new Guid( listparam );
        int itemId = Int32.Parse( itemparam );
        SPList list = this.Web.Lists[ listGuid ];
        SPListItem item = list.Items.GetItemById( itemId );

        return item;
    }

Ebből az SPListItem példányból elő kell állítani a fenti XML-t, amihez én egy saját Contact osztályt használtam, ami a SharePointos típusból tudja inicializálni magát és kisorosítva épp a kívánt XML-t adja.

Meg kell írnunk azt a kódot, ami beteszi a sablonba az XML-t és visszaküldi a felhasználónak. Azt már korábban láttuk, hogyan tudunk egy XML partot betenni egy DOCX package-be. Itt most csak arra kell figyelnünk, hogy a sablon dokumentumunkból készítsünk egy munka másolatot, hiszen webes környezetben előfordulhat, hogy több felhasználó hívja meg ugyanezt az oldalt egyidőben. Ehhez feltételeztem, hogy a Word sablon dokumentumot egy WordExport nevű feature-ben fogom telepíteni. Így készül az ideiglenes munkafájl az SPUtility.GetGenericSetupPath metódus és a System.IO.Path osztály segítségével:

    string featureFolder = SPUtility.GetGenericSetupPath( @"TEMPLATEFEATURESWordExport" );
    string originalTemplatePath = Path.Combine( featureFolder, "Sablon.docx" );
    string currentTemplatePath = Path.GetTempFileName();
    File.Copy( originalTemplatePath, currentTemplatePath, true );

Miután beírtuk a tartalmat a munkafájlba, vissza kell küldenünk azt a felhasználónak, például így:

    this.Response.ClearContent();
    this.Response.ClearHeaders();
    this.Response.AddHeader( "content-disposition", "attachment; filename=export.docx" );
    this.Response.ContentEncoding = Encoding.UTF8;
    this.Response.TransmitFile( currentTemplatePath );
    this.Response.Flush();
    this.Response.Close();

És persze nem szabad elfeledkeznünk az ideiglenes állomány törléséről sem:

    File.Delete( currentTemplatePath );

Ezzel tehát megvan a kód, már csak telepítenünk kell, amihez természetesen előbb egy feature-t készítünk belőle! Ehhez először is egy feature.xml leíró fájlra lesz szükségünk:

    <?xml version="1.0" encoding="utf-8"?>
    <Feature xmlns="http://schemas.microsoft.com/sharepoint/" 
        Id="{63b1e30f-b4e9-4caa-b8ed-3552103f06c5}" 
        Title="Word export"
        Description="Lehetővé teszi névjegy lista elemeinek exportálását Word dokumentumba."
        Version="1.0.0.1"
        Scope="Web"
        Hidden="false"
        >
        <ElementManifests>
            <ElementManifest Location="WordExportPage.xml"/>
        </ElementManifests>
    </Feature>

A lényeg persze a WordExportPage.xml fájlba került, itt található ugyanis az exportálás menüpont hozzárendelése a névjegy lista (RegistrationId=105) elemeinek helyi menüjéhez (Location=EditControlBlock) és nézet oldali eszközsávjához (Location=DisplayFormToolbar):

    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
        <CustomAction 
            Id="MyDetailsLink"
            Title="Exportálás Wordbe"
            Description="Erre a linkre kattintva a lista elemet Word dokumentumba exportálhatja."
            RegistrationType="List"
            RegistrationId="105"
            Location="EditControlBlock"
            ImageUrl="/_layouts/images/doc16.gif"
            >
            <UrlAction Url="/_layouts/WordExport.aspx?listid={ListId}&amp;itemid={ItemId}" />
        </CustomAction>

        <CustomAction 
            Id="MyWordExportButton" 
            Title="Exportálás Wordbe" 
            Description="Erre a gombra kattintva a lista elemet Word dokumentumba exportálhatja."
            RegistrationType="List" 
            RegistrationId="105"     
            Location="DisplayFormToolbar"
            ImageUrl="/_layouts/images/doc16.gif"        
            >
            <UrlAction Url="/_layouts/WordExport.aspx?listid={ListId}&amp;itemid={ItemId}" />
        </CustomAction>
    </Elements>

Érdemes megfigyelni, hogy az UrlAction Url attribútumában a {ListId} és az {ItemId} tokenek segítségével tudjuk átadni az oldalunk számára szükséges paramétereket.

Ezt a feature-t aktiválva megjelenik a felhasználónak a névjegy lista elemein egy Exportálás Wordbe opció, melyre kattintva elnavigálhat az általunk készített WordExport.aspx oldalra, amely query string paraméterben megkapja, hogy a felhasználó melyik lista melyik elemére kattintott. Az oldal ezek alapján kibogarássza az eredeti lista elemet, majd fogja a sablon DOCX fájlt, készít róla egy másolatot a Temp mappába, beleírja a lista elem adatait, ezután visszaküldi a fájlt a felhasználónak, végül pedig letörni az ideiglenes állományt.

Mindezt szerver oldalon anélkül, hogy Office lenne telepítve a szerverre, vagy ismernünk kellene az Office objektum modelljét!

(Vége)

 

VB és VBA

A magyar műszaki felsőoktatás egyik fellegvárában egy kiváló tanszék (félreértések elkerülése végett: nem a miénk) kitalálta, hogy tárgyat akar indítani "VB/VBA" témában. A levelezésből kiderült, hogy valóban Visual Basic 6-ra és Visual Basic for Applicationsre gondoltak. Igen, mindezt most, 2008-ban! Mi sem lehet hasznosabb annál, mint ha 10 éves technológiát kezdünk el tanítani egy olyan generációnak, amelyik 1-3 év múlva végez. Erre mondaná néhány kollégám: ez itt kérem abszurdisztán.

A tárgy mögött álló szakmai indok szerint ennek azért van létjogosultsága, mert a Vista, a Windows Server 2008 és az Office következő verziója is támogatni fogja a VB-t és a VBA-t. Továbbá az is kiderült a levelekből, hogy következetesen keveredik a VB és a VBA neve, szerepe és célja. Mikor erre rájöttem, nem tudtam, hogy sírjak vagy nevessek. Különösen összevetve mindezt a stratégiai jellegű minőségfejlesztéssel.

Néhány dolgot mindenesetre érdemesnek látok tisztázni:

Ne keverjük össze az almát a körtével! Adott két nagyban hasonlító, de teljesen más célú környezet, a VB és a VBA. Ezen kívül adott két szempont, az egyik, hogy egy adott technológiára érdemes-e még fejleszteni, meg hogy az adott technológiával készült alkalmazások használhatóak-e még.

Nyelvek: 1. VB

A Visual Basic 6 nyelvet már 2002-ben (!) felváltotta a Visual Basic .NET a Visual Studio .NET-tel, aztán jött a VS 2003, majd a VS 2005 és most a Visual Basic 9-ről (!) beszélünk a VS 2008-ban! A két nyelv között ég és föld a különbség. Az a VB6 programozó, aki ma erőlködés nélkül megért egy LINQ-kel és generikus típusokkal, osztályokkal és kivételkezeléssel teletűzdelt Visual Basic 9 kódot, az előtt emelem a kalapom. Ennyit fejlődött a nyelv, nem beszélve a két runtime közötti óriási különbségről.

Nyelvek: 2. VBA

A Visual Basic for Applications a VB6 Office-ban, Corel-ban és tetszőleges egyéb környezetben történő felhasználása annak érdekében, hogy az alkalmazást kívülről egyszerűen programozhatóvá tegyék. A gyökerei VB6-ba nyúlnak vissza és azóta nem fejlődött, tehát kb. 10 éves technológiáról van szó. Nyilvánvalóan még sokáig supportált lesz, de új megoldások fejlesztése igencsak megkérdőjelezhető, mert

"As of July 1, 2007, Microsoft will no longer offer VBA distribution licenses to new customers."

Nyelvek: 3. Visual Studio for Applications (VSTA)

A VSTA a VBA utódja abból a szempontból, hogy saját alkalmazásunkba programozói környezet építhető. Ez is .NET alapú:

"Enables ISVs and enterprises to embed a streamlined IDE into their applications, accelerating customization development by end users, resellers, system integrators, and internal teams.  Includes support for Visual Basic and Visual C# along with other tools for application customization."

Nyelvek 4. Visual Studio Tools for Office (VSTO)

A VSTO az Office programozás jövője, azaz ebből a szempontból a VBA felváltója, méghozzá egyértelműen, már 2003-től kezdve. Már alapból a VS 2008 része és természetesen .NET alapú fejlesztést támogat. Kár is részletezni, hogy sokkal hatékonyabb, mint a VBA és ezé a jövő.

Support lifecycle:

Természetesen a VB6 és a VBA támogatott még jó sokáig, de ennek az az EGYETLEN oka, hogy tele van a világ ilyen kódokkal. Nem pedig az, hogy az MS arra buzdítana bárkit, hogy ezt használja.

A VBA oldalon ez áll:

"Microsoft does not expect to make significant enhancements to VBA."

"As of July 1, 2007, Microsoft will no longer offer VBA distribution licenses to new customers."

Ugyanitt ez javasolt helyette:

"Microsoft is investing its application programmability resources in Microsoft® Visual Studio® Tools for Applications (VSTA) and its companion set of tools, Microsoft® Visual Studio® Tools for Office (VSTO). We encourage you to consider VSTA for new applications that require application programmability technology."

Már 2003-ban óriási különbség volt a VSTO javára (lásd Comparing Microsoft Visual Basic for Applications 6.0 and Microsoft Visual Studio Tools for the Microsoft Office System – Office 2003!) és ez a szakadék az azóta eltelt években tovább növekedett. Már 2005-ben sem volt nehéz felsorolni 9 ütős érvet a VSTO mellett. És azóta eltelt újabb 3 év.

 

Word dokumentum generálása adatkötéssel – 5. rész: A kód neve

Az előző részben láttuk, hogyan kapcsolódik a DOCX állományban lévő customXml part kétirányú adatkötéssel a content control vezérlőkhöz. Ha ezzel a módszerrel akarunk programozottan dokumentumot előállítani, akkor már csak egyetlen lépés van hátra: olyan kódot kell írnunk, amely belenyúl az Open XML állományba és felülírja a korábban már odatett XML partot, aminek tartalma azután az adatkötéseken keresztül automatikusan megjelenik a felhasználó számára.

A feladat megoldásában a System.IO.Packaging névtér nagy segítségünkre lesz. A Package osztály segítségével meg tudjuk nyitni a DOCX fájlt ZIP tudomány nélkül, csak az elérési útját kell ismernünk:

    // A sablon dokumentum megnyitása.
Package package = Package.Open( path, FileMode.Open, FileAccess.ReadWrite );

A következő lépés az XML part megkeresése. Az egyes part-okra a csomagon belüli URI-jük segítségével hivatkozhatunk. A Word 2007 Content Control Toolkit által generált Item1.xml itt található:

    // Az XML part útvonala a sablon dokumentumban.
    Uri partUri = new Uri( "/customXml/Item1.xml", UriKind.Relative );

Lekérdezhetjük, hogy egyáltalán létezik-e ilyen part a dokumentumban:

    // Ellenőrizzük, hogy a sablonban van-e XML part.
    if( package.PartExists( partUri ) )
    {
        // itt folytatjuk...

Ha létezik, akkor el is kérhetjük, mégpedig egy PackagePart formájában:

    // Az XML part elkérése.
    PackagePart xmlPart = package.GetPart( partUri );

Az XML part tartalmát streamként tudjuk elérni. Ha például egy content nevű változóban megtalálható a beírandó XML UTF-16 formátumban, akkor annak beírására használhatjuk például az alábbi kódot:

    // Az XML part tartalmát kezelő stream elkérése.
    using( Stream xmlStream = xmlPart.GetStream() )
    {
        // A stream hosszának beállítása, hogy rövidebb szöveg esetén a régi tartalom levágódjon.
        xmlStream.SetLength( content.Length );

        // Az új tartalom beírása a streambe. Unicode kell, mert az XML stringben utf-16 szerepel.
        using( StreamWriter writer = new StreamWriter( xmlStream, Encoding.Unicode ) )
        {
            writer.Write( content );
            writer.Flush();
            // writer.Close(); automatikus a Dispose miatt.
        }

        // Az XML part mentése.
        // xmlStream.Close(); automatikus a Dispose miatt.
    }

Nincs is más hátra, mint a dokumentum módosításait elmenteni a diszkre:

    // A dokumentum változásainak mentése.
    package.Flush();
    package.Close();

Miért vacakoltam az UTF-16 kódolással? Azért, mert a beírandó XML előállítására szerintem az a legegyszerűbb megoldás, ha készítünk például egy Contact osztályt, annak beállítjuk úgy a tulajdonságait, ahogy azokat a Word dokumentumban látni szeretnénk, majd egyszerűen XmlSerializer segítségével kisorosítjuk:

    XmlSerializer serializer = new XmlSerializer( typeof( Contact ) );

    using( StringWriter writer = new StringWriter( CultureInfo.InvariantCulture ) )
    {
        serializer.Serialize( writer, this );
        result = writer.ToString();
        // writer.Close(); automatikus a Dispose miatt.
    }

Mivel itt StringWritert használok, az eredmény a .NET Framework sztringjeinek alapértelmezett kódolása, azaz "utf-16" lesz, amivel tapasztalataim szerint a Word nem birkózik meg. Persze biztosan lehet egyszerűbben is…

Egyetlen dologra hívnám fel a figyelmet – azon kívül természetesen, hogy a fenti kód a probléma megoldásának igen egyszerű módja: kódból módosítunk egy Word dokumentumot, de mindezt úgy tesszük, hogy nem használjuk hozzá a Word objektum modelljét. Sőt, nem használjuk a Word egyik komponensét sem, azaz a fenti kód működik akkor is, ha nincs Word a gépen! Ez igen fontos fegyvertény az Open XML mellett, hiszen aki próbált már szerver oldalon Office dokumentumot előállítani az biztosan belefutott abba a problémába, hogy az Office-t nem kiszolgáló oldali automatizálásra tervezték. Ez még a 2007-es verzióra is igaz, de nem az Open XML-re!

Ezt a tudásunkat felhasználva akár a SharePointot is kiegészíthetjük, készíthetünk például egy olyan új funkciót a Névjegyalbum listákba, amely lehetővé teszi a névjegy lista elemek alapján megcímzett, fejléces levelek egy kattintással történő előállítását. Ehhez nem kell mást tennünk, mint…

(folytatjuk)

Word dokumentum generálása adatkötéssel – 4. rész: Kapcsolat

Ahogy az előző részben láttuk, a content control-ok vagy más néven a structured document tags szolgáltatás az Office dokumentumokban lehetővé teszi a formázás és az adatok elkülönítését. Két korlátozó körülményt azonban mindenképpen meg kell említenünk:

  1. Ez a szolgáltatás egyelőre csak a Word 2007-ben érhető el, az Office család más termékeiben nincs ilyen lehetőség.
  2. Elég fájó, de sajnos nincs táblázat vezérlő, sőt az ismétlődéseket (pl. felsorolásokban) sem tudja kezelni ez a funkció. Mivel ez sokaknak fáj, ezért várhatóan az Office 14-ben vagy talán már egy javítócsomagban megkapjuk ezt is.

Nem beszéltünk még arról, hogy hol tárolódnak az adatok és hogyan kapcsoljuk azokat a vezérlőkhöz. Az adatok a DOCX állományon belül egy önálló XML fájlban tárolódnak, alapértelmezés szerint a customXml mappában.Itt nyers XML-t kell elképzelni, semmi Open XML specifikus elem nincs benne, az viszont praktikus, ha van egy önálló, egyedi névtere. Ha például a dokumentumunk egy levél, amelyben a címzett és a feladó adatait programozottan akarjuk kitölteni, akkor a szükséges adatokat betehetjük a customXmlitem1.xml fájlba az alábbi formában:

    <?xml version="1.0" encoding="utf-16"?>
    <Contact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                     xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                     xmlns="http://www.msdnkk.hu/samples/Contact">
        <FirstName>György</FirstName>
        <LastName>Balássy</LastName>
        <Company>MSDN Kompetencia Központ</Company>
        <City>Budapest</City>
        <Zip>1117</Zip>
        <Address>Magyar Tudósok krt. 2.</Address>
        <Sender>Feladó Ferenc</Sender>
    </Contact>

Ennek az XML fájlnak az írása és olvasása megoldható a korábban már említetett Packaging API segítségével, hiszen ez is egy Open XML document part.

Hogyan kapcsoljuk ezt a fájlt a csomag többi részéhez? A word_relsdocument.xml.rels fájlt kell kiegészítenünk az alábbiakkal:

    <?xml version="1.0" encoding="utf-8"?>
    <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <!-- Sok Relationship elem van itt már... -->
        <Relationship 
            Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml" 
            Target="../customXml/item1.xml" 
            Id="R0fbcbf7dffdc49b6" />
    </Relationships>

A [Content_Types].xml fájlhoz nem kell nyúlnunk, mert abban már szerepel egy definíció, amely magában foglal minden XML kiterjesztésű állományt. Kiegészíthetjük viszont egy XML properties résszel:

    <?xml version="1.0" encoding="utf-8" ?>
    <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
        <Default Extension="xml" ContentType="application/xml" />
        <!-- A dokumentum többi része itt Override elemekben -->
        <Override 
            PartName="/customXml/itemProps1.xml" 
            ContentType="application/vnd.openxmlformats-officedocument.customXmlProperties+xml" />
    </Types>

Az XML properties fájlban további tulajdonságokat adhatunk meg, például egy ún. data store ID-t:

    <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
    <ds:datastoreItem 
        ds:itemID="{70372b4c-0b6e-4f5d-9fa2-39118fe7a889}" 
        xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml" />

Ha több customXml partunk is van, akkor még egy ds:schemaRefs elem segítségével összekapcsolhatjuk a data store-t egy adott XML sémával. Ennek akkor van jelentősége, ha egyébként a dokumentumban több azonos sémájú XML part is van, mert így meg tudjuk adni, hogy pontosan melyikhez kívánunk kapcsolódni.

A tárolást tehát megoldottuk, következő probléma, hogy az egyes vezérlőket hogyan kapcsoljuk az XML fájlban lévő elemek valamelyikéhez. A megoldás a cikksorozat címében oly sokszor említett adatkötés. Nem is akármilyen, hanem kétirányú! Tehát akár kódból módosítjuk az XML állományt, akár a felhasználó ad Wordben új értéket valamelyik vezérlőnek, a másik automatikusan frissül, ezzel semmilyen további munkánk nincsen!

Az adatkötés megadása a worddocument.xml fájlban történik az egyes w:sdtPr elemekbe ágyazott w:dataBinding elemekkel. Itt két dolgot kell megadnunk:

  1. Egy névtér aliast a w:prefixMappings attribútumban.
  2. A névtér aliast használó és az XML dokumentumban egy elemet azonosító XPath kifejezést a w:xpath attribútumban.
  3. Ha több azonos névterű XML partunk is van, akkor még egy data store ID-t, ami alapján a Word megtalálja majd az XML partot. Ezt a w:storeItemID attribútumban lehet megadni.

Végül például egy Keresztnév  értéket bekérő vezérlő, amely a fent bemutatott XML dokumentum FistName mezőjéhez van kötve így festhet:

    <w:sdt>
        <w:sdtPr>
            <w:dataBinding 
                w:prefixMappings="xmlns:ns0='http://www.msdnkk.hu/samples/Contact'" 
                w:xpath="/ns0:Contact[1]/ns0:FirstName[1]" 
                w:storeItemID="{70372b4c-0b6e-4f5d-9fa2-39118fe7a889}" />
            <w:rPr>
                <w:i />
            </w:rPr>
            <w:alias w:val="Keresztnév" />
            <w:tag w:val="Keresztnev" />
            <w:id w:val="370331103" />
            <w:placeholder>
                <w:docPart w:val="DefaultPlaceholder_22675703" />
            </w:placeholder>
            <w:text />
        </w:sdtPr>
        <w:sdtContent>
            <w:r w:rsidR="00136851" w:rsidRPr="00136851">
                <w:rPr>
                    <w:i />
                </w:rPr>
                <w:t>Keresztnév</w:t>
            </w:r>
        </w:sdtContent>
    </w:sdt>

A jó hír az, hogy mindezt nem kell kézzel odaheggesztenünk minden egyes vezérlőhöz. Bár sem a Wordben, sem pedig a Visual Studioban nincs erre eszköz, szerencsére a CodePlexről letölthetjük a Word 2007 Content Control Toolkitet, ami sokat segíthet a munkában. Egyetlen képernyős alkalmazásról van szó és mivel Windows Formsban készült, kiválóan olvasható Reflectorral (megjegyzem tanulni is lehet belőle, például nagyon érdekes, hogyan vezérli ez a külső alkalmazás a Word kurzorát):

Content Control Toolkit

Az alkalmazás használata nagyon egyszerű:

  1. Készítsük el Wordben a sablon dokumentumot és tegyük bele a vezérlőket a Developer fülről.
  2. Töltsük be a Word dokumentumot a Content Control Toolkit (CCT) eszközbe, ami után bal oldalon megjelennek a vezérlők.
  3. A jobb alsó Create a new Custom XML Part linkre kattintva adjunk új XML partot a dokumentumhoz.
  4. Készítsük el azt az XML dokumentumot például Visual Studioban, amit egyszerűen elő tudunk állítani később kódból, és amilyen formátumú fájlt majd a DOCX állományba szeretnénk helyezni.
  5. Másoljuk be az XML tartalmát az Edit View fülön lévő mezőbe.
  6. Váltsunk vissza Bind View nézetre, ahol megjelenik az XML hierarchia.
  7. Jelöljük ki a bal oldali listában valamelyik vezérlőnket (ez kell), majd a jobb oldali hierarchiában fogjuk meg a hozzá illő XML elemet és dobjuk rá a vezérlőre. Ekkor elkészül az adatkötés. Ha inkább kézzel szerkesztenénk a paramétereken, akkor kattintsunk duplán bármelyik vezérlő sorára és a felbukkanó ablakban adjuk meg az adatokat.
  8. Végül ne felejtsük el menteni a dokumentumot.

Ezzel még csak az adatkötés paraméterezése készült el, illetve az eszköz megoldja azt is, hogy a DOCX állományban létrejöjjön egy XML part. Ami még hátra van, az a DOCX állományban lévő XML tartalmának módosítása kódból. De ezt majd legközelebb, addig is ezt érdemes kipróbálni!

(folytatjuk)

Word dokumentum generálása adatkötéssel – 3. rész: Kontroll

Bár a Word 2007 preferált fájlformátuma a DOCX teljes mértékben nyitott és XML alapú, elmondhatjuk, hogy a tartalom programozott közvetlen előállítása mégsem igazán egyszerű, mert az adat és a megjelenítés erősen keveredik a WordML nyelvben. Már a Word 2003-ban megjelent az a lehetőség, hogy a dokumentumhoz XSD sémát rendelhetünk, amely alapján a szöveg egyes részeit nyers XML-ben exportálhatjuk, de sajnos ez nem teszi lehetővé a tartalom generálását, ahogyan azt korábban láttuk.

Szerencsére ezen kívül van egy harmadik XML alapú lehetőség is, amely a Word 2007-tel vált elérhetővé.

2. Structured document tags

A Word 2007 vezette be az ún. content control vezérlőket vagy más néven a structured document tag-eket, azaz SDT-ket (ez borzasztóan magyartalanul hangzik, de sajnos nem tudom, hogy mi lett a magyar terminológia 😦 ). A módszer lényege, hogy a dokumentum egyes részeibe nem csak passzív helyőrzőket, hanem aktív vezérlőket teszünk, melyek tartalma a dokumentumban tárolt (ugyebár ZIP fájlról van szó) XML fájlhoz kapcsolódik.

Ha bekapcsoljuk a Developer fület, a Controls csoportban találjuk ezeket a vezérlőket:

Vezérlők a Developer fülön

Összesen 7 féle létezik:

  • Rich Text
  • Text
  • Picture
  • Combo Box
  • Drop-Down List
  • Date Picker
  • Building Block Gallery

A nevek magukért beszélnek. Ha ugyanebben a csoportban átkapcsolunk Design Mode-ba, beszúrhatjuk ezeket a vezérlőket a dokumentumunk szövegébe. Például ha szükséges, hogy a felhasználók megadjanak egy dátumot, amely mondjuk egy szerződés keltét jelzi, beszúrhatunk egy Date Picker vezérlőt, amely így fog megjelenni:

Date Picker

Fontos tehát, hogy aktív vezérlőről van szó, amely nem csak a fejlesztők, hanem a felhasználók számára is megkönnyíti a munkát. A szalagon a Properties gombra kattintva még egy beállító ablakot is kapunk:

Date Picker Properties

Két fontos opció elérhető minden vezérlőnél:

  • A Title mezőben megadott érték megjelenik a felhasználóknak, közvetlenül a vezérlő felett, ezt tehát érdemes barátságosan kitölteni:

Title értéke

  • A Tag mezőben megadott érték a felhasználói felületen nem jelenik meg, ez nekünk fejlesztőknek lehet hasznos.

Az így beállított vezérlő egy w:sdt elem formájában mentődik el a document.xml fájlba:

    <w:sdt>
        <w:sdtPr>
            <w:rPr>
                <w:lang w:val="en-US"/>
            </w:rPr>
            <w:alias w:val="Szerződés dátuma"/>
            <w:tag w:val="SzerzodesDatum"/>
            <w:id w:val="107276272"/>
            <w:placeholder>
                <w:docPart w:val="DefaultPlaceholder_22675705"/>
            </w:placeholder>
            <w:showingPlcHdr/>
            <w:date>
                <w:dateFormat w:val="yyyy.MM.dd."/>
                <w:lid w:val="hu-HU"/>
                <w:storeMappedDataAs w:val="dateTime"/>
                <w:calendar w:val="gregorian"/>
            </w:date>
        </w:sdtPr>
        <w:sdtContent>
            <w:r w:rsidRPr="005B7BC2">
                <w:rPr>
                    <w:rStyle w:val="PlaceholderText"/>
                    <w:lang w:val="en-US"/>
                </w:rPr>
                <w:t>Click</w:t>
            </w:r>
            <w:proofErr w:type="gramEnd"/>
            <w:r w:rsidRPr="005B7BC2">
                <w:rPr>
                    <w:rStyle w:val="PlaceholderText"/>
                    <w:lang w:val="en-US"/>
                </w:rPr>
                <w:t xml:space="preserve"> here to enter a date.</w:t>
            </w:r>
        </w:sdtContent>
    </w:sdt>

A w:sdtPr a properties, azaz a tulajdonságokra vonatkozó rész, a w:sdtContent pedig a felhasználó által megadott tartalom. A tulajdonságok között megtaláljuk a korábban megadott alias és tag értékeket. Itt található még a w:showingPlcHdr elem is, amely megmutatja, hogy a w:sdtContent részben nem a felhasználó által megadott érték, hanem még az alap helyőrző, placeholder szerepel. A w:date elembe a Date Picker vezérlőre vonatkozó egyedi beállításokat menti a Word.

Az w:sdtContent elem most elég bonyolultnak tűnik, de már értjük, hogy miért: run elemeket tartalmaz, mert arra lehet formázási beállításokat megadni. Ha a felhasználó kiválaszt egy dátumot, mindez sokkal átláthatóbb lesz, marad a nyers text:

    <w:sdtContent>
        <w:r w:rsidR="001B1478">
            <w:t>2008.04.15.</w:t>
        </w:r>
    </w:sdtContent>

Mi az, amit tehát ezzel elértünk? Definiáltuk, hogy a dokumentum fontos részein milyen formátumú tartalomnak kell megjelennie és a felhasználó által megadott adatot úgy perzisztáltuk WordML-ben, hogy az a megjelenítéstől teljesen független, ráadásul a korábbiaknál egyszerűbben található meg programozottan a dokumentumban.

A jó hír az, hogy még arra sincs szükség, hogy a Word által generált XML-ben w:sdt elemeket keresgéljünk, ugyanis ezeknek a vezérlőknek a tartalmát adatkötésen keresztül is elérhetjük.

(folytatjuk)