[续]基于XML的WEB系统报表精确打印实现

来源:互联网 发布:软妹服装淘宝店铺 编辑:程序博客网 时间:2024/05/16 10:31

[续]基于XML的WEB系统报表精确打印实现

前一段时间写了篇《Web嵌入.net打印控件》http://www.blog.163.com/yixiao.he/blog/static/3889872005105846190/

但因这半年在做一WIN项目,所以一直未完善,近来又做一WEB项目,所以将该打印控件进行了完善。

 

一、WEB表单页面中XML传递

由于并非所有用户都需要进行预览和打印,所以打印控件最好不放在表单页面,在需要打印时,在表单页面生成需要打印的XML文档,通过session传给 reports/printbill.aspx文件,该文件再根据打印模式 printmode 属性的设置进行相应的操作。也就是说,整个项目打印全部都用printbill.aspx文件进行打印

二、控件与页面之间的XML传递

   有几种方法,有些可行,有些有问题,有些不可行!

  (一) 页面生成一个xml文件,随机或按用户名命名,形一个文件放在WEB服务器上,然后将文件名传给打印控件,打印控件根据传过来的参数取到要打印的XML文件路径,如http://localhost/tdxd/reports/temp/1.xml

但这种办法存在一个问题是形成的xml文件会越来越多,没有合适的方法去删除这些文件,而且读写文件,效率可能会低一些。

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Try
            doc.Load(strXml)  'strXML为从页面传来的参数
            Me.Label1.Text = "OK"
        Catch ex As Exception
            Me.Label1.Text = "Error"
        End Try
    End Sub

  (二) 通过WebServices来传递数据。

       这样做法的好处是将所以打印的程序,如打开XML模板,并根据要打印的数据形成最终打印XML,都放在一个WEBServices的函数里来处理,这样系统会更清晰。

      但WEB引用在需要改变时,需要把XML引用的URL行为改为动态

系统会自动加一个 app.config文件

<appSettings><add key="WinCtlLib.wsPrint.WSPrint" value="http://localhost/tdxd/WebServices/WSPrint.asmx"/></appSettings>

在使用单独的WEB项目或WIN项目时,这种方案都是比较好的,但现在是将WIN控件嵌入到WEB页面中,没有app.config文件,所以更改WebServices路径后会出错

 

        Try

            Dim ws As New wsPrint.WSPrint
            doc.LoadXml(ws.PrintXmlDoc(sXmlName, sTableName, sRecNo))
            Me.Label1.Text = "OK"
        Catch ex As Exception
            Me.Label1.Text = "Error" & ex.Message
        End Try
(三)

  即本文开始说的方法,通过SESSION将待打印的XML文件传给printBill.aspx  该文件再将该XML传给控件

<OBJECT style="WIDTH: 480px; HEIGHT: 160px" classid="http:WinCtlLib.dll#WinCtlLib.ctlXmlPrint"
 VIEWASTEXT>
 <PARAM VALUE="<%=sXml%>">
</OBJECT>

 

控件代码

Imports System.Xml
Imports WinCtlLib.Hot.Print.RemotePrint
Imports System.Drawing.Printing
Public Class ctlXmlPrint
    Inherits System.Windows.Forms.UserControl

#Region " Windows 窗体设计器生成的代码 "

    Public Sub New()
        MyBase.New()

        '该调用是 Windows 窗体设计器所必需的。
        InitializeComponent()

        '在 InitializeComponent() 调用之后添加任何初始化
        AddHandler PrintDocument1.PrintPage, AddressOf pd_PrintPage

    End Sub

    'UserControl1 重写 dispose 以清理组件列表。
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Windows 窗体设计器所必需的
    Private components As System.ComponentModel.IContainer

    '注意: 以下过程是 Windows 窗体设计器所必需的
    '可以使用 Windows 窗体设计器修改此过程。
    '不要使用代码编辑器修改它。
    Friend WithEvents PageSetupDialog1 As System.Windows.Forms.PageSetupDialog
    Friend WithEvents PrintDocument1 As System.Drawing.Printing.PrintDocument
    Friend WithEvents PrintPreviewDialog1 As System.Windows.Forms.PrintPreviewDialog
    Friend WithEvents btnShowXml As System.Windows.Forms.Button
    Friend WithEvents lblMsg As System.Windows.Forms.Label
    Friend WithEvents btnPreview As System.Windows.Forms.Button
    Friend WithEvents btnPrint As System.Windows.Forms.Button
    Friend WithEvents btnPageSetting As System.Windows.Forms.Button
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(ctlXmlPrint))
        Me.PageSetupDialog1 = New System.Windows.Forms.PageSetupDialog
        Me.PrintDocument1 = New System.Drawing.Printing.PrintDocument
        Me.PrintPreviewDialog1 = New System.Windows.Forms.PrintPreviewDialog
        Me.lblMsg = New System.Windows.Forms.Label
        Me.btnShowXml = New System.Windows.Forms.Button
        Me.btnPreview = New System.Windows.Forms.Button
        Me.btnPrint = New System.Windows.Forms.Button
        Me.btnPageSetting = New System.Windows.Forms.Button
        Me.SuspendLayout()
        '
        'PageSetupDialog1
        '
        Me.PageSetupDialog1.Document = Me.PrintDocument1
        '
        'PrintPreviewDialog1
        '
        Me.PrintPreviewDialog1.AutoScrollMargin = New System.Drawing.Size(0, 0)
        Me.PrintPreviewDialog1.AutoScrollMinSize = New System.Drawing.Size(0, 0)
        Me.PrintPreviewDialog1.ClientSize = New System.Drawing.Size(400, 300)
        Me.PrintPreviewDialog1.Document = Me.PrintDocument1
        Me.PrintPreviewDialog1.Enabled = True
        Me.PrintPreviewDialog1.Icon = CType(resources.GetObject("PrintPreviewDialog1.Icon"), System.Drawing.Icon)
        Me.PrintPreviewDialog1.Location = New System.Drawing.Point(290, 17)
        Me.PrintPreviewDialog1.MinimumSize = New System.Drawing.Size(375, 250)
        Me.PrintPreviewDialog1.Name = "PrintPreviewDialog1"
        Me.PrintPreviewDialog1.TransparencyKey = System.Drawing.Color.Empty
        Me.PrintPreviewDialog1.Visible = False
        '
        'lblMsg
        '
        Me.lblMsg.Location = New System.Drawing.Point(0, 25)
        Me.lblMsg.Name = "lblMsg"
        Me.lblMsg.Size = New System.Drawing.Size(296, 12)
        Me.lblMsg.TabIndex = 0
        Me.lblMsg.Text = "测试"
        '
        'btnShowXml
        '
        Me.btnShowXml.BackColor = System.Drawing.Color.Azure
        Me.btnShowXml.FlatStyle = System.Windows.Forms.FlatStyle.Flat
        Me.btnShowXml.Location = New System.Drawing.Point(0, 0)
        Me.btnShowXml.Name = "btnShowXml"
        Me.btnShowXml.TabIndex = 6
        Me.btnShowXml.Text = "显示Xml"
        Me.btnShowXml.TextAlign = System.Drawing.ContentAlignment.TopCenter
        '
        'btnPreview
        '
        Me.btnPreview.BackColor = System.Drawing.Color.Azure
        Me.btnPreview.FlatStyle = System.Windows.Forms.FlatStyle.Flat
        Me.btnPreview.Location = New System.Drawing.Point(75, 0)
        Me.btnPreview.Name = "btnPreview"
        Me.btnPreview.TabIndex = 7
        Me.btnPreview.Text = "预览"
        Me.btnPreview.TextAlign = System.Drawing.ContentAlignment.TopCenter
        '
        'btnPrint
        '
        Me.btnPrint.BackColor = System.Drawing.Color.Azure
        Me.btnPrint.FlatStyle = System.Windows.Forms.FlatStyle.Flat
        Me.btnPrint.Location = New System.Drawing.Point(150, 0)
        Me.btnPrint.Name = "btnPrint"
        Me.btnPrint.TabIndex = 8
        Me.btnPrint.Text = "打印"
        Me.btnPrint.TextAlign = System.Drawing.ContentAlignment.TopCenter
        '
        'btnPageSetting
        '
        Me.btnPageSetting.BackColor = System.Drawing.Color.Azure
        Me.btnPageSetting.FlatStyle = System.Windows.Forms.FlatStyle.Flat
        Me.btnPageSetting.Location = New System.Drawing.Point(225, 0)
        Me.btnPageSetting.Name = "btnPageSetting"
        Me.btnPageSetting.TabIndex = 9
        Me.btnPageSetting.Text = "页面设置"
        Me.btnPageSetting.TextAlign = System.Drawing.ContentAlignment.TopCenter
        '
        'ctlXmlPrint
        '
        Me.BackColor = System.Drawing.SystemColors.Window
        Me.Controls.Add(Me.btnPageSetting)
        Me.Controls.Add(Me.btnPrint)
        Me.Controls.Add(Me.btnPreview)
        Me.Controls.Add(Me.btnShowXml)
        Me.Controls.Add(Me.lblMsg)
        Me.Name = "ctlXmlPrint"
        Me.Size = New System.Drawing.Size(302, 40)
        Me.ResumeLayout(False)

    End Sub

#End Region
    Private doc As New XmlDocument
    Public Shared Pages As Integer = 1

#Region "    属性定义    "
    '要打印的XML文档
    Dim _sXml As String
    Public Property sXml() As String
        Get
            Return _sXml
        End Get
        Set(ByVal Value As String)
            _sXml = Value
        End Set
    End Property

    Enum emPrintMode
        预览 = 1
        打印 = 2
        页面设置 = 3
    End Enum

    '打印模式
    Dim _PrintMode As emPrintMode
    Property PrintMode() As emPrintMode
        Get
            Return _PrintMode
        End Get
        Set(ByVal Value As emPrintMode)
            _PrintMode = Value
        End Set
    End Property
#End Region

#Region "    函数定义    "
    '预览
    Public Function PrintPreview()
        Try
            Call SettingPrinter(doc("root")("pagesetting"))
            Me.PrintPreviewDialog1.ShowDialog()
            Me.lblMsg.Text = "预览完成"
        Catch ex As Exception
            Me.lblMsg.Text = "预览失败:" & ex.Message
        End Try

    End Function
    '打印
    Public Function Print()
        Try
            Call SettingPrinter(doc("root")("pagesetting"))
            Me.PrintDocument1.Print()
            Me.lblMsg.Text = "打印完成"
        Catch ex As Exception
            Me.lblMsg.Text = "打印失败:" & ex.Message
        End Try
    End Function
    '页面设置
    Public Function PrintSetting()
        Try
            Me.PageSetupDialog1.ShowDialog()
            Me.lblMsg.Text = "已打开页面设置"
        Catch ex As Exception
            Me.lblMsg.Text = "开页面设置打开失败:" & ex.Message
        End Try

    End Function
    '根据 PrintMode 设置 自动调用相应函数
    Public Function PirntAuto()
        Select Case Me.PrintMode
            Case emPrintMode.预览
                Call Me.PrintPreview()
            Case emPrintMode.打印
                Call Me.Print()
            Case emPrintMode.页面设置
                Call Me.PrintSetting()
        End Select
    End Function
#End Region

#Region "    打印函数     "
    Private Sub pd_PrintPage(ByVal sender As Object, ByVal ev As PrintPageEventArgs)
        Dim g As Graphics = ev.Graphics
        Dim HasMorePages As Boolean = False
        Dim printElement As PrintElement = Nothing

        Dim node As XmlNode
        For Each node In doc("root")("reporttable").ChildNodes
            printElement = Parser.CreateElement(node) '调用解析器生成相应的对象

            Try
                HasMorePages = printElement.Draw(g) '是否需要分页
            Catch ex As Exception
                Me.lblMsg.Text = ex.Message
            End Try
        Next node

        '在页底中间输出页码
        Dim font As New Font("黑体", 12.0F)
        Dim brush = New SolidBrush(Color.Black)
        g.DrawString("第 " + Pages.ToString() + " 页", font, brush, ev.MarginBounds.Width / 2 + ev.MarginBounds.Left - 30, ev.PageBounds.Height - 60)

        If HasMorePages Then
            Pages += 1
        End If
        ev.HasMorePages = HasMorePages
    End Sub 'pd_PrintPage

    Private Sub SettingPrinter(ByVal ps As XmlNode)
        '打印方向(纵/横)
        Me.PrintDocument1.DefaultPageSettings.Landscape = Boolean.Parse(ps("landscape").InnerText)
        '设置纸张类型
        Dim papername As String = ps("paperkind").InnerText
        Dim fitpaper As Boolean = False
        '获取打印机支持的所有纸张类型
        Dim size As PaperSize
        For Each size In Me.PrintDocument1.PrinterSettings.PaperSizes
            If papername = size.PaperName Then '看该打印机是否有我们需要的纸张类型
                Me.PrintDocument1.DefaultPageSettings.PaperSize = size
                fitpaper = True
            End If
        Next size
        If Not fitpaper Then
            '假如没有我们需要的标准类型,则使用自定义的尺寸
            Me.PrintDocument1.DefaultPageSettings.PaperSize = New PaperSize("Custom", Integer.Parse(ps("paperwidth").InnerText), Integer.Parse(ps("paperheight").InnerText))
        End If

        '设置页边距
        Me.PrintDocument1.DefaultPageSettings.Margins.Left = Integer.Parse(ps("pageleft").InnerText)
        Me.PrintDocument1.DefaultPageSettings.Margins.Top = Integer.Parse(ps("pagetop").InnerText)
        Me.PrintDocument1.DefaultPageSettings.Margins.Right = Integer.Parse(ps("pageright").InnerText)
        Me.PrintDocument1.DefaultPageSettings.Margins.Bottom = Integer.Parse(ps("pagebottom").InnerText)
    End Sub 'SettingPrinter
#End Region


    Private Sub btnShowXml_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShowXml.Click
        MsgBox(doc.OuterXml.ToString.Replace("""", "'"))
        System.Windows.Forms.Clipboard.SetDataObject(doc.OuterXml.ToString.Replace("""", "'"))
    End Sub

    Private Sub btnPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPreview.Click
        Call Me.PrintPreview()
    End Sub

    Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click
        Call Me.Print()
    End Sub

    Private Sub btnPageSetting_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPageSetting.Click
        Call Me.PrintSetting()
    End Sub

    Private Sub ctlXmlPrint_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            doc.LoadXml(sXml)
            Me.lblMsg.Text = "数据加载完成"
        Catch ex As Exception
            Me.lblMsg.Text = "数据加载失败:" & ex.Message
        End Try
    End Sub