Nhờ giúp đỡ sửa code lấy tên sheet

Liên hệ QC
Tôi tuân thủ nội quy khi đăng bài

hieuhus

Thành viên mới
Tham gia
5/11/10
Bài viết
19
Được thích
4
Chào cả nhà.
Mình có tìm được 1 đoạn VBA về việc lấy tên sheet. Do mình không biết gì về VBA cả nên nhờ mọi người sửa giúp mình.
Khi chạy code này thì sẽ bật / tắt các file excel, nếu 1 vài file thì không có vấn đề gì nhưng khi thực hiện 20-30 file thì màn hình cứ nhấp nháy bật / tắt file nhìn rất khó chịu.
Nhờ các bạn xóa đoạn code liên quan đến việc đó giúp mình.
Trân trọng cảm ơn.
------------------

Sub FolderCrawler()
FileType = "*.xls*" 'The file type to search for
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = ThisWorkbook.Path
.AllowMultiSelect = False
If .Show = -1 Then
FilePath = .SelectedItems(1) & "\"
Else
Exit Sub 'Cancel was pressed
End If

End With
OutputRow = 2 'The first row of the active sheet to start writing to
ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = FilePath & FileType
OutputRow = OutputRow + 1
Curr_File = Dir(FilePath & FileType)
Do Until Curr_File = ""
Set FldrWkbk = Workbooks.Open(FilePath & Curr_File, False, True)
ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = Curr_File
ThisWorkbook.ActiveSheet.Range("B" & OutputRow).ClearContents 'Clear any previous values
OutputRow = OutputRow + 1

For Each Sht In FldrWkbk.Sheets
ThisWorkbook.ActiveSheet.Range("B" & OutputRow) = Sht.Name
ThisWorkbook.ActiveSheet.Range("A" & OutputRow).ClearContents 'Clear any previous values
OutputRow = OutputRow + 1
Next Sht
FldrWkbk.Close SaveChanges:=False
Curr_File = Dir
Loop
Set FldrWkbk = Nothing
ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = "---END OF FOLDER---"
End Sub
 
Chào cả nhà.
Mình có tìm được 1 đoạn VBA về việc lấy tên sheet. Do mình không biết gì về VBA cả nên nhờ mọi người sửa giúp mình.
Khi chạy code này thì sẽ bật / tắt các file excel, nếu 1 vài file thì không có vấn đề gì nhưng khi thực hiện 20-30 file thì màn hình cứ nhấp nháy bật / tắt file nhìn rất khó chịu.
Nhờ các bạn xóa đoạn code liên quan đến việc đó giúp mình.
Trân trọng cảm ơn.
------------------

Sub FolderCrawler()
FileType = "*.xls*" 'The file type to search for
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = ThisWorkbook.Path
.AllowMultiSelect = False
If .Show = -1 Then
FilePath = .SelectedItems(1) & "\"
Else
Exit Sub 'Cancel was pressed
End If

End With
OutputRow = 2 'The first row of the active sheet to start writing to
ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = FilePath & FileType
OutputRow = OutputRow + 1
Curr_File = Dir(FilePath & FileType)
Do Until Curr_File = ""
Set FldrWkbk = Workbooks.Open(FilePath & Curr_File, False, True)
ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = Curr_File
ThisWorkbook.ActiveSheet.Range("B" & OutputRow).ClearContents 'Clear any previous values
OutputRow = OutputRow + 1

For Each Sht In FldrWkbk.Sheets
ThisWorkbook.ActiveSheet.Range("B" & OutputRow) = Sht.Name
ThisWorkbook.ActiveSheet.Range("A" & OutputRow).ClearContents 'Clear any previous values
OutputRow = OutputRow + 1
Next Sht
FldrWkbk.Close SaveChanges:=False
Curr_File = Dir
Loop
Set FldrWkbk = Nothing
ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = "---END OF FOLDER---"
End Sub
Không phải là xoá mà là thêm vào đầu chương trình
Mã:
Application.ScreenUpdating = False
Và cuối chương trình
Mã:
Application.ScreenUpdating = true
Thử xem nha!
 
Upvote 0
Khi chạy code này thì sẽ bật / tắt các file excel, nếu 1 vài file thì không có vấn đề gì nhưng khi thực hiện 20-30 file thì màn hình cứ nhấp nháy bật / tắt file nhìn rất khó chịu.
Nhờ các bạn xóa đoạn code liên quan đến việc đó giúp mình.
Trân trọng cảm ơn.
Thay code trên bằng code này. Sẽ không còn nhấp nháy màn hình nữa
Mã:
Sub FolderCrawler()
    Application.ScreenUpdating = 0
    Application.DisplayAlerts = 0
    FileType = "*.xls*" 'The file type to search for
    With Application.FileDialog(msoFileDialogFolderPicker)
        .InitialFileName = ThisWorkbook.Path
        .AllowMultiSelect = False
        If .Show = -1 Then
            FilePath = .SelectedItems(1) & "\"
        Else
            Exit Sub 'Cancel was pressed
        End If
    End With
    OutputRow = 2 'The first row of the active sheet to start writing to
    ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = FilePath & FileType
    OutputRow = OutputRow + 1
    Curr_File = Dir(FilePath & FileType)
    Do Until Curr_File = ""
        Set FldrWkbk = Workbooks.Open(FilePath & Curr_File, False, True)
        ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = Curr_File
        ThisWorkbook.ActiveSheet.Range("B" & OutputRow).ClearContents 'Clear any previous values
        OutputRow = OutputRow + 1
        For Each Sht In FldrWkbk.Sheets
            ThisWorkbook.ActiveSheet.Range("B" & OutputRow) = Sht.Name
            ThisWorkbook.ActiveSheet.Range("A" & OutputRow).ClearContents 'Clear any previous values
            OutputRow = OutputRow + 1
        Next Sht
        FldrWkbk.Close SaveChanges:=False
        Curr_File = Dir
    Loop
    Set FldrWkbk = Nothing
    ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = "---END OF FOLDER---"
    Application.ScreenUpdating = 1
    Application.DisplayAlerts = 1
End Sub
 
Upvote 0
Không phải là xoá mà là thêm vào đầu chương trình
Mã:
Application.ScreenUpdating = False
Và cuối chương trình
Mã:
Application.ScreenUpdating = true
Thử xem nha!
Mình thử được rồi. Cảm ơn bạn
Bài đã được tự động gộp:

Thay code trên bằng code này. Sẽ không còn nhấp nháy màn hình nữa
Mã:
Sub FolderCrawler()
    Application.ScreenUpdating = 0
    Application.DisplayAlerts = 0
    FileType = "*.xls*" 'The file type to search for
    With Application.FileDialog(msoFileDialogFolderPicker)
        .InitialFileName = ThisWorkbook.Path
        .AllowMultiSelect = False
        If .Show = -1 Then
            FilePath = .SelectedItems(1) & "\"
        Else
            Exit Sub 'Cancel was pressed
        End If
    End With
    OutputRow = 2 'The first row of the active sheet to start writing to
    ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = FilePath & FileType
    OutputRow = OutputRow + 1
    Curr_File = Dir(FilePath & FileType)
    Do Until Curr_File = ""
        Set FldrWkbk = Workbooks.Open(FilePath & Curr_File, False, True)
        ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = Curr_File
        ThisWorkbook.ActiveSheet.Range("B" & OutputRow).ClearContents 'Clear any previous values
        OutputRow = OutputRow + 1
        For Each Sht In FldrWkbk.Sheets
            ThisWorkbook.ActiveSheet.Range("B" & OutputRow) = Sht.Name
            ThisWorkbook.ActiveSheet.Range("A" & OutputRow).ClearContents 'Clear any previous values
            OutputRow = OutputRow + 1
        Next Sht
        FldrWkbk.Close SaveChanges:=False
        Curr_File = Dir
    Loop
    Set FldrWkbk = Nothing
    ThisWorkbook.ActiveSheet.Range("A" & OutputRow) = "---END OF FOLDER---"
    Application.ScreenUpdating = 1
    Application.DisplayAlerts = 1
End Sub
Cảm ơn bạn
Bài đã được tự động gộp:

Nhờ các bạn viết giúp mình 1 đoạn code tạo button Clear để trước khi chạy 1 folder mới thì click vào là xóa hết dữ liệu đã có
 
Lần chỉnh sửa cuối:
Upvote 0
Thay code trên bằng code này. Sẽ không còn nhấp nháy màn hình nữa
...
Cỡ hạng code hoành tráng thế này người ta viết cẩn thận hơn. Đề phòng trường hợp hàm được gọi từ hàm khác:

Sau dòng Sub..., thêm cái này:
GoSub SetScreenMode

Trước dòng End Sub, thêm cái này
GoSub ResetScreenMode
Exit Sub
' -------
SetScreenMode:
Dim ScreenUpdatingSaved, DíplayAlertsSaved
ScreenUpdatingSaved = Application.ScreenUpdating
DíplayAlertsSaved = Application.DíplayAlerts
Application.ScreenUpdating = False
Application.DíplayAlerts = False
Return
' --------
ResetScreenMode:
Application.ScreenUpdating = ScreenUpdatingSaved
Application.DíplayAlerts = DíplayAlertsSaved
Return
'===
End Sub

Như vậy, nếu hàm này được gọi từ hàm khác, nó cũng không làm hàm kia bị chưng hửng.
 
Lần chỉnh sửa cuối:
Upvote 0
Như vậy, nếu hàm này được gọi từ hàm khác, nó cũng không làm hàm kia bị chưng hửng.
Cháu chào chú. Cho cháu hỏi thêm 1 chút về vấn đề này xíu
Cái khúc dưới này sẽ được nằm trong Sub phải không ạ?
Tại trước giờ cháu thấy có cái đoạn Goto xxx gì đó thôi. Chưa thấy Gotosub như chú chỉ bao giờ
SetScreenMode:
Dim ScreenUpdatingSaved, DisplayAlertsSaved
ScreenUpdatingSaved = Application.ScreenUpdating
DíplayAlertsSaved = Application.DisplayAlerts
Application.ScreenUpdating = False
Application.DíplayAlerts = False
Return
' --------
ResetScreenMode:
Application.ScreenUpdating = ScreenUpdatingSaved
Application.DisplayAlerts = DisplayAlertsSaved
Return
'===
End Sub
Thêm 1 chút nữa chú có thể giải thích kỹ hơn về lợi ích mà mình làm như chú hướng dẫn được không ạ?
Tại cháu muốn hiểu chính xác những gì chú hướng dẫn và có thể áp dụng đúng những gì mình hiểu được ạ.
Cháu cảm ơn ạ!
 
Upvote 0
Cháu chào chú. Cho cháu hỏi thêm 1 chút về vấn đề này xíu
Cái khúc dưới này sẽ được nằm trong Sub phải không ạ?
Tại trước giờ cháu thấy có cái đoạn Goto xxx gì đó thôi. Chưa thấy Gotosub như chú chỉ bao giờ

GoSub chứ không phải GotoSub.
Đây là một lệnh thời thượng cổ. Nó dùng để rẽ nhánh chứ không phải gọi một Sub khác.

Sub con khác có tên tuổi cùng giao diện đàng hoàng. Và là giang sơn riêng biệt, chỉ chia với Sub gọi nó các món Public, và các tham gọi qua ByRef (giao diện).
Khi Sub con được gọi, mọi điều khiển được chuyển qua Sub con cho đến khi nó thoát thì trở về Sub mẹ.

Sub trong trường hợp của GoSub chỉ là một đoạn code đặt bên trong Sub mẹ.
Khi lệnh GoSub được chạy, VBA sẽ tạm save địa chỉ dòng hiện tại và dựa vào cái tên biểu (Label) mà rẽ nhánh vào đó (giống như Goto). Khi chạy đến lệnh Return thì VBA trở về dòng ngay sau địa chỉ mà nó đã saved.

Lưu ý: Cũng như lệnh Goto, nhiều dân lập trình không thích dùng cái này.

Thêm 1 chút nữa chú có thể giải thích kỹ hơn về lợi ích mà mình làm như chú hướng dẫn được không ạ?
Tại cháu muốn hiểu chính xác những gì chú hướng dẫn và có thể áp dụng đúng những gì mình hiểu được ạ.
Cháu cảm ơn ạ!

Dưới đây, tôi sẽ gọi Sub bình thường là Sub độc lập, hoặc Sub chính, Sub mẹ; và loại Sub ở trên là Sub nội.

Người ta cũng dùng với ý định tương tự như Sub con riêng. Tức là để tách rời công việc với nhiệm vụ chính của hàm, hoặc để cho code có thể lặp lại nhiều lần, hoặc cả hai. Tuy nhiên, khác với Sub con là một bộ phận riêng, Sub khác cũng gọi được; loại Sub nội này là của riêng Sub mẹ (cũng như biến nội); cá Sub's khác không thể trực tiếp thấy nó.

Bạn có thể ví Sub như một ngôi nhà. Sub này Sub kia trong một Module là các nhà cùng trong một Huyện.
Sub nội một phòng hoặc một nhóm phòng, hoặc một khu trong nhà được ngăn riêng ra. Tức là chúng hoàn toàn thuộc về nhà chính.

Tại sao dùng Sub nội thay vì Sub độc lập?
(i) Lý do chính là tại vì lười biếng truyền tham số.
(thú thật là dùng cái này có nhiều khuyết điểm, nhưng đã nói lười biếng mờ)
(ii) Lý do phụ là lắm khi tham số cần truyền nhiều quá, dùng Sub nội đỡ mất công phải giở thủ thuật gom tham số.
Đừng nghĩ đến tốc độ, tuy lệnh rẽ nhánh nhanh hơn lệnh gọi Sub độc lập. Bản than Sub độc lập cần thì giờ nối các tham và lập stack, chạy xong thì phải xả stack. Nhưng một vài phần triệu giây thì chả thấm thía gì.
(iii) Lý do rất ít người hưởng ứng là chúng cũng có thể dùng để giải quyết bẫy lỗi. Thay vì On Error Goto <Label>, ta cũng có thể On Error GoSub <Label>

Khuyết điểm của Sub nội:
a/ Khúc đuôi của code sẽ rườm rà. Người đọc không quen sẽ hơi lọng cọng. Tuy nhiên người quen chú thích code thì sẽ tránh được điểm này.
b/ Lệnh GoSub là lệnh rẽ nhánh kiểu Goto. Nhiều lập trình viên coi đồ này là tà ma ngoại đạo.
c/ Nhiều người mới bắt đầu sẽ dễ bị vướng các điều mà tôi nêu ra trong "để ý" ở sau.

Khi dùng Sub nội thì phải để ý gì?
1. Code của Sub nội chỉ liên quan đến tình trạng bên trong Sub chứa nó. Nếu code này cần cho Sub khác thì tốt hơn nên viết Sub độc lập.
2. Tuy code có thể đặt bất cứ vị trí nào trong Sub chứa nó, nhưng tốt hơn nên đặt chúng ở vị trí cuối cùng, trước End Sub.
3. Dùng Label để đặt tên Sub nội.
4. Dùng lệnh Return dùng kết thúc Sub nội và bảo VBA trở về dòng lệnh ngay sau GoSub... Nếu bạn quên lệnh này thì VBA cứ chạy tiếp cho đến khi gặp một Return (của sub nội khác), hoặc Exit Sub, hoặc End Sub.
5. Trước code các Sub nội là code Sub chính, phải có lệnh Exit Sub. Nếu không có lệnh này, VBA sẽ tỉnh bơ coi cái Label kế tiếp như một label thông thường và tiếp tục chạy cho đến khi gặp lệnh Return thì VBA nảy lỗi (vì trước đó nó đâu có "save" cái địa chỉ để về - xem "khi lệnh GoSub được gọi..." ở trên).
6. Các Sub nội có thể gọi nhau hoặc tự gọi nó (đệ quy).
 
Upvote 0
@VetMini cám ơn chú về những chia sẻ trên đã cho cháu thêm kiến thức. Tới tận giờ cháu mới biết thêm về cái này và chức năng cái Return ấy ạ.
Cháu cám ơn nhiều ạ
 
Upvote 0
đang rảnh tôi gợi ý cho làm thôi còn tôi thì làm biếng :p

nếu File lớn trên vài MB mà dùng Workbook ... ó pền nó chậm lắm .. dùng ADODB hay DAO mà lấy tốt hơn
 
Upvote 0
Bạn ngắt code lấy nhiều file ra chạy riêng sau đó chạy lấy tên Sheet sau
Sub LietkeSheetName_CodeName()
Application.DisplayAlerts = False
Dim SoSheet As Byte, i As Byte
Sheet1.Range("A2:B1000").ClearContents
SoSheet = Worksheets.Count
For i = 1 To SoSheet
Sheet1.Range("A" & (i + 1)).Value = Worksheets(i).CodeName
Sheet1.Range("B" & (i + 1)).Value = Worksheets(i).Name
Next i
Application.DisplayAlerts = True
End Sub
Sưu tầm
 
Upvote 0
Bạn ngắt code lấy nhiều file ra chạy riêng sau đó chạy lấy tên Sheet sau
Sub LietkeSheetName_CodeName()
Application.DisplayAlerts = False
Dim SoSheet As Byte, i As Byte
Sheet1.Range("A2:B1000").ClearContents
SoSheet = Worksheets.Count
For i = 1 To SoSheet
Sheet1.Range("A" & (i + 1)).Value = Worksheets(i).CodeName
Sheet1.Range("B" & (i + 1)).Value = Worksheets(i).Name
Next i
Application.DisplayAlerts = True
End Sub
Sưu tầm
Code này gặp file có số sheets lớn hơn 255 thì tèo mất.
 
Upvote 0
Code ấy thời xưa chứ có gì đâu.
Nếu bạn trở lại thời đầu của GPE, ngay cả các tay gọi là "huyền tghoaij" cũng dùng loại kiểu cổ điển ấy.
Hồi RAM còn tính trên MegaByte, người ta phải thận trọng phần chứa biến.

Khoảng thập niên 1980's, tôi còn làm trên máy bộ nhớ 32 ngàn words (64 ngàn bytes). Hệ điều hành chiếm phân nửa. Lập trình phải có kỹ năng thu gọn trong phần còn lại, tên biến dài cũng tốn bộ nhớ.
 
Upvote 0
Code ấy thời xưa chứ có gì đâu.
Nếu bạn trở lại thời đầu của GPE, ngay cả các tay gọi là "huyền tghoaij" cũng dùng loại kiểu cổ điển ấy.
Hồi RAM còn tính trên MegaByte, người ta phải thận trọng phần chứa biến.

Khoảng thập niên 1980's, tôi còn làm trên máy bộ nhớ 32 ngàn words (64 ngàn bytes). Hệ điều hành chiếm phân nửa. Lập trình phải có kỹ năng thu gọn trong phần còn lại, tên biến dài cũng tốn bộ nhớ.
Đó là hoài niệm rồi bác nhỉ.
Giờ thấy người ta khuyên không nên khai báo As Integer nữa vì As Long lớn hơn nhưng lại tiết kiệm "nội lực" của VBA hơn.
 
Upvote 0
... vì As Long lớn hơn nhưng lại tiết kiệm "nội lực" của VBA hơn.
Biết register của CPU là cái gì không?
Những CPU đời sau dùng registers 32 bits (Long) hoặc 64 bits (Long Long). Như vậy, số Long bây giờ là bản chất của CPU thay vì Integer (16 bits).
 
Upvote 0
Code này gặp file có số sheets lớn hơn 255 thì tèo mất.
Hiếm khi gặp file lớn dữ vậy cho nên cũng khong quan trọng lắm.
Quan trọng ở chỗ người cho code chỉ nói: "Bạn ngắt code lấy nhiều file ra chạy riêng sau đó chạy lấy tên Sheet sau"
Code này chỉ:
- Lấy tên các sheets trong file hiện hành
- Xóa một đống dữ liệu trữ trong file giện hành. Nếu người đưa code bảo dùng hàm chính mở từng file ra và chạy code này thì chết cửa tứ. có
- Mặc định rằng file hiện hành có Sheet1

Người ta lụm đâu đó một đoạn code, đem về xúi người khác dùng mà chả cho biết nó làm gì. Cái ấy mới nguy hiểm.
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom