公卫人

 找回密码
 立即注册

QQ登录

只需一步,快速开始

楼主: YAR

[分享] Excel VBA常用代码

[复制链接]
 楼主| YAR 发表于 2023-1-26 19:14:30 | 显示全部楼层
011.汇总分表成总表(保留分表格式)
% i% J9 N# m7 T6 R# h9 `1 L$ [9 ?$ w) ~8 W( k
9 u# Y7 Y$ b6 Z  J1 R4 ]1 H: z! a
Sub CollectDataFromShtFormat()4 p: o) S5 l6 ?7 v7 x% E- }
    Dim sht As Worksheet, rng As Range, k As Long, nTitleCount As Long1 r, y' l* T$ E: N1 ]2 ]- O
    On Error Resume Next; p4 _, c# j5 ~' P0 K
    nTitleCount = Val(InputBox("请输入标题的行数", "提醒", 1))
" Z+ V- ^1 X" }* j+ V- S4 U    If nTitleCount < 0 Then MsgBox "标题行数不能为负数。", 64, "提示": Exit Sub( B/ Y: ~  ?* R
    Application.ScreenUpdating = False' E- z) x3 O5 z) t
    Cells.ClearContents '清空当前表数据
; ~- o6 d3 h) V  S# c% s4 F# l8 p    For Each sht In Worksheets '遍历工作表: L. A) R; h- e: e
        If sht.Name <> ActiveSheet.Name Then2 P; p, ^' d& ?0 B
        '如果工作表名称不等于当前表名则进行汇总动作……* f; s9 z- T8 K  x; x
            Set rng = sht.UsedRange
9 u$ u( {1 Q: X3 `- H            k = k + 1 '累计K值( N! A$ R) S  Q! m
            If k = 1 Then '如果是首个表格,则K为1,则把标题行一起复制到汇总表! V. ~! ~; x% l- Y: _! H3 r
                sht.Cells.Copy: Range("a1").PasteSpecial Paste:=xlPasteFormats '只粘贴格式; O- q/ p/ F1 `. C! l+ }
                rng.Copy: Range("a1").PasteSpecial Paste:=xlPasteValues '只粘贴数值
' H- ]* W  y+ L% _* r            Else '否则,扣除标题行后再复制黏贴到总表,只黏贴数值
& l: c- l5 P6 q4 h! O                rng.Offset(nTitleCount).Copy* T! }; J' J( v
                With Cells(ActiveSheet.UsedRange.Rows.Count + 1, 1)
# h4 Q/ [  \3 x% o6 k' C' R+ v9 D                    .PasteSpecial Paste:=xlPasteFormats '粘贴格式" e* u- B& B( `4 g1 S
                    .PasteSpecial Paste:=xlPasteValues '粘贴数值
0 w! r0 K4 Q* M+ C                End With
. v0 N7 G# t5 d% [            End If, ]# B5 i+ E9 `) H9 q# F* o) P4 [
        End If
1 P" I' E  j2 D& Y' A- a7 Q' q    Next
8 G# U2 D, `  d+ z, ^    Range("a1").Activate1 w* X1 f6 v% q7 g8 G& y* t0 g
    Application.ScreenUpdating = True '恢复屏幕刷新, I9 X: a; o1 V# {/ x8 S
    MsgBox "汇总OK,一共汇总了:" & k & "张工作表"
4 B6 f& {; Q* eEnd Sub
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:18:18 | 显示全部楼层
012.工作表排序% u, h7 T) z" a$ `+ n' I* }

# X: V! p7 g* _% u/ W8 I4 |; n
, T$ W1 I+ [% E. l: qSub GetShtName()$ s: U8 O& d  F, R7 ~
    Dim k As Long, sht As Worksheet
0 {+ N5 D9 [' C: W$ Q0 g, R    Application.ScreenUpdating = False6 e  O$ @, l& D3 w& |3 D8 a4 F
    With Columns(1)
) b9 ?% ]1 \: u. A  C5 H        .ClearContents '清空A列原有数据, `5 s0 E/ r5 n6 x
        .NumberFormat = "@" '设置单元格格式为文本
6 O+ ?1 W6 H* [9 E6 z- _    End With" h7 D# X' ^- X. y& p' f
    Cells(1, 1) = "目录"  f' B% p7 Z/ I8 X* W& E
    k = 1
- o' ?5 J# e: f  s2 l, F    For Each sht In ThisWorkbook.Worksheets '遍历工作表7 G5 G, u) H, r! ]0 Z
        If sht.Name <> ActiveSheet.Name Then '如果sht不等于当前工作表名称
( y* \8 f- W+ a2 n- A2 c5 a, j( S            k = k + 1 '累加工作表个数2 h, O+ k7 e# S6 k* A+ Z
            Cells(k, 1) = sht.Name '工作表名称写入A列
4 z1 b& E5 u1 l; d  A. j' q8 A) ~        End If
2 I% A4 c- x  Z+ K7 E0 g, v7 j5 [    Next
% {* g& M- t1 b, y: i/ m# t    Application.ScreenUpdating = True
7 B: e, K3 j0 K- k0 s$ D3 {End Sub
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:24:12 | 显示全部楼层
013.批量工作表加密! ^/ N! Y, q( X( A/ H" f

7 `% F5 y4 M; P$ S' I! e4 O& r: o% _8 q$ s( G
Sub ProtectSht()
% U. t! s. }; X9 I/ |    Dim strAds As String, sht As Worksheet; ~& z- [* s  K: u9 X
    Dim strKey As String, strTemp As String" b  e( S# e1 v+ @5 ?8 e2 a
    Dim rng As Range, strMsg As String
$ j; w) C- |1 ~! B$ H& B$ A    Dim strNoShtName As String, strYesShtName As String3 _* [. Q" E0 n- ]' ^: r
    On Error Resume Next
% P2 b5 R5 v2 i, A  z) I3 `    strAds = InputBox("请输入单元格保存范围,例如A1:B10." & vbCr _( s! |4 V% h1 ?4 \# R. u% h7 H
                                & "可以设置不连续单元格,中间请以逗号分隔。比如A1:B10,D2:D8" & vbCr _
  i; X- P# T9 L& w                                & "如果需要全表保护,可以直接确定。", Default:="全表保护")+ o7 w/ k+ W6 J4 b# A: w. `5 _9 C
    If StrPtr(strAds) = False Then Exit Sub
& X' `: e) V! Q3 `) F7 f    If strAds = "全表保护" Then strAds = Cells.Address
5 A" l% w2 e: j- \2 y    Set rng = Range(strAds) '测试输入的单元格区域是否有效( j0 q- ^3 u+ {% \
    If Err Then MsgBox "你输入的单元格区域地址不是正确的格式,请重新操作。": Exit Sub. U2 U" N: ~0 V+ Y4 N/ B
    strKey = InputBox("请输入保护密码。") '第一次输入密码
, Q6 ^  @$ z, |! S    If StrPtr(strKey) = False Then Exit Sub
/ Y" D' T' j+ W7 D    strTemp = InputBox("请再次输入保护密码。") '第二次输入密码4 h$ x6 ^  f! j( |# I  B
    If StrPtr(strKey) = False Then Exit Sub8 ?* j# s5 ?) m  v- j, q7 Z
    If strKey <> strTemp Then MsgBox "你两次输入的密码不一致,系统退出,请重新操作。": Exit Sub" ^/ m6 d( M8 L# U, G1 u. G0 J
    For Each sht In Worksheets '遍历工作表加密保护
% L" c* ?$ s# k! c: \6 }! I' {        With sht9 @$ u4 I# j0 V" ~, y0 w0 ~) o! I+ ?
            If .ProtectContents = False Then '如果工作表未保护
* O+ h7 G, V! X" `6 j* o                .Cells.Locked = False '全部单元格区域取消锁定4 L( i# D& @, z# E! o7 s
                .Range(strAds).Locked = True '需要保护的区域锁定
' W. _; c6 O7 u3 O                .Protect strKey, True, True, True '保护工作表,只允许编辑非锁定区域
0 h5 o6 \( l+ U0 v# w; `0 y                strYesShtName = strYesShtName & "," & .Name '保护成功的工作表名称/ X. [; a( r, Z
            Else
% }  i9 M8 e4 V/ m                strNoShtName = strNoShtName & "," & .Name '自身已有保护功能的工作表
% c# D0 s+ ?3 ^+ c5 l2 E4 V            End If
: ~- p' _$ d0 ?/ s; ~+ C, R8 ]        End With3 X- k& h5 p3 C* y. B* Z; L
    Next6 k! o! b# h! ]! Z
    If strYesShtName <> "" Then strMsg = "工作表:" & Mid(strYesShtName, 2) & "的" & strAds & "区域保护完成"/ C: J5 h2 r8 p8 [. y2 Z
    If strNoShtName <> "" Then strMsg = strMsg & vbCrLf & "以下工作表自身已有保护,无法再次保护:" & Mid(strNoShtName, 2)/ |! Z. [+ T# r
    MsgBox (strMsg)6 w- L+ z; b1 _+ J5 O
End Sub
8 c! }3 ]6 h% |7 F& E
/ R7 D. X; y5 n2 {5 h# V; |
. g( y+ }$ E( z+ {8 D: z4 O7 K, r( `$ U! c

" |2 h3 P) H# M) c# g
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:26:41 | 显示全部楼层
014.批量工作表破密
, X8 u& c9 a7 e( O/ H+ g8 @* C! O/ o6 T: t* z
$ T, _+ ?$ b, R/ P9 E* B1 @
Sub UnProtct()7 _" c( Z9 h2 I/ L. n
    MsgBox "**提示:当要求输入密码时请点击取消!”"9 A) a7 p) Q) l* b! c' `
    Application.DisplayAlerts = False
  j& a) v( S6 M2 `0 H4 c2 X    On Error Resume Next* A3 H, ^, U' i  a7 w7 ~
    Dim sht As Worksheet. Y! L9 l$ B/ \7 W0 `7 H& G: j
    For Each sht In Worksheets
2 o1 L1 o+ K3 F4 X8 n2 m  ]        With sht
7 y" t1 s6 {7 D( p            .Protect DrawingObjects:=True, Contents:=True, Scenarios:=True, AllowFiltering:=True, AllowUsingPivotTables:=True
6 i* `. @( Z& P/ K: z            .Protect DrawingObjects:=False, Contents:=True, Scenarios:=False, AllowFiltering:=True, AllowUsingPivotTables:=True/ R( C+ b) f5 O
            .Protect DrawingObjects:=True, Contents:=True, Scenarios:=False, AllowFiltering:=True, AllowUsingPivotTables:=True
. y$ ~. `: C2 P5 q7 j            .Protect DrawingObjects:=False, Contents:=True, Scenarios:=True, AllowFiltering:=True, AllowUsingPivotTables:=True
# R( w. w' Q4 ]# I4 Q4 L: E. E% [! U3 _            .Unprotect* e5 t  G9 p& @  Y9 b9 P
        End With) l: C7 v" z4 F& L
    Next
9 y4 m+ W/ j. ]5 X+ T    MsgBox "ok". Y% p+ M8 F& i( ?5 K2 {$ T
End Sub
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:29:38 | 显示全部楼层
015.按任意列拆分多个表
+ d9 B- G0 n  M2 Z; Y  o& [4 N7 X
9 ~1 G+ S% T( o$ s2 R+ O5 e/ r3 U- a6 b
Sub SplitShts()4 _$ r2 q/ @- E3 F7 e2 y4 n
    Dim d As Object, sht As Worksheet' k3 ?5 |3 P. I' {2 m+ k# r
    Dim aData, aResult, aTemp, aKeys, i&, j&, k&, x&3 }+ v6 J3 [) \: ^3 M2 i
    Dim rngData As Range, rngGist As Range
7 \& m# Z: `4 L% ]* L: U" }    Dim lngTitleCount&, lngGistCol&, lngColCount&! V& m' o" f2 h+ @7 N( R% t
    Dim rngFormat As Range, aRef, strYesOrNo As String
) \% d. j) \6 l    Dim strKey As String, strTemp As String) `  z+ X5 w7 y+ M8 T9 S
    On Error Resume Next '忽略错误,程序继续运行4 n6 D3 |2 k9 h( |! I2 [
    Set d = CreateObject("scripting.dictionary")
8 U1 j2 ~5 Z( J0 P+ f    Set rngGist = Application.InputBox("请框选拆分依据列!只能选择单列单元格区域!", Title:="提示", Type:=8)
! g: D2 C0 n' P& ?+ N* D    '用户选择的拆分依据列7 p. w+ G8 u& h# Y! _4 r% t
    lngGistCol = rngGist.Column
& ~4 ~( H9 V5 M- I    '拆分依据列的列标! ~2 U$ k, g9 ?" O$ J
    lngTitleCount = Val(Application.InputBox("请输入总表标题行的行数?", Default:=1))' s- r3 I# l+ M( k0 h# r/ z* F: U
    '用户设置总表的标题行数
3 O/ [( J  y7 i: R; r    If lngTitleCount < 0 Then MsgBox "标题行数不能为负数,程序退出。": Exit Sub; y/ P! `+ P$ R, ~
    strYesOrNo = MsgBox("是否需要在分表保留总表格式?", vbYesNo)
8 B2 W5 r8 h+ ^    Set rngData = rngGist.Parent.UsedRange
) I7 ]9 u4 x4 y4 p    '总表的数据区域' ~8 \' Q& c/ z4 D8 ?
    Set rngFormat = rngGist.Parent.Cells
) U: ~" R; C* Z1 x; g' q    '总表的单元格区域用于粘贴总表格式
! _* C1 v+ |0 |- F" R6 m    aData = rngData.Value '数据源装入数组+ `3 n/ D  y: A. l) @
    lngGistCol = lngGistCol - rngData.Column + 1- u* ]& n( h, P1 |" U
    '计算依据列在数组中的位置
1 q5 T0 o9 m' t; [: Y9 ], N) b    lngColCount = UBound(aData, 2)3 x. c- Y5 R! R% Z9 k
    '数据源的列数
$ ]( V2 Y; S' n. _, a$ l1 B  K    Application.ScreenUpdating = False- g) Z+ g* B/ s
    Application.DisplayAlerts = False
# W" g' @3 K9 A0 t5 w    ReDim aRef(1 To UBound(aData))
6 l- t1 M% o9 V3 s( R, F    For i = 1 To UBound(aData) '处理依据列的异常值,空白/错误值/整行空白等( R4 n% I7 X+ g; K* P8 N' D
        If IsError(aData(i, lngGistCol)) Then
5 |4 P0 t; J' W" }/ y* q! z            aRef(i) = "错误值": o2 t# e9 I% P1 i. H/ X, j
        ElseIf aData(i, lngGistCol) = "" Then, Y% X2 k+ \& X) D% k3 ^
            strTemp = "" '判断是否整行数据为空
: J1 `7 ~. X  n& h; N            For j = 1 To lngColCount
5 U7 [+ u, I* s& a# B                strTemp = strTemp & aData(i, j)
* e8 C) o! G, J, C: O/ k            Next+ ?2 _2 {. |! Q& l, q$ }1 V* c/ G/ q+ A
            If strTemp = "" Then '如果整行为空% ]8 x2 n" U  X# d( \# R% c% w
                aRef(i) = "整行空白"3 A( P# U' Y) p( u; i/ c3 m
            Else4 R6 q/ c. `4 i2 x
                aRef(i) = "空白单元格"
& @2 w' B/ e) A& L            End If
* ?' @; ^& X( g: U! f# P, i        Else
6 \6 s* R" ?) Y) ~' D2 t* z            strKey = aData(i, lngGistCol)
) N2 _! B0 Z+ W            aRef(i) = strKey; f. h. z: d6 R
        End If( W( R) }$ z% s" g
    Next2 h5 B. f6 l4 H, J
    For i = lngTitleCount + 1 To UBound(aData)
9 `5 J$ C( J9 g        strKey = aRef(i)
" t' W3 l) h" L        If strKey <> "整行空白" Then7 Z' |1 A- b3 v9 h  p5 Z/ J
            If Not d.exists(strKey) Then2 W* U7 C8 w5 d3 R) Y+ c0 Y
            '字典中不存在关键字时则遍历建表8 t9 n: r- Z0 ~" b5 y
                d(strKey) = ""3 J+ ]5 q8 D2 K0 \0 m; L
                ReDim aResult(1 To UBound(aData), 1 To lngColCount) '声明一个结果数组$ }% C, L$ g+ E1 G0 }3 J( c
                k = 0
2 f7 c+ }/ n! F0 V3 d# L! T, b                For x = lngTitleCount + 1 To UBound(aData) '遍历数据源- X- L* O- v9 h+ f/ k* h  ^
                    strTemp = aRef(x), P' w- w- Q+ X5 c  h
                    If strTemp = strKey Then '如果记录符合条件,则装入结果数组/ a5 C* ?& i; ]8 w4 M
                        k = k + 1" M+ L2 @! I" l6 w
                        For j = 1 To lngColCount
, K' C$ g+ [* m# c3 ?0 v                            aResult(k, j) = aData(x, j)
2 S8 K6 Y. T7 Z7 B" T  [                        Next; y: B2 C1 J$ l. J9 ^+ k9 i5 }
                    End If. E+ q6 H" O/ Q
                Next: r! v  T* c+ k  i" b) t' h) `
                For Each sht In ActiveWorkbook.Worksheets '删除旧表
6 `2 e" j& S$ a: |5 _5 T                    If sht.Name = strKey Then sht.Delete2 ]' q( m% `# p  j: y& K. W
                Next
9 H- u! ?- R- y7 D! d# x                With Worksheets.Add(, Sheets(Sheets.Count))
4 y8 g5 t& M! r2 j! K                '新建一个工作表8 ~  L+ f+ e7 X( F
                    .Name = strKey
  j" q" E1 _- G; q: \( T                    .Range("a1").Resize(UBound(aData), lngColCount).NumberFormat = "@"2 p( f2 i* h1 [( G$ g' ]7 {
                    '设置单元格为文本格式" y+ w1 _6 w: @- o6 A
                    If lngTitleCount > 0 Then .Range("a1").Resize(lngTitleCount, lngColCount) = aData* }; U, `/ V8 Z! k4 m% u0 \, e
                    '标题行
  f( F5 C: t# z( R8 d7 P' H                    .Range("a1").Offset(lngTitleCount, 0).Resize(k, lngColCount) = aResult
4 q% S7 v/ B2 K3 U; x# s* P# k                    '写入数据2 \/ p8 N) H( l* o
                    If strYesOrNo = vbYes Then '如果用户选择保留总表格式5 |1 J) C2 D8 }, Z0 a
                        rngFormat.Copy
6 K/ e6 |! {# r3 r) f& N1 Q7 K  _                        .Range("a1").PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False  q6 T  Z, t1 M- }* U
                         '复制粘贴总表的格式
2 Z& |/ n! }- h                        .Range("a1").Offset(lngTitleCount + k, 0).Resize(UBound(aData) - k - lngTitleCount, 1).EntireRow.Delete
9 x. W/ V( l% ]6 y3 {+ `                        '删除多余的格式单元格
! p6 g) H# x' E& C/ o0 m                    End If4 u* }) }2 a5 h& e0 k
                    .Range("a1").Select  \$ u9 R" F! U/ P/ |, L+ ~9 g
                End With$ c, C0 F: }  w0 T4 \" ]" u
            End If2 T2 ~1 M1 m4 i: V
        End If3 @: V5 g' a  I  P2 F
    Next
! g0 g  B+ G. n% j- P5 l    rngData.Parent.Activate '回到总表
! G$ `8 z4 y! g1 [: O; y! B    Application.ScreenUpdating = True
; q! E3 d' Z% }& e$ {7 i5 |; k    Application.DisplayAlerts = True7 z) F2 ]0 d# N& N5 c( c  q
    Set d = Nothing3 B  P% S7 z6 g8 \) I0 O. ]9 f+ x
    Set rngData = Nothing
" ?# T. n9 g0 {. W: P9 d/ M. j2 T, Y6 Q    Set rngGist = Nothing7 u, X; G$ [* [( J* W: G1 l
    Set rngFormat = Nothing
, }1 Y( y  q+ s    Erase aData: Erase aResult+ z  D) Q+ F7 V- w+ t
    MsgBox "数据拆分完成!"
% z( Z  a/ K& ]End Sub
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:35:32 | 显示全部楼层
016.按任意列拆分方法二
( G7 E; S* ]" z# _+ D) c( o+ e5 y! W( y- e
, H% P4 |$ e7 S7 g# k: _1 i  C
Private Sub Worksheet_Change(ByVal Target As Range)
5 C; |# H& U# M0 M   ActiveWorkbook.RefreshAll! z$ i1 Z$ @2 ?$ K& ?9 A1 _
End Sub
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:37:02 | 显示全部楼层
017.批量将工作表转换为独立的工作簿
/ {: d# q# Q' l; q0 {! w) K) B9 Q7 e
% L) R  ^1 l( Q: t* @: Q/ Q  F
6 C% H) N  e8 a' w
1 ]: e0 y6 u1 l' d1 jSub EachShtToWorkbook()" ]7 e' Y& H4 }. I
    Dim sht As Worksheet, strPath As String
2 r. i$ h3 O) T! A- G+ P8 @    With Application.FileDialog(msoFileDialogFolderPicker)
1 y: X, a7 p5 p- D0 A6 m" h& t   '选择保存工作薄的文件路径, N0 y  Y' w% D: y# z
        If .Show Then strPath = .SelectedItems(1) Else Exit Sub1 ~8 r" K5 n. C: |# ~' b- V% `5 F
        '读取选择的文件路径,如果用户未选取路径则退出程序
( F% S$ n" B# ?    End With
0 t0 Q) l$ W0 Q: L1 e; ]& b    If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
* ^& y2 v$ M, ~3 I    Application.DisplayAlerts = False! W! u, D( p1 {
    '取消显示系统警告和消息,避免重名工作簿无法保存。当有重名工作簿时,会直接覆盖保存。
" H( Q( v4 @- H+ N    Application.ScreenUpdating = False '取消屏幕刷新
5 }* t$ D7 u) M9 Y" ]    For Each sht In Worksheets '遍历工作表
- H- \! K2 o6 v* W        sht.Copy '复制工作表,工作表单纯复制后,会成为活动工作薄
  J1 E2 U; q/ I. q& {        With ActiveWorkbook5 h/ M* X+ ~; m, m  |8 l
            .SaveAs strPath & sht.Name, xlWorkbookDefault7 ]4 Y6 k! l! O7 d4 }# ?0 k2 F" K
            '保存活动工作薄到指定路径下,以当前系统默认文件格式
! B" W9 H+ H# o. Z+ n! @, c' W            .Close True '关闭工作薄并保存! k. R5 N+ P2 S
        End With
0 r1 b3 l0 }& b    Next4 S. |. ^- U7 d3 P
    MsgBox "处理完成。", , "提醒"9 v  e/ R5 Y3 b0 |+ W3 u
    Application.ScreenUpdating = True '恢复屏幕刷新
$ ?* B% q' d% W4 |% s    Application.DisplayAlerts = True '恢复显示系统警告和消息
: x, y: ~) f2 |! CEnd Sub
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:38:13 | 显示全部楼层
018.将总表按任意列拆分成多个工作簿
. r) v0 W7 m5 v* M8 G/ [
0 ?: R$ Y2 f7 r  ?2 @& B1 T9 }0 L: t. q
Sub SplitShts()# R# M7 h" E- ]8 d& [
    Dim d As Object, sht As Worksheet7 n/ I( s  J6 t4 j1 S) U
    Dim aData, aResult, aTemp, aKeys, i&, j&, k&, x&
5 N. [$ P7 W0 ]) `' d4 p% H    Dim rngData As Range, rngGist As Range, ws As Workbook
3 i& M  z( R, d1 ?$ [: _& i    Dim lngTitleCount&, lngGistCol&, lngColCount&
5 [0 y* K0 r$ r- H: [9 c    Dim rngFormat As Range, aRef, strYesOrNo As String
. Z* n5 ?2 ]4 A- H    Dim strKey As String, strTemp As String, strPath As String
, y0 p6 M5 I* b. p: X6 A% f    On Error Resume Next '忽略错误,程序继续运行; l# }8 J  k3 d
    Set d = CreateObject("scripting.dictionary")) S' M7 b+ j! C7 c, ]5 Y
    With Application.FileDialog(msoFileDialogFolderPicker)2 q) Q& u2 ]' D$ _& ~' M) o
    '用户选择保存工作簿的路径
* b( y; F$ J1 X5 @" B( j4 w$ B        If .Show Then strPath = .SelectedItems(1) Else Exit Sub# F  Q! g3 O/ A+ M
    End With: Z$ S4 Y7 q8 Z$ U9 h
    If Right(strPath, 1) <> "\" Then strPath = strPath & "\": h& q. L& T, U6 W1 V: k
    Set rngGist = Application.InputBox("请框选拆分依据列!只能选择单列单元格区域!", Title:="提示", Type:=8)& q8 x* g3 i7 Q( q' [, Y
    '用户选择的拆分依据列" t9 g  Z8 E! J' H* f
    If rngGist Is Nothing Then Exit Sub
& ~* k1 W/ R2 l  X    lngGistCol = rngGist.Column '拆分依据列的列标
3 e. {+ d. g( S- |1 g9 I9 K8 E    lngTitleCount = Val(Application.InputBox("请输入总表标题行的行数?", Default:=1))
& Z, N7 O: h) d+ g% P    '用户设置总表的标题行数( Q/ S$ c5 a" G! f/ t+ ^; ^
    If lngTitleCount < 0 Then MsgBox "标题行数不能为负数,程序退出。": Exit Sub
& E* D  R6 ]! ~    strYesOrNo = MsgBox("是否需要在分表保留总表格式?", vbYesNo)8 u2 f- C: r& N  d
    Set rngData = rngGist.Parent.UsedRange
+ m7 L  T8 O: O0 t  [' p. f* n/ I    '总表的数据区域7 [+ C; X4 Y0 A6 z$ _: ~: J
    Set rngFormat = rngGist.Parent.Cells
- G. `. }. W3 [, c2 Q5 ^5 h    '总表的单元格区域用于粘贴总表格式2 `: x1 z; @! i( s# b6 Y
    aData = rngData.Value '数据源装入数组
1 B7 O9 }: L/ u& |) Y3 @9 T5 F) J+ K    lngGistCol = lngGistCol - rngData.Column + 17 g, z4 P3 S+ q8 C
    '计算依据列在数组中的位置
8 M# i2 e- y7 x, e* W/ x) e    lngColCount = UBound(aData, 2)
, Z# b9 a% m- y- |" n. Y    '数据源的列数" X9 k  H- Z# P' k% `
    Application.ScreenUpdating = False
6 j! C% o# m5 L( ~    Application.DisplayAlerts = False+ A8 M9 r; y7 V& B7 \
    ReDim aRef(1 To UBound(aData))" t: b$ N% t# T+ ?, I3 E( ~5 `
    For i = 1 To UBound(aData) '处理依据列的异常值,空白/错误值/整行空白等
" G- v! u8 W* F2 U# R, M2 g( C4 ~        If IsError(aData(i, lngGistCol)) Then
$ e, o  ], M' ~" {            aRef(i) = "错误值"
' L0 C3 H- ?/ P8 {7 j        ElseIf aData(i, lngGistCol) = "" Then+ A' R9 ^; \. b% O/ `
            strTemp = "" '判断是否整行数据为空
9 v/ v9 H/ Q2 x- S" ]3 u5 l, P            For j = 1 To lngColCount% |5 J" v$ p; y9 Z  O' y4 V; e) J/ t
                strTemp = strTemp & aData(i, j)0 E  L$ Z' U/ o8 z
            Next/ I$ e3 a4 @) T) _" B6 Z2 _
            If strTemp = "" Then '如果整行为空6 V- ~: U; S- u
                aRef(i) = "整行空白"
+ E- q5 b6 e% I8 P            Else
- X. l, `+ a. r                aRef(i) = "空白单元格"
8 k% J5 Z8 M$ d' F% x            End If& l  H* h) }' c& `
        Else
& S$ |: z0 n* N) B/ I: o* Z' p            strKey = aData(i, lngGistCol)
+ Q" h5 t) |( L$ {. c9 _1 y7 Z, J            aRef(i) = strKey0 [, F6 k/ C% |* e
        End If
( K$ U' H, t( v9 L& k) X6 V    Next3 N+ O( K+ U" x9 M0 \: _4 Z
    For i = lngTitleCount + 1 To UBound(aData)! G# J2 e7 o6 E( ^% r. a( Q
        strKey = aRef(i)+ p# C( p# \$ d0 v6 r
        If strKey <> "整行空白" Then4 H# H7 }  q% p% \- ]& C
            If Not d.exists(strKey) Then1 F. h( M( W- M- T6 H
            '字典中不存在关键字时则遍历建表/ V' v% \* m& C! X. _1 X; z
                d(strKey) = "") P4 s  B; a5 @3 y4 J2 I& x7 `
                ReDim aResult(1 To UBound(aData), 1 To lngColCount) '声明一个结果数组
: J: ^# {( l9 F- n; A/ k                k = 0
$ }  o( ^. U9 D, C9 i5 T                For x = lngTitleCount + 1 To UBound(aData) '遍历数据源
% X: ~$ x& e9 S8 V  v                    strTemp = aRef(x)
9 {9 }! ^6 ]( a% P) V                    If strTemp = strKey Then '如果记录符合条件,则装入结果数组
. X0 n; w+ j/ J  v  Z                        k = k + 1
& S  U' g! b/ Z0 x8 R  Y- A7 {, |                        For j = 1 To lngColCount
& x, G; [+ R, m+ k& n+ \+ O                            aResult(k, j) = aData(x, j)5 [/ F4 r/ W. T6 m* x- @
                        Next
; ]# C5 I- s0 X                    End If
; y- t6 d0 x- o; j6 }# F, D. s                Next
$ `0 M+ b: W. z' U& Q: L                Set ws = Workbooks.Add0 G! q  _! {  [2 r% r) E/ R4 O) c
                With ws.Sheets(1)
/ t$ A4 G. E' g* @9 |; @7 h% h                '新建一个工作簿0 h: Q- w% w7 ]  l
                    .Range("a1").Resize(UBound(aData), lngColCount).NumberFormat = "@"
2 R- \4 a, T% a8 e/ J) k                    '设置单元格为文本格式% J; L9 p5 ~: i8 x+ P& g/ s. F
                    If lngTitleCount > 0 Then .Range("a1").Resize(lngTitleCount, lngColCount) = aData% [7 }0 t) l" ^  l9 T4 ]$ D
                    '标题行
3 C* H. B9 w& E: T                    .Range("a1").Offset(lngTitleCount, 0).Resize(k, lngColCount) = aResult
3 d9 }% u6 _$ X' Z- M# R                    '写入数据0 _, }) f) b1 C8 \9 j
                    If strYesOrNo = vbYes Then '如果用户选择保留总表格式
: u0 f, @# p8 J' k                        rngFormat.Copy7 O/ f' y+ |  i7 |; R
                        .Range("a1").PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
6 L3 l7 I- H, d; w                         '复制粘贴总表的格式
) Z/ z! i9 o, g' H                        .Range("a1").Offset(lngTitleCount + k, 0).Resize(UBound(aData) - k - lngTitleCount, 1).EntireRow.Delete5 P5 j$ M& `1 Q2 ~3 ^9 M% _- O
                        '删除多余的格式单元格* }, i9 L& P: y/ F9 c) |, ?
                    End If
0 M8 l) s7 l8 Y& @9 H" K                    .Range("a1").Select6 g4 Z. {: J* G6 F* \/ v5 ^8 J% u
                End With: ?1 T5 z; U6 M2 z+ B9 u
                ws.SaveAs strPath & strKey, xlWorkbookDefault3 ^% S$ V; @, j8 X1 |- L! H
                ws.Close False
6 x& P- s8 S" ]) a: Y' h, m- U            End If! t. W8 P7 f) B
        End If1 W; ^7 _& r: V
    Next* L/ N7 I% C4 B
    Application.ScreenUpdating = True0 a$ l# _# k0 h
    Application.DisplayAlerts = True
4 e  h( o' U: A" `" f  Z    Set d = Nothing
9 B3 }6 [4 x- Y    Set rngData = Nothing
. ~( B" [8 P, G, A: k    Set rngGist = Nothing  I& `7 d; z' U) [
    Set rngFormat = Nothing
3 A+ W: c* n8 b% o    Erase aData: Erase aResult* }, [2 {1 p, G2 Z3 @
    MsgBox "数据拆分完成!", v" |7 U- N  Y' [" c
End Sub
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:39:29 | 显示全部楼层
019.选中行或列会填充颜色
% ]( {- n) E# [5 ^# Y: p) x/ E$ J$ l" k6 }$ ?% H$ ?

* a. l: R' s, }: vPrivate Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)/ a  T: d& n  D: t. I  C: E7 C# h
    Application.ScreenUpdating = False2 }* O+ e" s( G0 O7 Q
    Cells.Interior.ColorIndex = -4142 '取消单元格原有填充色,但不包含条件格式产生的颜色。1 |, p. z) b/ T, X4 C
    Rows(Target.Row).Interior.ColorIndex = 33 '活动单元格整行填充颜色
7 l  \9 V; G/ H- Z# l$ q$ ?- L    Columns(Target.Column).Interior.ColorIndex = 33 '活动单元格整列填充颜色
2 @; F* B( d( A, {$ N    Application.ScreenUpdating = True
! B5 J9 T1 k& G# K/ P1 @End Sub
回复

使用道具 举报

 楼主| YAR 发表于 2023-1-26 19:40:43 | 显示全部楼层
020.按指定名称批量创建工作簿
( P, r5 s+ ^8 S# ?) @4 Y3 C, `3 ^8 `7 b) L$ ]! }: Z% h

- H# I/ l" w( i% q
- E; H& |. W# K" w' [! YSub CreateFiles()
  p) @$ g! Z: I7 Q. E$ m    Dim strPath As String, strFileName As String( u  C+ o/ R5 H- E; e# ?, I
    Dim i As Long, r
, W/ n8 [# v' Z/ U0 q    On Error Resume Next7 w, W# N3 ]" d% `6 L/ M/ i( ]
    With Application.FileDialog(msoFileDialogFolderPicker): k! Y) d& c+ x& c) @7 G% L
        '用户选择文件夹路径
1 [' ~1 h  N! o$ l        If .Show Then strPath = .SelectedItems(1) Else Exit Sub1 c: a6 ^  i  u2 s. \6 {; h
        '如果用户为选择文件夹则退出程序7 u/ B( `3 L$ g% M
    End With7 |4 A% o( j% Z
    If Right(strPath, 1) <> "\" Then strPath = strPath & "\"6 G* r$ z1 w, c
    Application.ScreenUpdating = False '取消屏幕刷新  X; S1 i/ `/ k- \4 \
    Application.DisplayAlerts = False '取消警告提示,当有重名工作簿时直接覆盖7 ~0 f1 H  T$ G; `
    r = Range("a1:a" & Cells(Rows.Count, 1).End(xlUp).Row) '数据装入数组r" k! M7 g  z# H
    For i = 2 To UBound(r) '标题不要,因此从第2个元素开始遍历数组r
6 P& p. B% I0 T! C" _# i        With Workbooks.Add '新建工作簿. z" i! z' M. ^  S: X
            .SaveAs strPath & r(i, 1), xlWorkbookDefault
& U2 O& }& N! M/ u8 ]( Z- X            '以指定名称、默认文件类型保存工作簿
$ \0 O& W8 C, |: T0 k2 i# V            .Close True '关闭工作簿
) q" W% U7 n; o        End With
( |' P, R+ L3 `( d1 v5 C* b    Next2 X. C2 j- s. w
    Application.ScreenUpdating = True
5 X9 Z4 U0 @+ @' l3 O    Application.DisplayAlerts = True# [6 F- k) N) T3 i$ w* @
    MsgBox "创建完成。"$ y4 C5 i. d8 T& C7 q, x% Y7 z
End Sub
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|会员|至尊|接种|公卫人 ( 沪ICP备06060850号-3 )

GMT+8, 2024-5-18 22:01 , Processed in 0.067047 second(s), 7 queries , Gzip On, MemCached On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表