Monthly Archives: April 2008

Hullanak az IIS-ek

Az utóbbi időben egyre több olyan hír jelent meg a világhálón, amelyek szerint durva hiba lehet a Windows-ban, az IIS-ben vagy az SQL Serverben, mert sorra hullanak azok a szerverek, melyek ezeket használják. Április 17-én a Microsoft kiadott egy Security Advisory-t (951306), amely azonban nem írt arról, hogy pontosan mi a hiba oka, csak azt tette egyértelművé, hogy nincs patch, mi javítaná.

Nos, azóta a Microsoft jobban utánajárt a dolognak és kiderítették, hogy nem termék hibáról van szó, hanem SQL injection módszerrel sikerült megfektetni az érintett webhelyeket. Azaz a webhely programozója tehet arról, hogy security bugot hagyott a kódjában. Számomra ugyan meglepő, hogy ez a támadási módszer a mai napig ilyen jól működik, de hát elég sok régi kód van még sok helyen használatban…

A Microsoft részletes válasza megtalálható ezeken a címeken:

A lényeg:

  • Nem találtak hibát Microsoft termékben, amit ez a támadási hullám kihasználna.
  • A támadásokat SQL injectionön keresztül hajtották végre.
  • A támadás teljesen automatikus, egy január óta működő web bot keresők segítségével megtalálja a támadható weblapokat. Egyelőre nem ismert (vagy nem publikus) hogy milyen kifejezésre keres ez a web bot. Gyaníthatóan .asp és .aspx kiterjesztésű oldalakra vadászik.

Akinek esetleg még új az SQL injection fogalma, annak nagyon tudom javasolni Scott Guthrie rövid írását a témáról.

 

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.

 

Informatika Tisztán – Csoportmunka modul

Holnap kerül megrendezésre első alkalommal a tavalyi nagy sikerű Informatika Tisztán sorozat második, csoportmunkával foglalkozó szakmai napja a Sugár mozijában, amit további alkalmak fognak követni Budapesten és vidéken egyaránt. Múlt héten volt szerencsém végighallgatni az előadásokat és bátran állíthatom, hogy érdemes eljönni a rendezvényre.

Ha valaki úgy dönt, hogy a nap utolsó előadásán is marad, őt lesz szerencsém megbombázni egy nagy adag Windows SharePoint Services üzemeltetési információval. Az előadás annyiban formabontó, hogy a rendszergazdák számára legfontosabb felügyeleti funkciók bemutatása közben nulláról építünk fel és üzemelünk be egy WSS-t. Ebből talán már érezhető, hogy elég demó intenzív lesz az előadás.

Tudomásom szerint nem lesz nyomtatott handout, aki esetleg mégis szeretne jegyzetelni, annak azt javaslom, hogy töltse le az előadás fóliáit innen, nyomtassa ki a számára szimpatikus formátumban és hozza el magával. A PPT fájlban ugyanis számos olyan rejtett dia, többnyire képernyőkép van, amit holnap nem fogok bemutatni, de a demók során látni fogunk.

Akit érdekel az Exchange, SharePoint és az Office üzemeltetői szemmel, tartson velünk!

 

Web Konferencia 2008

A hétvégén került megrendezésre a Web Konferencia 2008, melyen számos remek előadás mellett Bátorfi Zsolt barátom a Silverlightról, jómagam pedig az ASP.NET 3.5-ről és a Visual Studio 2008-ról beszéltem. A résztvevőknek megígértem, hogy közzéteszem az előadáshoz tartozó prezentációt és a bemutatott alkalmazás forráskódját is, íme:

Többen megkérdezték, hogy hogyan lehet ASP.NET platformra fejleszteni, ha nem rendelkezünk Visual Studioval? A legegyszerűbb megoldás, hogy le kell tölteni a Visual Studio 2008 webfejlesztére specializált, ingyenes kistestvérét a Visual Web Developer 2008 Express Editiont. Ez annyira ingyenes, hogy nem csak tanulásra, hanem éles projektekre is használható. Hasonlóan, a Microsoft kínál ingyenes adatbáziskezelőt is, SQL Server 2005 Express Edition néven. Természetesen mindkettőben vannak korlátozások, de általában tökéletesen használhatóak mind a technológiával való ismerkedésre, mind pedig projektekre.

Ezen kívül készítettünk néhány induló készletet, amely segítségével kezdő lendülethez juthatunk az új technológiákkal történő ismerkedéshez:

 

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)

NXT.NET for Lego Mindstorms

Néhány hónappal ezelőtt Dávid Zoli blogbejegyzése kapcsán figyeltem fel a Lego Mindstorms NXT készletére. Aki esetleg nem ismerné, ez egy olyan standard LEGO csomag, amiből programozható robotot építhetünk. A robot "agya" az ún. NXT Brick képes egyszerre négy szenzor jelét venni és három motort vezérelni, sőt a legszebb az egészben, hogy Bluetooth kapcsolatos keresztül távvezérelhető. Szóval nem csak egy gyerekjátékról van szó, sokkal több lehetőséget rejt ez a készlet magában. Nem véletlen, hogy a világban több helyen már ezt használják arra, hogy a diákokkal megszerettessék a programozást és elsajátíttassák a programozás alapjait. Aki nem hiszi, nézze meg ezt a videót egy Lego robotról, amelyik kirakja a Rubik kockát!

Mivel a Bluetooth kapcsolat soros portként látszik, ezért nem ördöngösség a .NET Framework SerialPort osztályán keresztül programozni. Bár ezt már többen megírták, én mégis nekiláttam, hogy életem első robotját a saját .NET alkalmazásomon keresztül távirányítsam. A dolog meglepően gyorsan működött, bár persze számos fejlesztői doksit kellett végigbújni, melyek szerencsére publikusan elérhetőek a Lego oldalán.

Az eredmény egy osztálykönyvtár lett, mely végül az NXT.NET nevet kapta. Teljes mértékben felügyelt kódban, C# 3.0-ban íródott és végül sikerült megoldani, hogy ugyanaz a forráskód változtatás nélkül csont nélkül forduljon .NET Framework 3.5-re és .NET Compact Framework 3.5-re is, tehát egyúttal a mobil változat is elkészült. A kód teljes mértékben angolul kommentezett, ide vezettem át mindent, amit a neten talált forráskódokból és dokumentációkból sikerült kiokoskodnom, így a C# fordító által generált XML kimenetből NDoc segítségével előállt az osztálykönyvtár fejlesztői CHM súgója, melyből íme egy képernyőfotó az elérhető típusok érzékeltetésére (ez is letölthető a CodePlexről):

Kattins a képre a teljes méret megtekintéséhez

A library teszteléséhez készült egy desktop és egy mobil alkalmazás, mindkettő természetesen felügyelt kódban. Bár még nem tud mindent, az alap kommunikáció, tulajdonságok lekérdezése, szenzorok konfigurálása és lekérdezése már megy. Ez látszik belőle Visual Studio 2008-ban:

NXT.NET desktop alkalmazás

Bár a motorok vezérlése még csak alapszinten implementált, elérkezettnek láttam az időt ahhoz, hogy megosszam az eredményt azokkal, akiket érdekel. A projekt súgóját és lefordított állományait kitettem a CodePlexre, onnan lehet letölteni őket. A forráskódokat egyelőre nem osztottam meg, de ha lesz érdeklődés a projekttel kapcsolatban, akkor tervezem azt is kitenni a netre.

Érdekel ez egyáltalán valakit rajtam kívül? Használ ma idehaza valaki Lego Mindstorms NXT-t?

 

Informatika Tisztán – Csoportmunka

Aki tavaly figyelemmel kísérte az Informatika Tisztán sorozatot biztosan emlékszik, hogy érdemes volt ellátogatni a Sugárba vagy valamelyik vidéki helyszínre. A tavalyi Rendszerfelügyelet téma mellé áprilistól új téma kerül terítékre, mégpedig a csoportmunka. A Csoportmunka és Kommunikáció modul az Office 2007, az Exchange Server 2007 és a Windows SharePoint Services 3.0 területeire fókuszál, elsősorban üzemeltetői szemmel.

A SharePoint témakörhöz van egy kis közöm, így bátran tudom ajánlani azoknak, akik még egyáltalán nem használják és nem tudják, hogy mire lehet képes, és azoknak is, akik már elhatározták, hogy szeretnék használni, csak még nem tudják, hogyan tegyék meg a kezdő lépéseket. A nap utolsó előadásában nulláról építünk fel egy Windows SharePoint Services portált, így lépésről lépésre tudunk végigmenni azokon a beállításokon, amelyekkel a rendszergazdák biztosan találkozni fognak. A felhasznált operációs rendszer Windows Server 2003 lesz, tehát bárki ki tudja próbálni az elhangzottakat, ha rendelkezik ilyen licenccel. Ha valakit mégis a Windows Server 2008-ra történő WSS telepítés érdekel, annak szintén érdemes eljönni az előadásra, mert a WSS beállításai azonosak, az operációs rendszer előkészítésével kapcsolatban pedig már korábban készült magyar nyelvű screencast.

A Csoportmunka előadás összesen 7 alkalommal lesz megtekinthető, ebből kettő budapesti és az első alkalom 2008. április 29., kedd. Várunk mindenkit!

Bővebb információk az Informatika Tisztán eseménysorozat honlapján találhatóak.

 

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)

Word dokumentum generálása adatkötéssel – 2. rész: Új remény

Ahogy az előző részben megállapítottuk, a Word 2007 alapértelmezett Open XML fájl formátumainak programozott módon történő közvetlen kezelése nem éppen kellemes élmény. Bár kapunk támogatást a fájl kibontásához és a részek eléréséhez, sőt az egyes részek tartalmát is tudjuk szerkeszteni, ez utóbbinak a megalkotása során váratlan akadályokba ütközhetünk. Mindennek pedig az az oka, hogy a Word ML nyelvben a tartalom, azon belül is a sok sallang között a dokumentum információtartalma és a megjelenítés bizony elég erősen keveredik.

A szétválasztásra szerencsére van lehetőség, és a megoldás lelke természetesen az XML.

1. Custom XML

Ha már a Word XML támogatása szóba került, mindenképpen meg kell említenünk a Custom XML szolgáltatást, amely már megvolt a Word 2003-ban is és lényegében nem is változott a 2007-es verzióban. Ennek a funkciónak a lényege, hogy a dokumentumunkhoz hozzárendelünk egy XSD sémát, majd definiáljuk, hogy melyik szövegrész melyik XML elemnek felel meg. Végül a Word Mentés ablakában kiválasztjuk, hogy nem az egész dokumentumot akarjuk menteni Word formátumban címestül, bekezdésestül, formázásostul, hanem csak az információk alapján előállított nyers XML-t.

Ennek a szolgáltatásnak tehát az a célja, hogy a szövegből ki tudjuk nyerni a lényegi információt, mellőzve minden körítést. A módszer sajnos nem alkalmas dokumentum előállítására, a mentéskor előálló XML és az eredeti dokumentum között nincs kapcsolat és nem tudok olyan módszerről, ami lehetővé tenné, hogy egy adott XML tartalmát jelenítse meg a Word a sablon dokumentumunkban. Krisztián számára viszont jó hír, hogy tökéletesen kezeli a táblázatokat 😉

Vegyük például az alábbi dokumentumot, amely egy tanfolyami ajánlatot tartalmaz:

Egy általános Word dokumentum

Ha az a feladatunk, hogy ebből kellene kinyernünk az oktató nevét, óraszámot illetve az érintett témákat, akkor használhatjuk a Custom XML szolgáltatást. Ehhez először készítenünk kell egy XSD sémát. Bevallom nem sűrűn gyártok sémát, az XSD szintaktika nem megy fejből, ezért inkább gyártottam egy XML dokumentumot Visual Studioval, pont olyan felépítésűt, amire szükségem van a Word feldolgozásnál is:

    <?xml version="1.0" encoding="utf-8"?>
    <Tanfolyam>
        <Oktato>Oktató neve</Oktato>
        <Oraszam>111</Oraszam>
        <Tartalom>
            <Tema>
                <Cim>Elsé téma</Cim>
                <Szint>könnyű</Szint>
            </Tema>
            <Tema>
                <Cim>Második téma</Cim>
                <Szint>közepes</Szint>
            </Tema>
            <Tema>
                <Cim>Harmadik téma</Cim>
                <Szint>nehéz</Szint>
            </Tema>
        </Tartalom>
    </Tanfolyam>

Miután ez megvolt, megkértem a Studiot, hogy generáljon ebből XSD-t:

VS: Create Schema

Íme az eredmény, amit így nem kellett megírnom:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema attributeFormDefault="unqualified" 
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="Tanfolyam"> <xs:complexType> <xs:sequence> <xs:element name="Oktato" type="xs:string" /> <xs:element name="Oraszam" type="xs:unsignedByte" /> <xs:element name="Tartalom"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" name="Tema"> <xs:complexType> <xs:sequence> <xs:element name="Cim" type="xs:string" /> <xs:element name="Szint" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

Megvan tehát a séma, irány a Word! Először is elő kell varázsolnunk a szalagra a Developer fület, amit a Word options ablakban tehetünk meg:

Word options

Ha megjelent a Developer tab, bökjünk rá az XML csoportban található Structure gombra, majd a megjelenő jobb oldali XML Structure munkaablakban a Templates and Add-Ins… linkre:

XML Structure munkaablak

A felugró Templates and Add-Ins ablakban az Add Schema gombra kattintva válasszuk ki a korábban előállított XSD fájlunkat és adjuk meg a hozzá tartozó névtér URI-t. Ez lesz a Word által generált XML dokumentum alapértelmezett névtere, tehát jól gondoljuk ki, mit adunk meg:

Templates and Add Ins ablak

Innentől kezdve nincs is más dolgunk, mint a szöveg egyes részeit kijelölni és a munkaablak alsó részében rábökni az alkalmazandó XML elem nevére, aminek hatására lila jelölők tűnnek fel a dokumentumban, ha a Show XML tags in the document opciót bekapcsoljuk:

XML séma alkalmazása

Az ablak legalsó opcióját érdemes bekapcsolva hagyni: a List only child elements of current element azt jelenti, hogy a Word követi merre jár a kurzorunk a dokumentumban és csak azokat az elemeket kínálja fel, amik a séma alapján ott elérhetőek. Ez sokat segít.

Célszerű figyelni a munkaablak felső részében a sárga bejegyzéseket, amelyek felett tooltipben megjelenik, ha valamelyik elemet nem a sémának megfelelően használjuk.

Hasznos beállítási lehetőségeket találunk, ha a legalsó XML Options linkre kattintunk:

XML options

A Save data only bekapcsolásával érhetjük el, hogy csak az adatok mentődjenek, a formázás ne, sőt megadhatunk egy XSL transzformációt is, amit mentésnél alkalmaz a Word.

A validálási lehetőségek között szerintem célszerű bekapcsolni az Ignore mixed content opciót. Ezt bekapcsolva a Word eltekint az általunk XML elemként megjelölt részek közötti egyéb szövegtől. E nélkül a sémában a szabadszöveges részeket is definiálnunk kellene.

Érdemes kipróbálni, hogy a Word felismeri a táblázatokat, így ha később a táblázatba újabb sorokat szúrunk be, azokra is alkalmazni fogja az előző sor XML séma beállításait. Ha bekapcsoljuk a Show placeholder text for all empty elements opciót, akkor még az is látszik messziről, hogy a szöveg mely részét kell kitöltenie a felhasználónak (ez persze nem csak táblázatnál működik):

Táblázat és placeholder

Ha készen vagyunk a dokumentum felcímkézésével el is menthetjük és odaadhatjuk a felhasználóknak. Miután ők megszerkesztik a szöveget csak arra kell figyelniük, hogy a Save As dialógus ablakban Word 2003 XML Document típust válasszanak ki és jelöljék be a Save data only opciót:

Save As

Fontos, hogy Word 2003 XML Document a típus neve és nem 2007! Íme az eredmény:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <Tanfolyam xmlns="www.msdnkk.hu">
        <Oktato>Balássy György</Oktato>
        <Oraszam>24</Oraszam>
        <Tartalom>
            <Tema>
                <Cim>Bevezetés a SharePoint objektum modell használatába</Cim>
                <Szint>könnyű</Szint>
            </Tema>
            <Tema>
                <Cim>SharePoint webszolgáltatások</Cim>
                <Szint>könnyű</Szint>
            </Tema>
            <Tema>
                <Cim>Alkalmazás oldalak</Cim>
                <Szint>közepes</Szint>
            </Tema>
            <Tema>
                <Cim>Feature Framework</Cim>
                <Szint>közepes</Szint>
            </Tema>
            <Tema>
                <Cim>nincs címe</Cim>
                <Szint>nincs szintje</Szint>
            </Tema>
            <Tema>
                <Cim>Eseménykezelők</Cim>
                <Szint>közepes</Szint>
            </Tema>
            <Tema>
                <Cim>Webkijelzők készítése</Cim>
                <Szint>közepes</Szint>
            </Tema>
            <Tema>
                <Cim>Munkafolyamatok fejlesztése</Cim>
                <Szint>nehéz</Szint>
            </Tema>
        </Tartalom>
    </Tanfolyam>

Innen már aztán gyerekjáték akármilyen alkalmazásban feldolgozni az adatokat, hiszen ez standard XML, semmilyen formázást, Word ML-t vagy egyéb Word specifikus részt nem tartalmaz. Aki nem hiszi, innen letöltheti a cikkhez tartozó fájlokat. Persze az igazán szép az lenne, ha rá tudnánk kényszeríteni a felhasználókat, hogy mindig ebben a formátumban mentsenek, én erre sajnos nem találtam módszert 😦 Ha valaki tud, írja meg!

Sajnos ahogy azt korábban említettem, ezzel az XML-es módszerrel nem tudunk dokumentumot generálni. Csak arra jó, hogy a szövegből kinyerjük az adatokat, tudomásom szerint nem lehet megfordítani a folyamatot. Szerencsére van egy másik, szintén XML alapú szolgáltatás a Wordben, ami nem csak a dokumentum előállítását, de az adatkötésen alapuló generálást is biztosítja.

(folytatjuk)