Ridurre a una riga commessa



  • Ridurre a una riga commessa
    di Scumm Bar (utente non iscritto) data: 12/06/2017 17:48:14

    Buonasera,
    vi scrivo perchè ho una tabella che mi sta attanagliando. In allegato trovate il file dove potete vedere due tabelle: la prima è quella che ho ora, la seconda è quella che vorrei.

    La particolarità è: ridurre ad una riga tutti i codici commessa uguali (colonna A). Per tutte le altro colonne se trova stringhe alfanumeriche uguali o celle vuote deve mettere la prima cella piena. Es:

    ""
    EUROPA
    ""
    EUROPA

    Deve mettere EUROPA. Invece se trova, oltre celle uguali, anche stringhe alfanumeriche diverse, deve tenerle entrambe separate da "/". Es:

    OPT1
    ""
    OPT3
    ""
    OPT1

    Deve dare come risultato OPT1/OPT3.

    Vi chiedo aiuto perchè non so veramente da dove cominciare. Grazie a tutti anticipatamente.
    Saluti



  • di Vecchio Frac data: 13/06/2017 16:41:42

    Il raggruppamento è per Commessa giusto? All'interno del raggruppamento con codice commessa uguale, devi fondere in una riga le celle mercato con valore uguale, e quelle con valore vuoto e per le altre unire i valori.





  • di Scumm Bar (utente non iscritto) data: 13/06/2017 17:11:51

    Si la richiesta è esattamente questa. Grazie in anticipo



  • di Vecchio Frac data: 13/06/2017 21:58:45

    Ecco una proposta.
    Vabbè, fa schifo. Ho scritto di fretta mi dispiace, chiedo un po' scusa a tutti... si può, si deve ottimizzare.
    Genera un foglio "Result" dove fa finire il risultato dell'elaborazione.
    Non ci sono controlli errore... se esiste già un foglio "Result" temo che succeda un pasticcio :)
    E anche la connessione ADO... è tarata per un file xls, non xlsx... l'ho già detto che fa schifo e andrebbe migliorato? ^^
     
    Option Explicit
    
    Sub group()
    Dim objConnection As Object
    Dim rs As Object
    Dim rstmp As Object, rstmp2 As Object
    Dim s As String, m As String
    Dim j As Long, k As Long, c As Long
    Dim v As Variant
    
    Const adOpenStatic = 3
    Const adLockOptimistic = 3
    Const adCmdText = &H1
    
        Sheets.Add.Name = "Result"
        
        s = ThisWorkbook.Path & "	emporary.xlsx"
        ThisWorkbook.SaveCopyAs s
        
        Set objConnection = CreateObject("ADODB.Connection")
        Set rs = CreateObject("ADODB.Recordset")
        Set rstmp = CreateObject("ADODB.Recordset")
        Set rstmp2 = CreateObject("ADODB.Recordset")
        
        objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
            "Data Source=" & s & ";Extended Properties=""Excel 8.0;HDR=Yes;"";"
        
        rs.Open "SELECT DISTINCT Commessa FROM [Macro$A1:J16]", _
            objConnection, adOpenStatic, adLockOptimistic, adCmdText
            
        rstmp2.Open "SELECT * FROM [Macro$A1:J16]", _
            objConnection, adOpenStatic, adLockOptimistic, adCmdText
        c = rstmp2.Fields.Count
        
        
        Dim i As Integer
        
        Do Until rs.EOF
            Cells(j + 1, 1) = rs("Commessa")
            m = ""
            k = 1
            For i = 1 To c - 1
                rstmp.Open "SELECT DISTINCT [" & rstmp2.Fields(i).Name & "] FROM [Macro$A1:J16] WHERE Commessa = '" & rs("Commessa") & "'", _
                    objConnection, adOpenStatic, adLockOptimistic, adCmdText
                m = ""
                Do Until rstmp.EOF
                    m = m & rstmp(rstmp2.Fields(i).Name) & "/"
                    rstmp.movenext
                Loop
                m = Left(m, Len(m) - 1)
                m = Replace(m, "//", "/")
                If Left(m, 1) = "/" Then m = Mid(m, 2)
                k = k + 1
                Cells(j + 1, k) = m
                m = ""
                rstmp.Close
            Next
            j = j + 1
            rs.movenext
        Loop 
        
        rs.Close
        objConnection.Close
        Kill s
    End Sub
    






  • di alfrimpa data: 13/06/2017 22:49:10

    Mamma mia Vecchio Frac nonostante sia stato lontano dal forum per tanto tempo non ti sei per nulla "arrugginito" complimenti.

    Sfido chiunque a trovare qualcuno in grado di migliorare questa macro.

    Alfredo





  • di Nick (utente non iscritto) data: 13/06/2017 22:55:05

    Ci sono troppi

    m=""

    ... basta solo quella subito prima il Do Until ...


    ... (ovviamente è solo una battuta ... ) ...



  • di Scumm Bar (utente non iscritto) data: 14/06/2017 08:54:37

    Scusate l'ignoranza a livello di VBA sono 3 anni luce indietro da voi. Vedo impostato $A1:J16, ma siccome non ho sempre una lughezza fissa della tabella ho provato a scrivere $A1:J200, però va in debug.

    Comunque sulle prime 16 righe funziona perfettamente! Grazie!



  • di Vecchio Frac data: 14/06/2017 10:50:31

    Ma certo che va ottimizzato, ci mancherebbe :)

    @Scumm Bar (quanti ricordi Guybrush Threepwood ^^)
    Ho realizzato un codice ad hoc per l'esempio che hai allegato.
    Devi per forza cambiare il range in cui giace la tabella originale.
    Un esempio potrebbe essere:


    rs.Open "SELECT DISTINCT Commessa FROM [Macro$" & range("A1").currentregion.address & "]", _
    objConnection, adOpenStatic, adLockOptimistic, adCmdText


    in modo da dare in pasto al recordset l'intera tabella che comincia da A1 (presuppone che la tabella sia contigua e uniforme cioè non ci devono essere colonne vuote e righe vuote in mezzo).








  • di Vecchio Frac data: 14/06/2017 10:53:33

    cit. " ho provato a scrivere $A1:J200, però va in debug"
    ---> per curiosità ho lanciato la macro sul tuo file, impostando A1:J200 ma non "va in debug". Dovresti essere così cortese da indicare quale linea di codice viene evidenziata al momento dello stop e che tipo di errore ricevi.






  • di Scumm Bar (utente non iscritto) data: 14/06/2017 15:28:07

    Debug sulla linea:

    m = Left(m, Len(m) - 1)

    Penso di aver capito il problema: impostandola su $A1:J200 alla prima cella vuota da errore (m = ""), come posso fare per gestire un range variabile in base all'ultima cella occupata?

    ...Sono un temibile pirata!



  • di Vecchio Frac data: 14/06/2017 15:54:05

    Grande ^_^

    cit. "come posso fare per gestire un range variabile in base all'ultima cella occupata? "
    ---> La modifica già proposta non funziona?

    rs.Open "SELECT DISTINCT Commessa FROM [Macro$" & range("A1").currentregion.address & "]", _
    objConnection, adOpenStatic, adLockOptimistic, adCmdText





  • di Textomb data: 14/06/2017 19:47:53

    un grande saluto al mio amico Vecchio Frac!!!
    ho provato anch'io una soluzione alternativa.
    Ho fatto alcuni Test e sembra che funzioni correttamente...
     
    Option Explicit
    
    Sub GroupT()
        Dim dicA As Object
        Dim dicB As Object
        Dim Itm
        Dim sh As Worksheet
        Dim sh_Result As Worksheet
        Dim nCol As Long
        Dim Rng_Filter As Range
        Dim cell As Range
        Dim Lr_sh As Long
        Dim StrUnito As String
        Dim M_Value(1 To 10) As String ' Vettore riga
    
     
        Set sh = Worksheets("Macro")
        Set sh_Result = ThisWorkbook.Worksheets.Add
        
        Lr_sh = sh.Range("A1").End(xlDown).Row
        
        Set dicA = CreateObject("Scripting.Dictionary")
        Set dicB = CreateObject("Scripting.Dictionary")
        
        ' Trovo i valori univoci della colonna A
        For Each cell In sh.Range("A2:A" & Lr_sh)
            If Not dicA.Exists(cell.Value) Then
                dicA.Add Key:=cell.Value, Item:=""
            End If
        Next
        
        ' Ciclo i valori univoci della dicA ed estrapolo la stringa da riportare su ogni colonna-
        For Each Itm In dicA.Keys
            sh.Range("A1").AutoFilter field:=1, Criteria1:=Itm
            M_Value(1) = Itm
    
            For nCol = Columns("B").Column To Columns("J").Column
                Set Rng_Filter = Range(sh.Cells(1, nCol), sh.Cells(Lr_sh, nCol)).Offset(1).Resize(Lr_sh - 1).SpecialCells(xlCellTypeVisible)
                dicB.RemoveAll
                StrUnito = ""
                
                    ' costruisco la stringa da riportare nella relativa colonna
                    For Each cell In Rng_Filter
                        If Not cell.Value = "" And Not dicB.Exists(cell.Value) Then
                            dicB.Add cell.Value, ""
                            StrUnito = StrUnito & cell.Value & "/"
                        End If
                    Next
                    
                ' riporto la stringa nell'elemento della matrice
                If StrUnito = "" Then
                    M_Value(nCol) = ""
                Else
                    M_Value(nCol) = Left(StrUnito, Len(StrUnito) - 1)
                End If
                
            Next
            
            ' Riporto il vettore M_Value nella sua destinazione finale
            sh_Result.Range("A" & Rows.Count).End(xlUp).Offset(1).Resize(1, 10).Value = M_Value
            Erase M_Value
        
        Next
        
        sh.AutoFilterMode = False
        
        Set dicA = Nothing
        Set dicB = Nothing
        Set sh_Result = Nothing
        Set sh = Nothing
        
    End Sub
    



  • di Vecchio Frac data: 14/06/2017 22:36:56

    @Textomb
    Sarà un caso fortuito ma Ti ho pensato davvero proprio stamattina :)





  • di Scumm Bar (utente non iscritto) data: 15/06/2017 08:38:29

    Funzionano entrambe. Grazie veramente a tutti!