微博:EXCELers / 知識(shí)星球:Excel HI,大家好,,我是星光,。今天咱們來(lái)繼續(xù)學(xué)習(xí)VBA編程常用對(duì)象操作之單元格。在上一章咱們分享了如何按條件刪除整行數(shù)據(jù),,這一章再講下如何對(duì)單元格進(jìn)行合并與反合并,。 從數(shù)據(jù)源的數(shù)據(jù)規(guī)范性角度來(lái)說(shuō),,合并單元格并不是個(gè)好東西,嚴(yán)重不利于數(shù)據(jù)的再次統(tǒng)計(jì)與分析,,但在日常工作的各種結(jié)構(gòu)性報(bào)表中,,咱們往往又沒(méi)辦法擺脫它的存在。這時(shí)總會(huì)有些朋友告誡大家說(shuō),,合并單元格不是個(gè)好人,,你別用它,不和它交往就行了……可世界是如此復(fù)雜,,單純?nèi)缥?,都不敢有如此自閉成仙的想法……我不找合并單元格,合并單元格還找我呢,?誰(shuí)家的報(bào)表不帶點(diǎn)合并單元格?惹不起也躲不了——所以,,關(guān)于單元格合并與反合并,,多少還是要了解一下▼
單元格合并
打個(gè)響指,先來(lái)看單元格的合并,。如下圖所示的數(shù)據(jù),,需要將指定列單元格相鄰且值相同的合并成為一個(gè)合并單元格。 示例代碼如下▼
代碼如看不全,,可以左右拖動(dòng).... Sub rngMerge() Dim rngData As Range, rngMerge As Range Dim y As Long, i As Long Dim iStart As Long, iEnd As Long Set rngData = Application.InputBox('請(qǐng)選擇單列數(shù)據(jù)', _ '您好:', Default:='B:B', Type:=8) rngData.Parent.Select '激活數(shù)據(jù)所在工作表 Set rngData = Intersect(rngData, ActiveSheet.UsedRange) If rngData Is Nothing Then MsgBox '你選擇的區(qū)域不存在數(shù)據(jù),。' Exit Sub End If iStart = rngData.Row '開(kāi)始行 iEnd = rngData.Rows.Count + iStart '結(jié)束行 y = rngData.Column '選中列的列號(hào) Application.ScreenUpdating = False Application.DisplayAlerts = False For i = iStart + 1 To iEnd '+1是為了扣掉標(biāo)題行 If Cells(i, y) = Cells(i - 1, y) Then '如果相鄰的兩個(gè)單元格值相等 If rngMerge Is Nothing Then 'rngMerge變量用于存放應(yīng)合并的單元格 Set rngMerge = Union(Cells(i, y), Cells(i - 1, y)) '相鄰單元格合并 Else Set rngMerge = Union(rngMerge, Cells(i, y)) '累加合并 End If Else If Not rngMerge Is Nothing Then rngMerge.Merge Set rngMerge = Nothing End If End If Next rngData.VerticalAlignment = xlCenter Application.ScreenUpdating = True Application.DisplayAlerts = True End Sub
運(yùn)行代碼后效果如下▼
代碼解析▼
第5行代碼使用Application對(duì)象的InputBox方法創(chuàng)建一個(gè)對(duì)話框,允許用戶鼠標(biāo)選取單列數(shù)據(jù),,并賦值給變量rngData,。運(yùn)行后結(jié)果如下圖所示。
該函數(shù)有6個(gè)參數(shù),,語(yǔ)法格式如下,。
Application.InputBox (Prompt, Title, Default, Left, Top, HelpFile, HelpContextID, Type)
Prompt是對(duì)話框的提示內(nèi)容,本例為'請(qǐng)選擇單列數(shù)據(jù)',。
Title是對(duì)話框的標(biāo)題,,本例為'您好'。
Default是對(duì)話框的默認(rèn)值,,本例為'B:B',,也就是B列的地址。
Left和Top分別指定了對(duì)話框相對(duì)于屏幕左上角的 X/Y的坐標(biāo),,不常用,。
HelpFile是幫助文件名,HelpContextID是幫助主題上下文ID,,兩個(gè)都不常用,。 Type指定返回的數(shù)據(jù)類型,。如果省略,則對(duì)話框默認(rèn)返回文本,。本例Type=8,,表示對(duì)話框必須返回單元格對(duì)象。此外還可以指定其它返回類型,,這部分內(nèi)容等到了數(shù)據(jù)交互章節(jié)咱們?cè)偌?xì)說(shuō),。
……
第7行代碼使用單元格對(duì)象的Parent屬性,激活用戶所選擇的單元格對(duì)象的所屬工作表,。Parent是父親的意思,,眾所周知,自古以來(lái)工作表就是單元格的爸爸……▼ 第8行代碼使用Intersect語(yǔ)句返回用戶所選擇的單元格區(qū)域和工作表已使用區(qū)域的交集,,這有什么好處呢,?——可以避免用戶選擇整列區(qū)域時(shí)運(yùn)算量虛增。如果你看我的函數(shù)教程,,應(yīng)該記得COUNTIF/SUMIF等工作表函數(shù)均采用了這類優(yōu)化方案,。
Set rngData = Intersect(rngData, ActiveSheet.UsedRange)
第9至第12行代碼判斷用戶是否選擇的是空白區(qū)域,如果是空白區(qū)域,,則交集運(yùn)算后的rngData變量必然為Nothing,,于是使用MsgBox語(yǔ)句顯示提醒信息,并退出程序,。
If rngData Is Nothing Then MsgBox '你選擇的區(qū)域不存在數(shù)據(jù),。' Exit Sub End If
第13至第15行代碼分別計(jì)算了用戶所選擇區(qū)域的開(kāi)始行、結(jié)束行和列標(biāo),。有的朋友可能會(huì)想,,開(kāi)始行難道不是1嗎?本例中確實(shí)為1,,但實(shí)際情況,,用戶選擇的區(qū)域也可能是A3:A10不是?
iStart = rngData.Row '開(kāi)始行 iEnd = rngData.Rows.Count + iStart - 1 '結(jié)束行 y = rngData.Column '選中列的列號(hào)
第16行代碼取消屏幕刷新,。第17行代碼取消系統(tǒng)顯示警告消息,,避免當(dāng)單元格合并時(shí)出現(xiàn)'僅保留左上角的值,放棄其它值'類似的警告對(duì)話框,。 Application.ScreenUpdating = False Application.DisplayAlerts = False
第18至第31行代碼是For語(yǔ)句的計(jì)數(shù)循環(huán)體,。
第19行代碼判斷相鄰的兩個(gè)單元格的值是否相等。如果相等,,則使用Union語(yǔ)句合并成為一個(gè)單元格對(duì)象(第21-24行代碼),。如果不相等(第25-30行代碼),則判斷rngMerge變量是否為Nothing。如條件不成立,,則使用單元格對(duì)象的Merge方法使其合并成一個(gè)合并單元格,。 第32行代碼設(shè)置文本對(duì)齊方式為水平居中。
第33和第34行代碼恢復(fù)系統(tǒng)屏幕刷新和顯示警告信息的功能,。
……
畢竟沒(méi)有廣告的微信文是不真誠(chéng)的▼
2 丨
撤銷單元格合并
講完了單元格合并的代碼,,咱們?cè)倭囊幌?/span>如何批量撤銷合并單元格,并將內(nèi)容填充完整,。如果說(shuō)單元格合并是一桶統(tǒng)江山,,難度頗高,那么撤銷合并單元格就是禍國(guó)殃民,,相對(duì)就容易些——二八佳人體似酥,,腰懸利劍斬愚夫……了解一下?
一種常用而簡(jiǎn)單的基礎(chǔ)操作技巧是先撤銷合并單元格,,然后使用定位功能,,定位空值單元格,對(duì)其批量填充,,視頻操作演示如下▼但這種方法會(huì)誤傷本身就是空值的單元格,,比如上圖中的B11。
VBA代碼解決方案如下▼
Sub rngUnMerge() Dim rngData As Range, rngMerge As Range Dim y As Long, i As Long, c As Long Dim iStart As Long, iEnd As Long Set rngData = Application.InputBox('請(qǐng)選擇單列數(shù)據(jù)', '您好:', _ Default:='B:B', Type:=8) rngData.Parent.Select '激活數(shù)據(jù)所在工作表 Set rngData = Intersect(rngData, ActiveSheet.UsedRange) If rngData Is Nothing Then MsgBox '你選擇的區(qū)域不存在數(shù)據(jù),。': Exit Sub iStart = rngData.Row '開(kāi)始行 iEnd = rngData.Rows.Count + iStart - 1 '結(jié)束行 y = rngData.Column '選中列的列號(hào) Application.ScreenUpdating = False Application.DisplayAlerts = False For i = iStart + 1 To iEnd Set rngMerge = Cells(i, y).MergeArea '可能存在的合并單元格區(qū)域 c = rngMerge.Count '合并單元格的行數(shù) If c > 1 Then rngMerge.UnMerge '取消合并單元格 rngMerge.Value = Cells(i, y) '填充首個(gè)單元格的值 i = i + c - 1 '跳過(guò)已經(jīng)處理的合并單元格的行數(shù) End If Next Application.ScreenUpdating = True Application.DisplayAlerts = True End Sub
代碼解析如下▼
第5至第13行代碼上一節(jié)已經(jīng)講過(guò)了,,攤手,,聰明懶散如我肯定不會(huì)重復(fù)說(shuō)明,。
第15行代碼利用單元格的MergeArea屬性,獲取合并單元格區(qū)域,,并賦值給變量rngMerge,;如果沒(méi)有合并單元格,則返回單元格自身,。
第16行代碼計(jì)算合并單元格的行數(shù),,并賦值變量c。
第17行至19行代碼判斷合并單元格的行數(shù)是否大于1,,如果條件成立,,則取消合并單元格,同時(shí)將合并區(qū)域填充為首個(gè)單元格的值,。
第20行代碼讓變量i跳過(guò)已處理的合并單元格的行數(shù),,避免重復(fù)循環(huán)。
……
……
就這樣,,沒(méi)了,。
本期作業(yè)是下載示例文件,獨(dú)立完成編寫單元格合并與撤銷的代碼,;操作區(qū)域可以固定為B1:B13區(qū)域,,不用通過(guò)交互語(yǔ)句實(shí)現(xiàn)動(dòng)態(tài)選取,。
|