2010-01-29 21 views
26

2007'de Excel'de bazı VBA programlama yapıyorum ve tüm veri sayfalarının başka bir sayfaya kopyalanacağı bir çalışma kitabına sahibim. Yeni sayfa birkaç başlık satırına sahip olacak ve nerede bulunduklarını takip etmek istiyorum, böylece sürekli olarak onlarda kelime bulmak zorunda kalmam.Sınıfları VBA'da kullanmanın yararları nelerdir?

Sınıfları kullanmak ve excel doc açıkken onları çalıştırmaya devam ettirmek en basit şey midir? Yoksa bu işlenmeyi zorlaştıracak mıdır ve altprogramlarla çalışmaya devam etmeli miyim? Sınıfları kullanmanın yararları nelerdir? Sütunlarda birkaç nesne, sadece sayfalar ve doğrulama var gibi değil.

Teşekkürler!

cevap

6

Çok sayıda alt yordam veya alt yordam çok uzunsa, kodun sınıflara yapılandırılması yardımcı olabilir. Eğer sadece bir çift altprogram varsa, her biri her defasında sadece 10 satırlık kod olacaksa, bu öldürmek bitti. Kodu sınıflara yapılandırmanın yararı, çizgiye geri döndüğünüzde okunması ve değiştirilmesi daha kolay olmasıdır. Kodun sınıflara göre yapılandırılmasının bir başka nedeni, kodun muhtemelen

69

hattında değiştirilmesi gerekmesi halinde, yalnızca altprogramlar yerine sınıfları kullanmanın avantajı, sınıfların daha temiz kod yazmanıza olanak veren bir soyutlama düzeyi oluşturmasıdır. Kuşkusuz, eğer daha önce VBA'da dersleri hiç kullanmadıysanız, bir öğrenme eğrisi var, ama kesinlikle bunu anlamanın zamanı olduğuna inanıyorum.

Sınıflara geçmeniz gereken bir anahtar işlev, işlevlerinize ve alt programlarınıza sürekli olarak parametre ekliyor olmanızdır. Bu durumda, dersleri kullanmak neredeyse her zaman en iyisidir.

ben one of my previous Stack Overflow answers gelen sınıfların bir açıklama kopyaladıktan:


İşte size yardımcı olabilecek bir sınıf kullanarak nasıl uzun bir örnek. Bu örnek uzun sürse de, birkaç nesne yönelimli programlama ilkesinin gerçekten kodunuzu temizlemenize nasıl yardımcı olabileceğini gösterecektir. VBA düzenleyicisinde Insert > Class Module'a gidin. Özellikler penceresinde (varsayılan olarak ekranın sol alt köşesinde), modülün adını WorkLogItem olarak değiştirin. sınıfa aşağıdaki kodu ekleyin:

Option Explicit 

Private pTaskID As Long 
Private pPersonName As String 
Private pHoursWorked As Double 

Public Property Get TaskID() As Long 
    TaskID = pTaskID 
End Property 

Public Property Let TaskID(lTaskID As Long) 
    pTaskID = lTaskID 
End Property 

Public Property Get PersonName() As String 
    PersonName = pPersonName 
End Property 

Public Property Let PersonName(lPersonName As String) 
    pPersonName = lPersonName 
End Property 

Public Property Get HoursWorked() As Double 
    HoursWorked = pHoursWorked 
End Property 

Public Property Let HoursWorked(lHoursWorked As Double) 
    pHoursWorked = lHoursWorked 
End Property 

Yukarıdaki kod bize çalışıyoruz kılan verileri kendisine özel bir kesinlikle yazılan nesneyi verecektir. Verilerinizi depolamak için çok boyutlu diziler kullandığınızda, kodunuz buna benzer: arr(1,1) kimlik, arr(1,2) PersonName ve arr(1,3) HoursWorked. Bu sözdizimini kullanarak neyin ne olduğunu bilmek zor. Nesnelerinizi hala bir diziye yüklediğinizi varsayalım, bunun yerine yukarıda oluşturduğumuz WorkLogItem kullanın. Bu isim, kişinin adını almak için arr(1).PersonName yapabileceksiniz. Bu, kodunuzun okunmasını daha kolay hale getirir.

Bu örnekle devam edelim. Nesneleri dizide saklamak yerine, bir collection kullanmayı deneyeceğiz.

Sonraki, yeni bir sınıf modülü ekleyin ve ProcessWorkLog numaralı telefonu arayın. Orada aşağıdaki kodu koyun: Yukarıdaki sınıf WorkLogItem bir koleksiyonunda ile "bir şeyler yapmak" için kullanılacak gidiyor

Option Explicit 

Private pWorkLogItems As Collection 

Public Property Get WorkLogItems() As Collection 
    Set WorkLogItems = pWorkLogItems 
End Property 

Public Property Set WorkLogItems(lWorkLogItem As Collection) 
    Set pWorkLogItems = lWorkLogItem 
End Property 

Function GetHoursWorked(strPersonName As String) As Double 
    On Error GoTo Handle_Errors 
    Dim wli As WorkLogItem 
    Dim doubleTotal As Double 
    doubleTotal = 0 
    For Each wli In WorkLogItems 
     If strPersonName = wli.PersonName Then 
      doubleTotal = doubleTotal + wli.HoursWorked 
     End If 
    Next wli 

Exit_Here: 
    GetHoursWorked = doubleTotal 
     Exit Function 

Handle_Errors: 
     'You will probably want to catch the error that will ' 
     'occur if WorkLogItems has not been set ' 
     Resume Exit_Here 


End Function 

. Başlangıçta, çalışılan toplam saat sayısını saymak için ayarladık. Yazdığımız kodu test edelim.Yeni bir Modül oluşturun (bu sefer bir sınıf modülü değil, sadece bir "normal" modül). Aşağıdaki kodu modüle yapıştırın:

Yukarıdaki kodda
Option Explicit 

Function PopulateArray() As Collection 
    Dim clnWlis As Collection 
    Dim wli As WorkLogItem 
    'Put some data in the collection' 
    Set clnWlis = New Collection 

    Set wli = New WorkLogItem 
    wli.TaskID = 1 
    wli.PersonName = "Fred" 
    wli.HoursWorked = 4.5 
    clnWlis.Add wli 

    Set wli = New WorkLogItem 
    wli.TaskID = 2 
    wli.PersonName = "Sally" 
    wli.HoursWorked = 3 
    clnWlis.Add wli 

    Set wli = New WorkLogItem 
    wli.TaskID = 3 
    wli.PersonName = "Fred" 
    wli.HoursWorked = 2.5 
    clnWlis.Add wli 

    Set PopulateArray = clnWlis 
End Function 

Sub TestGetHoursWorked() 
    Dim pwl As ProcessWorkLog 
    Dim arrWli() As WorkLogItem 
    Set pwl = New ProcessWorkLog 
    Set pwl.WorkLogItems = PopulateArray() 
    Debug.Print pwl.GetHoursWorked("Fred") 

End Sub 

, PopulateArray() basitçe WorkLogItem bir koleksiyon oluşturur. Gerçek kodunuzda, bir koleksiyon veya dizi doldurmak için Excel sayfalarınızı veya veri nesnelerini ayrıştırmak üzere sınıf oluşturabilirsiniz.

TestGetHoursWorked() kodu, sınıfların nasıl kullanıldığını gösterir. ProcessWorkLog'un bir nesne olarak başlatıldığını fark edersiniz. Örneklendikten sonra, WorkLogItem topluluğunun bir koleksiyonu pwl nesnesinin bir parçası haline gelir. Bunu Set pwl.WorkLogItems = PopulateArray() numaralı hattan fark ediyorsunuz. Ardından, biz sadece WorkLogItems koleksiyonuna hareket eden yazdığımız fonksiyonu çağırıyoruz.

Bu neden yardımcı oluyor?

Verilerinizin değiştiğini ve yeni bir yöntem eklemek istediğinizi varsayalım. WorkLogItem ürününüzün artık HoursOnBreak için bir alan içerdiğini ve bunu hesaplamak için yeni bir yöntem eklemek istediğinizi varsayalım.

yapmanız gereken tek şey şöyle WorkLogItem Bir mülkü ekleyin: Eğer toplama doldurmamak için yöntemini değiştirmek gerekir Tabii

Private pHoursOnBreak As Double 

Public Property Get HoursOnBreak() As Double 
    HoursOnBreak = pHoursOnBreak 
End Property 

Public Property Let HoursOnBreak(lHoursOnBreak As Double) 
    pHoursOnBreak = lHoursOnBreak 
End Property 

(kullandığım örnek yöntemi PopulateArray(), ama Muhtemelen bunun için ayrı bir dersiniz olmalı. Sonra sadece ProcessWorkLog sınıfa yeni yöntemini ekleyin:

:

Function GetHoursOnBreak(strPersonName As String) As Double 
    'Code to get hours on break 
End Function 

Şimdi, GetHoursOnBreak sonucunu döndürmek için bizim TestGetHoursWorked() yöntemlerini güncellemeleri istiyorsa, tüm biz yapmak aşağıdaki satırı eklemeniz gerekir

Debug.Print pwl.GetHoursOnBreak("Fred") 

Verilerinizi temsil eden bir değerler dizisi geçirdiyseniz, dizilerinizi kullandığınız dizinin her yerini bulmanız ve sonra buna göre güncelleştirmeniz gerekir. Bunun yerine sınıfları (ve bunların örneklenmiş nesnelerini) kullanırsanız, değişikliklerle çalışmak için kodunuzu daha kolay bir şekilde güncelleyebilirsiniz. Ayrıca, sınıfın birden fazla yolla kullanılmasına izin verdiğinizde (belki de başka bir işlev 6'ya ihtiyaç duyarken bir işlev yalnızca nesne özelliklerinin 4'üne gereksinim duyar), aynı nesneye yine de başvurabilirler. Bu, farklı işlev türleri için birden fazla dizinin olmasını engeller.

Daha fazla okumak için, VBA Developer's Handbook, 2nd edition'un bir kopyasını almanızı öneririm yüksek öneririm. Kitap harika örnekler ve en iyi uygulamalar ve tonlarca örnek kodla dolu. VBA'ya ciddi bir proje için çok fazla yatırım yapıyorsanız, bu kitaba bakmak için zaman ayırmaya değer.

+7

+1, BÜYÜK cevap. Herkese açık, net ve çok yararlı. VBA Geliştiricinin El Kitabı için –

+2

+1! –

+0

Hala faydalı 5 yıl sonra, teşekkürler Ben! +1 benden. – FreeMan

3

Diğer katkıda bulunanların belirtmiş olduğu avantajlara ekleyebileceğiniz başka bir şey var (üzgünüm, eğer Ben McCormack'ın mükemmel cevabının bir yerinde olsaydı ve onu özledim). VBA komut dosyanızın bir noktada yeniden programlanması muhtemelse, sınıfların kullanımları olabilir. Örneğin, bir çeşit sipariş yönetim sistemi tasarlıyorum. Pek çok meslektaş tarafından uzunca bir süre kullanılmalı, ancak sipariş kuralları değiştiğinde yeniden programlamaya ihtiyaç duyulabilir. Bu nedenle, bir stok kalemiyle ilgili tüm bilgileri toplayan temel bir stok kalemi sınıfı tasarladım. Bununla birlikte, bu verilerin herhangi bir düzen için nasıl analiz edildiği ile ilgili kurallar, kolay erişilebilir ve iyi yorumlanmış alt rutinlerde yazılmıştır.Bunu yaparak, gelecekteki VBA programcılarının, siparişlerin üretildiği matematik kurallarını, tüm verinin belirli bir stok kalemi hakkında nasıl toplandığını ele almak zorunda kalmadan kolayca değiştirebileceğini umuyorum (bu, hepsi sınıftaki alt rutinler ve işlevler tarafından gerçekleştirilir) , sınıf bir stok numarası verildiğinde aktive edilir). Bir 'genel' özellik, aynı zamanda daha kolay bir zamana sahip olmak için, bir sonraki programcıya ve kendinize izin vererek, intellisense tarafından alınır.

ben, o zaman programın içeriğiyle alakalı olması muhtemeldir nokta sınıfları onlar bazı bilgileri temel seti veya bazı kavramsal nesne kodlamak eğer bu şekilde sonradan kullanıcılar hayatını kolaylaştıracak olmasıdır tahmin kullanın.

İlgili konular