Cara menghindari penggunaan Select di Excel VBA
Saya telah mendengar banyak tentang kebencian yang dapat dimengerti saat menggunakan .Select
Excel VBA, tetapi saya tidak yakin bagaimana cara menghindarinya. Saya menemukan bahwa kode saya akan lebih dapat digunakan kembali jika saya dapat menggunakan variabel daripada Select
fungsi. Namun, saya tidak yakin bagaimana merujuk ke hal-hal (seperti ActiveCell
, dll.) Jika tidak menggunakan Select
.
Saya telah menemukan artikel ini tentang rentang dan contoh tentang manfaat tidak menggunakan pilih , tetapi saya tidak dapat menemukan apa pun tentang caranya .
Jawaban
Beberapa contoh bagaimana menghindari pemilihan
Gunakan Dim
variabel d
Dim rng as Range
Set
variabel ke kisaran yang diperlukan. Ada banyak cara untuk merujuk ke rentang sel tunggal:
Set rng = Range("A1")
Set rng = Cells(1, 1)
Set rng = Range("NamedRange")
Atau rentang multisel:
Set rng = Range("A1:B10")
Set rng = Range("A1", "B10")
Set rng = Range(Cells(1, 1), Cells(10, 2))
Set rng = Range("AnotherNamedRange")
Set rng = Range("A1").Resize(10, 2)
Anda dapat menggunakan pintasan ke Evaluate
metode tersebut, tetapi ini kurang efisien dan umumnya harus dihindari dalam kode produksi.
Set rng = [A1]
Set rng = [A1:B10]
Semua contoh di atas merujuk ke sel di lembar aktif . Kecuali Anda secara khusus ingin bekerja hanya dengan lembar aktif, lebih baik untuk meredupkan Worksheet
variabel juga:
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
Set rng = ws.Cells(1, 1)
With ws
Set rng = .Range(.Cells(1, 1), .Cells(2, 10))
End With
Jika Anda benar- benar ingin bekerja dengan ActiveSheet
, agar jelas, sebaiknya eksplisit. Tapi hati-hati, karena beberapa Worksheet
metode mengubah lembar aktif.
Set rng = ActiveSheet.Range("A1")
Sekali lagi, ini mengacu pada buku kerja yang aktif . Kecuali jika Anda secara khusus ingin bekerja hanya dengan ActiveWorkbook
atau ThisWorkbook
, lebih baik Redupkan Workbook
variabel juga.
Dim wb As Workbook
Set wb = Application.Workbooks("Book1")
Set rng = wb.Worksheets("Sheet1").Range("A1")
Jika Anda benar- benar ingin bekerja dengan ActiveWorkbook
, agar jelas, sebaiknya eksplisit. Tapi hati-hati, karena banyak WorkBook
metode mengubah buku aktif.
Set rng = ActiveWorkbook.Worksheets("Sheet1").Range("A1")
Anda juga dapat menggunakan ThisWorkbook
objek untuk merujuk ke buku yang berisi kode yang sedang berjalan.
Set rng = ThisWorkbook.Worksheets("Sheet1").Range("A1")
Bagian kode yang umum (buruk) adalah membuka buku, mendapatkan beberapa data, lalu menutupnya lagi
Ini buruk:
Sub foo()
Dim v as Variant
Workbooks("Book1.xlsx").Sheets(1).Range("A1").Clear
Workbooks.Open("C:\Path\To\SomeClosedBook.xlsx")
v = ActiveWorkbook.Sheets(1).Range("A1").Value
Workbooks("SomeAlreadyOpenBook.xlsx").Activate
ActiveWorkbook.Sheets("SomeSheet").Range("A1").Value = v
Workbooks(2).Activate
ActiveWorkbook.Close()
End Sub
Dan akan lebih baik seperti:
Sub foo()
Dim v as Variant
Dim wb1 as Workbook
Dim wb2 as Workbook
Set wb1 = Workbooks("SomeAlreadyOpenBook.xlsx")
Set wb2 = Workbooks.Open("C:\Path\To\SomeClosedBook.xlsx")
v = wb2.Sheets("SomeSheet").Range("A1").Value
wb1.Sheets("SomeOtherSheet").Range("A1").Value = v
wb2.Close()
End Sub
Meneruskan rentang ke Sub
s dan Function
s Anda sebagai variabel Rentang:
Sub ClearRange(r as Range)
r.ClearContents
'....
End Sub
Sub MyMacro()
Dim rng as Range
Set rng = ThisWorkbook.Worksheets("SomeSheet").Range("A1:B10")
ClearRange rng
End Sub
Anda juga harus menerapkan Metode (seperti Find
dan Copy
) ke variabel:
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = ThisWorkbook.Worksheets("SomeSheet").Range("A1:A10")
Set rng2 = ThisWorkbook.Worksheets("SomeSheet").Range("B1:B10")
rng1.Copy rng2
Jika Anda melakukan perulangan pada rentang sel, seringkali lebih baik (lebih cepat) untuk menyalin nilai rentang ke larik varian terlebih dahulu dan mengulanginya:
Dim dat As Variant
Dim rng As Range
Dim i As Long
Set rng = ThisWorkbook.Worksheets("SomeSheet").Range("A1:A10000")
dat = rng.Value ' dat is now array (1 to 10000, 1 to 1)
for i = LBound(dat, 1) to UBound(dat, 1)
dat(i,1) = dat(i, 1) * 10 ' Or whatever operation you need to perform
next
rng.Value = dat ' put new values back on sheet
Ini adalah pengecap kecil untuk apa yang mungkin.
Dua alasan utama mengapa .Select
, .Activate
, Selection
, Activecell
, Activesheet
, Activeworkbook
, dll harus dihindari
- Ini memperlambat kode Anda.
- Ini biasanya merupakan penyebab utama error runtime.
Bagaimana kita menghindarinya?
1) Bekerja langsung dengan objek yang relevan
Pertimbangkan kode ini
Sheets("Sheet1").Activate
Range("A1").Select
Selection.Value = "Blah"
Selection.NumberFormat = "@"
Kode ini juga dapat ditulis sebagai
With Sheets("Sheet1").Range("A1")
.Value = "Blah"
.NumberFormat = "@"
End With
2) Jika diperlukan, deklarasikan variabel Anda. Kode yang sama di atas dapat ditulis sebagai
Dim ws as worksheet
Set ws = Sheets("Sheet1")
With ws.Range("A1")
.Value = "Blah"
.NumberFormat = "@"
End With
Satu titik kecil penekanan saya akan menambahkan ke semua jawaban luar biasa yang diberikan sebelumnya:
Mungkin hal terbesar yang dapat Anda lakukan untuk menghindari penggunaan Select adalah sebanyak mungkin menggunakan rentang bernama (dikombinasikan dengan nama variabel yang bermakna) dalam kode VBA Anda . Hal ini telah disebutkan di atas, tetapi sedikit dikaburkan; Namun, hal itu membutuhkan perhatian khusus.
Berikut adalah beberapa alasan tambahan untuk menggunakan rentang nama secara bebas, meskipun saya yakin saya dapat memikirkan lebih banyak.
Rentang bernama membuat kode Anda lebih mudah dibaca dan dipahami.
Contoh:
Dim Months As Range
Dim MonthlySales As Range
Set Months = Range("Months")
' E.g, "Months" might be a named range referring to A1:A12
Set MonthlySales = Range("MonthlySales")
' E.g, "Monthly Sales" might be a named range referring to B1:B12
Dim Month As Range
For Each Month in Months
Debug.Print MonthlySales(Month.Row)
Next Month
Cukup jelas apa yang dinamai range Months
dan isi MonthlySales
, dan apa yang dilakukan prosedur.
Mengapa ini penting? Sebagian karena lebih mudah bagi orang lain untuk memahaminya, tetapi meskipun Anda adalah satu-satunya orang yang pernah melihat atau menggunakan kode Anda, Anda tetap harus menggunakan rentang bernama dan nama variabel yang bagus karena Anda akan lupa apa yang ingin Anda lakukan dengannya. setahun kemudian, dan Anda akan membuang waktu 30 menit hanya untuk mencari tahu apa yang dilakukan kode Anda.
Rentang bernama memastikan bahwa makro Anda tidak rusak ketika (bukan jika!) Konfigurasi spreadsheet berubah.
Perhatikan, jika contoh di atas pernah ditulis seperti ini:
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Range("A1:A12")
Set rng2 = Range("B1:B12")
Dim rng3 As Range
For Each rng3 in rng1
Debug.Print rng2(rng3.Row)
Next rng3
Kode ini akan bekerja dengan baik pada awalnya - itu sampai Anda atau pengguna masa depan memutuskan "astaga, saya pikir saya akan menambahkan kolom baru dengan tahun di Kolom A
!", Atau meletakkan kolom pengeluaran antara bulan dan kolom penjualan, atau tambahkan tajuk ke setiap kolom. Sekarang, kode Anda rusak. Dan karena Anda menggunakan nama variabel yang buruk, Anda akan membutuhkan lebih banyak waktu untuk mencari tahu cara memperbaikinya daripada yang seharusnya.
Jika Anda telah menggunakan rentang bernama untuk memulai, kolom Months
dan Sales
dapat dipindahkan sesuka Anda, dan kode Anda akan terus berfungsi dengan baik.
Saya akan memberikan jawaban singkat karena semua orang memberikan jawaban panjang.
Anda akan mendapatkan .select dan .activate setiap kali Anda merekam makro dan menggunakannya kembali. Saat Anda memilih sel atau lembar, itu akan membuatnya aktif. Sejak saat itu setiap kali Anda menggunakan referensi yang tidak memenuhi syarat seperti Range.Value
mereka hanya menggunakan sel dan lembar aktif. Ini juga bisa menjadi masalah jika Anda tidak memperhatikan di mana kode Anda ditempatkan atau pengguna mengklik buku kerja.
Jadi, Anda dapat menghilangkan masalah ini dengan mereferensikan sel Anda secara langsung. Yang mana:
'create and set a range
Dim Rng As Excel.Range
Set Rng = Workbooks("Book1").Worksheets("Sheet1").Range("A1")
'OR
Set Rng = Workbooks(1).Worksheets(1).Cells(1, 1)
Atau Anda bisa
'Just deal with the cell directly rather than creating a range
'I want to put the string "Hello" in Range A1 of sheet 1
Workbooks("Book1").Worksheets("Sheet1").Range("A1").value = "Hello"
'OR
Workbooks(1).Worksheets(1).Cells(1, 1).value = "Hello"
Ada berbagai kombinasi metode ini, tetapi itu akan menjadi gagasan umum yang diungkapkan secepat mungkin untuk orang yang tidak sabar seperti saya.
"... dan saya menemukan bahwa kode saya akan lebih dapat digunakan kembali jika saya dapat menggunakan variabel daripada fungsi Select."
Meskipun saya tidak dapat memikirkan lebih dari segelintir situasi di mana .Select
akan menjadi pilihan yang lebih baik daripada referensi sel langsung, saya akan membela Selection
dan menunjukkan bahwa itu tidak boleh dibuang karena alasan yang sama yang .Select
harus dihindari.
Ada kalanya memiliki sub rutin makro yang pendek dan hemat waktu yang ditetapkan ke kombinasi tombol pintas yang tersedia dengan ketukan beberapa tombol akan menghemat banyak waktu. Mampu memilih sekelompok sel untuk memberlakukan kode operasional pada karya keajaiban ketika berhadapan dengan data yang dikantongi yang tidak sesuai dengan format data selebar lembar kerja. Sama seperti Anda memilih sekelompok sel dan menerapkan perubahan format, memilih sekelompok sel untuk menjalankan kode makro khusus dapat menjadi penghemat waktu yang utama.
Contoh sub framework berbasis seleksi:
Public Sub Run_on_Selected()
Dim rng As Range, rSEL As Range
Set rSEL = Selection 'store the current selection in case it changes
For Each rng In rSEL
Debug.Print rng.Address(0, 0)
'cell-by-cell operational code here
Next rng
Set rSEL = Nothing
End Sub
Public Sub Run_on_Selected_Visible()
'this is better for selected ranges on filtered data or containing hidden rows/columns
Dim rng As Range, rSEL As Range
Set rSEL = Selection 'store the current selection in case it changes
For Each rng In rSEL.SpecialCells(xlCellTypeVisible)
Debug.Print rng.Address(0, 0)
'cell-by-cell operational code here
Next rng
Set rSEL = Nothing
End Sub
Public Sub Run_on_Discontiguous_Area()
'this is better for selected ranges of discontiguous areas
Dim ara As Range, rng As Range, rSEL As Range
Set rSEL = Selection 'store the current selection in case it changes
For Each ara In rSEL.Areas
Debug.Print ara.Address(0, 0)
'cell group operational code here
For Each rng In ara.Areas
Debug.Print rng.Address(0, 0)
'cell-by-cell operational code here
Next rng
Next ara
Set rSEL = Nothing
End Sub
Kode sebenarnya yang akan diproses dapat berupa apa saja dari satu baris hingga beberapa modul. Saya telah menggunakan metode ini untuk memulai rutinitas yang berjalan lama pada pilihan sel yang compang-camping yang berisi nama file buku kerja eksternal.
Singkatnya, jangan membuang Selection
karena hubungannya yang erat dengan .Select
dan ActiveCell
. Sebagai properti lembar kerja, ia memiliki banyak tujuan lain.
(Ya, saya tahu pertanyaan ini tentang .Select
, Selection
tetapi saya ingin menghapus kesalahpahaman yang mungkin disimpulkan oleh pembuat kode VBA pemula.)
Menghindari Select
dan Activate
merupakan langkah yang membuat Anda menjadi pengembang VBA yang sedikit lebih baik. Secara umum, Select
dan Activate
digunakan saat makro direkam, sehingga Parent
lembar kerja atau rentang selalu dianggap sebagai yang aktif.
Inilah cara Anda menghindari Select
dan Activate
dalam kasus berikut:
Menambahkan Lembar Kerja baru dan menyalin sel di atasnya:
Dari (kode yang dihasilkan dengan perekam makro):
Sub Makro2()
Range("B2").Select
Sheets.Add After:=ActiveSheet
Sheets("Tabelle1").Select
Sheets("Tabelle1").Name = "NewName"
ActiveCell.FormulaR1C1 = "12"
Range("B2").Select
Selection.Copy
Range("B3").Select
ActiveSheet.Paste
Application.CutCopyMode = False
End Sub
Untuk:
Sub TestMe()
Dim ws As Worksheet
Set ws = Worksheets.Add
With ws
.Name = "NewName"
.Range("B2") = 12
.Range("B2").Copy Destination:=.Range("B3")
End With
End Sub
Saat Anda ingin menyalin rentang antara lembar kerja:
Dari:
Sheets("Source").Select
Columns("A:D").Select
Selection.Copy
Sheets("Target").Select
Columns("A:D").Select
ActiveSheet.Paste
Untuk:
Worksheets("Source").Columns("A:D").Copy Destination:=Worksheets("Target").Range("a1")
Menggunakan rentang bernama mewah
Anda dapat mengaksesnya dengan []
, yang sangat indah, dibandingkan dengan cara lain. Periksa diri Anda sendiri:
Dim Months As Range
Dim MonthlySales As Range
Set Months = Range("Months")
Set MonthlySales = Range("MonthlySales")
Set Months =[Months]
Set MonthlySales = [MonthlySales]
Contoh dari atas akan terlihat seperti ini:
Worksheets("Source").Columns("A:D").Copy Destination:=Worksheets("Target").[A1]
Bukan menyalin nilai, tapi mengambilnya
Biasanya, jika Anda mau select
, kemungkinan besar Anda sedang menyalin sesuatu. Jika Anda hanya tertarik pada nilainya, ini adalah opsi yang baik untuk menghindari pemilihan:
Range("B1:B6").Value = Range("A1:A6").Value
Cobalah selalu untuk mereferensikan Lembar Kerja juga
Ini mungkin kesalahan paling umum di vba . Setiap kali Anda menyalin rentang, terkadang lembar kerja tidak direferensikan dan dengan demikian VBA menganggap lembar yang salah sebagai Lembar Kerja Aktif.
'This will work only if the 2. Worksheet is selected!
Public Sub TestMe()
Dim rng As Range
Set rng = Worksheets(2).Range(Cells(1, 1), Cells(2, 2)).Copy
End Sub
'This works always!
Public Sub TestMe2()
Dim rng As Range
With Worksheets(2)
.Range(.Cells(1, 1), .Cells(2, 2)).Copy
End With
End Sub
Bisakah saya benar-benar tidak pernah menggunakan .Select
atau .Activate
untuk apa pun?
- Contoh yang baik tentang kapan Anda dapat dibenarkan dalam menggunakan
.Activate
dan.Select
adalah ketika Anda ingin memastikan bahwa Lembar Kerja tertentu dipilih untuk alasan visual. Misalnya, Excel Anda akan selalu terbuka dengan lembar kerja sampul yang dipilih terlebih dahulu, mengabaikan yang merupakan Lembar Aktif saat file ditutup.
Jadi, sesuatu seperti kode di bawah ini benar-benar OK:
Private Sub Workbook_Open()
Worksheets("Cover").Activate
End Sub
Contoh bagus lainnya adalah ketika Anda perlu mengekspor semua lembar menjadi satu file PDF, seperti yang disebutkan dalam kasus ini - Bagaimana cara menghindari pernyataan pilih / aktif di VBA dalam contoh ini?
Ketika sebuah perintah hanya bekerja dengan
ActiveWindow
seperti ActiveWindow.Zoom atau ActiveWindow.FreezePanes
Harap dicatat bahwa berikut ini saya membandingkan pendekatan Select (yang OP ingin hindari), dengan pendekatan Range (dan ini adalah jawaban untuk pertanyaan). Jadi jangan berhenti membaca saat Anda melihat Select pertama.
Itu sangat tergantung pada apa yang Anda coba lakukan. Bagaimanapun, contoh sederhana bisa bermanfaat. Misalkan Anda ingin menyetel nilai sel aktif ke "foo". Menggunakan ActiveCell Anda akan menulis sesuatu seperti ini:
Sub Macro1()
ActiveCell.Value = "foo"
End Sub
Jika Anda ingin menggunakannya untuk sel yang bukan yang aktif, misalnya untuk "B2", Anda harus memilihnya terlebih dahulu, seperti ini:
Sub Macro2()
Range("B2").Select
Macro1
End Sub
Menggunakan Rentang Anda bisa menulis makro yang lebih umum yang bisa digunakan untuk mengatur nilai sel apa pun yang Anda inginkan ke apa pun yang Anda inginkan:
Sub SetValue(cellAddress As String, aVal As Variant)
Range(cellAddress).Value = aVal
End Sub
Kemudian Anda dapat menulis ulang Macro2 sebagai:
Sub Macro2()
SetCellValue "B2", "foo"
End Sub
Dan Macro1 sebagai:
Sub Macro1()
SetValue ActiveCell.Address, "foo"
End Sub
Selalu nyatakan buku kerja, lembar kerja, dan sel / rentang.
Sebagai contoh:
Thisworkbook.Worksheets("fred").cells(1,1)
Workbooks("bob").Worksheets("fred").cells(1,1)
Karena pengguna akhir akan selalu hanya mengklik tombol dan segera setelah fokus berpindah dari buku kerja, kode ingin bekerja dengannya maka semuanya menjadi salah total.
Dan jangan pernah menggunakan indeks buku kerja.
Workbooks(1).Worksheets("fred").cells(1,1)
Anda tidak tahu buku kerja lain apa yang akan dibuka saat pengguna menjalankan kode Anda.
Metode ini agak distigmatisasi, jadi memimpin Vityata dan Jeeped demi menggambar garis di pasir:
Panggilan .Activate
, .Select
, Selection
, ActiveSomething
metode / properti
Pada dasarnya karena mereka dipanggil terutama untuk menangani masukan pengguna melalui UI aplikasi. Karena ini adalah metode yang dipanggil saat pengguna menangani objek melalui UI, merekalah yang direkam oleh perekam makro, dan itulah mengapa memanggilnya rapuh atau berlebihan untuk sebagian besar situasi: Anda tidak perlu memilih objek untuk melakukan tindakan dengan Selection
tepat setelahnya.
Namun, definisi ini menetapkan situasi di mana mereka dipanggil:
Ketika menelepon .Activate
, .Select
, .Selection
, .ActiveSomething
metode / properti
Pada dasarnya ketika Anda mengharapkan pengguna akhir untuk memainkan peran dalam eksekusi.
Jika Anda mengembangkan dan mengharapkan pengguna untuk memilih contoh objek untuk ditangani kode Anda, maka .Selection
atau .ActiveObject
sesuai.
Di sisi lain, .Select
dan .Activate
berguna ketika Anda dapat menyimpulkan tindakan pengguna selanjutnya dan Anda ingin kode Anda memandu pengguna, mungkin menghemat waktu dan klik mouse. Misalnya, jika kode Anda baru saja membuat contoh baru dari bagan atau yang diperbarui, pengguna mungkin ingin memeriksanya, dan Anda dapat memanggilnya .Activate
atau lembar untuk menghemat waktu pengguna mencarinya; atau jika Anda tahu bahwa pengguna perlu memperbarui beberapa nilai rentang, Anda dapat memilih rentang tersebut secara terprogram.
Penggunaan IMHO .select
berasal dari orang-orang, yang seperti saya mulai belajar VBA dengan kebutuhan melalui pencatatan makro dan kemudian memodifikasi kode tanpa menyadarinya .select
dan selanjutnya selection
hanyalah perantara yang tidak perlu.
.select
dapat dihindari, seperti yang sudah banyak diposting, dengan bekerja langsung dengan objek yang sudah ada, yang memungkinkan berbagai referensi tidak langsung seperti menghitung i dan j dengan cara yang kompleks dan kemudian mengedit sel (i, j), dll.
Jika tidak, tidak ada yang salah secara implisit dengan .select
dirinya sendiri dan Anda dapat menemukan kegunaannya dengan mudah, misalnya saya memiliki spreadsheet yang saya isi dengan tanggal, mengaktifkan makro yang melakukan sihir dengannya dan mengekspornya dalam format yang dapat diterima pada lembar terpisah, yang mana , bagaimanapun, membutuhkan beberapa input manual akhir (tidak dapat diprediksi) ke dalam sel yang berdekatan. Jadi, inilah saatnya untuk .select
menyelamatkan saya dari gerakan mouse tambahan dan klik.
Untuk menghindari penggunaan .Select
metode ini, Anda dapat menetapkan variabel yang sama dengan properti yang Anda inginkan.
► Misalnya, jika Anda ingin nilainya di dalam, Cell A1
Anda dapat mengatur variabel yang sama dengan properti nilai sel itu.
- Contoh
valOne = Range("A1").Value
► Misalnya, jika Anda ingin nama you could set a variable equal to the
kode properti 'Sheet3 Codename` dari lembar kerja itu.
- Contoh
valTwo = Sheets("Sheet3").Codename
Saya perhatikan bahwa tidak ada dari jawaban ini yang menyebutkan Properti .Offset . Ini juga dapat digunakan untuk menghindari penggunaan Select
tindakan saat memanipulasi sel tertentu, terutama yang mengacu pada sel yang dipilih (seperti yang disebutkan OP ActiveCell
).
Berikut ini beberapa contoh.
Saya juga akan menganggap "ActiveCell" adalah J4 .
ActiveCell.Offset(2, 0).Value = 12
- Ini akan mengubah sel
J6
menjadi nilai 12 - Sebuah minus -2 akan mereferensikan J2
ActiveCell.Offset(0,1).Copy ActiveCell.Offset(,2)
- Ini akan menyalin sel
k4
keL4
. - Perhatikan bahwa "0" tidak diperlukan dalam parameter offset jika tidak diperlukan (, 2)
- Mirip dengan contoh sebelumnya, minus 1 akan menjadi
i4
ActiveCell.Offset(, -1).EntireColumn.ClearContents
- Ini akan menghapus nilai di semua sel di kolom k.
Ini tidak berarti bahwa mereka "lebih baik" daripada opsi di atas, tetapi hanya mencantumkan alternatif.
Bagaimana cara menghindari salin-tempel?
Mari kita hadapi itu: yang ini sering muncul saat merekam makro:
Range("X1").Select
Selection.Copy
Range("Y9).Select
Selection.Paste
Sedangkan satu-satunya hal yang diinginkan orang tersebut adalah:
Range("Y9").Value = Range("X1").Value
Oleh karena itu, daripada menggunakan salin-tempel di makro VBA, saya menyarankan pendekatan sederhana berikut:
Destination_Range.Value = Source_Range.Value
Bekerja dengan fitur .Parent , contoh ini menunjukkan bagaimana menyetel hanya satu referensi myRng yang memungkinkan akses dinamis ke seluruh lingkungan tanpa .Select, .Activate, .Activecell, .ActiveWorkbook, .ActiveSheet, dan seterusnya. (Tidak ada fitur .Child generik .)
Sub ShowParents()
Dim myRng As Range
Set myRng = ActiveCell
Debug.Print myRng.Address ' An address of the selected cell
Debug.Print myRng.Parent.name ' The name of sheet, where MyRng is in
Debug.Print myRng.Parent.Parent.name ' The name of workbook, where MyRng is in
Debug.Print myRng.Parent.Parent.Parent.name ' The name of application, where MyRng is in
' You may use this feature to set reference to these objects
Dim mySh As Worksheet
Dim myWbk As Workbook
Dim myApp As Application
Set mySh = myRng.Parent
Set myWbk = myRng.Parent.Parent
Set myApp = myRng.Parent.Parent.Parent
Debug.Print mySh.name, mySh.Cells(10, 1).Value
Debug.Print myWbk.name, myWbk.Sheets.Count
Debug.Print myApp.name, myApp.Workbooks.Count
' You may use dynamically addressing
With myRng
.Copy
' Pastes in D1 on sheet 2 in the same workbook, where the copied cell is
.Parent.Parent.Sheets(2).Range("D1").PasteSpecial xlValues
' Or myWbk.Sheets(2).Range("D1").PasteSpecial xlValues
' We may dynamically call active application too
.Parent.Parent.Parent.CutCopyMode = False
' Or myApp.CutCopyMode = False
End With
End Sub
Alasan utama untuk tidak pernah menggunakan Select atau Activesheet adalah karena kebanyakan orang akan memiliki setidaknya beberapa workbook yang terbuka (terkadang lusinan) saat mereka menjalankan makro Anda, dan jika mereka mengklik dari sheet Anda saat makro Anda berjalan dan mengklik beberapa workbook lainnya. buku yang telah mereka buka, lalu "Lembar Aktif" berubah, dan buku kerja target untuk perintah "Pilih" yang tidak memenuhi syarat juga berubah.
Paling-paling, makro Anda akan macet, paling buruk Anda mungkin berakhir dengan menulis nilai atau mengubah sel di buku kerja yang salah tanpa cara untuk "Membatalkan" mereka.
Saya memiliki aturan emas sederhana yang saya ikuti: Tambahkan variabel bernama "wb" dan "ws" untuk objek Buku Kerja dan objek Lembar Kerja dan selalu gunakan variabel tersebut untuk merujuk ke buku makro saya. Jika saya perlu merujuk ke lebih dari satu buku, atau lebih dari satu lembar, saya menambahkan lebih banyak variabel.
Sebagai contoh,
Dim wb as Workbook
Dim ws as Worksheet
Set wb = ThisWorkBook
Set ws = wb.sheets("Output")
Perintah "Set wb = ThisWorkbook" benar-benar penting. "ThisWorkbook" adalah nilai khusus di Excel, dan itu berarti buku kerja tempat kode VBA Anda saat ini dijalankan . Pintasan yang sangat membantu untuk mengatur variabel Buku Kerja Anda.
Setelah Anda selesai melakukannya di bagian atas Sub Anda, menggunakannya sangat mudah, cukup gunakan di mana pun Anda akan menggunakan "Pilihan":
Jadi untuk mengubah nilai sel "A1" di "Output" menjadi "Hello", alih-alih:
Sheets("Output").Activate
ActiveSheet.Range("A1").Select
Selection.Value = "Hello"
Sekarang kita bisa melakukan ini:
ws.Range("A1").Value = "Hello"
Yang tidak hanya jauh lebih andal dan kecil kemungkinannya untuk mogok jika pengguna bekerja dengan banyak spreadsheet; itu juga jauh lebih pendek, lebih cepat dan lebih mudah untuk ditulis.
Sebagai bonus tambahan, jika Anda selalu memberi nama variabel "wb" dan "ws", Anda dapat menyalin dan menempelkan kode dari satu buku ke buku lain dan biasanya akan bekerja dengan perubahan minimal yang diperlukan, jika ada.