Seite 1 von 1

Suchen im Getlist Array [ERLEDIGT]

Verfasst: Di, 02. Feb 2016 15:14
von Manfred
ich habe folgende Aufgabe: Ich möchte eine Anwendung im VIO Modus programmieren, mit Eingabemasken. Die beinhalten dann natürlich GET Felder. So weit so gut. Jetzt möchte ich aber an anderer Stelle die Werte in den Getfeldern ändern und direkt am Bildschirm anzeigen. Damit ich mir nicht merken muß wo die getfelder sind am Bildschirm, möchte ich es genauso machen, wie bei XbpSle. Dort wird ja auch nur der Wert mit SetData() geändert und dann wird er direkt angezeigt.
Da ich die Maske aber sehr einfach gestalten möchte, also nicht GET Objekte selbst erzeugen will, habe ich mir mal angeschaut, wie der PP das macht. Er erzeugt einen Satz in dem getlist. Wenn ich die Position davon weiß, kann ich mit getlist[x]:varput() und dann getlist[x]:updatebuffer() das genauso machen. Das klappt auch. Aaaber, wie finde ich mit AScan das entsprechende Get im Getlist Array? Der Name der var steht in der memvar :name. hat jemand eine Ahnung, wie ich in dem Array suchen muß, damit ich den namen finde und damit die Position des getfeldes im getlist?

Oder mache ich es eh zu kompliziert und es geht viel einfacher? Ich merke, ich habe schon lange nicht mehr VIO Programme erstellt.

Re: Suchen im Getlist Array

Verfasst: Di, 02. Feb 2016 15:41
von georg
Hallo, Manfred -


etwa so:

Code: Alles auswählen

nLen := Len(GetList)
FOR nI := 1 TO nLen
   IF GetList[nI]:name == "feldname"
      ...
   ENDIF
NEXT

Re: Suchen im Getlist Array

Verfasst: Di, 02. Feb 2016 15:49
von Manfred
Ok,

so habe ich das derzeit, aber ist das die eleganteste Lösung? geht das nicht mit Ascan()?

Re: Suchen im Getlist Array

Verfasst: Di, 02. Feb 2016 15:56
von georg
Hallo, Manfred -


geht sicher auch und macht quasi das gleiche über einen Codeblock. Diese Schleife ist wahrscheinlich einen Tick je Element schneller.

Re: Suchen im Getlist Array

Verfasst: Di, 02. Feb 2016 16:03
von Manfred
ach so, in dem Falle wäre Ascan "langsamer"? Dann ist das ok, ich dachte nur Ascan würde sich genauso verhalten wie die DbXXX Funktionen. Die sind ja auch schneller als Schleifen.

Re: Suchen im Getlist Array

Verfasst: Di, 02. Feb 2016 18:12
von georg
Hallo, Manfred -


das wäre

Code: Alles auswählen

nTreffer := AScan(GetList, {|x| x:name == "feldname"})
Aus meiner Sicht wird da intern ebenfalls eine Schleife abgearbeitet und jedesmal der Codeblock ausgeführt, und da rechne ich mit einem kleinen Overhead. Genau weiss man das erst, wenn man beide Varianten mit grossen Arrays zum Test durchlaufen hat.

Re: Suchen im Getlist Array

Verfasst: Di, 02. Feb 2016 18:17
von Manfred
Hi georg,

hast Du das ausprobiert? ich meine das klappt nicht, weil sowas hatte ich schon probiert. Allerdings nur auf der Kommandozeile der VX.

Re: Suchen im Getlist Array

Verfasst: Di, 02. Feb 2016 19:07
von georg
Hallo, Manfred -


weiss nicht ...

So sollte es laut Dokumentation aussehen, aber ich mache das immer mit einem Loop ...

Re: Suchen im Getlist Array

Verfasst: Di, 02. Feb 2016 23:16
von AUGE_OHR
Manfred hat geschrieben:hast Du das ausprobiert?
JA ... aber ...
Frage : an welcher Stelle hast du es ausprobiert ... vor oder nach dem READ ?

ich nehme mal an nach dem READ ... probiere mal

Code: Alles auswählen

LOCAL Getlist := {}   
   @ x.y GET blabla
   READ
? LEN(Getlist)
und du wirst 0 erhalten ;)

wenn du die Getlist "nach" einem READ weiter benutzen willst musst du die Option SAVE anhängen.
p.s. und dann irgendwann mit CLEAR GETS aufräumen.

Re: Suchen im Getlist Array

Verfasst: Mi, 03. Feb 2016 7:11
von Manfred
?
das verstehe ich jetzt nicht. Das getlist ist an der Stelle auf jeden Fall gefüllt.

Re: Suchen im Getlist Array

Verfasst: Mi, 03. Feb 2016 7:31
von brandelh
Hier definiert man, dass während einem READ eigener code abgearbeitet wird
@ ... GET cVar1 VALID MeineFunktion_NACH_Feld( cVar , "cVar1")
@ ... GET cVar2 WHEN MeineFunktion_VOR_Feld( cVar , "cVar1" )
Aber nur solange READ aktiv ist, kann man das GETLIST-Array (Array mit GET Objekten) auswerten und eventuell Werte in den GETs ändern.

AScan ist normal etwas schneller als eine eigene Schleife, aber das wird bei 100 Elementen kaum messbar sein.
Die eigene Schleife ist meist leichter zu debuggen und zu verstehen was abgeht.
Eigentlich ist das ganze kein Hexenwerk, so habe ich früher komplexe Rechnungserfassung programmiert ...

Hier der Aufbau per Schleife der Rechnungszeilen, 2 Funktionen haben entschieden, ob das nächste GET übersprungen wird (WHEN) und ob die Eingabe OK war (VALID):

Code: Alles auswählen

              for x := 1 to REZEIMAX

                y := 1

                @5+x,1  get rechnung[ x+offset , ARENUM ]  ;
                        picture "999"  when springen(rechnung)
                        #ifdef __XPP__
                           aTail(getlist):subscript := {x + Offset, y++}
                        #endif
                @5+x,5  get rechnung[ x+offset , AANZ ]   ;
                        picture "@E 99.9"       valid rechn_n(rechnung) ;
                        when springen(rechnung)
                        #ifdef __XPP__
                           aTail(getlist):subscript := {x + Offset, y++}
                        #endif
                @5+x,9  get rechnung[ x+offset , AANZ_ART ]     ;
                        picture "!"  when springen(rechnung)
                        #ifdef __XPP__
                           aTail(getlist):subscript := {x + Offset, y++}
                        #endif
                @5+x,11 get rechnung[ x+offset , AARTNR ]     ;
                        picture "@!@S15"        valid rechn_n(rechnung) ;
                        when springen(rechnung)
                        #ifdef __XPP__
                           aTail(getlist):subscript := {x + Offset, y++}
                        #endif
                @5+x,27 get rechnung[ x+offset , AA_BEZ ]     ;
                        picture "@S28"  when springen(rechnung)
                        #ifdef __XPP__
                           aTail(getlist):subscript := {x + Offset, y++}
                        #endif
                @5+x,56 get rechnung[ x+offset , ACODE ]      ;
                        picture "!!"             valid rechn_n_code() ;
                        when springen(rechnung)
                        #ifdef __XPP__
                           aTail(getlist):subscript := {x + Offset, y++}
                        #endif
                @5+x,59 get rechnung[ x+offset , APREIS ]     ;
                        picture "@E 99,999.99"   valid rechn_n(rechnung) ;
                        when springen(rechnung)
                        #ifdef __XPP__
                           aTail(getlist):subscript := {x + Offset, y++}
                        #endif
                @5+x,69 get rechnung[ x+offset , AGES_PREIS ] ;
                        picture "@E 999,999.99"  valid rechn_n(rechnung) ;
                        when springen(rechnung)
                        #ifdef __XPP__
                           aTail(getlist):subscript := {x + Offset, y++} // Zugriff auf aktuelles Get-Objekt
                        #endif

              next
Alaska hat sich entschieden die Instanzvariable subscript nicht auszufüllen, da sie die intern nicht benutzen,
ich brauche die aber schon für meine Zwecke. DU kannst hier erkennen, wie man beim Aufbau auf das aktuelle GET-Objekt zugreifen kann !

Hier die VALID Funktion, die das aktuell aktive GET-Objekt abfragt (genau dafür gibt es eine Funktion):

Code: Alles auswählen

*--------------------------------------------------------- RECHN_N -----------
function rechn_n( rechnung )
   local oGET, ZeilNum,aSubscript,x
   oGet       := Getactive()            // aktuelles Getobjekt lesen
   aSubscript := oGet:subscript         // Array mit Position ermitteln
   ZeilNum    := aSubscript[ 1 ]        // Zeilennummer in 1.

   if rechnung[ ZeilNum , AANZ   ]  #  0      .AND.  ;
      rechnung[ ZeilNum , APREIS ]  #  0
      rechnung[ ZeilNum , AGES_PREIS ] := round( ;
         rechnung[ ZeilNum , AANZ   ]   * ;
         rechnung[ ZeilNum , APREIS ]   ,2  )
   endif

   x=ascan( getlist , {|o|  iif( o:subscript[1]=ZeilNum    .AND.  ;
                                 o:subscript[2]=APREIS , .t. ,.f.) } )

   if x > 0                      // Einzelpreis suchen und mit Gesamtpreis anzeigen
      getlist[x]:display()
      getlist[x+1]:display()
   endif

   if empty(rechnung[ ZeilNum , AGES_PREIS ])  .AND.  ! empty(rechnung[ ZeilNum , APREIS ])

      meldung(12,"F",{"Achtung: Gesamtpreis ist   0   !!!!",;
                      "Dies ist meist ein Fehler, bitte Stückzahl und Einzelpreis überprüfen !"})
   endif
return .t.
Hier die Funktion die das nächste zu editierende GET auswählt:

Code: Alles auswählen

*--------------------------------------------------------- Springen ---------
function springen( rechnung )
   local oGET, ZeilNum,aSubscript,x, edit, feld, ZeileLeer, VorZeileLeer
   oGet       := Getactive()            // aktuelles Getobjekt lesen
   aSubscript := oGet:subscript         // Array mit Position ermitteln
   ZeilNum    := aSubscript[ 1 ]        // Zeilennummer in 1.
   Feld       := aSubscript[ 2 ]        // Arrayelement in 2.
   edit       := .t.                    // Standard Feld editierbar
   ZeileLeer  := .t.                    //    "     Zeile ist leer
   VorZeileLeer := .t.                  //    "     VorZeile ist leer
   for x = AANZ to AGES_PREIS          // Ermitteln ob Zeile leer
       if ! empty( rechnung[ ZeilNum , x ] )
          ZeileLeer := .f.
          exit
       endif
   next
   if ZeilNum = 1
      VorZeileLeer := .t.
   else
     for x := AANZ to AGES_PREIS          // Ermitteln ob Vorzeile leer
       if ! empty( rechnung[ ZeilNum - 1 , x ] )
          VorZeileLeer := .f.
          exit
       endif
     next
   endif

   do case
      case feld = ARENUM
           if ZeilNum = 1      // erste Zeile immer editieren
              edit := .t.
           else
              edit := ! VorZeileLeer  // sonst nur wenn letzte Zeile ! leer
           endif
      case feld # ARENUM  .AND.  empty( rechnung[ ZeilNum , ARENUM ] )
           edit := .f.
      case feld = AANZ
           if ZeilNum = 1      // erste Zeile immer editieren
              edit := .t.
           else
              edit := ! VorZeileLeer  // sonst nur wenn letzte Zeile ! leer
           endif
      case feld = AANZ_ART     // Anzahlart nur wenn Anzahl in dieser Zeile
           edit := ! empty( rechnung[ ZeilNum , AANZ ] )
      case feld = AARTNR
           if ZeilNum = 1      // erste Zeile immer editieren
              edit := .t.
           else
              edit := ! VorZeileLeer  // sonst nur wenn letzte Zeile ! leer
           endif
      case feld = AA_BEZ
           if ZeilNum = 1      // erste Zeile immer editieren
              edit := .t.
           else
              edit := ! VorZeileLeer  // sonst nur wenn letzte Zeile ! leer
           endif
      case feld = ACODE        // Rechnungsart, wenn Artikelnr. oder Bez.
           edit := ! ( empty( rechnung[ ZeilNum , AARTNR ] )  .AND.  ;
                      empty( rechnung[ ZeilNum , AA_BEZ ] )  )
      case feld = APREIS       // Einzelpreis, wenn Artikelnr. oder Bez.
           edit := ! ( empty( rechnung[ ZeilNum , AARTNR ] )  .AND.  ;
                      empty( rechnung[ ZeilNum , AA_BEZ ] )  )
      case feld = AGES_PREIS
         if rechnung[ ZeilNum , AANZ   ]  #  0      .AND.  ;
            rechnung[ ZeilNum , APREIS ]  #  0
            edit := .f.  // Wenn Anzahl und Einzelpreis festliegen, rechnen!
         else                  // Sonst, wenn Artikelnr. oder Bez. eingeben.
           edit := ! ( empty( rechnung[ ZeilNum , AARTNR ] )  .AND.  ;
                      empty( rechnung[ ZeilNum , AA_BEZ ] )  )
         endif
   endcase

return ( edit )

Re: Suchen im Getlist Array

Verfasst: Mi, 03. Feb 2016 7:44
von brandelh
Hier ein anderes Beispiel mit Adressübernahme, sobald man F2 gedrückt hat.
GET Teil:

Code: Alles auswählen

      @ 4,pos1 say "Rechnungsnummer:"
      @ 6,pos1 say "Kundennummer (F2): "        get m_kdnr   valid re_kdnr_ok(m_kdnr)
      @ 6,pos2 say "1.Zeile:" get m_re_adr_1
      @ 7,pos2 say "2.Zeile:" get m_re_adr_2
      @ 8,pos2 say "3.Zeile:" get m_re_adr_3
      @ 9,pos1 say "Hier Namenszeile -->"
      @ 9,pos2 say "4.Zeile:" get m_re_adr_4
      @10,pos2 say "5.Zeile:" get m_re_adr_5
      @11,pos2 say "6.Zeile:" get m_re_adr_6
      @12,pos2 say "7.Zeile:" get m_re_adr_7
      @13,pos2 say "8.Zeile:" get m_re_adr_8
SET KEY ... to verweist auf die Funktion:

Code: Alles auswählen

*-----------------------------------------------------------------------------
procedure f2_RE_adress(nochmal)      && Adressenübername in Rechnungsmodul
...
getvar :=  getfldvar()
altcurs :=  setcursor(1)
altselect :=  select()
... Auswahlliste aufbauen
if gefunden                    && Auswahlliste zeigen
   setcursor(0)
   tabelle(7,31,19,78,"KU",zeigfeld,namefeld,1,.t.,.f.,"F2READRESS",recc()/2)
   if lastkey()=K_ENTER                   && übergeben
      ... Datensatz ausgewählt
      do case
         case ku->geschl="W"
           anrede :=  "Frau"
         case ku->geschl="M"
           anrede :=  "Herr"
         case ku->geschl="F"
           anrede :=  "Firma"
         otherwise
           anrede :=  ""
       endcase

       *** Werte DIREKT übergeben ***

       x :=  ascan( getlist , {|o| if( upper(o:name)="M_KDNR" , .t. ,.f.) } )
       len1 :=  len(getlist[x]:varget())   // l„nge des Feldes ermitteln
       getlist[x]:varput( left(ku->kdnr+space(len1),len1) )

       x :=  ascan( getlist , {|o| if( upper(o:name)="M_RE_ADR_3" , .t. ,.f.) } )
       len1 :=  len(getlist[x]:varget())   // l„nge des Feldes ermitteln
       getlist[x]:varput( left( anrede+space(len1),len1) )

      ...

Wichtig, ist dass die Variablenlänge sauber eingehalten wird (Space auffüllen).
Ab und zu muss man auch eine Neuanzeige erzwingen ...

Code: Alles auswählen

            aeval( getlist() , {|x| iif(x:hasfocus, x:updatebuffer(), x:display()) } )