﻿Imports Microsoft.Office.DocumentFormat.OpenXml.Packaging
Imports System.Text
Imports System.Xml
Imports System.Xml.Linq
Imports System.IO
Imports <xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">


Module Module1
    ''' <summary>
    ''' Test Harness
    ''' </summary>
    ''' <remarks> Writes the Story onto the Console,Calls the CreateDocument Function and Displays the Word Document</remarks>
    Sub Main()
        ' each print request will have a title and we'll use
        ' this later as our file name
        Dim FileName = "Manifest.docx"

        ' Get the Story for the Main Document Part and
        ' display in Console
        Console.WriteLine(GetDocumentXML)
        ' create the word document
        If CreateDocument(FileName, GetDocumentXML) Then
            ' notify us of success
            Console.WriteLine("File Created")
            ' start the process assosiated with the filename
            Process.Start(FileName)
        Else
            ' indicate that we haven't succeeded this time
            ' well it's a start - must get the "DOT NET Gotcha's" book 
            ' so I can bubble up the error properly
            Console.WriteLine("Somethings wrong ")
        End If
        Console.ReadLine()
    End Sub

    ''' <summary>
    ''' Creates the Story
    ''' </summary>
    ''' <returns>Main Document Part's Story</returns>
    ''' <remarks></remarks>
    Private Function GetDocumentXML() As XDocument

        Dim Printout = <Print Title="Manifest">
                           <Sections>
                               <Section Type="Text" Style="Title">Stores Delivery Manifest</Section>
                               <Section Type="LineBreak"/>
                               <Section Type="Table" MinimumNoRows="10" Style="MediumGrid3-Accent1"
                                   HeaderRow="Y" TotalRow="Y"
                                   sqlQuery="Select .... from ..... where ..... 
                                                  Group by .... order by ......
								                  for xml raw ,type ,Root ('Rows')">
                                   <Columns>
                                       <Column Caption="Cd" Width="650"/>
                                       <Column Caption="Name" Width="3300"/>
                                       <Column Caption="Ctns" Width="1050" SubTotal="Y"/>
                                       <Column Caption="Units" Width="1050" SubTotal="Y"/>
                                       <Column Caption="Advice No" Width="1450"/>
                                       <Column Caption="Comments" Width="1600"/>
                                   </Columns>
                               </Section>
                           </Sections>
                       </Print>

        'set up the main Xelement of the Document
        Dim docXML = <w:body></w:body>

        ' set up an Xelement container
        Dim Xel As XElement
        'iterate thru' the sections

        For Each section In Printout.<Sections>.Elements
            ' what's the type ?
            Dim SectionType = section.@Type
            Select SectionType
                Case "Text"
                    Xel = <w:p>
                              <w:pPr><w:pStyle w:val=<%= section.@Style %>/></w:pPr>
                              <w:r><w:t><%= section.Value.ToString %></w:t></w:r>
                          </w:p>

                Case "LineBreak"
                    Xel = <w:p/>

                Case "Table"
                    ' Table data will be retrieved as xml from the data store using the query contained in sqlQuery 
                    Dim GridData = <Rows>
                                       <row C1="129" C2="SWAN CENTRE" C3="3" C4="420" C5="57437-129" C6=""/>
                                       <row C1="33" C2="BLANCHARDSTOWN" C3="1" C4="126" C5="57437-33" C6=""/>
                                       <row C1="63" C2="NORTH EARL STREET" C3="2" C4="256" C5="57437-63" C6=""/>
                                   </Rows>
                    ' The number of Rows .....
                    Dim Rows = GridData...<row>.Count
                    Dim MinimumNoRows = CInt(section.@MinimumNoRows)
                    Dim BlankRows As New List(Of Int16)
                    If Rows < MinimumNoRows Then
                        For r As Int16 = Rows + 1 To MinimumNoRows
                            BlankRows.Add(r)
                        Next
                    End If

                    ' Define format for Blank cells
                    Dim Cells = From column In section.<Columns>.Elements _
                                           Select <w:tc><w:p/></w:tc>

                    ' allow row banding conditional formatting only
                    Dim tableLook = "0" + CStr(400 - (section.@HeaderRow = "Y") * 20 - (section.@TotalRow = "Y") * 40)

                    ' do we need to add subtotals to the table 
                    Dim TotalRow = <w:p/>
                    If section.@TotalRow = "Y" Then
                        TotalRow = <w:tr/>
                        With TotalRow
                            Dim ij = 0
                            For Each column In section.<Columns>.Elements
                                ij += 1
                                If column.@SubTotal = "Y" Then
                                    .Add(<w:tc><w:p><w:r><w:t>
                                             <%= Aggregate item In GridData...<row> _
                                                 Into Sum(CDbl(item.Attribute("C" + CStr(ij)))) %>
                                             </w:t></w:r></w:p></w:tc>)
                                Else
                                    .Add(<w:tc><w:p/></w:tc>)
                                End If
                            Next
                            .Add(<w:p/>)
                        End With
                    End If


                    Xel = <w:tbl>
                              <w:tblPr>
                                  <w:tblStyle w:val=<%= section.@Style %>/>
                                  <w:tblW w:w="0" w:type="auto"/>
                                  <w:tblLayout w:type="fixed"/>
                                  <w:tblLook w:val=<%= tableLook %>/>
                              </w:tblPr>

                              <!-- Set up Column Widths -->
                              <w:tblGrid>
                                  <%= From column In section.<Columns>.Elements() _
                                      Select <w:gridCol w:w=<%= column.@Width %>/> %>
                              </w:tblGrid>

                              <!-- Set up Table Header Row -->
                              <w:tr>
                                  <%= From column In section.<Columns>.Elements() _
                                      Select <w:tc><w:p><w:r><w:t><%= column.@Caption %></w:t></w:r></w:p></w:tc> %>
                              </w:tr>

                              <!-- Now Write out the Row Data -->
                              <%= From r In GridData...<row> _
                                  Select <w:tr>
                                             <%= From a In r.Attributes() _
                                                 Select _
                                                 <w:tc><%= IIf(a.Value = "", <w:p/>, <w:p><w:r><w:t><%= a.Value %></w:t></w:r></w:p>) %></w:tc> %>
                                         </w:tr> %>

                              <!-- Make sure you have at least MinimumNoRows  -->
                              <%= From row In BlankRows _
                                  Select <w:tr>
                                             <%= Cells %>
                                         </w:tr> %>
                              <!-- Are there totals to Display -->
                              <%= TotalRow %>

                          </w:tbl>

                Case Else
                    Xel = <w:p/>
            End Select
            ' add Xelement to body of document
            docXML.Add(Xel)
        Next

        'Now create the XDocument
        Dim documentxml = _
        <?xml version="1.0" encoding="utf-8"?>
        <w:document xmlns:o="urn:schemas-microsoft-com:office:office"
            xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
            xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
            <%= docXML %>

        </w:document>

        Return documentxml
    End Function

    ''' <summary>
    ''' Creates a Word Document complete with referenced Style and Theme files
    ''' </summary>
    ''' <param name="FileName" >Filename to create</param>
    ''' <param name="DocumentXML">XML file containing the main story to print</param>
    ''' <returns>Success or Failure Boolean Value</returns>
    ''' <remarks></remarks>
    Public Function CreateDocument(ByRef FileName As String, _
                                   ByVal DocumentXML As XDocument) As Boolean
        Dim Dir = My.Computer.FileSystem.SpecialDirectories.MyDocuments + "\"
        Dim StyleFile = Dir + "styles.xml"
        Dim ThemeFile = Dir + "Theme1.xml"
        FileName = Dir + FileName
        Try
            ' Create the package
            Dim wordDoc = WordprocessingDocument.Create(FileName, _
                                        WordprocessingDocumentType.Document)
            Using (wordDoc)
                Dim mainPart = wordDoc.AddMainDocumentPart
                Dim stream = mainPart.GetStream
                Dim utf8encoder1 = New UTF8Encoding()
                Dim buf() = utf8encoder1.GetBytes(DocumentXML.ToString)
                stream.Write(buf, 0, buf.Length)

                Dim themepart = mainPart.AddNewPart(Of ThemePart)()
                stream = New FileStream(ThemeFile, FileMode.Open)
                themepart.FeedData(stream)

                Dim stylepart = mainPart.AddNewPart(Of StyleDefinitionsPart)()
                stream = New FileStream(StyleFile, FileMode.Open)
                stylepart.FeedData(stream)
            End Using
        Catch ex As Exception
            Return 0
        End Try
        Return -1
    End Function

End Module
