Iterando todas as células no Excel VBA ou VSTO 2005
Pergunta
Preciso simplesmente percorrer todas as células de uma planilha do Excel e verificar os valores nas células.As células podem conter texto, números ou estar em branco.Não estou muito familiarizado/confortável em trabalhar com o conceito de ‘Range’.Portanto, quaisquer códigos de amostra seriam muito apreciados.(Tentei pesquisar no Google, mas os trechos de código que encontrei não fizeram exatamente o que eu precisava)
Obrigado.
Solução
Sub CheckValues1()
Dim rwIndex As Integer
Dim colIndex As Integer
For rwIndex = 1 To 10
For colIndex = 1 To 5
If Cells(rwIndex, colIndex).Value <> 0 Then _
Cells(rwIndex, colIndex).Value = 0
Next colIndex
Next rwIndex
End Sub
Encontrei este trecho em http://www.java2s.com/Code/VBA-Excel-Access-Word/Excel/Checksvaluesinarange10rowsby5columns.htm Parece ser uma função bastante útil para ilustrar os meios de verificar valores nas células de maneira ordenada.
Imagine-o como uma espécie de array 2D e aplique a mesma lógica para percorrer as células.
Outras dicas
Se você precisar apenas olhar as células que estão em uso, você pode usar:
sub IterateCells()
For Each Cell in ActiveSheet.UsedRange.Cells
'do some stuff
Next
End Sub
que atingirá tudo no intervalo de A1 até a última célula com dados (a célula inferior direita)
Se você estiver apenas observando os valores das células, poderá armazená-los em uma matriz do tipo variante.Parece que obter o valor de um elemento em uma matriz pode ser muito mais rápido do que interagir com o Excel, então você pode ver alguma diferença no desempenho usando uma matriz de todos os valores de células em comparação com a obtenção repetida de células únicas.
Dim ValArray as Variant
ValArray = Range("A1:IV" & Rows.Count).Value
Então você pode obter um valor de célula apenas verificando ValArray( row , column )
Você pode usar For Each para iterar por todas as células em um intervalo definido.
Public Sub IterateThroughRange()
Dim wb As Workbook
Dim ws As Worksheet
Dim rng As Range
Dim cell As Range
Set wb = Application.Workbooks(1)
Set ws = wb.Sheets(1)
Set rng = ws.Range("A1", "C3")
For Each cell In rng.Cells
cell.Value = cell.Address
Next cell
End Sub
Para um aplicativo VB ou C#, uma maneira de fazer isso é usando o Office Interop.Isso depende de qual versão do Excel você está trabalhando.
Para o Excel 2003, este artigo do MSDN é um bom ponto de partida.Compreendendo o modelo de objeto do Excel da perspectiva de um desenvolvedor do Visual Studio 2005
Você basicamente precisará fazer o seguinte:
- Inicie o aplicativo Excel.
- Abra a pasta de trabalho do Excel.
- Recupere a planilha da pasta de trabalho por nome ou índice.
- Itere todas as células da planilha que foram recuperadas como um intervalo.
- Exemplo de trecho de código (não testado) abaixo para a última etapa.
Excel.Range allCellsRng;
string lowerRightCell = "IV65536";
allCellsRng = ws.get_Range("A1", lowerRightCell).Cells;
foreach (Range cell in allCellsRng)
{
if (null == cell.Value2 || isBlank(cell.Value2))
{
// Do something.
}
else if (isText(cell.Value2))
{
// Do something.
}
else if (isNumeric(cell.Value2))
{
// Do something.
}
}
Para Excel 2007, tente esta referência do MSDN.
Existem vários métodos para fazer isso, cada um com vantagens e desvantagens;Em primeiro lugar, você precisará ter uma instância de um objeto Worksheet, Application.ActiveSheet funciona se você quiser apenas aquele que o usuário está olhando.
O objeto Planilha possui três propriedades que podem ser utilizadas para acessar os dados da célula (Células, Linhas, Colunas) e um método que pode ser utilizado para obter um bloco de dados da célula, (get_Range).
Os intervalos podem ser redimensionados e tal, mas pode ser necessário usar as propriedades mencionadas acima para descobrir onde estão os limites dos seus dados.A vantagem de um Range se torna aparente quando você trabalha com grandes quantidades de dados porque os suplementos do VSTO são hospedados fora dos limites do próprio aplicativo Excel, portanto, todas as chamadas para o Excel precisam passar por uma camada com sobrecarga;obter um intervalo permite obter/definir todos os dados desejados em uma chamada, o que pode trazer enormes benefícios de desempenho, mas exige que você use detalhes explícitos em vez de iterar cada entrada.
Esta postagem no fórum do MSDN mostra um desenvolvedor VB.Net fazendo uma pergunta sobre como obter os resultados de um Range como um array
Você basicamente pode percorrer um intervalo
Pegue uma planilha
myWs = (Worksheet)MyWb.Worksheets[1];
Obtenha o intervalo de seu interesse Se você realmente deseja verificar cada célula, use os limites do Excel
O Excel 2007 "Big Grid" aumenta o número máximo de linhas por planilha de 65.536 para mais de 1 milhão e o número de colunas de 256 (iv) a 16.384 (XFD).daqui http://msdn.microsoft.com/en-us/library/aa730921.aspx#Office2007excelPerf_BigGridIncreasedLimitsExcel
e então percorrer o intervalo
Range myBigRange = myWs.get_Range("A1", "A256");
string myValue;
foreach(Range myCell in myBigRange )
{
myValue = myCell.Value2.ToString();
}
No Excel VBA, esta função fornecerá o conteúdo de qualquer célula em qualquer planilha.
Function getCellContent(Byref ws As Worksheet, ByVal rowindex As Integer, ByVal colindex As Integer) as String
getCellContent = CStr(ws.Cells(rowindex, colindex))
End Function
Então se você quiser verificar o valor das células, basta colocar a função em um loop, dar a ela a referência da planilha desejada e o índice da linha e o índice da coluna da célula.O índice de linha e o índice de coluna começam em 1, o que significa que a célula A1 será ws.Cells(1,1) e assim por diante.
Minhas habilidades em VBA estão um pouco enferrujadas, mas essa é a ideia geral do que eu faria.
A maneira mais fácil de fazer isso seria iterar um loop para cada coluna:
public sub CellProcessing()
on error goto errHandler
dim MAX_ROW as Integer 'how many rows in the spreadsheet
dim i as Integer
dim cols as String
for i = 1 to MAX_ROW
'perform checks on the cell here
'access the cell with Range("A" & i) to get cell A1 where i = 1
next i
exitHandler:
exit sub
errHandler:
msgbox "Error " & err.Number & ": " & err.Description
resume exitHandler
end sub
parece que o realce da sintaxe de cores não gosta do vba, mas espero que isso ajude um pouco (pelo menos lhe dará um ponto de partida para trabalhar).
- Brisqueteiro