Pergunta

Quando é apropriado usar uma classe no Visual Basic for Applications (VBA)?

Estou assumindo a acelerado desenvolvimento e redução de erros introduzindo é um benefício comum para a maioria das linguagens que suportam OOP. Mas com VBA existe um critério específico?

Foi útil?

Solução

Depende de quem vai desenvolver e manter o código. "Power User" macro escritores típicos hacking pequena ad-hoc aplicativos pode muito bem ser confundida usando classes. Mas para desenvolvimento sério, as razões para classes de uso são os mesmos que em outras línguas. Você tem as mesmas restrições que VB6 - nenhuma herança - mas você pode ter polimorfismo usando as interfaces

.

Um bom uso de classes é para representar entidades e coleções de entidades. Por exemplo, muitas vezes eu ver o código VBA que copia um intervalo do Excel em uma matriz bidimensional, então manipula a matriz bidimensional com um código como:

Total = 0
For i = 0 To NumRows-1
    Total = Total + (OrderArray(i,1) * OrderArray(i,3))
Next i

É mais legível para copiar o intervalo em uma coleção de objetos com propriedades adequadamente-nomeado, algo como:

Total = 0
For Each objOrder in colOrders
    Total = Total + objOrder.Quantity * objOrder.Price
Next i

Outro exemplo é a utilização de classes para implementar o padrão de design RAII (google para ele). Por exemplo, uma coisa que pode precisar fazer é para desproteger uma planilha, fazer algumas manipulações, então protegê-lo novamente. Usando um garante de classe que a planilha será sempre protegida novamente, mesmo se ocorrer um erro no seu código:

--- WorksheetProtector class module ---

Private m_objWorksheet As Worksheet
Private m_sPassword As String

Public Sub Unprotect(Worksheet As Worksheet, Password As String)
    ' Nothing to do if we didn't define a password for the worksheet
    If Len(Password) = 0 Then Exit Sub

    ' If the worksheet is already unprotected, nothing to do
    If Not Worksheet.ProtectContents Then Exit Sub

    ' Unprotect the worksheet
    Worksheet.Unprotect Password

    ' Remember the worksheet and password so we can protect again
    Set m_objWorksheet = Worksheet
    m_sPassword = Password
End Sub

Public Sub Protect()
    ' Protects the worksheet with the same password used to unprotect it
    If m_objWorksheet Is Nothing Then Exit Sub
    If Len(m_sPassword) = 0 Then Exit Sub

    ' If the worksheet is already protected, nothing to do
    If m_objWorksheet.ProtectContents Then Exit Sub

    m_objWorksheet.Protect m_sPassword
    Set m_objWorksheet = Nothing
    m_sPassword = ""
End Sub

Private Sub Class_Terminate()
    ' Reprotect the worksheet when this object goes out of scope
    On Error Resume Next
    Protect
End Sub

Você pode então usar isso para simplificar o seu código:

Public Sub DoSomething()
   Dim objWorksheetProtector as WorksheetProtector
   Set objWorksheetProtector = New WorksheetProtector
   objWorksheetProtector.Unprotect myWorksheet, myPassword

   ... manipulate myWorksheet - may raise an error

End Sub 

Quando isso Sub saídas, objWorksheetProtector sai do escopo, e a planilha está protegida novamente.

Outras dicas

Eu acho que os critérios é o mesmo que outras línguas

Se você precisa unir vários pedaços de dados e alguns métodos e também especificamente lidar com o que acontece quando o objeto é criado / terminados, aulas são ideais

dizer se você tem alguns procedimentos que fogo quando você abre um formulário e um deles está tomando um longo tempo, você pode decidir que quer tempo cada etapa ......

Você pode criar uma classe cronômetro com métodos para as funções óbvias para iniciar e parar, você pode então adicionar uma função para recuperar o tempo até agora e relatá-lo em um arquivo de texto, usando um argumento que representa o nome do ser processo cronometrado. Você poderia escrever a lógica para registrar apenas as performances mais lentos para investigação.

Você pode então adicionar uma barra de progresso objeto com métodos para abrir e fechá-lo e para exibir os nomes da ação atual, juntamente com tempos em ms e tempo provável restante com base em relatórios armazenados anteriores etc

Outro exemplo pode ser se você não gosta de lixo grupo de usuários do Access, você pode criar sua própria classe de usuário com métodos para loging dentro e fora e recursos de controle de acesso de usuário de nível de grupo / auditoria / log certas ações / erros etc tracking

Claro que você pode fazer isso usando um conjunto de métodos independentes e lotes de passagem variável, mas ter tudo encapsulado em uma classe só parece melhor para mim.

Você, mais cedo ou mais tarde chegará para os limites da VBA, mas é um idioma muito poderoso e se a sua empresa os laços que para isso você pode realmente obter alguns bons, soluções complexas de fora.

As aulas são extremamente útil quando se lida com as funções da API mais complexas, e particularmente quando eles exigem uma estrutura de dados.

funções

Por exemplo, o GetOpenFileName () e GetSaveFileName () tomar uma stucture OPENFILENAME com muitos membros. talvez não seja necessário para tirar proveito de todos eles, mas eles estão lá e deve ser inicializado.

Eu gosto de quebrar a estrutura (UDT) e as declarações de função API em uma classe CfileDialog. Os conjuntos de eventos Class_Initialize para cima os valores padrão dos membros da estrutura, de modo que quando eu uso a classe, eu só precisa definir os membros eu quero mudar (através de procedimentos de propriedade). constantes de flag são implementados como um Enum. Assim, por exemplo, para escolher uma planilha para abrir, o meu código pode ter esta aparência:

Dim strFileName As String
Dim dlgXLS As New CFileDialog

With dlgXLS
  .Title = "Choose a Spreadsheet"
  .Filter = "Excel (*.xls)|*.xls|All Files (*.*)|*.*"
  .Flags = ofnFileMustExist OR ofnExplorer

  If OpenFileDialog() Then
    strFileName = .FileName
  End If
End With
Set dlgXLS = Nothing

A classe define o diretório padrão para Meus Documentos, embora se eu quisesse eu poderia mudar isso com a propriedade InitDir.

Este é apenas um exemplo de como uma classe pode ser extremamente benéfico em uma aplicação de VBA.

Eu não diria que há um critério específico, mas eu nunca realmente encontrei um lugar útil para usar as classes no código VBA. Em minha mente está tão ligada aos modelos existentes em todo o aplicativos Office que a adição de fora abstração adicional de que o modelo de objeto apenas confunde as coisas.

Isso não quer dizer que um não encontrar um lugar útil para uma classe em VBA, ou fazer as coisas perfeitamente úteis usando uma classe, só que eu nunca encontrei-los úteis nesse ambiente.

Você também pode reutilizar o código VBA, sem o uso de classes reais. Por exemplo, se você tem um chamado, VBACode. Você pode acessar qualquer função ou sub em qualquer módulo com a seguinte sintaxe:

VBCode.mysub(param1, param2)

Se você criar uma referência a um modelo / doc (como se fosse uma dll), você pode fazer referência código de outros projetos da mesma forma.

O desenvolvimento de software, mesmo com o Microsoft Access, utilizando Programação Orientada a Objetos é geralmente uma boa prática. Vai permitir a escalabilidade no futuro, permitindo objectos a serem fracamente acoplados, juntamente com um número de vantagens. Isto significa basicamente que os objetos em seu sistema serão menos dependentes uns dos outros, de modo a refatoração se torna muito mais fácil. Você pode conseguir isso é Access usando módulos de classe. A desvantagem é que você não pode executar Class Herança ou Polimorfismo em VBA. No final, não há nenhuma regra dura e rápida sobre o uso de classes, apenas as melhores práticas. Mas tenha em mente que, como a sua aplicação cresce, mais fácil é manter usando classes.

Para recursão de dados (manuseio BOM A.K.A.), uma classe personalizada é extremamente útil e eu acho que às vezes indispensável. Você pode fazer uma função recursiva sem um módulo de classe, mas um monte de problemas de dados não podem ser tratadas de forma eficaz.

(Eu não sei por que as pessoas não estão fora tráfico BOM biblioteca de jogos para VBA. Talvez as ferramentas XML ter feito a diferença.)

Várias instâncias do formulário é a aplicação comum de uma classe (muitos problemas de automação são de outra maneira insolúvel), eu assumo a pergunta é sobre Personalizado classes.

Eu uso as classes quando eu preciso fazer alguma coisa e uma classe irá fazê-lo melhor :) Por exemplo, se você precisa para responder a eventos (ou intercepção), então você precisa de uma classe. Algumas pessoas odeiam UDTs (definidos pelo usuário tipos), mas eu como eles, então eu usá-los se eu quero código de auto-documentando plain-Inglês. Pharmacy.NCPDP sendo muito mais fácil de ler, em seguida, strPhrmNum :) Mas um UDT é limitado, por isso, dizer que eu quero ser capaz de definir Pharmacy.NCPDP e têm todas as outras propriedades preencher. E eu também quero fazer isso para que você não pode acidentalmente alterar os dados. Então eu preciso de uma classe, porque você não tem propriedades somente leitura em um UDT, etc.

Outra consideração é apenas legibilidade simples. Se você estiver fazendo estruturas de dados complexas, muitas vezes é benéfico para saber que você só precisa chamar Company.Owner.Phone.AreaCode em seguida, tentando manter o controle de onde tudo está estruturado. Especialmente para as pessoas que têm de manter essa base de código 2 anos depois que você saiu:)

Os meus próprios dois centavos é "Código Com Propósito". Não use uma classe sem uma razão. Mas se você tem uma razão, em seguida, fazê-lo:)

Eu uso as classes se eu quiser criar um pacote de auto-encapsulada de código que vou usar em muitos projetos VBA que vêm através de vários clientes.

Você pode definir uma classe wrapper sql no acesso que é mais conveniente do que os conjuntos de registros e querydefs. Por exemplo, se você deseja atualizar uma tabela com base em um critério em outra tabela relacionada, você não pode usar junta. Você poderia construir uma recorset VBA e querydef fazer isso no entanto acho que é mais fácil com uma classe. Além disso, o aplicativo pode ter algum conceito que precisam de mais que 2 mesas, talvez seja melhor imo para classes de uso para isso. Por exemplo. Você incidentes de pista aplicação. Incidente tem vários atributos que irá realizar em várias mesas {usuários e seus contatos ou perfis, descrição incidente; Monitoramento do Status; As listas de verificação para ajudar o oficial de suporte para responder tonthe incidente; Responder ...}. Para manter o controle de todas as consultas e relacionamentos envolvidos, oop pode ser útil. É um alívio para ser capaz de fazer Incident.Update (xxx) em vez de toda a codificação ...

Eu não vejo por que os critérios para a VBA seria diferente de outro idioma, especialmente se você está se referindo VB.NET.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top