Gambas-it

Gambas3 => Programmazione => Topic aperto da: tornu - 02 Gennaio 2018, 20:57:49

Titolo: [Risolto] Intercettazione errori
Inserito da: tornu - 02 Gennaio 2018, 20:57:49
Buonasera a tutti,
ho una Form con vari oggetti tra cui delle TextBox che devono contenere dei valori
con decimali controllati da una Classe che ne verifica la corretta digitazione, sia
per quanto riguarda l'uso della virgola o del punto. Nel caso di digitazione di
cifre intere vengono aggiunti automaticamente i decimali e formattati col separatore
delle miglia a partire dalla cifra 1000.
La Classe solleva dei messaggi di errore nel caso siano digitate cifre non conformi
ai controlli impostati, per esempio doppie virgole, doppi punti, etc...
Quello che voglio chiedervi, perchè non ci sono riuscito e sinceramente non sò se
è fattibile, come faccio a sapere quando la Classe solleva l'errore qual'è l'oggetto
della Form che lo ha scatenato?
Titolo: Re:Intercettazione errori
Inserito da: kicco - 02 Gennaio 2018, 21:38:05
 :ciao:
Magari non ho capito il problema: Ma  quando analizzi con la Tua Classe il contenuto di una delle TextBox, sai qual è quella che ha sollevato l'errore.
Non puoi passare l'informazione alla classe?
 :ciao: :ciao:
Titolo: Re:Intercettazione errori
Inserito da: tornu - 02 Gennaio 2018, 22:25:00
Ciao kicco,
certo che sì, era una soluzione che già mi era venuta in mente.
Passare alla Classe qual' è la TextBox che stà analizzando non è un problema,
il problema e come restituire alla Form l'informazione che identifica la TextBox
dopo che la Classe ha sollevato l'errore.
Le varie funzioni della Classe terminano tutte con Return ValoreFormattato
Titolo: Re:Intercettazione errori
Inserito da: kicco - 02 Gennaio 2018, 22:51:22
Le varie funzioni della Classe terminano tutte con Return ValoreFormattato
Possono terminare anche con più valori,  contenuti in un vettore,  per esempio.
 :ciao:
Titolo: Re:Intercettazione errori
Inserito da: Gianluigi - 02 Gennaio 2018, 23:03:19
Scusa sono rientrato adesso e sto per andare a nanna che domani mattina ho da fare.
Non ho tempo di analizzare il tuo problema ora, ma così su due piedi mi chiedo perchè devi restituire alla Form col valore che comunque potresti usando un vettore al posto della variabile di ritorno, se è la classe che solleva l'errore e la classe conosce il TextBox fallo dire alla classe, nel senso che la routine che sovrintende all'errore può passare la stringa completa del messaggio alla form.
Oppure return ValoreFormato è una stringa, se passa un numero (isNumeric) è il valore altrimenti ha passato l'errore.
Non so se può funzionare a te l'onere della prova, se entro domani pomeriggio non hai trovato la soluzione allora proverò a mettere in pratica quanto ho appena detto.

 :ciao: :ciao:
Titolo: Re:Intercettazione errori
Inserito da: vuott - 02 Gennaio 2018, 23:05:25
... contenuti in un vettore
...e, qualora il vettore venga creato nella routine chiamante, la funzione chiamata non avrà bisogno della parola-chiave "Return", poiché il passaggio del vettore, come parametro, avviene per "Indirizzo".
Titolo: Re:Intercettazione errori
Inserito da: tornu - 02 Gennaio 2018, 23:22:54
Questa la modalità che stò utilizzando

Classe CFormatValori:
Codice: [Seleziona]
Public Sub FormatVal2(stringa As String) As String '' Formattazione a due decimali e inserimento separatore migliaia
....
codice
....
Return stringa
End
Form:
Codice: [Seleziona]
Private FrmValori As New CFormatValori

Public Sub TextBox1_Activate()
  TextBox1.Text = FrmValori.FormatVal2(TextBox1.Text)
End
Domani rileggerò con attenzione i vostri suggerimenti, vediamo se riesco ad applicarli.
Titolo: Re:Intercettazione errori
Inserito da: Gianluigi - 03 Gennaio 2018, 16:06:59
Possono terminare anche con più valori,  contenuti in un vettore,  per esempio.
 :ciao:

Purtroppo il forum è diventato meno gentile e non avvisa più se altri hanno già risposto mentre stai scrivendo, poi la premura... .
Scusa  :-* non volevo rubarti l'idea.

Comunque ripensando al problema di Tornu io lo affronterei così:
Codice: [Seleziona]
Public Sub TextBox1_Change()

  myChange(TextBox1)

End

Public Sub TextBox1_KeyPress()

  myPress(TextBox1)

End

Private Sub myChange(hBox As TextBox)

  Dim c As String, i As Integer

  c = hBox.Text
  i = hBox.Pos
  If Asc(c, i) > 47 And Asc(c, i) < 58 Then
    Else If Asc(c, i) = 45 Then
    If i > 1 Then
      If Asc(c, i - 1) = 45 Then
        hBox.text = Mid(c, 1, Len(c) - 1)
      Endif
    Endif
  Else If Asc(c, i) = 44 Or If Asc(c, i) = 46 Then
    If i > 1 Then
      If Asc(c, i - 1) = 44 Or If Asc(c, i - 1) = 45 Or If Asc(c, i - 1) = 46 Then
        hBox.text = Mid(c, 1, Len(c) - 1)
      Endif
    Else
      hBox.Clear()
    Endif
  Else
    hBox.text = Mid(c, 1, Len(c) - 1)
  Endif

End

Private Sub myPress(hBox As TextBox)

  Dim s As String

  If Key.Code = Key.Return Or Key.Code = Key.Tab Then
    If IsNull(hBox.Text) Then Return
    s = ControlloValore(hBox.Text)
    If s <> "ERRORE INATTESO" Then
      hBox.Text = s
    Else
      Message.Warning(s, "OK")
      Stop Event
      hBox.Clear()
      hBox.SetFocus()
    Endif
  Endif

End

Private Function ControlloValore(value As String) As String

  Dim f As Float

  'Print value
  Try f = CFloat(Val(value))
  If Error Then Return "ERRORE INATTESO"
  'Print Val(value)
  Return Format(Val(value), ",#.#0")

End

 :ciao: :ciao:

P.S. Ho cambiato
Codice: [Seleziona]
Return Trim(Format(Val(value), "-,#.#0"))
perché era scritto inutilmente arzigogolato, non ricordo perché lo avevo scritto così in un'altra routine...  :-\
Titolo: Re:Intercettazione errori
Inserito da: kicco - 03 Gennaio 2018, 16:22:12
Possono terminare anche con più valori,  contenuti in un vettore,  per esempio.
 :ciao:

Purtroppo il forum è diventato meno gentile e non avvisa più se altri hanno già risposto mentre stai scrivendo, poi la premura... .
Scusa  :-* non volevo rubarti l'idea.
..rubare l'idea? ... di usare un vettore?  Ammetto che l'idea è talmente geniale che solo io potevo averla!  :P :P :P
E dai e dai anche noi asini finiamo per imparare qualcosa per ...osmosi! :P
 :ciao:
Titolo: Re:Intercettazione errori
Inserito da: Gianluigi - 03 Gennaio 2018, 16:26:19
per ...osmosi! :P
 :ciao:

 :rotfl: :rotfl: :rotfl:
anche il resto è divertente, ma "per osmosi"   :D :ok:

 :rotfl: :rotfl: :rotfl:
Titolo: Re:Intercettazione errori
Inserito da: tornu - 03 Gennaio 2018, 21:44:08
...
Comunque ripensando al problema di Tornu io lo affronterei così:
...
In questo modo mi costringi in ogni Form nel quale mi serve utilizzare questi controlli/formattazione dei valori
ripetere le stesse routine, ne ho già varie che svolgono queste funzioni (aggiungo alla mia "collezione"
anche questa da te proposta... non si sà mai  ;)), io cercavo di "centralizzare" tramite una Classe questi
controlli, ma come ho già detto ho il problema che l'errore sollevato dalla Classe mi deve evidenziare la
TextBox che lo ha generato e non sò come fare, le indicazioni datemi da kicco e vuott ancora non ho capito
come implementarle, continuo a studiare...
Titolo: Re:Intercettazione errori
Inserito da: Gianluigi - 03 Gennaio 2018, 22:53:57

In questo modo mi costringi in ogni Form ... ripetere le stesse routine...

Ma non puoi spostarle nella classe?  :-\
Ad esempio così:
Codice: [Seleziona]
Public Function myChange(char As String, pos As Integer) As String

  Dim c, sText As String, i As Integer
'Stop
  c = char
  i = pos
  If Asc(c, i) > 47 And Asc(c, i) < 58 Then
    sText = c
  Else If Asc(c, i) = 45 Then
    If i > 1 Then
      If Asc(c, i - 1) = 45 Then
        sText = Mid(c, 1, Len(c) - 1)
      Else
        sText = c
      Endif
    Else
      sText = c
    Endif
  Else If Asc(c, i) = 44 Or If Asc(c, i) = 46 Then
    If i > 1 Then
      If Asc(c, i - 1) = 44 Or If Asc(c, i - 1) = 45 Or If Asc(c, i - 1) = 46 Then
        sText = Mid(c, 1, Len(c) - 1)
      Else
        sText = c
      Endif
    Else
      sText = ""
    Endif
  Else
    sText = Mid(c, 1, Len(c) - 1)
  Endif
  Return sText

End


Public Function ControlloValore(value As String) As String

  Dim f As Float

  'Print value
  Try f = CFloat(Val(value))
  If Error Then Return "ERRORE INATTESO"
  'Print Val(value)
  Return Format(Val(value), ",#.#0")

End

 :ciao:
Titolo: Re:Intercettazione errori
Inserito da: tornu - 03 Gennaio 2018, 23:37:20
Si hai perfettamente ragione, chiedo scusa   :-[
Nel mentre avevo trovato la soluzione leggendo la nostra grande Wiki di cui spesso mi dimentico
nel capitolo Scrivere una Funzione, dove ho trovato una esauriente spiegazione di come
ritornare più valori da una funzione usando i vettori. Grazie a tutti per l'aiuto  :ciao:
Titolo: Re:Intercettazione errori
Inserito da: vuott - 04 Gennaio 2018, 01:16:05
la nostra grande Wiki di cui spesso mi dimentico


(https://memeguy.com/photos/images/trying-to-make-it-through-a-lecture-when-im-in-desperate-need-of-a-shit-55179.gif)
Titolo: Re:Intercettazione errori
Inserito da: Gianluigi - 04 Gennaio 2018, 09:59:06
Nel mentre avevo trovato la soluzione leggendo la nostra grande Wiki di cui spesso mi dimentico
nel capitolo Scrivere una Funzione (http://www.gambas-it.org/wiki/index.php?title=Scrivere_una_Funzione)...

Sarebbe cosa buona e giusta se indicassi qui la tua soluzione  :D

Grazie

 :ciao: :ciao:
Titolo: Re:[Risolto] Intercettazione errori
Inserito da: tornu - 04 Gennaio 2018, 20:03:14
Giusto, questa la soluzione che ho adottato.
Una piccola premessa sulla logica se qualcuno magari vuol provare il codice:
essendo la Classe pensata per formattare i valori dei campi di un gestionale, questi vanno
digitati interi (senza separatore migliaia) separando solo i decimali con la virgola o il punto,
sarà la Classe a formattarli in modo corretto, in caso contrario sarà sollevato l'errore ed
evidenziato il campo riportando il valore errato.
Classe
Codice: [Seleziona]
Public Sub FormatVal2(sStringa As String, sFlag As String) As String[] '' Formattazione a due decimali e inserimento separatore migliaia
  Dim sReturnVal As New String[]
  Dim iP, iP1, iTemp, iTemp1, iCount, iPunto, iVirgola As Integer
  Dim sInitStringa As String

'''' Sostituzione o aggiunta della virgola
  If InStr(sStringa, ",") <> 0 Then
    sStringa = Replace(sStringa, ",", ".")
  Endif

  If InStr(sStringa, ".") <> 0 Then
      sStringa = Replace(sStringa, ".", ",")
    Else
      sStringa = sStringa & ",00"
  Endif

''''' Controllo quante virgole o quanti punti contiene il valore da formattare
  For iCount = 1 To Len(sStringa)
    If InStr(".", Mid(sStringa, iCount, 1)) Then
      Inc iPunto
    Endif

    If InStr(",", Mid(sStringa, iCount, 1)) Then
      Inc iVirgola
    Endif
  Next

''''' Arrotondamento a due decimali
  If iPunto > 1 Or iVirgola > 1 Then  ' Se il valore da formattare contiene più di un punto o più di una virgola restituisce un'errore
      Message.Error("<B>Uso dei decimali non corretto</B>")
      sFlag = "Err"
      sReturnVal.Add(sStringa)
      sReturnVal.Add(sFlag)
      Return sReturnVal 'stringa
    Else
      iP = InStr(sStringa, ",") ' Assume la posizione della virgola
      iP1 = Len(sStringa) - iP ' Lunghezza della sStringa - la posizione della virgola
      sInitStringa = Left(sStringa, iP - 1)
      If iP = 1 Then
          Message.Error("<B>Uso dei decimali non corretto</B>")
          sFlag = "Err"
          sReturnVal.Add(sStringa)
          sReturnVal.Add(sFlag)
          Return sReturnVal 'stringa
        Else If iP1 = 2 Then
          sStringa = sStringa
        Else If iP1 <= 1 Then
          sStringa = sStringa & "0"
        Else If iP1 > 2 Then
          iTemp = CInt(Mid(sStringa, iP + 1, 2))
          iTemp1 = CInt(Mid(sStringa, iP + 1 + 2, 1))
          ' If iTemp1 >= 5 Then ' Se l'ultimo decimale e uguale o maggiore di 5 viene incrementato di uno
          '   Inc iTemp
          ' Endif
          If iTemp = 100 Then
              sStringa = CString(CInt(sInitStringa) + 1) & ",00"
            Else
              sStringa = sInitStringa & "," & CString(iTemp)
          Endif
      Endif

''''' Aggiunta puntini ogni 1000 (separatore migliaia)
      If Len(sStringa) >= 7 Then
        sStringa = Mid(sStringa, 1, (Len(sStringa) - 6)) & "." & Right(sStringa, 6)
      Endif

      If Len(sStringa) >= 11 Then
        sStringa = Mid(sStringa, 1, (Len(sStringa) - 10)) & "." & Right(sStringa, 10)
      Endif

      If Len(sStringa) >= 15 Then
        sStringa = Mid(sStringa, 1, (Len(sStringa) - 14)) & "." & Right(sStringa, 14)
      Endif

      If Len(sStringa) >= 19 Then
        sStringa = Mid(sStringa, 1, (Len(sStringa) - 18)) & "." & Right(sStringa, 18)
      Endif
     
      sReturnVal.Add(sStringa)
      sReturnVal.Add(sFlag)
   
      Return sReturnVal 'stringa
  Endif
End

Form
Codice: [Seleziona]
Private CFormat_Valori As New CFormatValori
Private ReturnVal As String[]

Public Sub Form_Open()
  Me.Center()

  TextBox1.SetFocus()
End

Public Sub TextBox1_KeyPress()
  TextBox1.Background = Color.Default
End

Public Sub TextBox1_Activate()  '  Public Sub TextBox1_LostFocus()
  Dim sFlag As String

  ReturnVal = CFormat_Valori.FormatVal2(TextBox1.Text, sFlag)

  If ReturnVal[1] = "" Then
      TextBox1.Text = ReturnVal[0]
    Else
      TextBox1.Text = ReturnVal[0]
      TextBox1.Background = Color.RGB(255, 255, 127)
  Endif
End
Saranno bene accetti suggerimenti ed eventuali migliorie.  :ciao:
Titolo: Re:[Risolto] Intercettazione errori
Inserito da: Gianluigi - 04 Gennaio 2018, 22:13:09
Grazie per la condivisione

 :ciao: