Welcome to MSDN Blogs Sign in | Join | Help

OpenXMLDiff vNxt - Just an easy way of doing things

 

Hello Guys – As I told you in my previous blog post, that I am working with Eric on the updated version of OpenXMLDiff. The good news is, I have it ready! It’s uploaded on http://code.msdn.com/openxmldiff. Go, Play with it … 

So, I am sure you’ll have many questions – what’s different? what’s changed? is it a console app? how can you use it? et cetera .. answering em’ all below:

The initial idea behind OpenXMLDiff was to find a easy way of comparing two office files. Once you start writing you OpenXML code, sometimes you’ll find it very necessary to know what’s changed when you changed “X”.

Eric, me and a lot of people struggled with this issue multiple times, e.g. when I wanted to compare two files, to know why only one of a few seemingly similar files work, and others throw an error.

Granted – we have other ways, but nothing (that I found ) was easy enough to say - “Hey! comparing OpenXML files is easy …”

image

OpenXMLDiff.dll

This is the core file which does the actual job. I’ve build it as a class library so that you can use it directly from your code if you wish to .. you are free to write you own PowerShell scripts, Winforms apps, Wrapper dlls around it. It’s a simple object model, just one method (Generate) with a couple of overloads to give you more flexibility. This method get’s the job done. But, before you call this method, you’ll need to pass on some options and algorithm to use (basically the options decide, what should be ignored while doing a diff between files).

While generating the report, you’ll also need to tell what sort of output you want? Text or HTML. I’d recommend using the HTML output, because it can highlight the changes in the files which makes things a lot easier.

Once the output is generated, It will fire an event to notify you about the outcome, (or you can just ignore the event if you are planning to to a synchronous call, but presence of event means that you can also use it asynchronously). You catch the event or you don’t -  you will be able to get all the generated output either by using the event parameters, or the read only properties css, js, diffs, sourceparts, targetparts and output

We’ll talk about the CSS and JS afterwards, but sourceparts,targetparts and diffs are dictionaries, which will contain the parts which had differences and the diffgram explaining the differences. The output is the actual report detailing the differences (In the format you’ve selected).

OpenXMLComparer.exe 

Class library given above is a facility; not a compulsion – I’ve also build this Winforms application which uses above dll to generate a report.

image

I’ll go into further details in the next post, but first I’d want you to play with this thing and give me the feedbacks – It’s a beta, need to do a few changes yet, still, I’m sure you’ll like it!

 



 

Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

Here is a news, I am acting as a volunteer

Surely, I am volunteering for something that we (you and me) like playing with

Here is the story – I really liked the utility that Eric is working on http://blogs.msdn.com/ericwhite/archive/2008/06/14/openxmldiff-exe-a-utility-to-find-the-differences-between-two-open-xml-documents.aspx.

Going through the post, I noticed that Eric is looking for volunteers for converting the project to GUI to work on some possible enhancements, I pinged Eric and he agreed to let me work on it!

so, I started working on it …. in this week (or next at max) there should be a few updates from my side.

 



Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

How to get a list of updates

Today of my team members asked me, how to get a list of Office and Windows updates.

Surprisingly, I realized, that there is no easy way to do it (or at least I couldn’t find it ) – finally came up with following code snippets:

'For getting a list of office updates
'--- --- --- --- --- --- --- --- --- 
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colItems = objWMIService.ExecQuery("Select * from Win32Reg_AddRemovePrograms where DisplayName Like '%update%office%' OR DisplayName Like '%update%visio%' OR DisplayName Like '%update%word%' OR DisplayName Like '%update%excel%' OR DisplayName Like '%update%powerpoint%' OR DisplayName Like '%update%project%' ",,48 )
For Each objItem in colItems
    Wscript.Echo "DisplayName: " & objItem.DisplayName
    Wscript.Echo "InstallDate: " & objItem.InstallDate
    Wscript.Echo "ProdID: " & objItem.ProdID
    Wscript.Echo "Publisher: " & objItem.Publisher
    Wscript.Echo "Version: " & objItem.Version
Next

'--- --- --- --- --- --- --- --- --- 
' For getting a list of  Windows Updates

' -----------------------------------
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_QuickFixEngineering",,48)
For Each objItem in colItems
    Wscript.Echo "Caption: " & objItem.Caption
    Wscript.Echo "CSName: " & objItem.CSName
    Wscript.Echo "Description: " & objItem.Description
    Wscript.Echo "FixComments: " & objItem.FixComments
    Wscript.Echo "HotFixID: " & objItem.HotFixID
    Wscript.Echo "InstallDate: " & objItem.InstallDate
    Wscript.Echo "InstalledBy: " & objItem.InstalledBy
    Wscript.Echo "InstalledOn: " & objItem.InstalledOn
    Wscript.Echo "Name: " & objItem.Name
    Wscript.Echo "ServicePackInEffect: " & objItem.ServicePackInEffect
    Wscript.Echo "Status: " & objItem.Status
Next

'-----------------------------------

 

 



Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

Posted by Pranav Wagh | 2 Comments
Filed under: ,

The Open XML SDK download and online docs are now available

Let’s see what the OpenXML guru’s take about it ..

Here is full description from none other then …Erika
Doug Mahugh: Open XML SDK Version 1 released
Look at it … Eric  released PowerShell cmdlets to manipulate OpenXML docs (using OpenXML SDK). WoW.. 



Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

Posted by Pranav Wagh | 0 Comments
Filed under: ,

My blog UI might suck for a few days

Yep. I am working on some changes on my blog and you might see some things broken, out of place or just plain ugly for a few days. Please bear with me for a few days.

I am thinking of using a good JavaScript library which can ease my some of my troubles. For now, I am playing with the idea of using www.mootools.com. Let’s see how it goes.



Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

Posted by Pranav Wagh | 0 Comments
Filed under:

One more step in the right direction, native ODF support in Office 2007 SP2

imageDid’ya see dat! I am pretty exited about these developments, As soon as these this is out I want to play with it and see how can this feature be utilized in Office Programmability scenarios

Are you surprised ? WHY ? It’s fairly consistent with our idea of promoting & encouraging freedom of choice.

Also, Microsoft will join the OASIS ODF Technical Committee, and users will be able to set ODF to be the default format in their Office Applications.

For more details have a look at following posts.

· Office support for document format standards – Doug Mahugh,

· Microsoft Announces Support for More Document Format Standards, including ODF – Eric White

· Microsoft adds “Save as ODF” to Office 2007 Service Pack 2 – Gray Knowlton

· Open XML, ODF, PDF, and XPS in Office – Jason Matusow

· OpenXML & ODF was never a zero-sum game – Stephen McGibbon

· Open XML Formats: ODF support in Office – Brian Jones

· More Interop for Microsoft Office (ODF, PDF, PDF/A, XPS) – Oliver Bell



 

Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

What’s "Works on My Machine" Certification Program anyways ?

A few of my readers asked me, what’s do I mean by "Works on My Machine certified”, in my previous post. Here is the ans -  All of this thing started with Joseph Cooney – He got an interestingly funny and brilliant idea. Which, in itself, works-on-my-machine-stampedserves as a code disclaimer. Then Jeff Atwood(coding horror  fame …) zazzed things up and came up with following images!

Maybe this is really a disclaimerworks-on-my-machine-starburst that I was looking for  -

 

 



                                                     

 

Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

 

 

Posted by Pranav Wagh | 0 Comments
Filed under:

Creating a new presentation by pulling slides from a presentation

You’ll remember that a few days back I’ve posted a code snippet which demonstrates how to create a PowerPoint presentation from scratch using System.IO.Packaging.

Here is the next part of the same code which is “works on my machine” certified :)

This is a simple WinForms Application which demonstrates how to  pull the slides from a presentation and creates a new presentation.

In simplest terms this is what the code is doing -

1. It let’s you browse to a PowerPoint presentation, iterates through all the slides and displays the slide heading  (GetSlideTitles)

2. Once you select the slides you want from the presentation, it pulls those slides and associated slide layouts from the presentation. Then it adds the slides to a new presentation. (PullSlide, GetURIFromTitle, AddSlide)

Imports System.IO
Imports System.IO.Packaging
Imports System.Xml
Public Class Form1
    Dim ppt As New pptHelper
    Private Sub SelectFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SelectFile.Click
        Dim rs As DialogResult
        Dim items() As Object = Nothing

        OpenFileDialog1.Filter = "PowerPoint Presentation|*.pptx"
        rs = OpenFileDialog1.ShowDialog()

        If rs = Windows.Forms.DialogResult.OK Then
            SlideList.Items.Clear()
            items = ppt.GetSlideTitles(OpenFileDialog1.FileName).ToArray()
            SlideList.Items.AddRange(items)
        End If
    End Sub

    Public Sub MoveSlide(ByVal filename As String, ByVal slidetitle As String, ByVal remove As Boolean) ' function which will be called from "move" and "move all" 

        SelectedSlides.Items.Add(slidetitle) ' add it to the selected slide list
        If remove Then
            SlideList.Items.Remove(SlideList.SelectedItem) ' removing it from the slidelist (just to ensure that you don't add slides multiple times)
        End If
    End Sub
    Private Sub Move_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SelectSlide.Click
        MoveSlide(OpenFileDialog1.FileName, SlideList.SelectedItem.ToString, True)
    End Sub
    Private Sub MoveAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SelectAll.Click

        For Each o As Object In SlideList.Items ' Iterating through the listbox and moving everything to selected file list
            MoveSlide(OpenFileDialog1.FileName, o.ToString, False)
        Next o

        SlideList.Items.Clear() ' clearing the list
    End Sub



    Private Sub CreatePresentation_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CreatePresentation.Click
        Dim rs As DialogResult
        Dim source As Package = Nothing
        Dim target As Package = Nothing
        'Dim p As Package = Nothing

        SaveFileDialog1.Filter = "PowerPoint Presentation|*.pptx"
        rs = SaveFileDialog1.ShowDialog()

        If rs = Windows.Forms.DialogResult.OK Then
            target = Package.Open(SaveFileDialog1.FileName, FileMode.Create, FileAccess.ReadWrite)
            source = Package.Open(OpenFileDialog1.FileName, FileMode.Open, FileAccess.Read)
        End If

        ppt.CreateBasicPresentation(target)

        For Each s As Object In SelectedSlides.Items
            ppt.CopySlide(source, target, s.ToString(), pptHelper.relations.slidePart)
        Next
        target.Flush()
        target.Close()
        MsgBox("Done!")
    End Sub
End Class



Public Class pptHelper

 

    Public Class contents
        Public Shared presentation = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"
        Public Shared slidemaster = "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"
        Public Shared slideLayout = "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"
        Public Shared slidePart = "application/vnd.openxmlformats-officedocument.presentationml.slide+xml"
        Public Shared themePart = "application/vnd.openxmlformats-officedocument.theme+xml"
    End Class

    Public Class relations
        Public Shared officedocument = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
        Public Shared slidemaster = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster"
        Public Shared slidelayout = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"
        Public Shared slidePart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"
        Public Shared themePart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
        Public Shared mainPart = "http://schemas.openxmlformats.org/presentationml/2006/main"
        Public Shared relationship = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
    End Class



    Dim id As Integer = CInt(New Random().NextDouble * 10000)

    Public Function AddSlide(ByVal pkg As Package, ByVal sldPart As PackagePart) As Boolean
        Dim xmlDoc As New XmlDocument
        Dim rId As String
        Dim xNode As XmlNode
        Dim partUri As Uri


        ' manage namespaces to perform Xml XPath queries.
        Dim nt As New NameTable()
        Dim nsManager As New XmlNamespaceManager(nt)
        nsManager.AddNamespace("p", relations.mainPart)
        nsManager.AddNamespace("r", relations.relationship)
        ' end manage

        Dim slide As PackagePart = pkg.CreatePart(sldPart.Uri, sldPart.ContentType)


        ' connect it with doc part and update document.xml
        Dim doc As PackagePart = pkg.GetPart(New Uri("/ppt/presentation.xml", UriKind.Relative))
        rId = doc.CreateRelationship(slide.Uri, TargetMode.Internal, relations.slidePart).Id

        xmlDoc.Load(doc.GetStream())
        xNode = xmlDoc.CreateNode(XmlNodeType.Element, "p", "sldId", relations.mainPart)
        Dim attrId As XmlAttribute = xmlDoc.CreateAttribute("id")
        attrId.Value = id.ToString()
        Dim attrRId As XmlAttribute = xmlDoc.CreateAttribute("r:id", relations.relationship)
        attrRId.Value = rId
        xNode.Attributes.SetNamedItem(attrId)
        xNode.Attributes.SetNamedItem(attrRId)
        'xNode.Attributes. = "<p:sldId id=" & id.ToString() & " r:id=" & rId & "/>"
        id = id + 1

        xmlDoc.SelectSingleNode("//p:sldIdLst", nsManager).AppendChild(xNode)
        xmlDoc.Save(doc.GetStream(FileMode.Create, FileAccess.ReadWrite))
        ' end connect

        'get slide layout part from the slide
        For Each r As PackageRelationship In sldPart.GetRelationshipsByType(relations.slidelayout)
            Console.WriteLine(r.TargetUri.OriginalString)
            partUri = PackUriHelper.ResolvePartUri(r.SourceUri, r.TargetUri)
            Exit For ' only one layout
        Next
        Dim lyt_src As PackagePart = sldPart.Package.GetPart(partUri)
        Dim layout As PackagePart = Nothing

        Try
            layout = pkg.CreatePart(lyt_src.Uri, lyt_src.ContentType)
            xmlDoc.Load(lyt_src.GetStream())
            xmlDoc.Save(layout.GetStream(FileMode.Create, FileAccess.ReadWrite))
            ' add relationships
            Dim master As PackagePart = pkg.GetPart(New Uri("/ppt/slideMasters/slideMaster1.xml", UriKind.Relative))
            rId = master.CreateRelationship(layout.Uri, TargetMode.Internal, relations.slidelayout).Id
            xNode = xmlDoc.CreateNode(XmlNodeType.Element, "p", "sldLayoutId", relations.mainPart)
            attrId = xmlDoc.CreateAttribute("id")

            ''BUGBUG: id attribute of <sldLayoutId> element needs to be pulled from the source presentation/package
            Dim srcSldMasterPart As PackagePart = sldPart.Package.GetPart(New Uri("/ppt/slideMasters/slideMaster1.xml", UriKind.Relative))
            Dim xmlDocSrcMaster As New XmlDocument
            Dim sSldLayourRId As String = ""
            Dim sldLytPartUri As Uri
            xmlDocSrcMaster.Load(srcSldMasterPart.GetStream())
            For Each r As PackageRelationship In srcSldMasterPart.GetRelationshipsByType(relations.slidelayout)

                Console.WriteLine(r.TargetUri.OriginalString)
                sldLytPartUri = PackUriHelper.ResolvePartUri(r.SourceUri, r.TargetUri)
                If Uri.Compare(sldLytPartUri, partUri, UriComponents.Path, UriFormat.Unescaped, StringComparison.CurrentCulture) = 0 Then
                    sSldLayourRId = r.Id
                    Exit For
                End If

            Next

            Dim xmlNodeSrcLayoutId As XmlNode = xmlDocSrcMaster.SelectSingleNode("//p:sldLayoutIdLst/p:sldLayoutId[@r:id='" & sSldLayourRId & "']", nsManager)

            Dim sSlideLayoutId As String = xmlNodeSrcLayoutId.Attributes.GetNamedItem("id").Value
            attrId.Value = sSlideLayoutId
            attrRId = xmlDoc.CreateAttribute("r:id", relations.relationship)
            attrRId.Value = rId
            xNode.Attributes.SetNamedItem(attrId)
            xNode.Attributes.SetNamedItem(attrRId)
            'xNode.Value = "<p:sldLayoutId id=" & id.ToString & " r:id=" & rId & "/>"
            id = id + 1

            layout.CreateRelationship(master.Uri, TargetMode.Internal, relations.slidemaster)



            xmlDoc.Load(master.GetStream())
            xmlDoc.SelectSingleNode("//p:sldLayoutIdLst", nsManager).AppendChild(xNode)
            xmlDoc.Save(master.GetStream(FileMode.Create, FileAccess.ReadWrite))
            ' end add


        Catch ex As Exception
            layout = pkg.GetPart(lyt_src.Uri)
        End Try

        'end get
        slide.CreateRelationship(layout.Uri, TargetMode.Internal, relations.slidelayout)

        xmlDoc.Load(sldPart.GetStream())
        xmlDoc.Save(slide.GetStream(FileMode.Create, FileAccess.ReadWrite))
    End Function


    Public Function PullSlide(ByRef pkg As Package, ByVal uri As Uri, ByVal relationship As String) As PackagePart
        Dim p As PackagePart = pkg.GetPart(uri)
        Return p
    End Function

    Public Function CopySlide(ByRef sourcePkg As Package, ByRef tgtPkg As Package, ByVal sourceSlide As String, ByVal relationship As String) As Boolean
        Dim sourceUri As Uri = GetUriByTitle(sourcePkg, sourceSlide)
        Dim p As PackagePart = PullSlide(sourcePkg, sourceUri, relationship)
        Return AddSlide(tgtPkg, p)
    End Function
    Public Sub CreateBasicPresentation(ByRef p As Package)
        Dim xmlDoc As New XmlDocument
        xmlDoc.LoadXml(My.Resources.presentation)

        Dim docUri As Uri = PackUriHelper.CreatePartUri(New Uri("ppt/presentation.xml", UriKind.Relative))
        Dim docPart As PackagePart = p.CreatePart(docUri, contents.presentation)
        p.CreateRelationship(docPart.Uri, TargetMode.Internal, relations.officedocument)

        xmlDoc.Save(docPart.GetStream(FileMode.Create, FileAccess.ReadWrite))

        Dim themeUri As Uri = PackUriHelper.CreatePartUri(New Uri("ppt/theme/theme1.xml", UriKind.Relative))
        Dim themePart As PackagePart = p.CreatePart(themeUri, contents.themePart)
        docPart.CreateRelationship(themePart.Uri, TargetMode.Internal, relations.themePart)

        xmlDoc.LoadXml(My.Resources.theme1)
        xmlDoc.Save(themePart.GetStream(FileMode.Create, FileAccess.ReadWrite))


        Dim slideMasterUri As Uri = PackUriHelper.CreatePartUri(New Uri("/ppt/slidemasters/slidemaster1.xml", UriKind.Relative))
        Dim slideMasterPart As PackagePart = p.CreatePart(slideMasterUri, contents.slidemaster)
        docPart.CreateRelationship(slideMasterPart.Uri, TargetMode.Internal, relations.slidemaster, "rId1")

        xmlDoc.LoadXml(My.Resources.slideMaster1)

        slideMasterPart.CreateRelationship(themePart.Uri, TargetMode.Internal, relations.themePart)
        xmlDoc.Save(slideMasterPart.GetStream(FileMode.Create, FileAccess.ReadWrite))
    End Sub

    Public Function GetSlideTitles(ByVal fileName As String) As List(Of String)
        ' Return a generic list containing all the slide titles.        
        ' Fill this collection with a list of all the titles
        ' of all the slides in the requested slide deck.
        Dim titles As New List(Of String)
        Dim documentPart As PackagePart = Nothing
        Dim documentUri As Uri = Nothing

        Using pptPackage As Package = Package.Open(fileName, FileMode.Open, FileAccess.Read)
            ' Get the main document part (presentation.xml).
            For Each relationship As PackageRelationship In pptPackage.GetRelationshipsByType(relations.officedocument)
                documentUri = PackUriHelper.ResolvePartUri(New Uri("/", UriKind.Relative), relationship.TargetUri)
                documentPart = pptPackage.GetPart(documentUri)

                ' There's only one document part. Get out now.
                Exit For
            Next

            ' Manage namespaces to perform Xml XPath queries.
            Dim nt As New NameTable()
            Dim nsManager As New XmlNamespaceManager(nt)
            nsManager.AddNamespace("p", relations.mainPart)

            '  Iterate through the slides and extract the title string from each.
            Dim xDoc As New XmlDocument(nt)
            xDoc.Load(documentPart.GetStream())

            Dim sheetNodes As XmlNodeList = xDoc.SelectNodes("//p:sldIdLst/p:sldId", nsManager)
            If sheetNodes IsNot Nothing Then
                Dim relAttr As XmlAttribute = Nothing
                Dim sheetRelationship As PackageRelationship = Nothing
                Dim sheetPart As PackagePart = Nothing
                Dim sheetUri As Uri = Nothing
                Dim sheetDoc As XmlDocument = Nothing
                Dim titleNode As XmlNode = Nothing

                ' Look at each sheet node, retrieving the relationship id.
                For Each xNode As XmlNode In sheetNodes
                    relAttr = xNode.Attributes("r:id")
                    If relAttr IsNot Nothing Then
                        ' Retrieve the PackageRelationship object for the sheet:
                        sheetRelationship = documentPart.GetRelationship(relAttr.Value)
                        If sheetRelationship IsNot Nothing Then
                            sheetUri = PackUriHelper.ResolvePartUri(documentUri, sheetRelationship.TargetUri)
                            sheetPart = pptPackage.GetPart(sheetUri)
                            If sheetPart IsNot Nothing Then
                                ' You've got a reference to the sheet. Now load its contents and
                                ' find the title.
                                sheetDoc = New XmlDocument(nt)
                                sheetDoc.Load(sheetPart.GetStream())

                                titleNode = sheetDoc.SelectSingleNode("//p:sp//p:ph[@type='title' or @type='ctrTitle']", nsManager)
                                If titleNode IsNot Nothing Then
                                    titles.Add(titleNode.ParentNode.ParentNode.ParentNode.InnerText)
                                End If
                            End If
                        End If
                    End If
                Next
            End If
        End Using
        Return titles
    End Function

    Public Function GetUriByTitle(ByRef pptPackage As Package, ByVal slideTitle As String) As Uri
        ' Given a slide document and a slide title, retrieve the 0-based index of the 
        ' first slide with a matching title. Return -1 if the title isn't found.

        ' Note: This code assumes that the first text found is the title.
        ' Also note that if the title contains more than one font,
        ' or is in any way anything other than plain text, PowerPoint
        ' breaks it up into multiple elements. This code won't find a match
        ' in that case.


        Dim returnValue As Uri
        Dim documentPart As PackagePart = Nothing

        'Using pptPackage As Package = package
        ' Get the main document part (presentation.xml).
        For Each relationship As PackageRelationship In pptPackage.GetRelationshipsByType(relations.officedocument)
            Dim documentUri As Uri = PackUriHelper.ResolvePartUri(New Uri("/", UriKind.Relative), relationship.TargetUri)
            documentPart = pptPackage.GetPart(documentUri)
            ' There is only one document.
            Exit For
        Next

        ' Manage namespaces to perform Xml XPath queries.
        Dim nt As New NameTable()
        Dim nsManager As New XmlNamespaceManager(nt)
        nsManager.AddNamespace("p", relations.mainPart)
        nsManager.AddNamespace("r", relations.relationship)

        ' Get the contents of the presentation part.
        Dim presentationDoc As New XmlDocument(nt)
        presentationDoc.Load(documentPart.GetStream())

        '  Iterate through the slides and extract the title string from each.
        Dim slidePart As PackagePart = Nothing
        Dim slideUri As Uri = Nothing

        ' Select each slide document part (slides/slideX.xml)
        ' via relationship with document part.
        For Each relation As PackageRelationship In documentPart.GetRelationshipsByType(relations.slidePart)
            slideUri = PackUriHelper.ResolvePartUri(documentPart.Uri, relation.TargetUri)
            slidePart = pptPackage.GetPart(slideUri)

            ' Get the slide part from the package.
            Dim doc As XmlDocument = New XmlDocument(nt)

            ' Load the slide contents:
            doc.Load(slidePart.GetStream())

            ' Locate the slide title using XPath.
            Dim titleNode As XmlNode = doc.SelectSingleNode("//p:sp//p:ph[@type='title' or @type='ctrTitle']", nsManager)
            If titleNode IsNot Nothing Then
                ' Perform a case-insensitive comparison.
                Dim titleText As String = titleNode.ParentNode.ParentNode.ParentNode.InnerText
                If String.Compare(titleText, slideTitle, True) = 0 Then
                    ' You've found the slide part with a matching title.
                    ' Get the relationship ID, and find the corresponding item in the 
                    ' document part:
                    Dim searchString As String = String.Format("//p:sldIdLst/p:sldId[@r:id='{0}']", relation.Id)
                    Dim node As XmlNode = presentationDoc.SelectSingleNode(searchString, nsManager)
                    If node IsNot Nothing Then
                        ' Retrieve the index of the selected node.
                        ' To do that, count the number of preceding
                        ' nodes by retrieving a reference to those nodes.
                        returnValue = slidePart.Uri
                    End If

                    ' Only retrieve information about the first slide that matches the specified title.
                    Exit For
                End If
            End If
        Next
        'End Using
        Return returnValue
    End Function
    Public Function GetUriByTitle(ByVal fileName As String, ByVal slideTitle As String) As String
        ' Given a slide document and a slide title, retrieve the 0-based index of the 
        ' first slide with a matching title. Return -1 if the title isn't found.

        ' Note: This code assumes that the first text found is the title.
        ' Also note that if the title contains more than one font,
        ' or is in any way anything other than plain text, PowerPoint
        ' breaks it up into multiple elements. This code won't find a match
        ' in that case.

        Dim returnValue As String = ""
        Dim documentPart As PackagePart = Nothing

        Using pptPackage As Package = Package.Open(fileName, FileMode.Open, FileAccess.ReadWrite)
            ' Get the main document part (presentation.xml).
            GetUriByTitle(pptPackage, slideTitle)

        End Using
        Return returnValue
    End Function

End Class

 

 

Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

Word 2007 “Save As Word XML document” and back without automation – 1

Did you even had a look at new Word XML File? or … like me, you also assumed that it’s going to be same or similar to Word 2003 XML?

Yesterday … one of my fellow MSFT was  working on Packaging API to create and modify a document.

We had a quick conversation …

Manjunath Khatawkar‎‎ [11:32 PM]:
Hi Pranav.. We are storing the WordOpenXml in database and I'm trying to create a new Package from the stored WordOpenXml string.. I keep getting the "File contains corrupted data" error.. but if i open a normal .docx file it works fine..
How can I create a Package from WordOpenXml string?

‎‎Pranav Wagh‎‎ [12:06 AM]:
  can you give me a sort of code snippet ..so that I can comment on it?

 

He sent me an email -

Hi Pranav,

I’m storing the WordOpenXml (see attachment) of a Word 2007 document in database.

During document assembly, I retrieve WordOpenXml from DB save it as a xml file on harddisk. When I try to create a Package, I get the "File contains corrupted data" exception. But if I open the xml in Word 2007 and save it as a .docx file, then I’m able to create a package.

Following is the code snippet

Package wordPackage = Package.Open(fileName);

What am I doing wrong here? Do I need to create package from scratch and add individual ParakagePart by looping thro’ the Xml?

Let me know.

Thanks,

Manju

 

What !! I didn’t even understand this email till I have the super surprise in front of me, in the form of XML file that he sent me  -

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?mso-application progid="Word.Document"?>
<pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
  <pkg:part pkg:name="/_rels/.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="512">
    <pkg:xmlData>
      <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
        <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
        <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
      </Relationships>
    </pkg:xmlData>
  </pkg:part>
  <pkg:part pkg:name="/word/_rels/document.xml.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="256">
    <pkg:xmlData>
      <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Target="webSettings.xml"/>
        <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>
        <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
        <Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
        <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/>
      </Relationships>
    </pkg:xmlData>
  </pkg:part>
  <pkg:part pkg:name="/word/document.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
    <pkg:xmlData>
      <w:document xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml">
        <w:body>
          <w:p w:rsidR="00C507F1" w:rsidRDefault="000B50AA">
            <w:r>
              <w:t>ABC</w:t>
            </w:r>
          </w:p>
          <w:sectPr w:rsidR="00C507F1" w:rsidSect="00262153">
            <w:pgSz w:w="12240" w:h="15840"/>
            <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/>
            <w:cols w:space="720"/>
            <w:docGrid w:linePitch="360"/>
          </w:sectPr>
        </w:body>
      </w:document>
    </pkg:xmlData>
  </pkg:part>
  <pkg:part pkg:name="/word/theme/theme1.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.theme+xml">
    <pkg:xmlData>
      <a:theme name="Office Theme" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
        <a:themeElements>
          <a:clrScheme name="Office">
            <a:dk1>
              <a:sysClr val="windowText" lastClr="000000"/>
            </a:dk1>
            <a:lt1>
              <a:sysClr val="window" lastClr="FFFFFF"/>
            </a:lt1>
            <a:dk2>
              <a:srgbClr val="1F497D"/>