Hola:
Quiero hacer un mantenimiento de una tabla que tiene una relación a muchos sobre otra en un entorno multiusuario. Cuando edito un registro de la tabla principal quiero mostrar en un browse los registros relacionados. Como la edición se puede abandonar cancelando, no puedo mostrar directamente los registros de la tabla dependiente y estoy intentando montar un array con los registros dependientes para mostrarlos ahi y dar altas y bajas y luego refrescar la tabla real en caso de aceptar _.
Estoy intentando hacer un browse sobre este array que en algunos momentos puede estar vacio y me estoy encontrando que ni con twbrowse ni con xbrowse puedo hacerlo y que en cuanto el array está vacio me truena irremediablemente. ¿ Alguna idea de como atacar esto ? ¿ Con alguna clase de rdd sobre arrays ? ¿ Cual ?
Saludos,
José Luis
browse sobre array
- José Luis Sánchez
- Posts: 484
- Joined: Thu Oct 13, 2005 9:23 am
- Location: Novelda - Alicante - España
- Contact:
- AngelSalom
- Posts: 664
- Joined: Fri Oct 07, 2005 7:38 am
- Location: Vinaros (Castellón ) - España
- Contact:
No quiero decir que los arrays sea una mala idea pero yo en _ desde siempre creo un fichero temporal con la estructura de la tabla relacionada y la lleno con los registros que cumplen los requisitos.
Una vez acabado el proceso, decides si actualizar o no la tabla.
Luego, se borra el fichero y, funciona perfecto.
Un saludo.
Una vez acabado el proceso, decides si actualizar o no la tabla.
Luego, se borra el fichero y, funciona perfecto.
Un saludo.
Angel Salom
http://www.visionwin.com
---------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.0
http://www.visionwin.com
---------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.0
-
- Posts: 108
- Joined: Sun Oct 09, 2005 6:12 pm
- Location: Mar del Plata - Argentina
- Contact:
Jose Luis:
Yo uso esto con twbrowse, basta con pasarle cualquier vector:
FUNCTION MCHOICE(aNcampos,X,Y,ANCHO,ALTO,cTitulo)
Local oDlg, aBrw, RET:=0, nItem:=1,largo:=len(aNcampos)
DEFAULT cTitulo:="Seleccione..."
DEFINE DIALOG oDlg RESOURCE "MCHOICE" TITLE cTitulo
oDlg:lHelpIcon:=.f.
REDEFINE LISTBOX aBrw FIELDS ANCAMPOS[NITEM] id 999 of odlg;
FIELDSIZES 281 ON DBLCLICK (Ret:=nItem,oDlg:End()) //COLORS CLR_BLUE
aBrw:cAlias = "Array" // Just put something
aBrw:bLogicLen = { || Len( aNcampos ) }
aBrw:SetArray(aNCampos)
aBrw:bGoTop = { || nItem := 1 }
aBrw:bGoBottom = { || nItem := Eval( aBrw:bLogicLen ) }
aBrw:bGoBottom = { || nItem := Eval( aBrw:bLogicLen ) }
aBrw:bSkip = { | nWant, nOld | nOld := nItem, nItem += nWant,;
nItem := Max( 1, Min( nItem, Eval( aBrw:bLogicLen ) ) ),;
nItem - nOld }
aBrw:bKeyChar = { | nK | if( nK==VK_RETURN,(Ret:=nItem,oDlg:End()),) } // Controlling keystrokes
aBrw:lDrawHeader := .f.
aBrw:lcellstyle := .t.
aBrw:nlinestyle := 2
aBrw:nclrpane:= {|| iif( (nItem/2)-INT(nItem/2) > 0, CLR_LBLUE, CLR_LGRAY) }
* oBrw:nClrPane:={|| IIF((wAlias)->(OrdKeyNo())%2==0,CLR_LBLUE,CLR_LGRAY)}
aBrw:GoTop()
oDlg:SetControl(aBrw)
//ACTIVATE DIALOG oDlg ON INIT (aBrw:GoTop(),aBrw:Refresh(),oDlg:setsize(ANCHO,ALTO),oDlg:Move(X,Y))
ACTIVATE DIALOG oDlg ON INIT (oDlg:Move(X,Y),oDlg:setsize(ANCHO,ALTO))
RETURN Ret
Tambien podes browsear matrices:
Static Function TotPractica(cAlias,oBrw)
Local oDlg, aBrw, RET:=0, nItem:=1
Local X:=390,Y:=200,ANCHO:=454,ALTO:=140,cTitulo:=oemtoansi("Totales por Pr ctica")
Local nReg
Local aPractica:={},cCodPra:=(cAlias)->PRACTICA,largo:=0,I:=1,cTipo,cRecno:=(cAlias)->(RECNO())
Local aOrdenado:={},aPrueba:={}
DEFAULT cTitulo:="Seleccione..."
(cAlias)->(DBGOTOP())
DO WHILE ! (cAlias)->(EOF())
IF LEN(aPractica)==0
aadd(aPractica,{BUS_DES("PRACTICA",1,(cAlias)->PRACTICA,"NOMBRE"),1,(cAlias)->APAGAR})
ELSE
cTipo:=BUS_DES("PRACTICA",1,(cAlias)->PRACTICA,"NOMBRE")
nReg:=ASCAN( aPractica, { |aField| aField[1]==cTipo } )
IF nReg == 0
aadd(aPractica,{BUS_DES("PRACTICA",1,(cAlias)->PRACTICA,"NOMBRE"),1,(cAlias)->APAGAR})
ELSE
aPractica[nReg,2]+=1
aPractica[nReg,3]+=(cAlias)->APAGAR
ENDIF
ENDIF
(cAlias)->(DBSKIP())
ENDDO
(cAlias)->(DBGOTO(cRecno))
oBrw:Refresh()
FOR I:=1 TO LEN(aPractica)
aPractica[i,2]:=TRANS(aPractica[i,2],"@E 9,999")
aPractica[i,3]:=TRANS(aPractica[i,3],"@E 999,999.99")+" "
NEXT
IF LEN(aPractica)==0
Aadd(aPractica,{SPAC(30),SPAC(9),SPAC(10)})
ENDIF
DEFINE DIALOG oDlg RESOURCE "MCHOICE" TITLE cTitulo
oDlg:lHelpIcon:=.f.
aOrdenado:=ASORT(aPractica,,,{|x,y| x[1] < y[1]})
REDEFINE LISTBOX aBrw FIELDS aOrdenado[NITEM,1],aOrdenado[NITEM,2],aOrdenado[NITEM,3] ;
HEADER oemtoansi("Descripci¢n")," Cant."," Importe ";
id 999 of odlg;
FIELDSIZES 269,59,96 ON DBLCLICK (Ret:=nItem,oDlg:End()) //COLORS CLR_BLUE
aBrw:cAlias = "Array" // Just put something
aBrw:bLogicLen = { || Len( aOrdenado ) }
aBrw:SetArray(aOrdenado)
aBrw:bGoTop = { || nItem := 1 }
aBrw:bGoBottom = { || nItem := Eval( aBrw:bLogicLen ) }
aBrw:bGoBottom = { || nItem := Eval( aBrw:bLogicLen ) }
aBrw:bSkip = { | nWant, nOld | nOld := nItem, nItem += nWant,;
nItem := Max( 1, Min( nItem, Eval( aBrw:bLogicLen ) ) ),;
nItem - nOld }
aBrw:bKeyChar = { | nK | if( nK==VK_RETURN,(Ret:=nItem,oDlg:End()),) } // Controlling keystrokes
aBrw:lcellstyle := .t.
aBrw:nlinestyle := 2
aBrw:aJustify:={0,2,1}
aBrw:nclrpane:= {|| iif( (nItem/2)-INT(nItem/2) > 0, CLR_LBLUE, CLR_LGRAY) }
aBrw:lAdjLastcol:=.F.
aBrw:GoTop()
oDlg:SetControl(aBrw)
ALTO:=50+16.0*LEN(aOrdenado)
IF(ALTO > 550,ALTO:=550,)
IF LEN(aOrdenado) < 15
ACTIVATE DIALOG oDlg ON INIT (oDlg:Move(X,Y),oDlg:setsize(ANCHO,ALTO))
ELSE
ACTIVATE DIALOG oDlg ON INIT (oDlg:Move(X,Y),oDlg:setsize(ANCHO,ALTO),oDlg:Center())
ENDIF
Return nil
Saludos,
Yo uso esto con twbrowse, basta con pasarle cualquier vector:
FUNCTION MCHOICE(aNcampos,X,Y,ANCHO,ALTO,cTitulo)
Local oDlg, aBrw, RET:=0, nItem:=1,largo:=len(aNcampos)
DEFAULT cTitulo:="Seleccione..."
DEFINE DIALOG oDlg RESOURCE "MCHOICE" TITLE cTitulo
oDlg:lHelpIcon:=.f.
REDEFINE LISTBOX aBrw FIELDS ANCAMPOS[NITEM] id 999 of odlg;
FIELDSIZES 281 ON DBLCLICK (Ret:=nItem,oDlg:End()) //COLORS CLR_BLUE
aBrw:cAlias = "Array" // Just put something
aBrw:bLogicLen = { || Len( aNcampos ) }
aBrw:SetArray(aNCampos)
aBrw:bGoTop = { || nItem := 1 }
aBrw:bGoBottom = { || nItem := Eval( aBrw:bLogicLen ) }
aBrw:bGoBottom = { || nItem := Eval( aBrw:bLogicLen ) }
aBrw:bSkip = { | nWant, nOld | nOld := nItem, nItem += nWant,;
nItem := Max( 1, Min( nItem, Eval( aBrw:bLogicLen ) ) ),;
nItem - nOld }
aBrw:bKeyChar = { | nK | if( nK==VK_RETURN,(Ret:=nItem,oDlg:End()),) } // Controlling keystrokes
aBrw:lDrawHeader := .f.
aBrw:lcellstyle := .t.
aBrw:nlinestyle := 2
aBrw:nclrpane:= {|| iif( (nItem/2)-INT(nItem/2) > 0, CLR_LBLUE, CLR_LGRAY) }
* oBrw:nClrPane:={|| IIF((wAlias)->(OrdKeyNo())%2==0,CLR_LBLUE,CLR_LGRAY)}
aBrw:GoTop()
oDlg:SetControl(aBrw)
//ACTIVATE DIALOG oDlg ON INIT (aBrw:GoTop(),aBrw:Refresh(),oDlg:setsize(ANCHO,ALTO),oDlg:Move(X,Y))
ACTIVATE DIALOG oDlg ON INIT (oDlg:Move(X,Y),oDlg:setsize(ANCHO,ALTO))
RETURN Ret
Tambien podes browsear matrices:
Static Function TotPractica(cAlias,oBrw)
Local oDlg, aBrw, RET:=0, nItem:=1
Local X:=390,Y:=200,ANCHO:=454,ALTO:=140,cTitulo:=oemtoansi("Totales por Pr ctica")
Local nReg
Local aPractica:={},cCodPra:=(cAlias)->PRACTICA,largo:=0,I:=1,cTipo,cRecno:=(cAlias)->(RECNO())
Local aOrdenado:={},aPrueba:={}
DEFAULT cTitulo:="Seleccione..."
(cAlias)->(DBGOTOP())
DO WHILE ! (cAlias)->(EOF())
IF LEN(aPractica)==0
aadd(aPractica,{BUS_DES("PRACTICA",1,(cAlias)->PRACTICA,"NOMBRE"),1,(cAlias)->APAGAR})
ELSE
cTipo:=BUS_DES("PRACTICA",1,(cAlias)->PRACTICA,"NOMBRE")
nReg:=ASCAN( aPractica, { |aField| aField[1]==cTipo } )
IF nReg == 0
aadd(aPractica,{BUS_DES("PRACTICA",1,(cAlias)->PRACTICA,"NOMBRE"),1,(cAlias)->APAGAR})
ELSE
aPractica[nReg,2]+=1
aPractica[nReg,3]+=(cAlias)->APAGAR
ENDIF
ENDIF
(cAlias)->(DBSKIP())
ENDDO
(cAlias)->(DBGOTO(cRecno))
oBrw:Refresh()
FOR I:=1 TO LEN(aPractica)
aPractica[i,2]:=TRANS(aPractica[i,2],"@E 9,999")
aPractica[i,3]:=TRANS(aPractica[i,3],"@E 999,999.99")+" "
NEXT
IF LEN(aPractica)==0
Aadd(aPractica,{SPAC(30),SPAC(9),SPAC(10)})
ENDIF
DEFINE DIALOG oDlg RESOURCE "MCHOICE" TITLE cTitulo
oDlg:lHelpIcon:=.f.
aOrdenado:=ASORT(aPractica,,,{|x,y| x[1] < y[1]})
REDEFINE LISTBOX aBrw FIELDS aOrdenado[NITEM,1],aOrdenado[NITEM,2],aOrdenado[NITEM,3] ;
HEADER oemtoansi("Descripci¢n")," Cant."," Importe ";
id 999 of odlg;
FIELDSIZES 269,59,96 ON DBLCLICK (Ret:=nItem,oDlg:End()) //COLORS CLR_BLUE
aBrw:cAlias = "Array" // Just put something
aBrw:bLogicLen = { || Len( aOrdenado ) }
aBrw:SetArray(aOrdenado)
aBrw:bGoTop = { || nItem := 1 }
aBrw:bGoBottom = { || nItem := Eval( aBrw:bLogicLen ) }
aBrw:bGoBottom = { || nItem := Eval( aBrw:bLogicLen ) }
aBrw:bSkip = { | nWant, nOld | nOld := nItem, nItem += nWant,;
nItem := Max( 1, Min( nItem, Eval( aBrw:bLogicLen ) ) ),;
nItem - nOld }
aBrw:bKeyChar = { | nK | if( nK==VK_RETURN,(Ret:=nItem,oDlg:End()),) } // Controlling keystrokes
aBrw:lcellstyle := .t.
aBrw:nlinestyle := 2
aBrw:aJustify:={0,2,1}
aBrw:nclrpane:= {|| iif( (nItem/2)-INT(nItem/2) > 0, CLR_LBLUE, CLR_LGRAY) }
aBrw:lAdjLastcol:=.F.
aBrw:GoTop()
oDlg:SetControl(aBrw)
ALTO:=50+16.0*LEN(aOrdenado)
IF(ALTO > 550,ALTO:=550,)
IF LEN(aOrdenado) < 15
ACTIVATE DIALOG oDlg ON INIT (oDlg:Move(X,Y),oDlg:setsize(ANCHO,ALTO))
ELSE
ACTIVATE DIALOG oDlg ON INIT (oDlg:Move(X,Y),oDlg:setsize(ANCHO,ALTO),oDlg:Center())
ENDIF
Return nil
Saludos,
- José Luis Sánchez
- Posts: 484
- Joined: Thu Oct 13, 2005 9:23 am
- Location: Novelda - Alicante - España
- Contact:
José:
Con wBrwosede Checcarelli, y obviamente con el nativo, se pueden crear browse de array vacios sin problemas.
Un array del tipo aXX:= {{"i", "a"}, {"ii","b"}, {"iii","c" }}, podría adoptar la forma, o hacerlo desde el principio, como aXX:= {{"", ""}, {"",""}, {"","" }} y ser browseado sin problemas.
Para usar array, yo prefiero usar TArray, que crea un objeto array con metodos del tipo :GoTo(), :LastRec(); :Seek(), y otros.
saludos
Con wBrwosede Checcarelli, y obviamente con el nativo, se pueden crear browse de array vacios sin problemas.
Un array del tipo aXX:= {{"i", "a"}, {"ii","b"}, {"iii","c" }}, podría adoptar la forma, o hacerlo desde el principio, como aXX:= {{"", ""}, {"",""}, {"","" }} y ser browseado sin problemas.
Para usar array, yo prefiero usar TArray, que crea un objeto array con metodos del tipo :GoTo(), :LastRec(); :Seek(), y otros.
saludos
Resistencia - "Ciudad de las Esculturas"
Chaco - Argentina
Chaco - Argentina
- Willi Quintana
- Posts: 859
- Joined: Sun Oct 09, 2005 10:41 pm
- Location: Cusco - Perú
- Contact:
Hola,,
Con la TWBROWSE sale asi:
AADD(aProducto, {"Procesador","Pza"," 45.00"}
...
REDEFINE LISTBOX oLbx ;
FIELDS aProducto[oLbx:nAt, 1], ;
aProducto[oLbx:nAt, 2], ;
aProducto[oLbx:nAt, 3] ;
HEADERS "Producto", ;
"Unidad", ;
"Stock" ;
FONT oFont1 ;
SIZES 400,50,65 ;
COLOR CLR_BLACK, cColor1;
ID 220 OF oFld:aDialogs[1]
oLbx:SetArray( aProducto )
La ultima linea es muy importante,,,,
Salu2
Con la TWBROWSE sale asi:
AADD(aProducto, {"Procesador","Pza"," 45.00"}
...
REDEFINE LISTBOX oLbx ;
FIELDS aProducto[oLbx:nAt, 1], ;
aProducto[oLbx:nAt, 2], ;
aProducto[oLbx:nAt, 3] ;
HEADERS "Producto", ;
"Unidad", ;
"Stock" ;
FONT oFont1 ;
SIZES 400,50,65 ;
COLOR CLR_BLACK, cColor1;
ID 220 OF oFld:aDialogs[1]
oLbx:SetArray( aProducto )
La ultima linea es muy importante,,,,
Salu2