Excel Power

Liên hệ QC

levanduyet

Hãy để gió cuốn đi.
Thành viên danh dự
Tham gia
30/5/06
Bài viết
1,798
Được thích
4,700
Giới tính
Nam
Bí mật quan trọng của các lập trình viên thành công là đừng bao giờ tốn thời gian để viết lại những đoạn code đã có (nếu bạn dư thời gian thì cứ xin mời)

Trong topic này chúng ta sẽ được xem các đoạn code của các lập trình viên VBA (thường là các chuyên gia). Các đoạn code này đã được kiểm chứng nên các bạn có thể yên tâm sử dụng chúng.
Lưu ý rằng, các đoạn code chỉ thực hiện một cách tổng quát chủ đích đưa ra. Còn việc áp dụng vào từng vấn đề của các bạn, các bạn vui lòng chỉnh sửa theo ý của mình.


1. Làm việc với các tập tin

Liệt kê các tập tin trong một thư mục:
Code của Nathan P. Oliver


Chương trình sẽ liệt kê: tên tập tin, kích thước, ngày chỉnh sửa của tất cả các tập tin trong thư mục được chọn và cả thư mục con của thư mục được chọn.
Mã:
Sub ExcelFileSearch()
    Dim srchExt As Variant, srchDir As Variant, i As Long, j As Long
    Dim strName As String, varArr(1 To 1048576, 1 To 3) As Variant
    Dim strFileFullName As String
    Dim ws As Worksheet
    Dim fso As Object
    Let srchExt = Application.InputBox("Please Enter File Extension", "Info Request")
    If srchExt = False And Not TypeName(srchExt) = "String" Then
        Exit Sub
    End If
    Let srchDir = BrowseForFolderShell
    If srchDir = False And Not TypeName(srchDir) = "String" Then
        Exit Sub
    End If
    Application.ScreenUpdating = False
    Set ws = ThisWorkbook.Worksheets.Add(Sheets(1))
    On Error Resume Next
    Application.DisplayAlerts = False
    ThisWorkbook.Worksheets("FileSearch Results").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0
    ws.Name = "FileSearch Results"
    Let strName = Dir$(srchDir & "\*" & srchExt)
    Do While strName <> vbNullString
        Let i = i + 1
        Let strFileFullName = srchDir & strName
        Let varArr(i, 1) = strFileFullName
        Let varArr(i, 2) = FileLen(strFileFullName) \ 1024
        Let varArr(i, 3) = FileDateTime(strFileFullName)
        Let strName = Dir$()
    Loop
    Set fso = CreateObject("Scripting.FileSystemObject")
    Call recurseSubFolders(fso.GetFolder(srchDir), varArr(), i, CStr(srchExt))
    Set fso = Nothing
    ThisWorkbook.Windows(1).DisplayHeadings = False
    With ws
        If i > 0 Then
            .Range("A2").Resize(i, UBound(varArr, 2)).Value = varArr
            For j = 1 To i
                .Hyperlinks.Add anchor:=.Cells(j + 1, 1), Address:=varArr(j, 1)
            Next
        End If
        .Range(.Cells(1, 4), .Cells(1, .Columns.Count)).EntireColumn.Hidden = True
        .Range(.Cells(.Rows.Count, 1).End(xlUp)(2), _
               .Cells(.Rows.Count, 1)).EntireRow.Hidden = True
        With .Range("A1:C1")
            .Value = Array("Full Name", "Kilobytes", "Last Modified")
            .Font.Underline = xlUnderlineStyleSingle
            .EntireColumn.AutoFit
            .HorizontalAlignment = xlCenter
        End With
    End With
    Application.ScreenUpdating = True
End Sub
Private Sub recurseSubFolders(ByRef Folder As Object, _
                              ByRef varArr() As Variant, _
                              ByRef i As Long, _
                              ByRef srchExt As String)
    Dim SubFolder As Object
    Dim strName As String, strFileFullName As String
    For Each SubFolder In Folder.SubFolders
        Let strName = Dir$(SubFolder.Path & "\*" & srchExt)
        Do While strName <> vbNullString
            Let i = i + 1
            Let strFileFullName = SubFolder.Path & "\" & strName
            Let varArr(i, 1) = strFileFullName
            Let varArr(i, 2) = FileLen(strFileFullName) \ 1024
            Let varArr(i, 3) = FileDateTime(strFileFullName)
            Let strName = Dir$()
        Loop
        If i > 1048576 Then Exit Sub
        Call recurseSubFolders(SubFolder, varArr(), i, srchExt)
    Next
End Sub
Private Function BrowseForFolderShell() As Variant
    Dim objShell As Object, objFolder As Object
    Set objShell = CreateObject("Shell.Application")
    Set objFolder = objShell.BrowseForFolder(0, "Please select a folder", 0, "C:\")
    If Not objFolder Is Nothing Then
        On Error Resume Next
        If IsError(objFolder.Items.Item.Path) Then
            BrowseForFolderShell = CStr(objFolder)
        Else
            On Error GoTo 0
            If Len(objFolder.Items.Item.Path) > 3 Then
                BrowseForFolderShell = objFolder.Items.Item.Path & _
                                       Application.PathSeparator
            Else
                BrowseForFolderShell = objFolder.Items.Item.Path
            End If
        End If
    Else
        BrowseForFolderShell = False
    End If
    Set objFolder = Nothing: Set objShell = Nothing
End Function

Lê Văn Duyệt

Nguồn: MrExcel Library
 
Lần chỉnh sửa cuối:
2. Nhập dữ liệu từ một tập tin comma-separated variable (CSV)

Code của Masaru Kaji ở thành phố Kobe, Nhật bản.

Ví dụ sau sẽ mở tập tin CSV trong Excel và xóa tập tin này đi.

Mã:
Sub OpenLargeCSVFast()
    Dim buf(1 To 16384) As Variant
    Dim i As Long

    'Ban thay duong dan va ten tap tin CSV o day
    Const strFilePath As String = "C:\temp\Test.CSV"

    Dim strRenamedPath As String
    strRenamedPath = Split(strFilePath, ".")(0) & "txt"
    With Application
        .ScreenUpdating = False
        .DisplayAlerts = False
    End With
    ' Thiet lap mot mang cho FieldInfo de mo tap tin CSV
    For i = 1 To 16384
        buf(i) = Array(i, 2)
    Next
    Name strFilePath As strRenamedPath
    Workbooks.OpenText Filename:=strRenamedPath, DataType:=xlDelimited, _
                       Comma:=True, FieldInfo:=buf
    Erase buf
    ActiveSheet.UsedRange.Copy ThisWorkbook.Sheets(1).Range("A1")
    ActiveWorkbook.Close False
    Kill strRenamedPath
    With Application
        .ScreenUpdating = True
        .DisplayAlerts = True
    End With
End Sub

Lê Văn Duyệt

Nguồn: MrExcel Library
 
3. Lấy dữ liệu từ tập tin text đưa vào Excel

Code của Suat Mehmet Ozgur Thổ Nhỉ Kỳ.

Thay vì đọc từng record một lần, đoạn code sau đưa nội dung vào bộ nhớ thông qua biến kiểu chuổi.
Sau đó xử lý biến chuổi này mà đưa từng dòng vào từng ô của Excel.

Chính vì vậy cách này rất nhanh.

Mã:
Sub ReadTxtLines()
'Do dung khai bao tre, nen khong can phai tham chieu den thu vien Scripting Runtime trong reference
    Dim sht As Worksheet
    Dim fso As Object
    Dim fil As Object
    Dim txt As Object
    Dim strtxt As String
    Dim tmpLoc As Long
    'Lam viec voi Sheet hien tai
    Set sht = ActiveSheet
    'Xoa du lieu tren Sheet hien tai
    sht.UsedRange.ClearContents
    'Tao doi tuong File system chung ta can de lam viec voi tap tin
    Set fso = CreateObject("Scripting.FileSystemObject")
    'Tap tin ban can mo
    Set fil = fso.GetFile("c:\service.log")
    'Mo tap tin nhu la mot  TextStream
    Set txt = fil.OpenAsTextStream(1)
    'Doc noi dung va dua vao bien kieu chuoi
    strtxt = txt.ReadAll
    'Dong textstream
    txt.Close
    'Tim ky tu xuong hang dau tien
    tmpLoc = InStr(1, strtxt, vbCrLf)
    'Dung vong lap de quet qua tung hang
    Do Until tmpLoc = 0
        sht.Cells(sht.Rows.Count, 1).End(xlUp).Offset(1).Value = _
        Left(strtxt, tmpLoc - 1)
        strtxt = Right(strtxt, Len(strtxt) - tmpLoc - 1)
        tmpLoc = InStr(1, strtxt, vbCrLf)
    Loop
    sht.Cells(sht.Rows.Count, 1).End(xlUp).Offset(1).Value = strtxt
    ' Giai phong bo nho
    Set fso = Nothing
End Sub

Lê Văn Duyệt

Nguồn: MrExcel Library
 
Lần chỉnh sửa cuối:
4. Tách từng sheet ra một workbook khác

Code của Tommy Miles Houston, Texas.

Đôi khi bạn muốn tách từng sheet thành một workbook khác nhau, code sau sẽ giúp bạn làm điều đó.

Bạn cần phải chọn lưu dưới dạng:
  • XLSM (macro-enabled)
  • XLSX (macros sẽ bị xoá)

Tác giả đề nghị xuất ra dạng xlsx.

Mã:
Sub SplitWorkbook()
    Dim ws As Worksheet
    Dim DisplayStatusBar As Boolean
    DisplayStatusBar = Application.DisplayStatusBar
    Application.DisplayStatusBar = True
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    For Each ws In ThisWorkbook.Sheets
        Dim NewFileName As String
        Application.StatusBar = ThisWorkbook.Sheets.Count & " Remaining Sheets"""
        If ThisWorkbook.Sheets.Count <> 1 Then
            NewFileName = ThisWorkbook.Path & "\" & ws.Name & ".xlsm"    'Macro _-Enabled
            ' NewFileName = ThisWorkbook.Path & "\" & ws.Name & ".xlsx" _
              ' Not Macro-Enabled
            ws.Copy
            ActiveWorkbook.Sheets(1).Name = "Sheet1"""
            ActiveWorkbook.SaveAs Filename:=NewFileName, _
                                  FileFormat:=xlOpenXMLWorkbookMacroEnabled
            ' ActiveWorkbook.SaveAs Filename:=NewFileName, _
              ' FileFormat:=xlOpenXMLWorkbook
            ActiveWorkbook.Close SaveChanges:=False
        Else
            NewFileName = ThisWorkbook.Path & " \ " & ws.Name & ".xlsm"
            ' NewFileName = ThisWorkbook.Path & " \ " & ws.Name & ".xlsx"
            ws.Name = "Sheet1"""
        End If
    Next
    Application.DisplayAlerts = True
    Application.StatusBar = False
    Application.DisplayStatusBar = DisplayStatusBar
    Application.ScreenUpdating = True
End Sub

Lê Văn Duyệt

Nguồn: MrExcel
 
Lần chỉnh sửa cuối:
5. Tổng hợp hai workbook lại với nhau

Code của Tommy Miles Houston, Texas.

Ví dụ sau sẽ tổng hợp tất cả các tập tin Excel trong cùng một thư mục xác định và tổng hợp lại thành một workbook mà thôi.
Đặt tên sheet mới dựa vào tên củ của nó. Chính vì vậy các bạn cũng nên chú ý điều này.

Mã:
Sub CombineWorkbooks()
    Dim CurFile As String, DirLoc As String
    Dim DestWB As Workbook
    Dim ws As Object    'Nhằm cho phép nhiều loại sheet
    ' Đường dẫn đến các tập tin
    DirLoc = ThisWorkbook.Path & "\tst\"   
    CurFile = Dir(DirLoc & "*.xls*")
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Set DestWB = Workbooks.Add(xlWorksheet)
    Do While CurFile <> vbNullString
        Dim OrigWB As Workbook
        Set OrigWB = Workbooks.Open(Filename:=DirLoc & CurFile, ReadOnly:=True)
        ' Limit to valid sheet names and removes .xls*
        CurFile = Left(Left(CurFile, Len(CurFile) - 5), 29)
        For Each ws In OrigWB.Sheets
            ws.Copy After:=DestWB.Sheets(DestWB.Sheets.Count)
            If OrigWB.Sheets.Count > 1 Then
                DestWB.Sheets(DestWB.Sheets.Count).Name = CurFile & ws.Index
            Else
                DestWB.Sheets(DestWB.Sheets.Count).Name = CurFile
            End If
        Next
        OrigWB.Close SaveChanges:=False
        CurFile = Dir
    Loop
    Application.DisplayAlerts = False
    DestWB.Sheets(1).Delete
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    Set DestWB = Nothing
End Sub

Lê Văn Duyệt

Nguồn: MrExcel
 
6. Lọc và copy dữ liệu qua một sheet khác

Code của Dennis Wallentin Ostersund, Sweden.

Ví dụ sau sẽ lọc dữ liệu ở một cột nhất định và đưa kết quả sang một sheet khác của workbook hiện tại (active workbook)

Mã:
Sub Filter_NewSheet()
    Dim wbBook As Workbook
    Dim wsSheet As Worksheet
    Dim rnStart As Range, rnData As Range
    Dim i As Long
    Set wbBook = ThisWorkbook
    Set wsSheet = wbBook.Worksheets("Sheet1")
    With wsSheet
        'Make sure that the first row contains headings.
        Set rnStart = .Range("A2")
        Set rnData = .Range(.Range("A2"), .Cells(.Rows.Count, 3).End(xlUp))
    End With
    Application.ScreenUpdating = True
    For i = 1 To 5
        'Here we filter the data with the first criterion.
        rnStart.AutoFilter Field:=1, Criteria1:="AA" & i
        'Copy the filtered list
        rnData.SpecialCells(xlCellTypeVisible).Copy
        'Add a new worksheet to the active workbook.
        Worksheets.Add Before:=wsSheet
        'Name the added new worksheets.
        ActiveSheet.Name = "AA" & i
        'Paste the filtered list.
        Range("A2").PasteSpecial xlPasteValues
    Next i
    'Reset the list to its original status.
    rnStart.AutoFilter Field:=1
    With Application
        .CutCopyMode = False
        .ScreenUpdating = False
    End With
End Sub

Lê Văn Duyệt

Nguồn: MrExcel
 
Lần chỉnh sửa cuối:
7. Liệt ke comments

Code của Tommy Miles.

Excel cho phép người dùng in comment trong workbook, nhưng không cho biết comment đó thuộc workbook nào hay sheet nào.

Ví dụ sau sẽ liệt kê Author (tác giả), Workbook, Sheet, Ô nào, và nội dung comment là gì.

Mã:
Sub ListComments()
    Dim wb As Workbook
    Dim ws As Worksheet
    Dim cmt As Comment
    Dim cmtCount As Long
    cmtCount = 2
    On Error Resume Next
    Set ws = ActiveSheet
    If ws Is Nothing Then Exit Sub
    On Error GoTo 0
    Application.ScreenUpdating = False
    Set wb = Workbooks.Add(xlWorksheet)
    With wb.Sheets(1)
        .Range("$A$1") = "Author"
        .Range("$B$1") = "Book"
        .Range("$C$1") = "Sheet"
        .Range("$D$1") = "Range"
        .Range("$E$1") = "Comment"
    End With
    For Each cmt In ws.Comments
        With wb.Sheets(1)
            .Cells(cmtCount, 1) = cmt.author
            .Cells(cmtCount, 2) = cmt.Parent.Parent.Parent.Name
            .Cells(cmtCount, 3) = cmt.Parent.Parent.Name
            .Cells(cmtCount, 4) = cmt.Parent.Address
            .Cells(cmtCount, 5) = CleanComment(cmt.author, cmt.Text)
        End With
        cmtCount = cmtCount + 1
    Next
    wb.Sheets(1).UsedRange.WrapText = False
    Application.ScreenUpdating = True
    Set ws = Nothing
    Set wb = Nothing
End Sub
Private Function CleanComment(author As String, cmt As String) As String
    Dim tmp As String
    tmp = Application.WorksheetFunction.Substitute(cmt, author & ":", "")
    tmp = Application.WorksheetFunction.Substitute(tmp, Chr(10), "")
    CleanComment = tmp
End Function

Lê Văn Duyệt

Nguồn: MrExcel
 
8. Thay đổi kích thước của comments

Code của Tom Urtis, San Francisco, California.


Excel không tự động thay đổi kích thước của comment. Ngoài ra nếu bạn có nhiều comment cần phải chỉnh sửa kích thước, nếu bạn là phải chỉnh sửa từng cái một... chắc chết quá. Đoạn code sau sẽ giúp bạn làm điều đó.

Mã:
Sub CommentFitter1()
    Application.ScreenUpdating = False
    Dim x As Range, y As Long
    For Each x In Cells.SpecialCells(xlCellTypeComments)
        Select Case True
        Case Len(x.NoteText) <> 0
            With x.Comment
                .Shape.TextFrame.AutoSize = True
                If .Shape.Width > 250 Then
                    y = .Shape.Width * .Shape.Height
                    .Shape.Width = 150
                    .Shape.Height = (y / 200) * 1.3
                End If
            End With
        End Select
    Next x
    Application.ScreenUpdating = True
End Sub

Lê Văn Duyệt

Nguồn: MrExcel
 
9. Thay đổi kích thước và canh giữa nội dung của comments

Code của Tom Urtis, San Francisco, California.

Đôi khi ngoài việc thay đổi kích thước của comment bạn còn muốn canh giữa nữa. Đoạn code sau sẽ giúp các bạn thực hiện điều đó:

Mã:
Sub CommentFitter2()
    Application.ScreenUpdating = False
    Dim x As Range, y As Long
    For Each x In Cells.SpecialCells(xlCellTypeComments)
        Select Case True
        Case Len(x.NoteText) <> 0
            With x.Comment
                .Shape.TextFrame.AutoSize = True
                If .Shape.Width > 250 Then
                    y = .Shape.Width * .Shape.Height
                    .Shape.ScaleHeight 0.9, msoFalse, msoScaleFromTopLeft
                    .Shape.ScaleWidth 1#, msoFalse, msoScaleFromTopLeft
                End If
            End With
        End Select
    Next x
    Application.ScreenUpdating = True
End Sub

Lê Văn Duyệt

Nguồn: MrExcel
 
10. Đưa Chart vào comments

Code của Tom Urtis, San Francisco, California.

Bạn có thể đưa hình ảnh vào comment, điều này chúng ta đã bàn nhiều lần trong diễn đàn.

Đoạn code sau sẽ giúp bạn thực hiện điều trên hoàn toàn tự động. Các bạn có thể thay đổi, hoặc chỉnh sửa theo nhu cầu của mình.

Mã:
Sub PlaceGraph()
    Dim x As String, z As Range
    Application.ScreenUpdating = False
    ' Đường dẫn tạm thời để lưu giữ hình ảnh
    ' Các bạn có thể thay đổi tùy theo nhu cầu của mình
    x = "C:\XWMJGraph.gif"
    ' Ô chứa comment
    Set z = Worksheets("ChartInComment").Range("A3")
    ' Xóa comment tại ô này
    On Error Resume Next
    z.Comment.Delete
    On Error GoTo 0
    ' Chọn và xuất chart
    ActiveSheet.ChartObjects("Chart 1").Activate
    ActiveChart.Export x
    ' Thêm comment mới vào ô, thiết lập kích thước và thêm chart (dạng hình ảnh) vào comment
    With z.AddComment
        With .Shape
            .Height = 322
            .Width = 465
            .Fill.UserPicture x
        End With
    End With
    ' Xóa tập tin hình ảnh tạm
    Kill x
    Range("A1").Activate
    Application.ScreenUpdating = True
    Set z = Nothing
End Sub

Lê Văn Duyệt

Nguồn: MrExcel
 
Web KT
Back
Top Bottom