EXCEL根据类别分页预览或者直接生成PDF

vbscript 复制代码
Sub PrintByCategoryWithOptions_SilentMode()
    Dim ws As Worksheet
    Dim dict As Object
    Dim key As Variant
    Dim lastRow As Long, i As Long
    Dim categoryColumn As Long
    Dim counter As Long
    Dim response As VbMsgBoxResult
    Dim outputMode As String
    Dim savePath As String
    Dim pdfFileName As String
    
    ' *************** 用户可修改参数 ***************
    Set ws = ThisWorkbook.Sheets("退款明细")  ' 工作表名
    categoryColumn = 3                        ' 分类列号(C列=3)
    Const titleRows As Long = 4               ' 标题行数(1-4行)
    Const lastCol As String = "J"             ' 最后一列字母
    ' *********************************************
    
    lastRow = ws.Cells(ws.Rows.Count, categoryColumn).End(xlUp).Row
    
    ' 创建字典存储分类信息
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 扫描所有分类并记录行范围
    Dim currentCategory As String
    Dim startRow As Long, endRow As Long
    Dim isNewCategory As Boolean
    
    startRow = titleRows + 1
    currentCategory = CStr(ws.Cells(startRow, categoryColumn).Value)
    
    For i = startRow To lastRow
        isNewCategory = (CStr(ws.Cells(i, categoryColumn).Value) <> currentCategory)
        
        If isNewCategory Or i = lastRow Then
            endRow = IIf(i = lastRow And Not isNewCategory, i, i - 1)
            
            If Not dict.Exists(currentCategory) And currentCategory <> "" Then
                dict.Add currentCategory, Array(startRow, endRow)
            End If
            
            If isNewCategory Then
                currentCategory = CStr(ws.Cells(i, categoryColumn).Value)
                startRow = i
            End If
        End If
    Next i
    
    ' 增强的输出模式选择
    response = Application.InputBox( _
        "请选择操作方式:" & vbCrLf & vbCrLf & _
        "1 - 打印预览(逐个查看)" & vbCrLf & _
        "2 - 生成PDF(逐个提示)" & vbCrLf & _
        "3 - 批量生成PDF(无提示)" & vbCrLf & vbCrLf & _
        "请输入数字选项 (1-3):", _
        "输出模式选择", "3", Type:=1)
    
    ' 处理用户选择
    If response = False Then Exit Sub  ' 用户取消
    
    Select Case response
        Case 1: outputMode = "PREVIEW"
        Case 2: outputMode = "PDF_PROMPT"
        Case 3: outputMode = "PDF_SILENT"
        Case Else
            MsgBox "无效选项,操作已取消", vbExclamation
            Exit Sub
    End Select
    
    ' PDF模式获取保存路径
    If outputMode Like "PDF*" Then
        savePath = BrowseForFolder("选择PDF保存位置")
        If savePath = "" Then Exit Sub
    End If
    
    ' 关闭屏幕更新加快速度
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.DisplayAlerts = False
    
    ' 备份原始设置
    Dim originalPrintArea As String
    originalPrintArea = ws.PageSetup.PrintArea
    
    ' 记录开始时间
    Dim startTime As Double
    startTime = Timer
    
    ' 按顺序处理每个分类
    Dim categories() As Variant
    categories = dict.keys
    
    For counter = 0 To dict.Count - 1
        key = categories(counter)
        Dim rowRange() As Variant
        rowRange = dict(key)
        startRow = rowRange(0)
        endRow = rowRange(1)
        
        ' 计算打印区域
        Dim printArea As String
        printArea = "$A$1:$" & lastCol & "$" & endRow
        
        ' 隐藏非当前分类的行
        HideNonCurrentRows ws, startRow, endRow, titleRows, lastRow
        
        ' 设置打印区域
        ws.PageSetup.PrintArea = printArea
        
        ' 根据模式执行操作
        Select Case outputMode
            Case "PREVIEW"
                ' 预览前提示信息
                Dim previewMsg As String
                previewMsg = "正在预览类别: " & key & vbCrLf & _
                             "(" & (counter + 1) & "/" & dict.Count & ")" & vbCrLf & _
                             "数据行范围: " & startRow & " - " & endRow & vbCrLf & _
                             "打印区域: A1:" & lastCol & endRow
                
                MsgBox previewMsg, vbInformation, "准备预览"
                ws.PrintPreview
                
                ' 预览后询问
                If MsgBox("类别: " & key & " 预览完成" & vbCrLf & _
                          "是否继续下一个类别?", vbYesNo + vbQuestion) = vbNo Then Exit For
                
            Case "PDF_PROMPT"
                ' 生成前提示信息
                Dim pdfMsg As String
                pdfMsg = "正在生成: " & key & vbCrLf & _
                         "(" & (counter + 1) & "/" & dict.Count & ")" & vbCrLf & _
                         "数据行范围: " & startRow & " - " & endRow
                
                MsgBox pdfMsg, vbInformation, "PDF生成中"
                
                ' 生成PDF文件
                pdfFileName = CleanFileName(key & "") & ".pdf"
                ws.ExportAsFixedFormat _
                    Type:=xlTypePDF, _
                    Filename:=savePath & pdfFileName, _
                    Quality:=xlQualityStandard, _
                    IncludeDocProperties:=True, _
                    IgnorePrintAreas:=False
                
            Case "PDF_SILENT"
                ' 静默模式 - 仅更新状态栏
                Application.StatusBar = "正在批量生成PDF (" & (counter + 1) & "/" & dict.Count & "): " & key
                
                ' 生成PDF文件
                pdfFileName = CleanFileName(key & "") & ".pdf"
                ws.ExportAsFixedFormat _
                    Type:=xlTypePDF, _
                    Filename:=savePath & pdfFileName, _
                    Quality:=xlQualityStandard, _
                    IncludeDocProperties:=True, _
                    IgnorePrintAreas:=False
        End Select
        
        ' 恢复所有行的可见性
        ws.Rows.Hidden = False
    Next counter
    
    ' 计算耗时
    Dim elapsedTime As Double
    elapsedTime = Round(Timer - startTime, 2)
    
    ' 恢复原始设置
    ws.PageSetup.PrintArea = originalPrintArea
    ws.Rows.Hidden = False
    Application.StatusBar = False
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.DisplayAlerts = True
    
    ' 完成提示
    Dim msg As String
    msg = "操作完成!" & vbCrLf & "共处理 " & dict.Count & " 个类别" & vbCrLf & _
          "耗时: " & elapsedTime & " 秒"
    
    If outputMode Like "PDF*" Then
        msg = msg & vbCrLf & "PDF保存到: " & savePath
        
        ' 完成后打开保存文件夹
        If MsgBox(msg & vbCrLf & vbCrLf & "是否打开保存文件夹?", vbQuestion + vbYesNo, "操作完成") = vbYes Then
            Shell "explorer.exe """ & savePath & """", vbNormalFocus
        End If
    Else
        MsgBox msg, vbInformation, "报告"
    End If
End Sub

' 辅助函数:隐藏非当前分类的行
Sub HideNonCurrentRows(ws As Worksheet, startRow As Long, endRow As Long, titleRows As Long, lastRow As Long)
    ws.Rows.Hidden = False
    If titleRows + 1 < startRow Then
        ws.Rows(titleRows + 1 & ":" & startRow - 1).Hidden = True
    End If
    If endRow < lastRow Then
        ws.Rows(endRow + 1 & ":" & lastRow).Hidden = True
    End If
End Sub

Function CleanFileName(str As String) As String
    Dim illegalChars As String
    illegalChars = "\/:*?""<>|"
    CleanFileName = str
    For i = 1 To Len(illegalChars)
        CleanFileName = Replace(CleanFileName, Mid(illegalChars, i, 1), "_")
    Next i
End Function

Function BrowseForFolder(title As String) As String
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = title
        If .Show <> -1 Then Exit Function
        BrowseForFolder = .SelectedItems(1)
        If Right(BrowseForFolder, 1) <> "\" Then BrowseForFolder = BrowseForFolder & "\"
    End With
End Function

使用方法:运行宏,粘贴代码。

请选择操作方式:

1 - 打印预览(逐个查看)

2 - 生成PDF(逐个提示)

3 - 批量生成PDF(无提示)

请输入数字选项 (1-3):

优势:

  1. 高效处理

    • 静默模式下可一次性处理数百个分类
    • 无需人工干预,适合批量操作
  2. 灵活选择

    • 根据需求选择不同详细程度的模式
    • 调试时用预览模式,日常操作用静默模式
  3. 用户体验

    • 完成后可直接打开保存文件夹
    • 显示处理时间便于性能评估
    • 状态栏进度反馈让用户了解运行状态
相关推荐
l1t2 小时前
在duckdb 1.4中编译和使用postgresql协议插件duckdb-pgwire
开发语言·数据库·c++·postgresql·插件·duckdb
武子康2 小时前
Java-138 深入浅出 MySQL Spring Boot 事务传播机制全解析:从 REQUIRED 到 NESTED 的实战详解 传播机制原理
java·大数据·数据库·spring boot·sql·mysql·事务
snpgroupcn3 小时前
SAP S/4HANA迁移方法选哪种?选择性数据转换是否合适?企业需要考虑哪些关键因素!
运维·数据库·云计算
敲码图一乐3 小时前
流量安全——基于Sentinel实现限流,熔断,降级
java·开发语言·数据库
何故染尘優4 小时前
Redis 如何配置 Key 的过期时间?它的实现原理?
数据库·redis·缓存
落日漫游5 小时前
MySQL常用命令全攻略
数据库·sql·oracle
野熊佩骑8 小时前
CentOS7二进制安装包方式部署K8S集群之ETCD集群部署
运维·数据库·云原生·容器·kubernetes·centos·etcd
野生技术架构师9 小时前
聊聊五种 Redis 部署模式
数据库·redis·缓存
IndulgeCui9 小时前
【金仓数据库产品体验官】KES-ORACLE兼容模式再体验之FLASHBACK
数据库