Cara menghindari penggunaan Select di Excel VBA

May 23 2012

Saya telah mendengar banyak tentang kebencian yang dapat dimengerti saat menggunakan .SelectExcel VBA, tetapi saya tidak yakin bagaimana cara menghindarinya. Saya menemukan bahwa kode saya akan lebih dapat digunakan kembali jika saya dapat menggunakan variabel daripada Selectfungsi. 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

578 chrisneilsen May 23 2012 at 17:23

Beberapa contoh bagaimana menghindari pemilihan

Gunakan Dimvariabel d

Dim rng as Range

Setvariabel 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 Evaluatemetode 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 Worksheetvariabel 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 Worksheetmetode 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 ActiveWorkbookatau ThisWorkbook, lebih baik Redupkan Workbookvariabel 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 WorkBookmetode mengubah buku aktif.

Set rng = ActiveWorkbook.Worksheets("Sheet1").Range("A1")

Anda juga dapat menggunakan ThisWorkbookobjek 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 Subs dan Functions 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 Finddan 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.

217 SiddharthRout May 23 2012 at 17:33

Dua alasan utama mengapa .Select, .Activate, Selection, Activecell, Activesheet, Activeworkbook, dll harus dihindari

  1. Ini memperlambat kode Anda.
  2. 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
89 RicksupportsMonica May 28 2014 at 21:04

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 Monthsdan 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 Monthsdan Salesdapat dipindahkan sesuka Anda, dan kode Anda akan terus berfungsi dengan baik.

48 MattB Feb 28 2014 at 04:09

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.Valuemereka 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.

34 Noname Feb 24 2015 at 22:41

"... 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 .Selectakan menjadi pilihan yang lebih baik daripada referensi sel langsung, saya akan membela Selectiondan menunjukkan bahwa itu tidak boleh dibuang karena alasan yang sama yang .Selectharus 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 Selectionkarena hubungannya yang erat dengan .Selectdan ActiveCell. Sebagai properti lembar kerja, ia memiliki banyak tujuan lain.

(Ya, saya tahu pertanyaan ini tentang .Select, Selectiontetapi saya ingin menghapus kesalahpahaman yang mungkin disimpulkan oleh pembuat kode VBA pemula.)

30 Vityata Mar 08 2016 at 17:04

Menghindari Selectdan Activatemerupakan langkah yang membuat Anda menjadi pengembang VBA yang sedikit lebih baik. Secara umum, Selectdan Activatedigunakan saat makro direkam, sehingga Parentlembar kerja atau rentang selalu dianggap sebagai yang aktif.

Inilah cara Anda menghindari Selectdan Activatedalam 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 .Selectatau .Activateuntuk apa pun?

  • Contoh yang baik tentang kapan Anda dapat dibenarkan dalam menggunakan .Activatedan .Selectadalah 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 ActiveWindowseperti ActiveWindow.Zoom atau ActiveWindow.FreezePanes

30 FrancescoBaruchelli May 23 2012 at 13:11

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
18 user1644564 Aug 25 2014 at 16:54

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.

11 LFB Jun 16 2018 at 21:18

Metode ini agak distigmatisasi, jadi memimpin Vityata dan Jeeped demi menggambar garis di pasir:

Panggilan .Activate, .Select, Selection, ActiveSomethingmetode / 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 Selectiontepat setelahnya.

Namun, definisi ini menetapkan situasi di mana mereka dipanggil:

Ketika menelepon .Activate, .Select, .Selection, .ActiveSomethingmetode / 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 .Selectionatau .ActiveObjectsesuai.

Di sisi lain, .Selectdan .Activateberguna 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 .Activateatau lembar untuk menghemat waktu pengguna mencarinya; atau jika Anda tahu bahwa pengguna perlu memperbarui beberapa nilai rentang, Anda dapat memilih rentang tersebut secara terprogram.

6 Eleshar Nov 20 2016 at 22:02

Penggunaan IMHO .selectberasal dari orang-orang, yang seperti saya mulai belajar VBA dengan kebutuhan melalui pencatatan makro dan kemudian memodifikasi kode tanpa menyadarinya .selectdan selanjutnya selectionhanyalah 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 .selectdirinya 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 .selectmenyelamatkan saya dari gerakan mouse tambahan dan klik.

4 FinPro.Online Sep 08 2016 at 13:36

Untuk menghindari penggunaan .Selectmetode ini, Anda dapat menetapkan variabel yang sama dengan properti yang Anda inginkan.

► Misalnya, jika Anda ingin nilainya di dalam, Cell A1Anda 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 thekode properti 'Sheet3 Codename` dari lembar kerja itu.

  • Contoh valTwo = Sheets("Sheet3").Codename
3 PGSystemTester Aug 17 2018 at 03:07

Saya perhatikan bahwa tidak ada dari jawaban ini yang menyebutkan Properti .Offset . Ini juga dapat digunakan untuk menghindari penggunaan Selecttindakan 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 J6menjadi nilai 12
  • Sebuah minus -2 akan mereferensikan J2

ActiveCell.Offset(0,1).Copy ActiveCell.Offset(,2)

  • Ini akan menyalin sel k4ke L4.
  • 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.

1 Dominique Oct 30 2020 at 22:55

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
barneyos Oct 30 2019 at 16:45

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
GeoffGriswald Mar 02 2020 at 20:04

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.