做了幾個(gè)月的Excel VBA,總結(jié)了一些常用的代碼倔约,我平時(shí)編程的時(shí)候參考這些代碼,基本可以完成大部分的工作坝初,現(xiàn)在共享出來供大家參考浸剩。
說明:本文為大大佐原創(chuàng),但部分代碼也是參考百度得來鳄袍。
初始化
Dim rng As Range, first_row, last_row, first_col,last_col,i, path As String
'intersect語句避免選擇整列造成無用計(jì)算
Set rng = Intersect(ActiveSheet.UsedRange, Selection)
'選中區(qū)域開始行號(hào)
first_row = rng.Row
'選中區(qū)域結(jié)束行號(hào)
last_row = first_row + rng.Rows.Count - 1
'選中區(qū)域開始列號(hào)
first_col = rng.Column
'選中區(qū)域結(jié)束列號(hào)
last_col = first_col + rng.Column .Count - 1
'獲取sheet1
Set sh = Sheets("sheets1")
'提示框確認(rèn)绢要,會(huì)暫停程序執(zhí)行
MsgBox "完成任務(wù)成功"
For i = first_row To last_row Step 1 '正序循環(huán) 從 first_row 到 last_row 每次循環(huán)+1
Next i
For i = 5 To 1000 Step 1 '正序循環(huán) 5 到1000 每次循環(huán)+1
Next i
If i Mod 2 = 0 Then ' 判斷i 對(duì)2取余為0則真
MsgBox "等于0"
Else
MsgBox "不等于0"
End If
Dim isBlank As Boolean
isBlank = Cells(i, 1).Value = "" '存儲(chǔ)單元格是否為空的結(jié)果
改變背景色
Range("A1").Interior.ColorIndex = xlNone
ColorIndex一覽
![image.png](https://upload-images.jianshu.io/upload_images/3947356-56ca2d9fe468334a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
改變文字顏色
Range("A1").Font.ColorIndex = 1
獲取單元格
Cells(1, 2)
Range("H7")
獲取范圍
Range(Cells(2, 3), Cells(4, 5))
Range("a1:c3")
'用快捷記號(hào)引用單元格
Worksheets("Sheet1").[A1:B5]
選中某sheet
Set NewSheet = Sheets("sheet1")
NewSheet.Select
選中或激活某單元格
'“Range”對(duì)象的的Select方法可以選擇一個(gè)或多個(gè)單元格,而Activate方法可以指定某一個(gè)單元格為活動(dòng)單元格畦木。
'下面的代碼首先選擇A1:E10區(qū)域袖扛,同時(shí)激活D4單元格:
Range("a1:e10").Select
Range("d4:e5").Activate
'而對(duì)于下面的代碼:
Range("a1:e10").Select
Range("f11:g15").Activate
'由于區(qū)域A1:E10和F11:G15沒有公共區(qū)域,將最終選擇F11:G15十籍,并激活F11單元格蛆封。
獲得文檔的路徑和文件名
ActiveWorkbook.Path '路徑
ActiveWorkbook.Name '名稱
ActiveWorkbook.FullName '路徑+名稱
'或?qū)ctiveWorkbook換成thisworkbook
隱藏文檔
Application.Visible = False
禁止屏幕更新
Application.ScreenUpdating = False
禁止顯示提示和警告消息
Application.DisplayAlerts = False
文件夾做成
strPath = "C:\temp"
MkDir strPath
狀態(tài)欄文字表示
Application.StatusBar = "計(jì)算中"
雙擊單元格內(nèi)容變換
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If (Target.Cells.Row >= 5 And Target.Cells.Row <= 8) Then
If Target.Cells.Value = "●" Then
Target.Cells.Value = ""
Else
Target.Cells.Value = "●"
End If
Cancel = True
End If
End Sub
文件夾選擇框方法1
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.BrowseForFolder(0, "文件", 0, 0)
If Not objFolder Is Nothing
Then path= objFolder.self.Path & ""
end if
Set objFolder = Nothing
Set objShell = Nothing
文件夾選擇框方法2(推薦)
Public Function ChooseFolder() As String
Dim dlgOpen As FileDialog
Set dlgOpen = Application.FileDialog(msoFileDialogFolderPicker)
With dlgOpen
.InitialFileName = ThisWorkbook.path & ""
If .Show = -1 Then
ChooseFolder = .SelectedItems(1)
End If
End With
Set dlgOpen = Nothing
End Function
'使用方法例:
Dim path As String
path = ChooseFolder()
If path <> "" Then
MsgBox "open folder"
End If
文件選擇框方法
Public Function ChooseOneFile(Optional TitleStr As String = "Please choose a file", Optional TypesDec As String = ".", Optional Exten As String = ".") As String
Dim dlgOpen As FileDialog
Set dlgOpen = Application.FileDialog(msoFileDialogFilePicker)
With dlgOpen
.Title = TitleStr
.Filters.Clear
.Filters.Add TypesDec, Exten
.AllowMultiSelect = False
.InitialFileName = ThisWorkbook.Path
If .Show = -1 Then
' .AllowMultiSelect = True
' For Each vrtSelectedItem In .SelectedItems
' MsgBox "Path name: " & vrtSelectedItem
' Next vrtSelectedItem
ChooseOneFile = .SelectedItems(1)
End If
End With
Set dlgOpen = Nothing
End Function
某列到關(guān)鍵字為止循環(huán)方法1(假設(shè)關(guān)鍵字是end)
Set CurrentCell = Range("A1")
Do While CurrentCell.Value <> "end"
……
Set CurrentCell = CurrentCell.Offset(1, 0)
Loop
某列到關(guān)鍵字為止循環(huán)方法2(假設(shè)關(guān)鍵字是空字符串)
i = StartRow
Do While Cells(i, 1) <> ""
……
i = i + 1
Loop
"For Each...Next 循環(huán)(知道確切邊界)
For Each c In Worksheets("Sheet1").Range("A1:D10").Cells
If Abs(c.Value) < 0.01 Then c.Value = 0
Next
"For Each...Next 循環(huán)(不知道確切邊界),在活動(dòng)單元格周圍的區(qū)域內(nèi)循環(huán)
For Each c In ActiveCell.CurrentRegion.Cells
If Abs(c.Value) < 0.01 Then c.Value = 0
Next
某列有數(shù)據(jù)的最末行的行數(shù)的取得(中間不能有空行)
lonRow=1
Do While Trim(Cells(lonRow, 2).Value) <> ""
lonRow = lonRow + 1
Loop
lonRow11 = lonRow11 - 1
A列有數(shù)據(jù)的最末行的行數(shù)的取得 另一種方法
Range("A65536").End(xlUp).Row
將文字復(fù)制到剪貼板
Dim MyData As DataObject
Set MyData = New DataObject
MyData.SetText Range("H7").Value
MyData.PutInClipboard
取得路徑中的文件名
Private Function GetFileName(ByVal s As String)
Dim sname() As String
sname = Split(s, "")
GetFileName = sname(UBound(sname))
End Function
取得路徑中的路徑名
Private Function GetPathName(ByVal s As String)
intFileNameStart = InStrRev(s, "")
GetPathName = Mid(s, 1, intFileNameStart)
End Function
由模板sheet拷貝做成一個(gè)新的sheet
ThisWorkbook.Worksheets("template").Copy After:=ThisWorkbook.Worksheets(Sheets.Count)
Set doc_s = ThisWorkbook.Worksheets(Sheets.Count)
doc_s.Name = "newsheetname" & Format(Now, "yyyyMMddhhmmss")
選中當(dāng)列的最后一個(gè)有內(nèi)容的單元格(中間不能有空行)
'刪除B3開始到B列最后一個(gè)有內(nèi)容的單元格為止的所有內(nèi)容
Range("B3").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.ClearContents
常量定義
Private Const StartRow As Integer = 3
判斷sheet是否存在
Private Function IsWorksheet(ByVal strSeetName As String) As Boolean
On Error GoTo ErrHandle
Dim blnRet As Boolean
blnRet = IsNull(Worksheets(strSeetName))
IsWorksheet = True
Exit Function
ErrHandle:
IsWorksheet = False
End Function
向單元格中寫入公式
Worksheets("Sheet1").Range("D6").Formula = "=SUM(D2:D5)"
引用命名單元格區(qū)域
Range("MyBook.xls!MyRange")
Range("[Report.xls]Sheet1!Sales"
選定命名的單元格區(qū)域
Application.Goto Reference:="MyBook.xls!MyRange"
'或者
worksheets("sheetname").range("rangename").select
Selection.ClearContents
使用Dictionary
'使用Dictionary需要添加參照Microsoft Scripting Runtime
Dim dic As New Dictionary
dic.Add "Table", "Cards" '前面是 Key 后面是 Value
dic.Add "Serial", "serialno"
dic.Add "Number", "surface"
MsgBox dic.Item("Table") '由Key取得Value
dic.Exists("Table") '判斷某Key是否存在
將EXCEL表格中的兩列表格插入到一個(gè)Dictionary中
'函數(shù):在ws工作表中,從iStartRow行開始到?jīng)]有數(shù)據(jù)為止勾栗,把iKeyCol列和iKeyCol右一列插入到一個(gè)字典中惨篱,并返回字典。
Public Function SetDic(ws As Worksheet, iStartRow, iKeyCol As Integer) As Dictionary
Dim dic As New Dictionary
Dim i As Integer
i = iStartRow
Do Until ws.Cells(i, iRuleCol).Value = ""
If Not dic.Exists(ws.Cells(i, iKeyCol).Value) Then
dic.Add ws.Cells(i, iKeyCol).Value, ws.Cells(i, iKeyCol + 1).Value
End If
i = i + 1
Loop
Set SetDic = dic
End Function
判斷文件夾或文件是否存在
'文件夾
If Dir("C:\aaa", vbDirectory) = "" Then
MkDir "C:\aaa"
End If
'文件
If Dir("C:\aaa\1.txt") = "" Then
msgbox "文件C:\aaa\1.txt不存在"
end if
一次注釋多行
視圖---工具欄---編輯 調(diào)出編輯工具欄围俘,工具欄上有個(gè)“設(shè)置注釋塊” 和 “解除注釋快”
打開文件并將文件賦予到第一個(gè)參數(shù)wb中
'注意砸讳,這里的path是文件的完整路徑,包括文件名界牡。
Public Function OpenWorkBook(wb As Workbook, path As String) As Boolean
On Error GoTo Err
OpenWorkBook = True
Dim isWbOpened As Boolean
isWbOpened = False
Dim fileName As String
fileName = GetFileName(path)
'check file is opened or either
Dim wbTemp As Workbook
For Each wbTemp In Workbooks
If wbTemp.Name = fileName Then isWbOpened = True
Next
'open file
If isWbOpened = False Then
Workbooks.Open path
End If
Set wb = Workbooks(fileName)
Exit Function
Err:
OpenWorkBook = False
End Function
打開一個(gè)文件簿寂,并將文件賦予到wb中,將文件的sheet頁賦予到ws中的完整代碼宿亡。(用到了上面的函數(shù))
'If OpenWorkBook(wb, path & "" & "filename") = False Then
MsgBox "open file error."
GoTo Err
End If
wb.Activate
Set ws = wb.Worksheets("sheetname")
打開一個(gè)不知道確切名字的文件(文件名中含有serachname)常遂,并將文件賦予到wb中,將文件的sheet頁賦予到ws中的完整代碼挽荠。
'用到了上上面的函數(shù)OpenWorkBook
'If OpenCompanyFile(wb, path, "searchname") = False Then
MsgBox "open file error."
GoTo Err
End If
wb.Activate
Set ws = wb.Worksheets("sheetname")
'直接使用的函數(shù)OpenCompanyFile
Function OpenCompanyFile(wbCom As Workbook, strPath As String, strFileName As String) As Boolean
Dim fs As Variant
fs = Dir(strPath & "\*.xls") 'seach files
OpenCompanyFile = False
Do While fs <> ""
If InStr(1, fs, strFileName) > 0 Then 'file name match
If OpenWorkBook(wbCom, strPath & "\" & fs) = False Then 'open file
OpenCompanyFile = False
Exit Do
Else
OpenCompanyFile = True
Exit Do
End If
End If
fs = Dir
Loop
End Function
數(shù)字轉(zhuǎn)字母(如1轉(zhuǎn)成A克胳,2轉(zhuǎn)成B)和字母轉(zhuǎn)數(shù)字
Chr(i + 64)
比如i=1的時(shí)候平绩,Chr(i + 64)=A
Asc(i - 64)
比如i=A的時(shí)候,Asc(i - 64)=1
復(fù)選框總開關(guān)實(shí)現(xiàn)漠另。假如有10個(gè)子checkbox1~checkbox10捏雌,還有一個(gè)總開關(guān)checkbox11,讓checkbox11控制1~10的選擇和非選擇笆搓。
Private Sub CheckBox11_Click()
Dim chb As Variant
If Me.CheckBox11.Value = True Then
For Each chb In ActiveSheet.OLEObjects
If chb.Name Like "CheckBox*" And chb.Name <> "CheckBox11" Then
chb.Object.Value = True
End If
Next
Else
For Each chb In ActiveSheet.OLEObjects
If chb.Name Like "CheckBox*" And chb.Name <> "CheckBox11" Then
chb.Object.Value = False
End If
Next
End If
End Sub
修改B6單元格所在的pivot的數(shù)據(jù)源性湿,并刷新pivot
Set pvt = ActiveSheet.Range("B6").PivotTable
pvt.ChangePivotCache ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
"SheetName!R4C2:R" & lngLastRow & "C22", Version:=xlPivotTableVersion10)
pvt.PivotCache.Refresh
將一個(gè)圖形(比如一個(gè)長(zhǎng)方形的框"Rectangle 2")移動(dòng)到與某個(gè)單元格對(duì)齊。
ws.Activate
Application.ScreenUpdating = True
ws.Shapes.Range(Array("Rectangle 2")).Select
ws.Shapes.Range(Array("Rectangle 2")).Top = ws.Range("T5").Top
ws.Shapes.Range(Array("Rectangle 2")).Left = ws.Range("T5").Left
Application.ScreenUpdating = False
遍歷控件满败。比如遍歷所有的checkbox是否被打挑窘奏。
If Me.OLEObjects("CheckBox" & i).Object.Value = True Then
flgChecked = True
end if
得到今天的日期
dateNow = WorksheetFunction.Text(Now(), "YYYY/MM/DD")
在某個(gè)sheet頁中查找某個(gè)關(guān)鍵字
'****************************************************
'Search keyword from a worksheet(not workbook!)
'****************************************************
Public Function SearchKeyWord(ws As Worksheet, keyword As String) As Boolean
Dim var1 As Variant
Set var1 = ws.Cells.Find(What:=keyword, After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, MatchByte:=False, SearchFormat:=False)
If var1 Is Nothing Then
SearchKeyWord = False
Else
SearchKeyWord = True
End If
End Function
單元格為空,取不到值的時(shí)候葫录,轉(zhuǎn)化為空字符串。Empty to ""
'****************************************************
'Empty to ""
'****************************************************
Public Function ChangeEmptyToString(var As Variant) As String
On Error GoTo Err
ChangeEmptyToString = CStr(var)
Exit Function
Err:
ChangeEmptyToString = ""
End Function
單元格為空领猾,取不到值的時(shí)候米同,轉(zhuǎn)化為0。Empty to 0
'****************************************************
'Empty to 0
'****************************************************
Public Function ChangeEmptyToLong(var As Variant) As Long
On Error GoTo Err
ChangeEmptyToLong = CLng(var)
Exit Function
Err:
ChangeEmptyToLong = 0
End Function
找到某個(gè)sheet頁中使用的最末行
Me.UsedRange.Rows.Count
遍歷文件夾下的所有文件(自定義文件夾和后綴名)摔竿,并返回文件列表字典
Function SetFilesToDic(ByVal path As String, ByVal extension As String) As Dictionary
Dim MyFile As String
Dim s As String
Dim count As Integer
Dim dic As New Dictionary
If Right(path, 1) <> "\" Then
path = path & "\"
End If
MyFile = Dir(path & "*." & extension)
count = 1
Do While MyFile <> ""
' If MyFile = "" Then
' Exit Do
' End If
dic.Add count, MyFile
count = count + 1
MyFile = Dir
Loop
Set SetFilesToDic = dic
' Debug.Print s
End Function
生成log
Sub txtPrint(ByVal txt = "") '第2參數(shù)可以指定保存txt文件路徑
If myPath = "" Then myPath = ActiveWorkbook.path & "\log.txt"
Open myPath For Append As #1
Print #1, txt
Close #1
End Sub
? [Non-Breaking Space]網(wǎng)頁空格在VBA中的處理
替換字符
ChrB(160) & ChrB(0)
上述最終解決方法來自于http://www.blueshop.com.tw/board/FUM20060608180224R4M/BRD2009031011234606U/2.html
Sdany用戶是通過如下思路找到解決方法的(用MidB和AscB):
Dim I As Integer
For I = 1 To LenB(Cells(1, 1))
Debug.Print AscB(MidB(Cells(1, 1), I, 1))
Next
延時(shí)
這段代碼在Excel VBA 和VB里都可以用
'***********VB 延時(shí)函數(shù)定義*************************************
'聲明
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
'延時(shí)
Public Sub Delay(ByVal num As Integer)
Dim t As Long
t = timeGetTime
Do Until timeGetTime - t >= num * 1000
DoEvents
Loop
End Sub
'***************************************************************
使用方法:
delay 3'3表示秒數(shù)
殺掉某程序執(zhí)行的所有進(jìn)程
Sub KillWord()
Dim Process
For Each Process In GetObject("winmgmts:").ExecQuery("select * from Win32_Process where name='WINWORD.EXE'")
Process.Terminate (0)
Next
End Sub
監(jiān)視某單元格的變化
這里最需要注意的問題就是面粮,如果在這個(gè)事件里對(duì)單元格進(jìn)行改變,會(huì)繼續(xù)出發(fā)此事件變成死循環(huán)继低。
所以要在對(duì)單元格進(jìn)行變化之前加上Application.EnableEvents = False熬苍,變完之后再改為True。
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Err
Application.EnableEvents = False
Dim c
Set dicKtoW = SetDic(ThisWorkbook.Sheets("reference"), 3, 1, 2)
Set dicKtoX = SetDic(ThisWorkbook.Sheets("reference"), 3, 1, 3)
For Each c In Target
If c.Column = 11 Then
'MsgBox c.Value
Me.Range("W" & c.Row).Value = GetDic(dicKtoW, c.Value)
Me.Range("X" & c.Row).Value = GetDic(dicKtoX, c.Value)
End If
Next
Set dicKtoW = Nothing
Set dicKtoX = Nothing
Application.EnableEvents = True
Exit Sub
Err:
MsgBox ("Error!Please contact macro developer.")
Application.EnableEvents = True
End Sub
On Error的用法
1.一般用法
On Error GoTo Label
各種代碼
exit sub
Label:
msgbox Err.Description
其他錯(cuò)誤處理
2.對(duì)于某段代碼單獨(dú)處理
On Error Resume Next
需要監(jiān)視的代碼
If Err.Number <> 0 Then
MsgBox Err.Description
End If
On Error GoTo 0
3.上述兩種的結(jié)合
On Error Resume Next
需要監(jiān)視的代碼
If Err.Number <> 0 Then
MsgBox Err.Description
Goto Label
End If
On Error GoTo 0
exit sub
Label:
其他錯(cuò)誤處理
EXCEL的分組功能和展開收縮功能
'將A列到C列進(jìn)行分組
Range("A:C").Columns.Group
'默認(rèn)情況下袁翁,分組后的A到C列會(huì)是展開狀態(tài)柴底,如果想讓A到C列收縮
Range("A:C").EntireColumn.Hidden=True