Notifications
Clear all

Apagar linhas em que uma certa coluna esteja vazia

5 Posts
4 Usuários
0 Reactions
1,046 Visualizações
(@outofmemry)
Posts: 9
Active Member
Topic starter
 

Oi, fiz um código que me percorre uma tabela (tabela1) a procura em uma certa coluna de células vazias. Quando encontra vai copiar a linha para outra tabela (tabela2) e apaga-la da tabela1.
O problema é que quando meto o código a correr o VBA fica "Not Running" e sou obrigado a forçar a paragem, no entanto quando vou ver ao excel a tabela2 verifico que foram copiadas algumas linhas (não são apagadas da tabela1 pois forço a paragem antes de chegar à instrução de apagar). Este processo está a ser realizado em uma tabela com 95k linhas, de forma a que também me parece que o código que fiz seja lento. Por isso venho aqui pedir dicas para o poder por a fazer mais depressa.
Aqui está o código:

Function DeleteRows() 

Debug.Print Time        
Dim shtSrc As Worksheet, shtDest As Worksheet
Dim lRow As Long, Row As Long
Dim rw As Range, rngDel As Range

Application.ScreenUpdating = False
viewmode = ActiveWindow.View
ActiveWindow.View = xlNormalView
Application.EnableEvents = False
Application.DisplayStatusBar = False
ActiveSheet.DisplayPageBreaks = False
Row = 2
lRow = Range("A" & Rows.Count).End(xlUp).Row
Set shtSrc = Worksheets("Sheet3")
Set shtDest = Worksheets("Sheet2")
shtSrc.Range("A1:AQ1").Copy Destination:=shtDest.Range("A1")

For i = 2 To lRow

    Set rw = shtSrc.Rows(i)

    If (rw.Cells(42).Value = "") Then
        rw.Copy shtDest.Rows(Row)
        AddToRange rngDel, rw
        Row = Row + 1
    End If

Next i

If Not rngDel Is Nothing Then
    rngDel.Delete
End If

Application.DisplayStatusBar = True
ActiveWindow.View = viewmode
Application.ScreenUpdating = False
Debug.Print Time

End Function

'utility sub for building up a range
Sub AddToRange(rngTot, rng)
    If rngTot Is Nothing Then
        Set rngTot = rng
    Else
        Set rngTot = Application.Union(rng, rngTot)
    End If
End Sub

Obrigado pela ajuda.

 
Postado : 06/11/2015 6:46 am
(@mprudencio)
Posts: 2749
Famed Member
 

Disponibilize parte desse arquivo para testes

Marcelo Prudencio
Microsoft Excel Brasil no Facebook

"Começar já é a metade do caminho."
Autor Desconhecido

Simplifica que simples fica.
Nicole Tomazella.

"O Simples é Sempre Melhor Que o Complicado"
Jorge Paulo Lemann.

 
Postado : 06/11/2015 6:49 am
(@messiasmbm)
Posts: 223
Estimable Member
 

coloque seu projeto para nós olharmos o que está errado ...
mas parece que é algo com loop.

 
Postado : 06/11/2015 9:07 am
(@nelson-s)
Posts: 96
Trusted Member
 

Pelo que eu entendi do problema dá a impressão que esse código é meio "enroscado". Duas rotinas para fazer algo que pode ser feito em uma só?

 
Postado : 06/11/2015 3:16 pm
(@outofmemry)
Posts: 9
Active Member
Topic starter
 

Desculpem não ter respondido mais cedo, no entanto já consegui resolver o problema com um código diferente.

Sub Keep_Highest_BC() ' Retira repetidos para outra tabela -> codigo das ot.
        
    Debug.Print Time
    Application.ScreenUpdating = False
    
    Dim d As Long, dHIGHs As Object, dDUPEs As Object
    Dim v As Long, vTMPs() As Variant, iCOLs As Long, Tam As Long

    'On Error GoTo bm_Safe_Exit
    Set dHIGHs = CreateObject("Scripting.Dictionary")
    Set dDUPEs = CreateObject("Scripting.Dictionary")

    With Worksheets("Sheet1")
        iCOLs = .Columns("AQ").Column
        .Cells(1, 1).Resize(2, iCOLs).Copy _
          Destination:=Worksheets("Sheet2").Cells(1, 1)
        With .Cells(2, 1).Resize(.Cells(Rows.Count, 2).End(xlUp).Row - 1, iCOLs) ' Vai guardar a info toda da tabela em vTMPs
            vTMPs = .Value2
        End With
    End With

    For v = LBound(vTMPs, 1) To UBound(vTMPs, 1)
         If vTMPs(v, 42) <> "" And vTMPs(v, 42) <> "#MULTIVALOR" And vTMPs(v, 40) <> "#MULTIVALOR" And vTMPs(v, 39) <> "#MULTIVALOR" Then
            If dHIGHs.exists(vTMPs(v, 2)) Then ' Vais verificar se o valor já existe
                If CDbl(Split(dHIGHs.Item(vTMPs(v, 2)), ChrW(8203))(2)) < vTMPs(v, 4) Then ' Para cada valor que este estiver em dHIGHs vai ver qual data fim mais recente
                    dDUPEs.Add Key:=vTMPs(v, 2) & v, Item:=dHIGHs.Item(vTMPs(v, 2)) 'Caso a linha já guardada tenha data menor vai copia-la para dDUPEs
                    dHIGHs.Item(vTMPs(v, 2)) = joinAtoAQ(vTMPs, v)                  ' E guardar a nova linha na dHIGHs
                Else
                    dDUPEs.Add Key:=vTMPs(v, 2) & v, Item:=joinAtoAQ(vTMPs, v) 'Caso a nova linha tenha data menor guarda logo em dDUPEs
                End If
            Else
                dHIGHs.Add Key:=vTMPs(v, 2), Item:=joinAtoAQ(vTMPs, v) 'Caso não exista em dHIGHs guarda logo lá, pois ainda não esta repetido
            End If
        
        Else
            dDUPEs.Add Key:=vTMPs(v, 2) & v, Item:=joinAtoAQ(vTMPs, v) ' Caso nao tenha info nas ultimas linhas é considerado repetido
        End If
    Next v

    With Worksheets("Sheet1") 'Vai apagar a tabela original, colocando uma tabela que contenha apenas os valores unicos
        With .Cells(2, 1).Resize(.Cells(Rows.Count, 2).End(xlUp).Row - 1, iCOLs)
            .ClearContents
            With .Resize(dHIGHs.Count, iCOLs)
                .Value = transposeSplitLargeItemArray(dHIGHs.items)
            End With
        End With
    End With

    With Worksheets("Sheet2") ' vai criar a tabela com valores repetidos
        With .Cells(1, 1).CurrentRegion.Offset(1, 0)
            .ClearContents
            With .Resize(dDUPEs.Count, iCOLs)
                .Value = transposeSplitLargeItemArray(dDUPEs.items)
                .Rows(1).Copy
                .PasteSpecial Paste:=xlPasteFormats
                Application.CutCopyMode = False
            End With
        End With
    End With
    
    Tam = Worksheets("Sheet2").ColocaDatas2
    ColocaDatas (Tam)

bm_Safe_Exit:
    dHIGHs.RemoveAll: Set dHIGHs = Nothing
    dDUPEs.RemoveAll: Set dDUPEs = Nothing
    
Application.ScreenUpdating = False

    Debug.Print Time
End Sub

Function joinAtoAQ(vTMP As Variant, ndx As Long)
    Dim sTMP As String, v As Long

    For v = LBound(vTMP, 2) To UBound(vTMP, 2)
        sTMP = sTMP & vTMP(ndx, v) & ChrW(8203)
    Next v
    joinAtoAQ = Left$(sTMP, Len(sTMP) - 1)
End Function

Function transposeSplitLargeItemArray(vITMs As Variant)
    Dim v As Long, w As Long, vTMPs As Variant, vITM As Variant

    ReDim vTMPs(LBound(vITMs) To UBound(vITMs), LBound(vITMs) To UBound(Split(vITMs(LBound(vITMs)), ChrW(8203))))
    For v = LBound(vITMs) To UBound(vITMs)
        vITM = Split(vITMs(v), ChrW(8203))
        For w = LBound(vITM) To UBound(vITM)
            vTMPs(v, w) = vITM(w)
        Next w
    Next v

    transposeSplitLargeItemArray = vTMPs
End Function

Obrigado pela ajuda e peço uma vez mais não ter respondido mais cedo.

 
Postado : 11/11/2015 10:01 am