/Files/Tonyyang/报表分组页码V1.2.rar
 
Option Compare Database
Option Explicit

'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'分组报表显示分组页码和页数类模块(方法一)
'
'功    能:在有分组的报表的每一页上显示组页码和组页数,在预
'         览时改变页面设置后仍能正确显示。
'作    者:t小雨(tcl013@126.com)(t小宝)
'版    本:1.1
'创建日期:2008-05-??
'整理日期:2008-05-30
'补充说明:这个代码是一年前做的,由于实现原理和过程有点复杂,
'         当时没有添加注释,已忘得差不多,加上表达能力有限,
'         现在勉强添加了不完全的注释,但能依照说明会用就行。
'         直接把代码放到报表中也是可以。
'         做成类模块只是为了好保存,以后调用方便,但由于在
'         类模块中不能使用报表的节的事件,调用起来还是有些
'         麻烦,不过总要比直接把代码放在报表简单一点。
'
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

'实现原理:
'通过报表上的辅助文本框获得组的总行数(记录数,后同)、1页的最大行数、当前页在当前组的截止行数,
'在页面页脚_Format事件中通过计算得到分组页码和页数。

'报表设计要求:
' 1、报表应包含组页眉、页面页眉、页面页脚
' 2、在组页眉上有一文本框,有如下属性
'    ControlSource(控件来源)="=Count(*)"
'    RunningSum(运行总和)=0(不)
' 3、在主体有一文本框,有如下属性
'    ControlSource(控件来源)="=1"
'    RunningSum(运行总和)=1(工作组之上)

'调用方法,有2种:
' 第1种:
' 1、在报表用New关键字声明一个 CreateGroupPage1 类的新实例
' 2、在报表的打开事件执行实例的 Init 方法,传入全部参数
' 3、在页面页脚的 Format (格式化)事件执行实例的 FormatPageFooter 方法
' 4、在页面页脚的 Print (打印)事件执行实例的 PrintPageFooter 方法
' 这种方法在显示分组页码的标签上显示效果如 分组字段值: 1 / 2
' 在报表中的代码类似下面:

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Dim newGroupPage As New CreateGroupPage1
'
' Private Sub Report_Open(Cancel As Integer)
'     newGroupPage.Init Me, Me.TxtGrpRows, Me.txtRunSum, Me.LplGrpPages
' End Sub
'
' Private Sub 页面页脚_Format(Cancel As Integer, FormatCount As Integer)
'     newGroupPage.FormatPageFooter
' End Sub
'
' Private Sub 页面页脚_Print(Cancel As Integer, PrintCount As Integer)
'     newGroupPage.PrintPageFooter
' End Sub
'
' Private Sub 组页眉0_Format(Cancel As Integer, FormatCount As Integer)
'     newGroupPage.FormatGroupLevel1Header
' End Sub
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

' 第2种:
' 1、在报表用 WithEvents 关键字声明一个 CreateGroupPage1 类的变量
' 2、在报表的打开事件用 Set New 语句创建新实例
' 3、在报表的打开事件执行实例的 Init 方法,不须传入最后一个参数(用于显示分组页码的标签)
' 4、在页面页脚的 Format(格式化) 事件执行实例的 FormatPageFooter 方法
' 5、在页面页脚的 Print(打印) 事件执行实例的 PrintPageFooter 方法
' 6、在组页眉的 Format(格式化) 事件执行实例的 FormatGroupLevel1Header 方法
' 7、在类的 Current 事件过程将事件参数返回的分组页码和页数赋给用于显示的标签
' 在报表中的代码类似下面:

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Dim WithEvents newGroupPage As CreateGroupPage1
'
' Private Sub Report_Open(Cancel As Integer)
'     Set newGroupPage = New CreateGroupPage1
'     newGroupPage.Init Me, Me.TxtGrpRows, Me.txtRunSum
' End Sub
'
' Private Sub 页面页脚_Format(Cancel As Integer, FormatCount As Integer)
'     newGroupPage.FormatPageFooter
' End Sub
'
' Private Sub 页面页脚_Print(Cancel As Integer, PrintCount As Integer)
'     newGroupPage.PrintPageFooter
' End Sub
'
' Private Sub 组页眉0_Format(Cancel As Integer, FormatCount As Integer)
'     newGroupPage.FormatGroupLevel1Header
' End Sub
'
' Private Sub newGroupPage_Current(GrpPage As Integer, GrpPages As Integer)
'     Me.LplGrpPages.Caption = Me.类别名称 & " 共 " & GrpPages & " 页,第 " & GrpPage & " 页"
' End Sub
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Public Event Current(GrpPage As Integer, GrpPages As Integer)
'在此自定义事件中可以获取分组页码信息,以便自定义显示页码格式

Dim MyRpt As Report
Dim txtRunSum As TextBox           ' 取得每个组的记录数的文本框
Dim TxtGrpRows As TextBox          ' 取得每个组的记录在组中的序号的文本框
Dim lblShowPage As Label           ' 用于显示分组页码信息的标签

Dim inMaxRows As Integer           ' 1页的最大行数(记录数)
Dim inRptPage As Integer           ' 报表本身页码
Dim blPrint As Boolean             ' 是否已经发生页面页脚的Print事件,为避免页面页脚的Format事件中的代码重复运行
Dim blFistPage As Boolean          ' 当前页是否是所在组的第一页

Public Sub Init(rpt As Report, GrpRows As TextBox, RunSum As TextBox, Optional ShowPage As Label)
' 过程中的检查参数代码不是必须的,仅为了防止以后忘记如何设计报表

Dim st1 As String

Set MyRpt = rpt
    
    Set TxtGrpRows = GrpRows
    With TxtGrpRows
        If .Section <> acGroupLevel1Header Then
            st1 = "作为第二个参数的文本框必须在分组页眉节上!"
        ElseIf .ControlSource <> "=Count(*)" Then
            st1 = "作为第二个参数的文本框的ControlSource属性必须是""=Count(*)""!"
        ElseIf .RunningSum <> 0 Then
            st1 = "作为第二个参数的文本框的RunningSum属性必须是0!"
        End If
    End With
    If Len(st1) > 0 Then
        MsgBox st1, vbExclamation, "参数错误"
        Exit Sub
    End If
    
    Set txtRunSum = RunSum
    With txtRunSum
        If .Section <> acDetail Then
             st1 = "作为第三个参数的文本框必须在报表主体节上!"
        ElseIf .ControlSource <> "=1" Then
            st1 = "作为第三个参数的文本框的ControlSource属性必须是""=1""!"
        ElseIf .RunningSum <> 1 Then
            st1 = "作为第三个参数的文本框的RunningSum属性必须是1!"
        End If
    End With
    If Len(st1) > 0 Then
        MsgBox st1, vbExclamation, "参数错误"
        Exit Sub
    End If
    
    If Not (ShowPage Is Nothing) Then Set lblShowPage = ShowPage
   
End Sub

Public Sub FormatGroupLevel1Header()
    If txtRunSum = 1 Then blFistPage = True           ' 为页面页脚Format事件作标记
End Sub

Public Sub FormatPageFooter()

Dim inGrpPage As Integer           ' 组页码
    Dim inGrpPages As Integer          ' 组页数
    Dim inLastRows As Integer          ' 截止当前页,所在组的所有行数

inLastRows = txtRunSum                                       ' 从文本框获得截止行数
    If inLastRows = 0 Then inLastRows = TxtGrpRows
    
    If MyRpt.Page = 1 Then
    '在第1页初始变量
        If MyRpt.Pages > 0 And MyRpt.Pages = inRptPage Then
        ' 这里已经是第2轮格式化第1页,报表加载时进行两轮格式化,第一轮Pages=0
        Else
            inMaxRows = 0
        End If
        inRptPage = 0
        blPrint = False
    End If
    
    If Not blPrint Then
    '仅在第1轮格式化中,获取每组第一页的行数
        If blFistPage Then
        '每组第一页的行数即是本组任一页的最大行数
            If inMaxRows < inLastRows Then inMaxRows = inLastRows
            blFistPage = False
        End If
        inRptPage = inRptPage + 1
    End If
    
    If MyRpt.Pages > 0 Then
        inGrpPages = Int(TxtGrpRows / inMaxRows + 0.9999)         ' 组的总行数除以1页的行数,得到组的页数
        inGrpPage = Int(inLastRows / inMaxRows + 0.9999)          ' 截止当前页的累计行数除以1页的行数,得到当前页的页码
        If Not (lblShowPage Is Nothing) Then
            lblShowPage.Caption = inGrpPage & " / " & inGrpPages
        End If
        RaiseEvent Current(inGrpPage, inGrpPages)
    End If

End Sub

Public Sub PrintPageFooter()
    blPrint = True
End Sub

 
方法二:
 
Option Compare Database
Option Explicit

'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'分组报表显示分组页码和页数类模块(方法二)
'
'功    能:在有分组的报表的每一页上显示组页码和组页数,在预
'         览时改变页面设置后仍能正确显示。
'作    者:t小雨(tcl013@126.com)(t小宝)
'版    本:1.1
'创建日期:2008-05-??
'整理日期:2008-05-30
'补充说明:这个代码是一年前做的,由于实现原理和过程相当复杂,
'         当时没有添加注释,已忘得差不多,加上表达能力有限,
'         现在勉强添加了不完全的注释,但能依照说明会用就行。
'         直接把代码放到报表中也是可以。
'         做成类模块只是为了好保存,以后调用方便,但由于在
'         类模块中不能使用报表的节的事件,调用起来还是有些
'         麻烦,不过总要比直接把代码放在报表简单一点。
'
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

'实现原理:
' 报表加载后:会发生两轮从第1页到最后1页每页的格式化事件,每轮结束后发生一次打印事件,
' 在第一轮格式化事件中报表的Pages属性始终为0。最后还会移到第一页。
' 重设纸张边距、方向或大小等后也发生类似上述过程,情况相对复杂一点,就不细说了。
' 在这些事件中把页码信息保存到数组中,数组元素和报表页数一样,每个元素代表一页的信息。
' 移动页后:也会发生一次格式化事件,在这些事件中把数组中页码的信息显示出来。
' 上面所说的事件都是页面页脚的事件。

'报表设计要求:
' 很简单,有一个分组字段和页面页脚即可

'调用方法有2种:
' 第1种:
' 1、在报表用New关键字声明一个 CreateGroupPage2 类的新实例
' 2、在报表的打开事件执行实例的 Init 方法,传入报表、分组字段和用于显示分组页码的标签
' 3、在页面页脚的 Format (格式化)事件执行实例的 FormatPageFooter 方法
' 4、在页面页脚的 Print (打印)事件执行实例的 PrintPageFooter 方法
' 这种方法在显示分组页码的标签上显示效果如 分组字段值: 1 / 2
' 在报表中的代码类似下面:

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'  Dim newGroupPage As New CreateGroupPage2
'
'  Private Sub Report_Open(Cancel As Integer)
'      newGroupPage.Init Me, Me.类别ID, Me.LplGrpPages
'  End Sub
'
'  Private Sub 页面页脚_Format(Cancel As Integer, FormatCount As Integer)
'      newGroupPage.FormatPageFooter
'  End Sub
'
'  Private Sub 页面页脚_Print(Cancel As Integer, PrintCount As Integer)
'      newGroupPage.PrintPageFooter
'  End Sub
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

' 第2种:
' 1、在报表用 WithEvents 关键字声明一个 CreateGroupPage2 类的变量
' 2、在报表的打开事件用 Set New 语句创建新实例
' 3、在报表的打开事件执行实例的 Init 方法,传入报表、分组字段,不须传入用于显示分组页码的标签
' 4、在页面页脚的 Format(格式化) 事件执行实例的 FormatPageFooter 方法
' 5、在页面页脚的 Print(打印) 事件执行实例的 PrintPageFooter 方法
' 6、在类的 Current 事件过程将事件参数返回的分组页码和页数赋给用于显示的标签
' 在报表中的代码类似下面:

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'  Dim WithEvents newGroupPage As CreateGroupPage2
'
'  Private Sub Report_Open(Cancel As Integer)
'      Set newGroupPage = New CreateGroupPage2
'      newGroupPage.Init Me, Me.类别ID, Me.LplGrpPages
'  End Sub
'
'  Private Sub 页面页脚_Format(Cancel As Integer, FormatCount As Integer)
'      newGroupPage.FormatPageFooter
'  End Sub
'
'  Private Sub 页面页脚_Print(Cancel As Integer, PrintCount As Integer)
'      newGroupPage.PrintPageFooter
'  End Sub
'
'  Private Sub newGroupPage_Current(GrpPage As Integer, GrpPages As Integer)
'      Me.LplGrpPages.Caption = Me.类别名称 & " 共 " & GrpPages & " 页,第 " & GrpPage & " 页"
'  End Sub
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' 这种方法在显示分组页码的标签上显示效果是自定义的

Public Event Current(GrpPage As Integer, GrpPages As Integer)
'在此自定义事件中可以获取分组页码信息,以便自定义显示页码格式

Dim MyRpt As Report
Dim ctrGroup As Control
Dim lblShowPage As Label

Dim blPrint As Boolean            ' 是否已经发生页面页脚的Print事件,为避免页面页脚的Format事件中的代码重复运行
Dim stGroupText As String         ' 分组字段值

Dim inRptPage As Integer          ' 报表页号
Dim inGrpPage As Integer          ' 组页号

Dim ainGrpPage() As Integer       ' 保存组页号的数组,用于显示
Dim ainGrpPages() As Integer      ' 保存每个组的总页数的数组,用于显示

Dim ainGrpPageTmp() As Integer    ' 保存组页号的数组,临时
Dim ainGrpPagesTmp() As Integer   ' 保存每个组的总页数的数组,临时

Public Sub Init(rpt As Report, Group As Control, Optional ShowPage As Label)
'rpt      :报表本身,必须
'Group    :用于分组的字段,必须
'ShowPage :用于显示分组页码的标签,可选

Set MyRpt = rpt
    Set ctrGroup = Group
    If Not (ShowPage Is Nothing) Then Set lblShowPage = ShowPage

End Sub

Public Sub FormatPageFooter()

Dim inShowGrpPage As Integer           ' 显示的组页码
Dim inShowGrpPages As Integer          ' 显示的组页数
Dim i As Integer, j As Integer

If MyRpt.Page = 1 Then
' 在第1页初始变量

If inRptPage > 0 And inRptPage = MyRpt.Pages Then
    ' 报表加载后第一轮格式化完毕发生
        For j = inRptPage - inGrpPage + 1 To inRptPage   ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ainGrpPagesTmp(j) = inGrpPage                '
        Next                                             '
        ReDim ainGrpPage(1 To inRptPage)                 ' 这一段代码与后面一段代码一样,因为后面无法判断加载完成
        ReDim ainGrpPages(1 To inRptPage)                '
        For i = 1 To inRptPage                           '
            ainGrpPage(i) = ainGrpPageTmp(i)             '
            ainGrpPages(i) = ainGrpPagesTmp(i)           '
        Next                                             '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    End If
    
    inRptPage = 0
    inGrpPage = 0
    stGroupText = ""
    blPrint = False
End If

If Not blPrint Then
'仅在第一轮格式化中获取页位置,保存到临时数组
    inRptPage = inRptPage + 1
    ReDim Preserve ainGrpPageTmp(1 To inRptPage)
    ReDim Preserve ainGrpPagesTmp(1 To inRptPage)
    
    If stGroupText = ctrGroup Then                      ' 当前页与上一页在同一组
        inGrpPage = inGrpPage + 1                       ' 累计本组页数,也即获得当前页在当前组中的页码
    Else                                                ' 当前页与上一页不在同一组,换组
        For j = inRptPage - inGrpPage To inRptPage - 1  ' 循环上一组的每一页
            ainGrpPagesTmp(j) = inGrpPage               ' 每个元素都储存总页数,页在组中的最大序号即总页数
        Next
        inGrpPage = 1                                   ' 重新开始累计本组页数
        stGroupText = ctrGroup
    End If

ainGrpPageTmp(inRptPage) = inGrpPage                ' 每个元素都储存页在组中的页码
End If

If MyRpt.Page = MyRpt.Pages Then
'报表已打开后重设纸张边距大小方向等会发生
    If inRptPage = MyRpt.Pages Then
    '仅在最后一页把临时数组中的页码信息更新到用于显示页码的数组
        For j = inRptPage - inGrpPage + 1 To inRptPage
            ainGrpPagesTmp(j) = inGrpPage               ' 这个循环代码与上面有重复,因为上面无法判断最后一页
        Next
        
        ReDim ainGrpPage(1 To inRptPage)                ' 数组大小为报表页数
        ReDim ainGrpPages(1 To inRptPage)
        For i = 1 To inRptPage
            ainGrpPage(i) = ainGrpPageTmp(i)
            ainGrpPages(i) = ainGrpPagesTmp(i)
        Next
    End If
End If

On Error Resume Next

If MyRpt.Pages > 0 Then
    inShowGrpPages = ainGrpPages(MyRpt.Page)   '
    inShowGrpPage = ainGrpPage(MyRpt.Page)    '
    If Not (lblShowPage Is Nothing) Then lblShowPage.Caption = _
        ctrGroup & ": " & inShowGrpPage & " / " & inShowGrpPages
    RaiseEvent Current(inShowGrpPage, inShowGrpPages)
End If

End Sub

Public Sub PrintPageFooter()
' 区分两轮格式化
    blPrint = True
End Sub

 
 

转载于:https://www.cnblogs.com/Tonyyang/archive/2011/11/21/2256843.html

Access 报表打印之分组页码实现(轉)相关推荐

  1. access 分组序号_二级Access数据库备考笔记之报表排序和分组

    时 间:2012-08-17 12:50:26 作 者:摘 要:二级Access数据库备考笔记之报表排序和分组 正 文: 报表排序和分组 缺省情况下,报表中的记录是按照自然顺序,即数据输入的先后顺序排 ...

  2. Access报表实现记账凭证打印

    哈喽哈喽,各位Access的好爱者们,大家好呀! 今天,我们接着来讲Access的报表.之前,我们讲了一些报表的基础,包括表格样式.合计.连续打印等功能,今天,我们来讲一下非常实用的报表打印功能,凭证 ...

  3. c mysql 报表_c 数据库报表打印

    C# WinForm开发系列 - Print 收集了一些打印方面文章, 包含WinForm, Asp.Net中使用, 有结合Excel/Word, 也有直接使用报表工具打印功能, Web打印采用css ...

  4. 利用XML实现通用WEB报表打印 卢彦

    利用XML实现通用WEB报表打印(1) 卢彦 摘要 开发B/S结构的应用程序最头疼的问题可能就是报表打印了,由于只能采用浏览器来作为用户界面进行交互,所以不能精确控制客户端的打印机.而很多B/S结构的 ...

  5. PDF报表打印 -- Jasper Report

    一. PDF报表打印概述 1 概述 在企业级应用开发中,报表生成.报表打印下载是其重要的一个环节.在之前的课程中我们已经学习了报表中比较重要的一种:Excel报表.其实除了Excel报表之外,PDF报 ...

  6. 利用XML实现通用WEB报表打印(转载)

    原文地址: http://www.microsoft.com/china/community/Column/65.mspx 利用XML实现通用WEB报表打印 卢彦 方案适用性 . 1. 远程数据打印. ...

  7. 水晶报表基础入门——4.水晶报表排序、分组技术

    6.1.3  水晶报表排序.分组技术 报表数据的预设排列顺序会与数据库中的数据记录的存放顺序相同,因此会毫无规则且不会依照任何顺序来排列.Crystal Reports提供"记录排序专家&q ...

  8. 利用XML实现通用WEB报表打印(参考)

    原文地址: http://www.microsoft.com/china/community/Column/65.mspx 利用XML实现通用WEB报表打印 卢彦 方案适用性 . 1. 远程数据打印. ...

  9. php报表打印,PHPExcel 打印报表

    因工作需求,需要将前端页面显示的 table 报表打印成 Excel 文件,因为报表类型多样,好多的 td 标签存在跨行又跨列的情况,PHPExcel 作为一款 php 处理 Excel 的插件,虽然 ...

最新文章

  1. SharePoint的Reporting Service Viewer Web Part
  2. 亿级流量治理系列:常用的限流算法有哪些?
  3. nyoj 234 吃土豆
  4. 如何使用Springboot开发实现一个物业管理系统
  5. html表格全屏显示,tableView滑动全屏显示
  6. spring与junit整合测试
  7. safari浏览器横屏怎么设置_如何避免苹果safari自带浏览器“跟踪”你的信息!
  8. heidisql连接远程数据库_远程连接数据库异常问题
  9. Linux tcpdump命令实战
  10. 2台服务器只执行一台的定时任务(redisson)
  11. 敏捷DoD和DoR的多种形态
  12. Java中的范围限定词
  13. 使用Excel打造一款个人日志系统
  14. 实验吧WEB CTF 猫抓老鼠 全网最简单易懂的解题方法
  15. 指令流水线 —— 分类和多发技术
  16. 自编码实例3:卷积网络的自编码
  17. 娄底高通量测序实验室设计原则探讨
  18. MIC灵敏度, MIC动态范围下限值估计, -3dB, dB加减
  19. 【论文阅读】Cross-X Learning for Fine-Grained Visual Categorization
  20. 怎么修改照片dpi值?怎么提高照片分辨率dpi?

热门文章

  1. Leetcode 345. 反转字符串中的元音字母 解题思路及C++实现
  2. 数据结构源码笔记(C语言):索引文件建立和查找
  3. Tensor2Tensor 踩坑记录
  4. 分别用递归和非递归方式实现二叉树先序、中序和后序遍历(java实现)
  5. Set Up a Mobile Worker
  6. JavaScript toFixed(num) 函数
  7. Python+selenium 自动化 - 实现自动导入、上传外部文件实例演示
  8. HTML areamap标签及在实际开发中的应用
  9. CTFshow 反序列化 web255
  10. CTFshow php特性 web132