Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2011
    Messaggi
    258

    EXCEL: Modificare valore cella da altro foglio

    Salve, ho creato un progetto excel con due foglio una di riepilogo e l'altro che fa da database dei dati, ora tramite la funzione cerca verticale richiamo i valori di una riga, io vorrei dalla pagina di riepilogo modificarli, senza dover entrare nel foglio database. Sapete darmi qualche consiglio su come fare?

  2. #2
    Quote Originariamente inviata da sixdas Visualizza il messaggio
    Salve, ho creato un progetto excel con due foglio una di riepilogo e l'altro che fa da database dei dati, ora tramite la funzione cerca verticale richiamo i valori di una riga, io vorrei dalla pagina di riepilogo modificarli, senza dover entrare nel foglio database. Sapete darmi qualche consiglio su come fare?

    Con le formule credo proprio che non ce la farai perché le formule possono modificare solo il valore visualizzato nella cella in cui sono contenute e non il valore di altre celle (sempre che non mi sia perso qualcosa ).

    Col vba invece non ci sono problemi, questo codice, per esempio, appena inserisci un valore nella cella C8 lo copia nel Foglio2:

    codice:
    Private Sub Worksheet_Change(ByVal Target As Range)
       If Not Intersect(Target, [C8]) Is Nothing Then
          [C8].Copy Destination:=Sheets("Foglio2").[C8]
       End If
    End Sub




    _
    La democrazia rappresentativa ha fatto il suo tempo, è ora di passare alla democrazia diretta.
    www.beppegrillo.it

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2011
    Messaggi
    258
    Quote Originariamente inviata da NonCeLaFaccio+ Visualizza il messaggio
    Con le formule credo proprio che non ce la farai perché le formule possono modificare solo il valore visualizzato nella cella in cui sono contenute e non il valore di altre celle (sempre che non mi sia perso qualcosa ).

    Col vba invece non ci sono problemi, questo codice, per esempio, appena inserisci un valore nella cella C8 lo copia nel Foglio2:

    codice:
    Private Sub Worksheet_Change(ByVal Target As Range)
       If Not Intersect(Target, [C8]) Is Nothing Then
          [C8].Copy Destination:=Sheets("Foglio2").[C8]
       End If
    End Sub
    _
    Ciao, ok il codice che hai scritto va bene, ma se la cella c8 della secondo foglio vorrei renderla dinamica, cioè ogni volta sara una diversa come potrei fare?
    Ultima modifica di sixdas; 04-12-2013 a 20:48

  4. #4
    Quote Originariamente inviata da sixdas Visualizza il messaggio
    Ciao, ok il codice che hai scritto va bene, ma se la cella c8 della secondo foglio vorrei renderla dinamica, cioè ogni volta sara una diversa come potrei fare?
    Sai qual è il mio problema nel farti degli esempi? Che mi dai pochissime informazioni e quindi posso fare solo esempi un po' scolastici perché non riesco a inquadrare il problema e a suggerirti soluzioni più specifiche.

    E' chiaro che tu hai tutto il diritto di tutelare la tua privacy e non raccontare su un forum pubblico quello che stai facendo però questo complica le cose e rallenta molto il discorso.

    Comunque proviamoci lo stesso.

    Adesso per esempio mi sto chiedendo cosa intendi esattamente per "rendere dinamica la cella di arrivo".

    Probabilmente hai in mente una qualche regola che la individui sulla base di un certo numero di elementi ... ma io non conosco né la regola né gli elementi da valutare quindi anche in questo caso mi limiterò ad un esempio un po' stupido che però spero possa far fare un passo avanti:

    codice:
    Private Sub Worksheet_Change(ByVal Target As Range)
       If Not Intersect(Target, [C8]) Is Nothing Then
          Sheets("Foglio2").Range([A1]) = [C8]
       End If
    End Sub

    Questo codice è simile al precedente perché anche questo copia il valore contenuto in C8 sul Foglio2 ma la cella in cui effettua la copia dev'essere indicata in A1.

    Se quindi in A1 scrivi, per esempio, F4 e poi inserisci un valore in C8, questo valore te lo ritroverai in F4 di Foglio2.

    Ovviamente trattandosi di un esempio non gestisco le condizioni di errore quindi in A1 devi inserire un valore valido come nome di cella altrimenti l'esecuzione si interromperà (se si interrompe clicca su Debug e poi clicca sul quadratino Ripristina in alto).

    Questa copia quindi non è più verso una casella fissa ma verso quella che viene indicata dinamicamente da un processo esterno che in questo caso è la digitazione manuale in A1 ma potrebbe essere qualsiasi altra cosa.
    La democrazia rappresentativa ha fatto il suo tempo, è ora di passare alla democrazia diretta.
    www.beppegrillo.it

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2011
    Messaggi
    258
    Ciao, infatti sono stato molto superficiale nel esporre il mio quesito. In realtà più che per privacy non saprei come descrivere il progetto, quindi ti allego un file di esempio molto semplificato di quello che vorrei realizzare e che in parte ho già realizzato e che quindi vorrei potenziare...In pratica il selezione il codice del cliente e mi vengono fuori i vari dettagli, io ho dei campi nella tabella che inizialmente non sono popolati subito, ma verranno aggiornati col tempo quindi, se io dalla ricerca ho quel campo vuoto voglio aggiornarlo senza dover entrare nel foglio database....

    https://dl.dropboxusercontent.com/u/76285749/Cartel1.xlsx

  6. #6
    Ok, adesso è più chiaro.

    Come ti dicevo, per ottenere il risultato che ti serve occorre il VBA quindi per prima cosa devi salvare il tuo foglio come "Cartella di lavoro con attivazione macro" e d'ora in poi lavorare su quello.

    Per cominciare devi assegnare un nome alle celle che verranno trattate in modo che anche aggiungendo o togliendo righe o colonne il codice continui a funzionare, io ho dato questi nomi:

    cod_cliente alla cella D3
    data_db alla cella E15
    data_ritiro alla cella E17

    Fatto questo premi ALT-F11, clicca due volte a sinistra su "Foglio1(riepilogo)" e incolla nell'area bianca questo codice

    codice:
    Private Sub Worksheet_Change(ByVal Target As Range)
       If Not Intersect(Target, Range("cod_cliente")) Is Nothing Then
          Range("data_ritiro") = ""
       End If
       If Not Intersect(Target, Range("data_ritiro")) Is Nothing And _
          Range("data_ritiro") <> "" And _
          Not IsError(Range("data_db").Value) _
       Then
          If Range("data_db").Value = "00.00.00" And _
             Range("cod_cliente").Value <> "" And _
             IsDate(Range("data_ritiro").Value) _
          Then
             For Each cliente In Sheets("Databse").Range("A:A")
                If CStr(cliente) = CStr(Range("cod_cliente").Value) Then
                   cliente.Offset(0, 5) = Range("data_ritiro").Value
                   Range("data_ritiro") = ""
                   Exit For
                Else
                   If cliente = "" Then
                      Exit For
                   End If
                End If
             Next
          End If
       End If
    End Sub

    Fatto questo dovresti già ottenere il funzionamento che desideri.

    Ora ti spiego cosa fa questo codice in modo che tu lo possa adattare ad altri campi o altre esigenze.

    La prima riga e l'ultima delimitano un insieme di istruzioni che viene attivato ogni volta che si modifica qualcosa sul foglio quindi tutto il codice contenuto all'interno viene eseguito ogni volta che sul foglio una cella cambia di valore.

    La cella che ha cambiato valore viene inserita nella variabile Target.

    E' chiaro però che bisogna eseguire delle azioni solo in certi casi e non ogni volta che cambia qualcosa quindi si usano delle If per decidere se bisogna intervenire o no.

    La prima If si chiede se è cambiato il codice cliente e, se è così, ripulisce la casella data_ritiro per evitare che resti sporca da un utilizzo precedente.

    La seconda If verifica innanzitutto:

    - se è stata modificata la data_ritiro: se non c'è una data da trasferire sul db non bisogna fare nulla.

    - se la data_ritiro contiene un valore: la cella potrebbe risultare modificata anche se un valore precedente venisse cancellato ed anche in questo caso non ci sarebbe nulla da trasferire sul db.

    - se la data_db non contiene un valore di errore: questo può verificarsi se si indica un codice cliente inesistente ed allora nella data_db compare il valore N/D, anche in quel caso non bisogna fare nessun trasferimento verso il db.

    Solo se tutte e tre queste condizioni sono verificate l'elaborazione prosegue altrimenti si va alla End If e l'elaborazione termina.

    Fatto questo primo controllo siamo sicuri che nella data_ritiro è stato digitato un valore e che il cliente su cui intervenire è stato correttamente individuato, ora si può proseguire con degli ulteriori controlli e si verifica quindi che

    - la data_db non sia valorizzata perché in quel caso la data è già presente e non bisogna fare nulla.

    - il cod_cliente sia impostato per essere sicuri che ci sia un valore da andare a cercare nel db.

    - nella data_ritiro sia stata inserita proprio una data e non un valore qualsiasi.

    A questo punto abbiamo fatto tutti i controlli e abbiamo tutti i dati quindi possiamo cercare il cliente nel db e andargli a impostare la data.

    Per fare questo si fa un ciclo For Each che esplora la colonna A finché non trova il codice cliente che è stato digitato e, una volta trovato, imposta la data_ritiro nella cella che si trova a destra di cinque caselle (offset(0,5)) rispetto al codice cliente, cioè nella data ed inoltre ripulisce la casella data_ritiro e termina il ciclo.

    Tutto qui, dimmi se c'è quelcosa che non è chiaro.

    Ciao
    La democrazia rappresentativa ha fatto il suo tempo, è ora di passare alla democrazia diretta.
    www.beppegrillo.it

  7. #7
    Utente di HTML.it
    Registrato dal
    Mar 2011
    Messaggi
    258
    Ciao, grazie per l'esempio, il tuo codice fa proprio quello che volevo io. Adesso vorrei adattarlo per le mie esigenze e vorrei farti qualche domanda.

    1) Posso ripetere quel pezzo di codice per ogni campo che voglio modificare, oppure ci sono problemi?
    2) Visto che ho devo salvare anche testo libero e non solo date, con cosa devo modificare IsDate?

    Grazie ancora.

  8. #8
    Quote Originariamente inviata da sixdas Visualizza il messaggio
    Ciao, grazie per l'esempio, il tuo codice fa proprio quello che volevo io. Adesso vorrei adattarlo per le mie esigenze e vorrei farti qualche domanda.

    1) Posso ripetere quel pezzo di codice per ogni campo che voglio modificare, oppure ci sono problemi?
    2) Visto che ho devo salvare anche testo libero e non solo date, con cosa devo modificare IsDate?

    Grazie ancora.
    Sì, sostanzialmente devi ripetere il codice per ogni campo però con qualche accortezza.

    Nel'esempio che segue ho immaginando che oltre al campo data ci sia anche un campo numerico e uno alfanumerico che ho chiamato campo_num e campo_alfanum con i corrispondenti campi del db campo_num_db e campo alfanum_db ed inoltre ho tolto un po' di Value inutili e ho cambiato il nome della cella E15 da data_db a data_ritiro_db per uniformità con gli altri.

    Nota che le righe precedute da un apice servono per commentare il codice e non vengono eseguite quindi puoi aggiungerne quante te ne pare per descrivere quello che viene fatto in ogni punto.

    Devi poi indicare il corretto offset per ogni campo, il 5 è corretto per la data perché la data si trova 5 posizioni a destra rispetto al codice cliente, per campo_num e campo_alfanum ho messo un 6 e 7 di fantasia, devi adeguarli a quelli veri semplicemente contando le colonne a partire dal codice cliente.
    Occhio che se in futuro aggiungerai colonne al database dovrai aggiornare gli offset perché excel non lo fa in automatico.


    codice:
    Private Sub Worksheet_Change(ByVal Target As Range)
    
    ' Prima IF. Non va ripetuta ma vanno ripetuti i campi da pulire
    
       If Not Intersect(Target, Range("cod_cliente")) Is Nothing Then
          Range("data_ritiro") = ""
          Range("campo_num") = ""
          Range("campo_alfanum") = ""
       End If
    
    ' Seconda If. Questa va ripetuta per ogni campo
    
    ' Campo data
       If Not Intersect(Target, Range("data_ritiro")) Is Nothing And _
          Range("data_ritiro") <> "" And _
          Not IsError(Range("data_ritiro_db")) _
       Then
          If Range("data_ritiro_db") = "00.00.00" And _
             Range("cod_cliente") <> "" And _
             IsDate(Range("data_ritiro")) _
          Then
             For Each cliente In Sheets("Databse").Range("A:A")
                If CStr(cliente) = CStr(Range("cod_cliente")) Then
                   cliente.Offset(0, 5) = Range("data_ritiro")
                   Range("data_ritiro") = ""
                   Exit For
                Else
                   If cliente = "" Then
                      Exit For
                   End If
                End If
             Next
          End If
       End If
    
    ' Campo numerico
       If Not Intersect(Target, Range("campo_num")) Is Nothing And _
          Range("campo_num") <> "" And _
          Not IsError(Range("campo_num_db")) _
       Then
          If Range("campo_num_db") = 0 And _
             Range("cod_cliente") <> "" And _
             IsNumeric(Range("campo_num")) _
          Then
             For Each cliente In Sheets("Databse").Range("A:A")
                If CStr(cliente) = CStr(Range("cod_cliente")) Then
                   cliente.Offset(0, 6) = Range("campo_num")
                   Range("campo_num") = ""
                   Exit For
                Else
                   If cliente = "" Then
                      Exit For
                   End If
                End If
             Next
          End If
       End If
    
    ' Campo alfanumerico
       If Not Intersect(Target, Range("campo_alfanum")) Is Nothing And _
          Range("campo_alfanum") <> "" And _
          Not IsError(Range("campo_alfanum_db")) _
       Then
          If Trim(Range("campo_alfanum_db")) = 0 And _
             Range("cod_cliente") <> "" _
          Then
             For Each cliente In Sheets("Databse").Range("A:A")
                If CStr(cliente) = CStr(Range("cod_cliente")) Then
                   cliente.Offset(0, 7) = Range("campo_alfanum")
                   Range("campo_alfanum") = ""
                   Exit For
                Else
                   If cliente = "" Then
                      Exit For
                   End If
                End If
             Next
          End If
       End If
    
    End Sub
    Prima di provarlo però devo dirti ancora alcune cose.

    Ho visto che c'è un malfunzionamento perché il formato data attribuito alla casella data_ritiro trasforma automaticamente i numeri in date e così questi passano il test isDate e vengono inserite date sbagliate nel db.
    Prova, ad esempio, a scrivere 555 e vedi che succede.
    Per risolvere devi dare il formato Generale alla casella e lo stesso dovrai fare per tutti i campi gialli da digitare.

    Un altro malfunzionamento si ha sui campi alfanumerici perché la cerca.vert assegna il valore zero alla cella in caso di assenza di valore sul db, questo lo puoi superare dando alla cella campo_alfanum_db il formato personalizzato # (cancelletto).
    A livello di codice questo problema obbliga a fare i test dei campi alfanumerici su 0 invece di "" come sarebbe più logico ma va bene così, non ci si può far nulla per quanto ne so.

    Come avrai visto ogni volta che apri un foglio con macro devi ricordarti di attivarle ma puoi superare questa cosa inserendo il foglio in una cartella e poi dicendo a excel di attivare automaticamente le macro per tutti i fogli contenuti in quella cartella, così non te lo chiede ogni volta. Si fa dalle Opzioni --> Centro protezione --> Impostazioni --> Percorsi attendibili

    Visto che i campi sono molti puoi migliorare il funzionamento attivando la casella gialla solo per i campi per i quali è necessario inserire il dato in modo che non si faccia confusione con tutte quelle caselle gialle inutili sempre visibili.

    Per farlo devi dare un nome anche alla casella affianco alla casella gialla, la B17, tanto per capirci, per esempio data_ritiro_msg o campo_num_msg o campo_alfanum_msg e poi usare questo codice:

    codice:
    Private Sub Worksheet_Change(ByVal Target As Range)
    
    ' Prima IF. Non va ripetuta ma vanno ripetute le istruzioni di pulizia di ogni campo
    
       If Not Intersect(Target, Range("cod_cliente")) Is Nothing Then
          
    ' Pulizia di data ritiro
          Range("data_ritiro") = ""
          If Range("data_ritiro_db") = "00.00.00" Then
             Range("data_ritiro").Interior.Color = vbYellow
             Range("data_ritiro_msg") = "Inserisci Data ritiro"
          Else
             Range("data_ritiro").Interior.ColorIndex = xlColorIndexNone
             Range("data_ritiro_msg") = ""
          End If
          
    ' Pulizia di campo num
          Range("campo_num") = ""
          If Range("campo_num_db") = 0 Then
             Range("campo_num").Interior.Color = vbYellow
             Range("campo_num_msg") = "Inserisci Campo num"
          Else
             Range("campo_num").Interior.ColorIndex = xlColorIndexNone
             Range("campo_num_msg") = ""
          End If
          
    ' Pulizia di campo alfanum
          Range("campo_alfanum") = ""
          If Range("campo_alfanum_db") = 0 Then
             Range("campo_alfanum").Interior.Color = vbYellow
             Range("campo_alfanum_msg") = "Inserisci Campo alfanum"
          Else
             Range("campo_alfanum").Interior.ColorIndex = xlColorIndexNone
             Range("campo_alfanum_msg") = ""
          End If
       End If
    
    ' Seconda If. Questa va ripetuta per ogni campo
    
    ' Campo data
       If Not Intersect(Target, Range("data_ritiro")) Is Nothing And _
          Range("data_ritiro") <> "" And _
          Not IsError(Range("data_ritiro_db")) _
       Then
          If Range("data_ritiro_db") = "00.00.00" And _
             Range("cod_cliente") <> "" And _
             IsDate(Range("data_ritiro")) _
          Then
             For Each cliente In Sheets("Databse").Range("A:A")
                If CStr(cliente) = CStr(Range("cod_cliente")) Then
                   cliente.Offset(0, 5) = Range("data_ritiro")
                   Range("data_ritiro") = ""
                   Range("data_ritiro").Interior.ColorIndex = xlColorIndexNone
                   Range("data_ritiro_msg") = ""
                   Exit For
                Else
                   If cliente = "" Then
                      Exit For
                   End If
                End If
             Next
          End If
       End If
    
    ' Campo numerico
       If Not Intersect(Target, Range("campo_num")) Is Nothing And _
          Range("campo_num") <> "" And _
          Not IsError(Range("campo_num_db")) _
       Then
          If Range("campo_num_db") = 0 And _
             Range("cod_cliente") <> "" And _
             IsNumeric(Range("campo_num")) _
          Then
             For Each cliente In Sheets("Databse").Range("A:A")
                If CStr(cliente) = CStr(Range("cod_cliente")) Then
                   cliente.Offset(0, 6) = Range("campo_num")
                   Range("campo_num") = ""
                   Range("campo_num").Interior.ColorIndex = xlColorIndexNone
                   Range("campo_num_msg") = ""
                   Exit For
                Else
                   If cliente = "" Then
                      Exit For
                   End If
                End If
             Next
          End If
       End If
    
    ' Campo alfanumerico
       If Not Intersect(Target, Range("campo_alfanum")) Is Nothing And _
          Range("campo_alfanum") <> "" And _
          Not IsError(Range("campo_alfanum_db")) _
       Then
          If Trim(Range("campo_alfanum_db")) = 0 And _
             Range("cod_cliente") <> "" _
          Then
             For Each cliente In Sheets("Databse").Range("A:A")
                If CStr(cliente) = CStr(Range("cod_cliente")) Then
                   cliente.Offset(0, 7) = Range("campo_alfanum")
                   Range("campo_alfanum") = ""
                   Range("campo_alfanum").Interior.ColorIndex = xlColorIndexNone
                   Range("campo_alfanum_msg") = ""
                   Exit For
                Else
                   If cliente = "" Then
                      Exit For
                   End If
                End If
             Next
          End If
       End If
       
    End Sub
    Non ho fatto test molto approfonditi quindi se qualcosa non funziona scrivi pure che lo mettiamo a posto.
    La democrazia rappresentativa ha fatto il suo tempo, è ora di passare alla democrazia diretta.
    www.beppegrillo.it

  9. #9
    Utente di HTML.it
    Registrato dal
    Mar 2011
    Messaggi
    258
    Ti ringrazio per la tua immensa disponibilità, con il tuo ultimo esempio sono riuscito a fare proprio quello che volevo, e con il fatto che le caselle scompaiono.... non si poteva chiedere di meglio

    Ne approfitto ancora per altre due domande anche se non importanti ne approfitto lo stesso della tua disponibilità.

    - Si può impostare un bottone che cliccando mi apra un altro foglio? tipo sono posizionato nel foglio1 voglio aprire premendo sul bottone il foglio52

    - Modificare il valore già inserito. (Questo punto non e fondamentale per l'attuale progetto ma potrebbe servirmi in futuro...)

  10. #10
    Bene, sono contento che funzioni

    Per modificare il valore esistente dovrebbe bastare eliminare il test che impedisce di farlo cioè la verifica che il campo ..._db sia vuoto.

    Praticamente questo test

    codice:
    If Range("data_ritiro_db") = "00.00.00" And _
       Range("cod_cliente") <> "" And _
       IsDate(Range("data_ritiro")) _
    Then

    deve diventare così

    codice:
    If Range("cod_cliente") <> "" And _
       IsDate(Range("data_ritiro")) _
    Then

    e similmente per gli altri.

    Adesso non ho modo di fare una prova ma dovrebbe bastare questo e, ovviamente, devi usare il codice in cui le caselle gialle sono sempre tutte visibili e non quello in cui compaiono e scompaiono.

    Per il pulsante non ho capito se il Foglio52 dell’esempio esiste già e vuoi selezionarlo o vuoi crearlo ex-novo per cui ti indico tutte due le soluzioni.

    In ogni caso devi inserire un pulsante ActiveX dalla scheda Sviluppo, poi cliccarci sopra due volte e inserire fra la “Private Sub CommandButton1_Click()” e la “End Sub” una di queste due istruzioni, la prima crea due nuovi fogli prima del primo foglio esistente (chiaramente puoi evitare di mettere i parametri Count, Before After ecc… è solo per fare un esempio un po’ più interessante) mentre la seconda seleziona un foglio specifico (metodo Select sull’oggetto Worksheets)

    codice:
       Worksheets.Add Count:=2, Before:=Sheets(1)
     
       Worksheets("Foglio52").Select


    La democrazia rappresentativa ha fatto il suo tempo, è ora di passare alla democrazia diretta.
    www.beppegrillo.it

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.