Eu tenho uma planilha do Excel que consiste em duas colunas, uma das quais é preenchida com strings e a outra vazia. Eu gostaria de usar o VBA para atribuir o valor das células na coluna vazia com base no valor da string adjacente na outra coluna.
Dim regexAdmin As Object Set regexAdmin = CreateObject("VBScript.RegExp") regexAdmin.IgnoreCase = True regexAdmin.Pattern = "Admin" Dim i As Integer For i = 1 To 10 "let"s say there is 10 rows Dim j As Integer For j = 1 To 2 If regexAdmin.test(Cells(i, j).Value) Then Cells(i, j + 1).Value = "Exploitation" End If Next j Next i
O O problema é que, ao usar esse loop para uma grande quantidade de dados, ele demora muito para funcionar e, na maioria das vezes, simplesmente trava o Excel.
Alguém conhece uma maneira melhor de fazer isso?
Resposta
A resposta curta é:
Não use vba , use uma fórmula. Em particular, uma combinação de IF
e PESQUISA .
=IF(SEARCH($A1,"Admin")>0,"Exploitation","")
Mas isso é revisão de código, então vamos fazer isso de qualquer maneira.
-
Regex é lento. Parece que você o está usando apenas para não diferenciar maiúsculas de minúsculas. Sendo assim, você pode comparar diretamente os valores das células usando
StrComp
com a opçãovbTextCompare
. ( artigo útil sobre StrComp ) -
i
ej
são normalmente usados para contadores de loop, masrow
ecol
faz mais sentido neste caso.
Veja como isso poderia ser:
Dim row As Integer For row = 1 To 10 "let"s say there is 10 rows Dim col As Integer For col = 1 To 2 If StrComp("Admin",Cells(row, col).Value,vbTextCompare) Then Cells(row, col + 1).Value = "Exploitation" End If Next col Next row
Resposta
Eu acho que a comparação de strings simples seria muito mais rápida do que Regex.
Dim pattern as string pattern = "Admin" Dim i As Integer For i = 1 To 10 "let"s say there is 10 rows Dim j As Integer For j = 1 To 2 If Cells(i, j) = pattern Then Cells(i, j + 1) = "Exploitation" End If Next j Next i
Comentários
- Este código não ‘ t aborda a comparação sem distinção entre maiúsculas e minúsculas, mas você ‘ está correto. O regex é um exagero e a comparação de strings é preferida neste caso. (Bem-vindo à revisão do código!)
Resposta
Posso sugerir uma redução de 50% no tempo de execução /esforço?
Dim row As Integer For row = 1 To 10 "let"s say there is 10 rows If StrComp("Admin",Cells(row, 1).Value,vbTextCompare) Then Cells(row, 2).Value = "Exploitation" End If Next row
Ninguém percebeu que o OP fala sobre “verificar UMA coluna, escrever no PRÓXIMO adjacente”, realmente? Por que fazer loop nas colunas então? A segunda passagem verificaria apenas uma célula vazia ou uma com “Exploração”.
Resposta
Uau. Só de ler as primeiras linhas me perguntei:
- Por que a ligação tardia?
- Por que usar uma regex?
@ ckuhn203 já abordou a nomenclatura em sua resposta, mas acho o seguinte:
Dim i As Integer For i = 1 To 10 "let"s say there is 10 rows
Transformou-se nisso:
Dim row As Integer For row = 1 To 10 "let"s say there is 10 rows
… Não precisa mais do comentário.
Eu gostaria de usar o VBA para atribuir o valor das células na coluna vazia com base no valor da string adjacente na outra coluna.
Eu acho que “s [mis | ab] usando VBA: o próprio Excel é muito bom em lidar com a atribuição de valores de células com base em outros células “valores.
regexAdmin.Pattern = "Admin"
Eu acho que “s [mis | ab] usando regex: se o seu padrão for apenas uma palavra simples, você provavelmente está tentando matar um mosquito com uma bazuca. Ferramenta errada para t o trabalho aqui.
Resposta
Sempre que você estiver acessando o objeto Range, isso deve ser feito com uma única operação de leitura / gravação.
Antes de entrar no loop for, você deve ler todo o intervalo com o qual deseja trabalhar.
data = Range(Cells(1,1), Cells(10,2)).Value
Agora você pode trabalhar com os dados:
For i = 1 To 10 "let"s say there is 10 rows Dim j As Integer For j = 1 To 2 If regexAdmin.test(data(i, j)) Then data(i, j + 1) = "Exploitation" End If Next j Next i
Por fim, escreva os dados de volta no excel:
Range(Cells(1,1), Cells(10,2)).Value = data
Resposta
Em B1:
=if(upper(A1)="ADMIN","Exploitation","")
Em seguida, basta preencher. Isso não diferencia maiúsculas de minúsculas.
Esse preenchimento automático pode ser feito de duas maneiras, interativamente na planilha ou programaticamente:
Interativamente : O Excel tem um recurso de preenchimento automático. Com B1 selecionado e a fórmula colocada, basta clicar duas vezes na alça de preenchimento, que é o pequeno quadrado no canto inferior direito da célula quando for selecionado. O Excel copiará de forma inteligente a fórmula até o final do intervalo contíguo que tem dados. Significa que se A1-A256 tiver dados sem espaços em branco, será preenchido automaticamente para B256. Como alternativa, se houver espaços em branco, role até a parte inferior e selecione B256 (ou qualquer que seja o final). Em seguida, Ctrl + Shift + seta para cima para selecionar o intervalo que conduz a B1 e Ctrl + D para copiá-lo para baixo (pense d = idem)
Usando VBA … se você deve fazer isso programaticamente: com a fórmula contendo a célula como sua seleção:
Selection.AutoFill Destination:=Range("B1:B19")
Existem outras opções disponíveis para preenchimento automático para fazer alguns truques interessantes.Pode copiar um valor literal em vez de uma fórmula ou também preencher uma série com base em um padrão. Você também pode definir padrões personalizados para que ele reconheça, como linhas de negócios que você costuma repetir em outras localidades ou cidades onde você tem lojas de varejo etc.
Comentários
- Bem-vindo à revisão do código! Perdi completamente que o OP não ‘ precisava pesquisar a coluna! ++ Melhor solução aqui.
Resposta
Combinar todas as outras respostas juntas, tornou insensível a maiúsculas e minúsculas como o regex no original, removeu a necessidade de especificar quantas linhas e declarar todas as variáveis porque Option Explicit
evita tantos erros em vba
Option Explicit Sub checkForExploit() Dim row As Integer Dim data() As Variant Dim datarange As Range Set datarange = Range("A1:B10") data = datarange.Value For row = 1 To UBound(data, 1) If LCase(data(row, 1)) = "admin" Then data(row, 2) = "Exploitation" End If Next row datarange.Value = data End Sub