使用Word为LightSwitch(或Sliverlight)创建主从报表


[原文发表地址]  Using
Word to Create Master-Detail Reports for LightSwitch (or Silverlight)

[原文发表时间] 2011-06-08 08:04 AM

前阵子公布的一个帖子:如何通过传递一个实体(entity, 如Customer)及使用Word Content 控件来使用Word 为LightSwitch创建简易的报表,在模板中布局内容并把它们绑定到文档中的XML。如果你错过了,这儿有:使用Microsoft Word来为LightSwitch(或Silverlight)创建报表

在那个帖子的评论当中,有人询问如何创建主从报表,比如一个Order及OrderDetails。在我的上一个帖子中,我发布了一个示例展示了一个实现的一个方法。该代码是一个更大的LightSwitch示例应用程序的一部分:Contoso Construction - LightSwitch Advanced Development Sample。在那个示例中我使用了和上述参考的帖子中同样的技术,来向客户端工程中添加一个helper类及Word文档模板,并把XML捆绑于内容控件。与实现主从格式化的唯一区别在于内容控件的布局和用于生成XML的代码。

在Contoso Construction示例中,我们有一个 父“Project”表:它有许多“ProjectMaterials”。如果你打开那个project屏幕,你就会在顶部看到一个按钮,这个按钮允许你生成一个project状态报表:它显示来自Customer,,Project及所有在construction project上使用的ProjectMaterials的域。

image

Project与ProjectMaterials是一对多的关系,因此我们可以有一或多行的materials可以显示。做到这一点的一个方法是布置一个单一的内容控件,它包含很多行,像这样:

image

因此在这种情况下,我有四个内容控件,它们代表我想要显示的ProjectMaterial表的4个域。然后当生成XML时所有你需要做的就是遍历子集合并把换行符插入其中。你可以轻松地使用Join方法来做这个,它接受一个数组,并创建一个具有你指定的分隔符的内容的字符串表示形式,对于我的话我使用的是回车符 返回 (vbCr)。因此在MyReportHelper类中,我们有诸如这样的代码,注意我是如何生成<projectmaterials>节点的:

Public Shared Sub RunProjectStatusReport(ByVal project As Project)
    If AutomationFactory.IsAvailable Then
        Try

           'Create the XML data from our entity properties.
            ' Project materials content controls on the Word template are set to allow carriage
            ' returns so we can easily display as many line items as we need
                    '
            Dim myXML = <customer>
                <fullname><%= project.Customer.FullName %></fullname>
                <homephone><%= project.Customer.HomePhone %></homephone>
                <mobilephone><%= project.Customer.MobilePhone %></mobilephone>
                <email><%= project.Customer.Email %></email>
                <fulladdress><%= project.Customer.FullAddress %></fulladdress>
                    <project>
                        <projectname><%= project.ProjectName %></projectname>
                        <startdate><%= project.StartDate.ToShortDateString %></startdate>
                        <estimatedenddate><%= project.EstmatedEndDate.ToShortDateString %></estimatedenddate>
                        <originalestimate><%= Format(project.OriginalEstimate, "c2") %></originalestimate>
                        <labor><%= Format(project.Labor, "c2") %></labor>
                        <totalcost><%= Format(project.TotalCost, "c2") %></totalcost>
                        <notes><%= project.Notes %></notes>
                        <projectmaterials>
                            <summary><%= Join((From m In project.ProjectMaterials
                             Select m.Summary).ToArray, vbCr) %></summary>
                            <quantity><%= Join((From m In project.ProjectMaterials
                             Select CStr(m.Quantity)).ToArray, vbCr) %></quantity>
                            <price><%= Join((From m In project.ProjectMaterials
                             Select Format(m.Price, "c2")).ToArray, vbCr) %></price>
                            <itemtotal><%= Join((From m In project.ProjectMaterials
                             Select Format(m.ItemTotal, "c2")).ToArray, vbCr) %></itemtotal>
                         </projectmaterials>
                      </project>
                  </customer>

          Using word = AutomationFactory.CreateObject("Word.Application")
           'The report template already has content controls bound to XML inside.
            ' Look in the ClientGenerated project to view the Word template.
            Dim resourceInfo = System.Windows.Application.GetResourceStream(                               New Uri("ProjectStatus.docx", UriKind.Relative))
            Dim fileName = CopyStreamToTempFile(resourceInfo.Stream, ".docx")

            Dim doc = word.Documents.Open(fileName)
            'Grab the existing bound custom XML in the doc
            Dim customXMLPart = doc.CustomXMLParts("urn:microsoft:contoso:projectstatus")

            Dim all = customXMLPart.SelectSingleNode("//*")
            Dim replaceNode = customXMLPart.SelectSingleNode("/ns0:root[1]/customer[1]")

           'replace the <customer> node in the existing custom XML with this new data
            all.ReplaceChildSubtree(myXML.ToString, replaceNode)

            word.Visible = True

          End Using
        Catch ex As Exception
          Throw New InvalidOperationException("Failed to create project status report.", ex)
        End Try
    End If
End Sub

希望这会有所帮助。有关如何创建Word模板,把它们绑定到XML以及如何创建MyReportHelper 类 的更多细节,请阅读使用Microsoft Word为LightSwitch(或Silverlight)创建报表

用得开心!

Comments (0)

Skip to main content