Excel VBA'da Seç kullanmaktan nasıl kaçınılır

May 23 2012

.SelectExcel VBA'da kullanımın anlaşılır iğrençliği hakkında çok şey duydum , ancak onu kullanmaktan nasıl kaçınacağımdan emin değilim. Selectİşlevler yerine değişkenleri kullanabilseydim kodumun daha fazla yeniden kullanılabilir olacağını görüyorum . Ancak, ActiveCellkullanmıyorsam şeylere ( vb.) Nasıl atıfta bulunacağımdan emin değilim Select.

Bu makaleyi aralıklarla buldum ve bu örneği select kullanmamanın faydaları üzerine buldum , ancak nasıl olduğuna dair hiçbir şey bulamıyorum .

Yanıtlar

578 chrisneilsen May 23 2012 at 17:23

Seçimden nasıl kaçınılacağına dair bazı örnekler

Dim'D değişkenlerini kullanın

Dim rng as Range

Setdeğişken gerekli aralığa. Tek hücreli bir aralığı ifade etmenin birçok yolu vardır:

Set rng = Range("A1")
Set rng = Cells(1, 1)
Set rng = Range("NamedRange")

Veya çok hücreli bir aralık:

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)

Sen edebilirsiniz kısayol kullanmak Evaluateyöntemle, ancak bu daha az verimlidir ve genellikle üretim kodunda kaçınılmalıdır.

Set rng = [A1]
Set rng = [A1:B10]

Yukarıdaki tüm örnekler, aktif sayfadaki hücrelere atıfta bulunmaktadır . Özellikle yalnızca etkin sayfayla çalışmak istemediğiniz sürece, bir Worksheetdeğişkeni de boyutlandırmak daha iyidir :

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

Eğer varsa do çalışmak isteyen ActiveSheet, netlik için o açık olmak en iyisidir. Ancak bazı Worksheetyöntemler aktif sayfayı değiştirdiği için dikkatli olun .

Set rng = ActiveSheet.Range("A1")

Yine, bu aktif çalışma kitabını ifade eder . Yalnızca ActiveWorkbookveya ile çalışmak istemediğiniz sürece ThisWorkbook, bir Workbookdeğişkeni Dim etmek daha iyidir .

Dim wb As Workbook
Set wb = Application.Workbooks("Book1")
Set rng = wb.Worksheets("Sheet1").Range("A1")

Eğer varsa do çalışmak isteyen ActiveWorkbook, netlik için o açık olmak en iyisidir. Ancak, birçok WorkBookyöntem aktif kitabı değiştirdiği için dikkatli olun .

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

ThisWorkbookNesneyi, çalışan kodu içeren kitaba başvurmak için de kullanabilirsiniz .

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

Yaygın (kötü) bir kod parçası, bir kitabı açmak, biraz veri almak ve tekrar kapatmaktır.

Bu kötü:

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

Ve şöyle daha iyi olurdu:

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

Aralık değişkenleri olarak Sube ve s'lerinize aralıkları geçirin Function:

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

Ayrıca değişkenlere Yöntemler ( Findve gibi Copy) uygulamalısınız:

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

Bir hücre aralığı üzerinde döngü yapıyorsanız, aralık değerlerini önce bir varyant diziye kopyalayıp bunun üzerinden geçmek genellikle daha iyidir (daha hızlıdır):

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

Bu, mümkün olanın küçük bir çeşididir.

217 SiddharthRout May 23 2012 at 17:33

İki ana nedenleri .Select, .Activate, Selection, Activecell, Activesheet, Activeworkbook, vb kaçınılmalıdır

  1. Kodunuzu yavaşlatır.
  2. Genellikle çalışma zamanı hatalarının ana nedenidir.

Bundan nasıl kaçınırız?

1) İlgili nesnelerle doğrudan çalışın

Bu kodu düşünün

Sheets("Sheet1").Activate
Range("A1").Select
Selection.Value = "Blah"
Selection.NumberFormat = "@"

Bu kod şu şekilde de yazılabilir:

With Sheets("Sheet1").Range("A1")
    .Value = "Blah"
    .NumberFormat = "@"
End With

2) Gerekirse değişkenlerinizi belirtin. Yukarıdaki aynı kod şu şekilde yazılabilir:

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

Daha önce verilen tüm mükemmel cevaplara ekleyeceğim küçük bir vurgu noktası:

Muhtemelen Select'i kullanmaktan kaçınmak için yapabileceğiniz en büyük şey , VBA kodunuzda adlandırılmış aralıkları (anlamlı değişken adlarıyla birlikte) kullanmaktır . Bu noktadan yukarıda bahsedilmişti, ancak biraz üzerinde parlatılmıştı; ancak, özel ilgiyi hak ediyor.

Burada, adlandırılmış aralıkları özgürce kullanmak için birkaç ek neden var, ancak daha fazlasını düşünebileceğime eminim.

Adlandırılmış aralıklar, kodunuzun okunmasını ve anlaşılmasını kolaylaştırır.

Misal:

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

Bu Ne adlandırılmış aralıklar oldukça açıktır Monthsve MonthlySalesiçerirler ve prosedür ne yaptığını.

Bu neden önemli? Kısmen başkalarının anlaması daha kolay olduğu için, ancak kodunuzu görecek veya kullanacak tek kişi siz olsanız bile, adlandırılmış aralıkları ve iyi değişken adlarını kullanmalısınız çünkü onunla ne yapmak istediğinizi unutacaksınız . bir yıl sonra ve sadece kodunuzun ne yaptığını bulmak için 30 dakika harcayacaksınız .

Adlandırılmış aralıklar, elektronik tablonun yapılandırması değiştiğinde (değilse!) Makrolarınızın bozulmamasını sağlar.

Yukarıdaki örnek şu şekilde yazılmışsa düşünün:

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

Bu kod ilk başta gayet iyi çalışacak - ta ki siz veya gelecekteki bir kullanıcı "gee wiz, Sanırım Sütun'a yıl ile yeni bir sütun ekleyeceğim A!" Veya aylar arasına bir giderler sütunu ekleyene kadar. satış sütunları veya her sütuna bir başlık ekleyin. Şimdi, kodunuz bozuldu. Ve berbat değişken isimleri kullandığınız için, onu nasıl düzelteceğinizi anlamanız gerekenden çok daha fazla zaman alacaktır.

Başlamak için adlandırılmış aralıklar kullandıysanız, Monthsve Salessütunları istediğiniz kadar hareket ettirilebilir ve kodunuz iyi çalışmaya devam ederdi.

48 MattB Feb 28 2014 at 04:09

Herkes uzun cevabı verdiği için kısa cevabı vereceğim.

Makroları her kaydedip yeniden kullandığınızda .select ve .activate elde edersiniz. Bir hücre veya sayfayı seçtiğinizde, onu aktif hale getirir. Bu noktadan itibaren, Range.Valuesadece aktif hücre ve sayfayı kullanıyorlarmış gibi, niteliksiz referanslar kullandığınızda. Bu, kodunuzun nereye yerleştirildiğini izlemiyorsanız veya bir kullanıcı çalışma kitabını tıkladığında da sorunlu olabilir.

Böylece, hücrelerinize doğrudan başvurarak bu sorunları ortadan kaldırabilirsiniz. Hangisi:

'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)

Ya da yapabilirsin

'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"

Bu yöntemlerin çeşitli kombinasyonları var ama benim gibi sabırsız insanlar için olabildiğince kısa sürede ifade edilen genel fikir bu olacaktır.

34 Noname Feb 24 2015 at 22:41

"... ve Seç işlevleri yerine değişkenleri kullanabilseydim kodumun daha yeniden kullanılabilir olacağını anlıyorum."

.SelectDoğrudan hücreye atıfta bulunmaktan daha iyi bir seçim olacak izole bir avuç durumdan fazlasını düşünemiyorum , savunmaya yükselir Selectionve .Selectkaçınılması gereken aynı nedenlerle atılmaması gerektiğini belirtirim .

Birkaç tuşa dokunarak kullanılabilen kısayol tuş kombinasyonlarına atanmış kısa, zaman kazandıran makro alt rutinlerine sahip olunması çok zaman kazandırır. Operasyonel kodu uygulamak için bir hücre grubu seçebilmek, çalışma sayfası genelindeki bir veri formatına uymayan cepli verilerle uğraşırken harikalar yaratır. Bir hücre grubunu seçip bir biçim değişikliği uygulamanıza çok benzer şekilde, özel makro kodunun çalıştırılacağı bir hücre grubu seçmek büyük bir zaman tasarrufu sağlayabilir.

Seçim tabanlı alt çerçeve örnekleri:

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

İşlenecek gerçek kod, tek bir satırdan birden çok modüle kadar herhangi bir şey olabilir. Bu yöntemi, harici çalışma kitaplarının dosya adlarını içeren düzensiz bir hücre seçimi üzerinde uzun süre çalışan rutinler başlatmak için kullandım.

Kısacası, atmayın Selectionnedeniyle ile yakın ilişkiye .Selectve ActiveCell. Bir çalışma sayfası özelliği olarak başka birçok amacı vardır.

(Evet, bu sorunun .Selectbununla ilgili olduğunu biliyorum , Selectionancak acemi VBA kodlayıcılarının çıkarabileceği yanlış anlamaları ortadan kaldırmak istedim.)

30 Vityata Mar 08 2016 at 17:04

Kaçınmak Selectve Activatesizi biraz daha iyi VBA geliştiricisi yapan harekettir. Genel olarak Selectve Activatebir makro kaydedildiğinde kullanılır, bu nedenle Parentçalışma sayfası veya aralık her zaman etkin olan olarak kabul edilir.

Bu kaçınmak nasıl olduğunu Selectve Activateaşağıdaki durumlarda:


Yeni bir Çalışma Sayfası eklemek ve üzerine bir hücre kopyalamak:

Gönderen (makro kaydedici ile oluşturulan kod):

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

Kime:

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

Çalışma sayfaları arasında aralığı kopyalamak istediğinizde:

Kimden:

Sheets("Source").Select
Columns("A:D").Select
Selection.Copy
Sheets("Target").Select
Columns("A:D").Select
ActiveSheet.Paste

Kime:

Worksheets("Source").Columns("A:D").Copy Destination:=Worksheets("Target").Range("a1")

Süslü adlandırılmış aralıkları kullanma

[]Diğer yolla kıyaslandığında gerçekten güzel olan bunlara erişebilirsiniz . Kendini kontrol et:

Dim Months As Range
Dim MonthlySales As Range

Set Months = Range("Months")    
Set MonthlySales = Range("MonthlySales")

Set Months =[Months]
Set MonthlySales = [MonthlySales]

Yukarıdaki örnek şöyle görünecektir:

Worksheets("Source").Columns("A:D").Copy Destination:=Worksheets("Target").[A1]

Değerleri kopyalamak değil, onları almak

Genellikle, eğer istekliysen select, büyük olasılıkla bir şeyler kopyalıyorsun. Yalnızca değerlerle ilgileniyorsanız, bu, aşağıdakileri seçmekten kaçınmak için iyi bir seçenektir:

Range("B1:B6").Value = Range("A1:A6").Value


Her zaman Çalışma Sayfasına da başvurmaya çalışın

Bu muhtemelen vba'daki en yaygın hatadır . Aralıkları kopyaladığınızda, bazen çalışma sayfasına başvurulmaz ve bu nedenle VBA, ActiveWorksheet'in yanlış sayfasını değerlendirir.

'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

Gerçekten hiç kullanmıyorum Can .Selectveya .Activateherhangi bir şey için?

  • Görsel nedenlerle belirli bir Çalışma Sayfasının seçildiğinden emin olmak istediğinizde .Activateve .Selectkullanımda haklı çıkabileceğiniz iyi bir örnek . Örneğin, dosya kapatıldığında ActiveSheet'in hangisi olduğu dikkate alınmaksızın, Excel'iniz her zaman ilk önce seçilen kapak çalışma sayfasıyla açılacaktır.

Bu nedenle, aşağıdaki kod gibi bir şey kesinlikle uygundur:

Private Sub Workbook_Open()
    Worksheets("Cover").Activate
End Sub
  • Bir başka iyi örnek, bu durumda belirtildiği gibi, tüm sayfaları tek bir PDF dosyasına aktarmanız gerektiğinde - Bu örnekte VBA'da seçme / etkin ifadelerden nasıl kaçınılır?

  • Bir komut yalnızca ActiveWindow.Zoom veya ActiveWindow.FreezePanesActiveWindow gibi çalıştığında

30 FrancescoBaruchelli May 23 2012 at 13:11

Lütfen aşağıda Seçim yaklaşımını (OP'nin kaçınmak istediği yaklaşım) Menzil yaklaşımıyla (ve bu sorunun cevabı) karşılaştırdığımı unutmayın. Bu yüzden ilk Seçimi gördüğünüzde okumayı bırakmayın.

Gerçekten ne yapmaya çalıştığınıza bağlı. Her neyse, basit bir örnek faydalı olabilir. Aktif hücrenin değerini "foo" olarak ayarlamak istediğinizi varsayalım. ActiveCell kullanarak şöyle bir şey yazarsınız:

Sub Macro1()
    ActiveCell.Value = "foo"
End Sub

Etkin olmayan bir hücre için kullanmak istiyorsanız, örneğin "B2" için, önce şu şekilde seçmelisiniz:

Sub Macro2()
    Range("B2").Select
    Macro1
End Sub

Aralıkları kullanarak, istediğiniz herhangi bir hücrenin değerini istediğiniz gibi ayarlamak için kullanılabilecek daha genel bir makro yazabilirsiniz:

Sub SetValue(cellAddress As String, aVal As Variant)
    Range(cellAddress).Value = aVal
End Sub

Ardından, Macro2'yi şu şekilde yeniden yazabilirsiniz:

Sub Macro2()
    SetCellValue "B2", "foo"
End Sub

Ve Macro1 as:

Sub Macro1()
    SetValue ActiveCell.Address, "foo"
End Sub
18 user1644564 Aug 25 2014 at 16:54

Daima çalışma kitabını, çalışma sayfasını ve hücreyi / aralığı belirtin.

Örneğin:

Thisworkbook.Worksheets("fred").cells(1,1)
Workbooks("bob").Worksheets("fred").cells(1,1)

Çünkü son kullanıcılar her zaman yalnızca düğmelere tıklar ve odak çalışma kitabından ayrılır ayrılmaz kod çalışmak ister ve işler tamamen ters gider.

Ve asla bir çalışma kitabının dizinini kullanmayın.

Workbooks(1).Worksheets("fred").cells(1,1)

Kullanıcı kodunuzu çalıştırdığında başka hangi çalışma kitaplarının açılacağını bilmiyorsunuz.

11 LFB Jun 16 2018 at 21:18

Bu yöntemler daha çok damgalandı, bu yüzden kuma bir çizgi çekmek uğruna Vityata ve Jeeped'in liderliğini üstleniyor :

Çağrı .Activate, .Select, Selection, ActiveSomethingyöntemler / özellikler

Temel olarak, öncelikle uygulama kullanıcı arayüzü aracılığıyla kullanıcı girişini işlemek için çağrıldıkları için. Kullanıcı UI aracılığıyla nesneleri işlediğinde çağrılan yöntemler olduklarından, bunlar makro kaydedici tarafından kaydedilenlerdir ve bu yüzden çoğu durumda onları çağırmak ya kırılgan ya da gereksizdir: bir Selectionhemen ardından bir eylem gerçekleştirmek için nesne .

Bununla birlikte, bu tanım, çağrıldıkları durumları belirler:

Çağırmak zaman .Activate, .Select, .Selection, .ActiveSomethingyöntemler / özellikler

Temel olarak, son kullanıcının yürütmede bir rol oynamasını beklediğinizde .

Geliştiriyorsanız ve kullanıcının kodunuzun işleyeceği nesne örneklerini seçmesini bekliyorsanız, o zaman .Selectionveya .ActiveObjectuygun olur.

Öte yandan, .Selectve .Activatekullanıcının bir sonraki eylemi çıkarabiliriz zaman kullanım ve muhtemelen onu / ona biraz zaman ve fare tıklamaları tasarruf kodunuzu kullanıcıya rehberlik etmek istiyorum. Örneğin, kodunuz bir grafiğin yepyeni bir örneğini oluşturduysa veya güncellediyse, kullanıcı onu kontrol etmek isteyebilir .Activateve kullanıcıyı arama zamanından kurtarmak için onu veya sayfasını çağırabilirsiniz ; veya kullanıcının bazı aralık değerlerini güncellemesinin gerekeceğini biliyorsanız, bu aralığı programlı olarak seçebilirsiniz.

6 Eleshar Nov 20 2016 at 22:02

IMHO kullanımı, .selectbenim gibi VBA'yı zorunlu olarak makroları kaydederek öğrenmeye başlayan ve daha sonra bunun farkına varmadan kodu değiştiren .selectve sonrasında selectionsadece gereksiz bir aracı olan insanlardan geliyor.

.select Halihazırda gönderilmiş olduğu gibi, zaten var olan nesnelerle doğrudan çalışarak, i ve j'yi karmaşık bir şekilde hesaplamak ve ardından hücreyi (i, j) düzenlemek vb.

Aksi takdirde, .selectkendisinde dolaylı olarak yanlış olan hiçbir şey yoktur ve bunun kullanımlarını kolayca bulabilirsiniz, örneğin tarihle doldurduğum bir elektronik tablom var, onunla biraz sihir yapan makroyu etkinleştirin ve kabul edilebilir bir biçimde ayrı bir sayfada dışa aktaran bir elektronik tablom var. ancak bitişik bir hücreye bazı son manuel (öngörülemeyen) girdiler gerektirir. İşte .selectbunun için an geldi , bana ek fare hareketi ve tıklama tasarrufu sağlıyor.

4 FinPro.Online Sep 08 2016 at 13:36

.SelectYöntemi kullanmaktan kaçınmak için, istediğiniz özelliğe eşit bir değişken ayarlayabilirsiniz.

► Örneğin, içindeki değeri istiyorsanız, Cell A1o hücrenin değer özelliğine eşit bir değişken ayarlayabilirsiniz.

  • Misal valOne = Range("A1").Value

► Örneğin you could set a variable equal to the, o çalışma sayfasının 'Sayfa3 Kod Adı` özelliğinin kod adını istiyorsanız .

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

Bu yanıtların hiçbirinin .Offset Özelliğinden bahsetmediğini fark ettim . Bu aynı zamanda Select, özellikle seçilen bir hücreye atıfta bulunarak (OP'nin bahsettiği gibi ActiveCell) belirli hücreleri işlerken eylemi kullanmaktan kaçınmak için de kullanılabilir .

İşte birkaç örnek.

Ayrıca "ActiveCell" in J4 olduğunu varsayacağım .

ActiveCell.Offset(2, 0).Value = 12

  • Bu, hücreyi J612 değerine değiştirecek
  • Eksi -2, J2'ye başvururdu

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

  • Bu hücreyi kopyalar k4için L4.
  • Gerekmiyorsa ofset parametresinde "0" gerekmediğine dikkat edin (, 2)
  • Önceki örneğe benzer şekilde eksi 1, i4

ActiveCell.Offset(, -1).EntireColumn.ClearContents

  • Bu, k sütunundaki tüm hücrelerdeki değerleri temizleyecektir.

Bunlar, yukarıdaki seçeneklerden "daha iyi" oldukları anlamına gelmez, sadece alternatifleri listeler.

1 Dominique Oct 30 2020 at 22:55

Kopyala-yapıştır nasıl önlenir?

Kabul edelim: bu, makroları kaydederken çok görünür:

Range("X1").Select
Selection.Copy
Range("Y9).Select
Selection.Paste

Kişinin istediği tek şey şudur:

Range("Y9").Value = Range("X1").Value

Bu nedenle, VBA makrolarında kopyala-yapıştır kullanmak yerine aşağıdaki basit yaklaşımı öneririm:

Destination_Range.Value = Source_Range.Value
barneyos Oct 30 2019 at 16:45

.Parent özelliğiyle çalışan bu örnek, yalnızca bir myRng referansının ayarlanmasının herhangi bir .Select, .Activate, .Activecell, .ActiveWorkbook, .ActiveSheet vb. Olmadan tüm ortama nasıl dinamik erişim sağladığını gösterir. (Herhangi bir jenerik .Child özelliği yoktur.)

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

Seç veya Etkin Sayfayı hiçbir zaman kullanmamanın ana nedeni, çoğu insanın makronuzu çalıştırdıklarında en az birkaç çalışma kitabının (bazen düzinelerce) açık olması ve makronuz çalışırken sayfanızdan uzağa tıklarlarsa ve başka bir sayfaya tıklarlarsa olmasıdır. Açtıkları kitap, ardından "Etkin Sayfa" değişir ve nitelenmemiş "Seç" komutu için hedef çalışma kitabı da değişir.

En iyi durumda, makronuz çökecektir, en kötü ihtimalle, yanlış çalışma kitabındaki değerleri "Geri Almanın" hiçbir yolu olmadan değerleri yazmaya veya hücreleri değiştirmeye başlayabilirsiniz.

Takip ettiğim basit bir altın kuralı var: Bir Çalışma Kitabı nesnesi ve bir Çalışma Sayfası nesnesi için "wb" ve "ws" adlı değişkenler ekleyin ve bunları her zaman makro kitabıma başvurmak için kullanın. Birden fazla kitaba veya birden fazla sayfaya başvurmam gerekirse, daha fazla değişken eklerim.

Örneğin,

Dim wb as Workbook
Dim ws as Worksheet
Set wb = ThisWorkBook
Set ws = wb.sheets("Output")

"Set wb = ThisWorkbook" komutu kesinlikle anahtardır. "ThisWorkbook", Excel'de özel bir değerdir ve VBA kodunuzun şu anda çalıştığı çalışma kitabı anlamına gelir . Çalışma Kitabı değişkeninizi ile ayarlamak için çok yararlı bir kısayol.

Aboneliğinizin üst kısmında bunu yaptıktan sonra, onları kullanmak daha kolay olamazdı, "Seçim" i kullandığınız her yerde kullanın:

Dolayısıyla, "Çıktı" daki "A1" hücresinin değerini "Merhaba" olarak değiştirmek için:

Sheets("Output").Activate
ActiveSheet.Range("A1").Select
Selection.Value = "Hello"

Şimdi bunu yapabiliriz:

ws.Range("A1").Value = "Hello"

Kullanıcı birden çok elektronik tablo ile çalışıyorsa, bu yalnızca çok daha güvenilir değildir ve çökme olasılığı daha düşük değildir; ayrıca çok daha kısa, daha hızlı ve yazması daha kolay.

Ek bir bonus olarak, değişkenlerinizi her zaman "wb" ve "ws" olarak adlandırırsanız, kodu bir kitaptan diğerine kopyalayıp yapıştırabilirsiniz ve bu, varsa, genellikle minimum değişiklikle çalışacaktır.