使用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)创建报表

用得开心!