› Sviluppare funzionalita su Microsoft Office con VBA › Non cancella ultima prenotazione a cavallo di 2 anni. Dic. 2024-Gen-2025
-
AutoreArticoli
-
Buonasera a tutti,
sto provando e riprovando ma senza riuscirci a risolvere un problema riscontrato quando in una prenotazione si accavallano due anni.
Mi spiego. Dopo aver inserito il cliente Rossi Mario "codice 4" periodo dal 20/12/2024 al 10/01/2025, se vado per cancellare l'ultima prenotazione inserita tramite il pulsante "Cancella Ult. Prenot." ecco qui il problema, non me la cancella.
Io non ci riesco se avete una dritta. Grazie
Allegati:
You must be logged in to view attached files.Allego file. Utilizza lo stesso metodo con cui inserisce le prenotazioni.
Allegati:
You must be logged in to view attached files.Buongiorno a tutti.
Grazie Alex, funziona alla grande. Ora per una mia curiosità confronterò i due codici passo passo per capire un pochettino cosa dovevo fare di preciso.
Quindi il modulo 3 adesso mi sa che non serve più, posso anche cancellarlo, giusto Alex?
' Questo è il modulo 3. Function giorni(mese) 'questa funzione serve a definire quanti giorni ha un mese in modo che nel calcolo di 'registrazione sul foglio si possa determinare _ automaticamente il fine mese. Per febbraio ho considerato fisso 28 giorni. Nel bisestile verrà fatto manualmente _ di colorare il 'giorno 29. Select Case mese Case 1, 3, 5, 7, 8, 10, 12 giorni = 31 Case 4, 6, 9, 11 giorni = 30 Case 2 giorni = 28 End Select End FunctionGrazie
Si puoi cancellarlo, sempre se non richiami la Function giorni in altre routine, ma in ogni caso è un Function che non funziona bene. Quindi laddove la richiami dovresti cambiare metodo e adottare quello che ti ho suggerito io con DateSerial
Grazie mille per l'aiuto e la spiegazione. Infatti, non funziona come la tua. A me non dava la possibilità di inserire il 13° mese (forse la mia pochissima esperienza) ne sono riuscito per il calcolo dell'anno bisestile. Invece con la tua routine va una meraviglia.
Grazie a te e al forum che ci ospita, mettiamo Risolto. Buona giornata.
Ti posto questa routine,che ho fatto per mio sfizio, che non fa altro che generarti in automatico il prospetto dell'anno che tu vuoi creare.
Il codice non fa altro che chiedeti l'anno , una volta inserito l'anno che vuoi generare come prospetto, ti aggounge un foglio lo rinomina con l'anno che hai inserito e tigenera il prospetto evidenziando le Festivita Nazionali e la Pasqua relativa a quell'anno. Se ti puo servire
. Il codice che ti posto lo devi inserire in un Modulo.`Option Explicit Sub prospettoAnno() Dim Giorni_Festivi As Variant Dim WB As Workbook, Anno As String, Sh As Worksheet Dim col As Integer, riga As Integer, numgiorni As Integer, mese As Integer Dim clic As Boolean, Festivita As Boolean Dim giornimese As Integer, nomemese As Integer Dim F As Variant Giorni_Festivi = Array("1-1", "6-1", "25-04", "1-5", "2-6", "15-8", "1-11", "8-12", "25-12", "26-12") Set WB = ThisWorkbook Anno = InputBox("Inserisci l'anno che vuoi generare") With WB col = 3 riga = 4 For Each ws In Worksheets If ws.Name = Anno Then clic = 1 End If Next If clic = 0 Then Set Sh = .Worksheets.Add(after:=.Sheets(.Sheets.Count)) Sh.Name = Anno With Cells(riga, col - 1) .Value = "MESE" .Font.Bold = True .Interior.Color = RGB(171, 205, 239) .Borders.Color = RGB(0, 0, 0) End With For numgiorni = 1 To 31 Cells(riga, col) = numgiorni Cells(riga, col).Interior.Color = RGB(0, 127, 255) Cells(riga, col).Borders.Color = RGB(0, 0, 0) col = col + 1 Next Else MsgBox "foglio esistente" End If For mese = 1 To 12 giornimese = DateDiff("d", DateSerial(Anno, mese, 1), DateSerial(Anno, mese + 1, 1)) riga = riga + 1 col = 3 For nomemese = 1 To giornimese For Each F In Giorni_Festivi If Day(F) = Day(DateSerial(Anno, mese, nomemese)) And Month(F) = Month(DateSerial(Anno, mese, 1)) Then Festivita = True Exit For End If Festivita = False Next F If DateSerial(Anno, mese, nomemese) = Pasqua(Year(DateSerial(Anno, mese, nomemese))) Then Festivita = True Cells(riga, col).Interior.Color = RGB(255, 0, 255) Cells(riga, col).Borders.Color = RGB(0, 0, 0) Festivita = False GoTo salta End If If Festivita = True Then Cells(riga, col).Interior.Color = RGB(255, 215, 0) Cells(riga, col).Borders.Color = RGB(0, 0, 0) Else Cells(riga, col).Interior.Color = RGB(0, 225, 0) Cells(riga, col).Borders.Color = RGB(0, 0, 0) End If salta: col = col + 1 Next Cells(riga, 2) = MonthName(mese) Cells(riga, 2).Font.Bold = True Cells(riga, 2).Interior.Color = RGB(171, 205, 239) Cells(riga, 2).Borders.Color = RGB(0, 0, 0) Next Range("b5:ag5").Copy Range("b17") ActiveSheet.Rows.RowHeight = 15 ActiveSheet.Columns.ColumnWidth = 5 ActiveSheet.Columns(2).ColumnWidth = 10 ActiveWindow.Zoom = 90 Range("b21").Interior.Color = RGB(255, 215, 0) Range("c21").Value = "Festivita Nazionali" Range("b22").Interior.Color = RGB(255, 0, 255) Range("c22").Value = "Pasqua" End With End Sub Public Function Pasqua(Anno As Integer) As Date Dim A As Integer, B As Integer, C As Integer, P As Integer Dim Q As Integer, R As Integer A = Anno Mod 19: B = Anno \ 100: C = Anno Mod 100 P = (19 * A + B - (B \ 4) - ((B - ((B + 8) \ 25) + 1) \ 3) + 15) Mod 30 Q = (32 + 2 * ((B Mod 4) + (C \ 4)) - P - (C Mod 4)) Mod 7 R = (P + Q - 7 * ((A + 11 * P + 22 * Q) \ 451) + 114) Pasqua = DateSerial(Anno, R \ 32, (R Mod 31) + 1) End Function `Qual è il punto di avere gusti diversi, se non mostrare che i cervelli lavorano diversamente, che pensiamo diversamente? ( Alan Turing)
Sempre il mare, uomo libero, amerai!
( Charles Baudelaire )Grazie Albatros, Ho visto solo adesso. Domani la prova e ti faccio sapere. Buona serata
Ciao @pixel ti giro una versione simile al tuo prospetto ma rifatto da capo. In pratica ho notato che nella versione che ti avevo postato un paio di giorni fa, avevi la possibilità di inserire un periodo che non va oltre 2 mesi. Cioè se per esempio volevi inserire un cliente dal 01-01-2024 al 20-03-2024 allora non potevi farlo con quel codice.
Ora ti allego un nuovo prospetto con codice più corto anche e che ti consente di inserire una prenotazione anche più lunga di 2 mesi (poi immagino che sarà difficile che un cliente ti prenoti la camera per molto tempo, però intanto è giusto che funzioni bene il prospetto).
Ovviamente non cambiare o spostare le celle/righe/colonne perché lo incasini. Se servono modifiche allora ci lavoriamo su.
Fammi sapere come va.
Allegati:
You must be logged in to view attached files.Ciao Albatros, ho provato la tua rountine caricandola dal pusante con Call, è molto interesssante. Solo che valuterò di inserirla o meno, perchè ci sarebbe da modificare un mondo di cose.
Grazie per il tempo e professionalità a me dedicato e qui condiviso.
GrazieCiao Alex, ho visto il nuovo file. Il codice che hai scritto è ancora più difficile. Sono riuscito con le tue indicazioni di un post precedente a creare solo il pulsante" Cancella ultima prenotazione inserita".
Ti riporto il codice intero con la modifica sperando che sta bene.
ti consente di inserire una prenotazione anche più lunga di 2 mesi (poi immagino che sarà difficile che un cliente ti prenoti la camera per molto tempo, però intanto è giusto che funzioni bene il prospetto).
Infatti, mai succederà. Per adesso la legge ci impone massimo 30 giorni consecutivi
Iniziamo con ciò che ho rilevato nel nuovo codice.
Ho notato che sul foglio Prospetto hai inserito nei vari mesi delle formule.
=MAIUSC(TESTO(DATA(B$2;2;1);"MMMM")) e così via.
Mi piacerebbe "almeno ci provo" capire la loro funzione.
Anche nel VBA del medesimo foglio hai inserito un altro codice.Poi ho dato un'occhiata al codice del pulsante Inserisci, non ho capito na mazza. Con il codice vecchio stavo incominciando a capire qualcosina, ma questo e arabo per me.
Ti faccio un esempio: con il codice vecchio sono riuscito ad inserire un altra camera, ma qui nulla da fare. Forse sarà più semplice di quel che penso" non so" però per il momento non ci riesco.
La domanda è: se volessi inserire la "Camera 2" iniziando dal Rigo 18. cosa dovrei fare?
Non è più semplice il vecchio codice?
'Pulsante Cancella ultima prenotazione camera 1 Dim ws As Worksheet Dim giornoArrivo As Integer, giornoPartenza As Integer Dim meseArrivo As Integer, mesePartenza As Integer Dim annoArrivo As Integer, annoPartenza As Integer Dim giorniMeseArrivo As Integer, giorniMesePartenza As Integer Dim giorniPernotto As Integer Dim i As Integer, x As Integer, j As Integer Dim periodo() As Variant Dim r As Range, c As Range Dim s As Variant Application.ScreenUpdating = False If txtGiornoArrivo = "" Or txtGiornoPartenza = "" Then Exit Sub i = MsgBox("Vuoi cancellare ultima prenotazione inserita Codice: " & txtCodiceCamera & " di " & txtCliente & "?", vbQuestion + vbYesNo, "Cancellazione prenotazione") If i = vbNo Then Exit Sub giornoArrivo = Day(txtDataArrivoCamera) giornoPartenza = Day(txtDataPartenzaCamera) meseArrivo = Month(txtDataArrivoCamera) mesePartenza = Month(txtDataPartenzaCamera) annoArrivo = Year(txtDataArrivoCamera) annoPartenza = Year(txtDataPartenzaCamera) If annoArrivo = annoPartenza Then Set r = Cells(meseArrivo + 2, giornoArrivo + 2) Set c = Cells(mesePartenza + 2, giornoPartenza + 1) Else Set r = Cells(meseArrivo + 2, giornoArrivo + 2) Set c = Cells(15, giornoPartenza + 1) End If Set ws = Application.ThisWorkbook.Worksheets("Prospetto") giorniMeseArrivo = DateSerial(annoArrivo, meseArrivo + 1, 1) - DateSerial(annoArrivo, meseArrivo, 1) giorniMesePartenza = DateSerial(annoPartenza, mesePartenza + 1, 1) - DateSerial(annoPartenza, mesePartenza, 1) giorniPernotto = DateSerial(annoPartenza, mesePartenza, giornoPartenza) - DateSerial(annoArrivo, meseArrivo, giornoArrivo) For i = 1 To giorniPernotto ReDim Preserve periodo(1 To giorniPernotto) periodo(i) = DateSerial(annoArrivo, meseArrivo, giornoArrivo) giornoArrivo = giornoArrivo + 1 Next i For x = r.Row To c.Row For i = 3 To 33 For j = LBound(periodo) To UBound(periodo) If DateSerial(annoArrivo, x - 2, i - 2) = periodo(j) Then If Cells(x, i) <> "" And Cells(x, i) <> txtCodiceCamera And Cells(x, i) <> "####" Then s = s & Cells(2, i) & " " & Cells(x, 2) & "," End If End If Next j Next i Next x If Right(s, 1) = "," Then s = Left(s, Len(s) - 1) If s <> "" Then s = Split(s, ",") i = MsgBox("Stanza occupata dal " & s(LBound(s)) & " al " & s(UBound(s)) & String(2, vbCrLf) & _ "Vuoi sovrascrivere?", vbInformation + vbYesNo, "Attenzione...") If i = vbNo Then Exit Sub End If giornoArrivo = Day(txtDataArrivoCamera) For x = r.Row To c.Row For i = 3 To 33 For j = LBound(periodo) To UBound(periodo) If DateSerial(annoArrivo, x - 2, i - 2) = periodo(j) Then If Cells(x, i) <> "####" Then If Cells(x, i).Interior.ColorIndex = 3 Then ' mia modifica sperando che sta bene Cells(x, i).Value = txtCodiceCamera: Cells(x, i).ClearContents ' cancella contenuto Cells(x, i).Interior.ColorIndex = 4 ' verde 'Else 'Cells(x, i).Value = txtCodiceCamera: Cells(x, i).Interior.ColorIndex = 3 End If End If End If Next j Next i Next x Set r = Nothing: Set c = Nothing Application.ScreenUpdating = TrueGrazie
Ho notato che sul foglio Prospetto hai inserito nei vari mesi delle formule. =MAIUSC(TESTO(DATA(B$2;2;1);"MMMM")) e così via.
Mi piacerebbe "almeno ci provo" capire la loro funzione.Diciamo che non alcuna funzionalità in particolare. Anziché scrivere i nomi dei mesi a mano lo faccio scrivere all'applicazione attraverso le formule.
Non è più semplice il vecchio codice?
Il "vecchio codice" si basava sulla creazione di un oggetto Range. Cioè in modo dinamico creavo un Range che partiva dalla data di arrivo e finiva alla data di partenza (meno un giorno). Una volta creato il Range lo manipolavo con il colore, contenuto, ecc...
Il problema è che non solo era limitato a 2 righe per volta ma la creazione del Range era macchinoso. Prima selezionava un periodo, poi un altro e infine li univa.
Con il codice "nuovo" invece passo in rassegna cella per cella di tutta la tabella e quando la cella in esame corrisponde alla data compresa nel periodo di prenotazione allora avvengono tutti i vari calcoli: Se è già prenotata chiedi se sovrascrivere, se è libera scrivi direttamente, se sovrascrivi allora colora di blue, ecc...
Per poterlo realizzare ho dovuto ricorrere agli Array Dinamici
Dim periodo () As Variant For i = 1 To giorniPernotto ReDim Preserve periodo(1 To giorniPernotto) periodo(i) = DateSerial(annoArrivo, meseArrivo, giornoArrivo) giornoArrivo = giornoArrivo + 1 Next iGli Array (spero che gli esperti del Forum non mi massacrano se uso terminologia non corretta) sono degli insiemi (può essere un insieme di persone, di numeri, di lettere....nel nostro caso di periodi). Siccome non so a priori quanto dura il periodo allora l'array deve essere "dinamico".
Una volta che ho l'array faccio un confronto cella per cella e vedo se quella cella si trova in una dara contenuta nell'array periodo().
Per conoscere qual è la data della cella in esame mi calcolo la riga e la colonna in cui si trova, poi con DateSerial mi creo la data.
Cmq mi rendo conto che non è facile capire il concetto.
Tieni presente che nell'evento Activate del foglio Prospetto avviene il calcolo dei giorni di ogni mese. Ho usato anche lì gli array ma non dinamici visto che i mesi sono 12. Una volta scoperti i giorni dei mesi ci vado ad applicare un "####" nei giorni non contemplati di quel mese (Es. Febbraio 2024 avrà "####" nei giorni 30 e 31)
Grazie alla presenza dei cancelletti avrò modo di saltare le celle quando dovrò inserire le prenotazioni.
La domanda è: se volessi inserire la "Camera 2" iniziando dal Rigo 18. cosa dovrei fare?
Cosa intendi? Vuoi inserire una nuova tabella sotto?
Esatto. Io creo un'altra tabella sotto come quella che già ce. Poi dovrei creare un altro pulsante che mi inserisca le prenotazione nella seconda tabella "camera 2" e così per la 3.
P.s. grazie per la spiegazione. Qualcosa lo capito.
Prova questo nuovo file...mi sto spaccando gli occhi
Allegati:
You must be logged in to view attached files.Ciao Alex, mi spiace per i tuoi occhi, però mette a dura prova anche un esperto come te. Ti lascio immaginare i miei occhi.
Il programma è ottimo, straordinario. Penso che meglio non si possa realizzare per la sua semplicità, allo stesso tempo la complessità delle cose.
Detto questo, ho notato qualche problema. Ti spiego.
Se inserisci la "Camera 1" con periodo Es. dal 25-12-2024 al 10-01-2025, la prenotazione la segna errata e la segna tra ottobre e novembre.
Questo succede anche se cambi il numero di stanza.Altro cosa che ho notato; se nella textbox "Camere" non c è scritto Camera 1, oppure Camera 2 e cosi via e provi a forzare l'inserimento, va in Errore Debug la riga sottostante:
k = v(1)
Ti ringrazio per il tuo impegno.Se inserisci la "Camera 1" con periodo Es. dal 25-12-2024 al 10-01-2025, la prenotazione la segna errata e la segna tra ottobre e novembre.
Hai ragione...hai ragione. Ho risolto. Bisognava portare il calcolo della variabile k al di fuori della condizione IF..... posta sopra.
Per quanto riguarda il problema dell'inserimento senza numero Camere....purtroppo ci deve essere il numero.
Il mio codice si basa proprio su quello. Attraverso la function CHOOSE vado a scegliere un numero da me descritto che equivale al numero riga in cui deve andare ad agire. In pratica con la variable v mi estrapolo "CAMERA" e il numero della camera in due vettori (grazie alla function Split) poi lo passo a k=v(1) infatti v(1) è il numero camera. Ricavato il numero lo passo alla function CHOOSE dove se il numero passato a k è 1 (nr. camera) allora preleva il numero 2 (numero rigo) , se invece è passato a k il 2 allora prende 18 e così via....k = Choose(k, 2, 18, 34, 50, 66, 82, 98)
Cmq ti ho inserito una gestione degli errori così non crasha nel caso non c'è il numero stanza o altri problemi.
Allegati:
You must be logged in to view attached files.Per quanto riguarda il problema dell'inserimento senza numero Camere....purtroppo ci deve essere il numero.
Infatti su questo hai ragione. Ho voluto solo segnalartelo.
Il mio codice si basa proprio su quello. Attraverso la function CHOOSE vado a scegliere un numero da me descritto che equivale al numero riga in cui deve andare ad agire. In pratica con la variable v mi estrapolo "CAMERA" e il numero della camera in due vettori (grazie alla function Split) poi lo passo a k=v(1) infatti v(1) è il numero camera. Ricavato il numero lo passo alla function CHOOSE dove se il numero passato a k è 1 (nr. camera) allora preleva il numero 2 (numero rigo) , se invece è passato a k il 2 allora prende 18 e così via....k = Choose(k, 2, 18, 34, 50, 66, 82, 98)
Con la tua spiegazione per me neofita è importante, oltre al tuo aiuto più che significante. Infatti proprio ciò che spighi tu, lo capito in parte. Infatti, creando un altra Camera in questo caso la numero 8, aggiungendo alla riga dopo il 98, 114, il codice mi scrivi la prenotazione.
Grazie mille Alex, ora provo il file da te aggiornato.
Non so come caspita fai. In breve tempo. Ti basta leggere il codice per capire subito dov' è l'inghippo. Dire che va una meraviglia e dire poco.
Ora vado avanti con il progetto.
Grazie Alex
Dim periodo () As Variant For i = 1 To giorniPernotto ReDim Preserve periodo(1 To giorniPernotto) periodo(i) = DateSerial(annoArrivo, meseArrivo, giornoArrivo) giornoArrivo = giornoArrivo + 1 NextCon Dim periodo() As Variant vado a creare un insieme, ad esempio un insieme di persone, numeri, colori, ecc...nel tuo caso specifico è un insieme di date. Nel gergo informatico si chiamano ARRAY. Gli Array possono essere monodimensionali o multidimensionali, statici o dinamici.
Il tuo è di tipo monodimensionale ed dinamico. È dinamico perché io non so in partenza quanti elementi deve contenere (che poi sempre in gergo informatico si dice lunghezza del vettore). Quindi al compilatore diciamo per prima cosa che vogliamo un array periodo() poi però lo dobbiamo dimensionare e lo facciamo con ReDim e gli diciamo che il vettore è lungo da 1 To giorniPernotto (è il numero di giorni in cui una persona pernotta, quindi se pernotta 4 giorni allora l'insieme deve contenere 4 elementi).
Ti ho fatto modificare il codice perché com'era scritto prima dicevo al compilatore che doveva creare un Array da 1 a giorniPernotto (esempio 1 a 4) ma inserendolo nel ciclo For i = 1 To giorniPernotto non è necessario Ridimensionare tutte le volte l'array perché io già so quanti elementi deve contenere perché se vedi un paio di righe sopra il ciclo andiamo a definire giorniPernotto = DateSerial(annoPartenza, mesePartenza, giornoPartenza) - DateSerial(annoArrivo, meseArrivo, giornoArrivo). Che poi volendo potevamo utilizzare DateDiff visto che avevamo già definito le date di partenza e arrivo...va be' pazienza.
Il Preserve serviva perché inserendolo nel ciclo For bisognava conservare i dati nell'Array ad ogni iterazione, perché tutte le volte che cicli l'array perde i dati senza il Preserve. Adesso non ti serve perché è fuori dal ciclo.
Grazie tante, la tua spiegazione è stata molto apprezzata. Al dire il vero ho capito poco per il momento, ma è già qualcosa. Ho trovato interessante il modo come spieghi ed illustri ciò che fai. Rimango esterrefatto dalla tua preparazione. Sicuramente tanti altri che leggono e seguono questo forum troveranno queste informazioni preziosi ed interessanti.
Grazie Alex
Bè insomma è bello che pixel restituisca un feedback così. Io lo gradisco tanto.
Anche perchè Alex è un mio adepto, l'ho convinto a costruirsi un gestionale su Access e c'è riuscito praticamente da solo
-
AutoreArticoli
