Problemas con decimales en importación desde Excel

659 views
Skip to first unread message

ultraton500

unread,
Nov 8, 2012, 2:09:18 PM11/8/12
to publice...@googlegroups.com
Hola compañeros, mediante APPEND FROM importo una tabla de excel (codigo,descripción y precio) a un cursor creado en el INIT cuyos campos son todos de tipo character.
El problema es que alguno de los datos numericos se importan con muchos decimales (por ej. 67.65000000000001) siendo que en la planilla importada tienen dos y aún habiendo declarado SET DECIMALS TO 2.

Podría solucionarlo definiendo como N(10,2) el campo del cursor en el que se va a importar el precio pero la razón de que creo todos los campos de tipo character es porque no se sabe de antemano cuál es la columna que 
contiene el precio. Justamente esta importación es para identificar qué contiene cada columna.

Alguien sabría decirme la forma de importar los datos numéricos tal como están en Excel?
Gracias desde ya por su ayuda.
Saludos,
Javier.

miltonvas

unread,
Nov 9, 2012, 12:08:13 AM11/9/12
to publice...@googlegroups.com
porque despues de importar no haces lo siguiente:

Replace all precio with str(round(val(precio),2),10,2)

saludos cordiales

Milton

ultraton500

unread,
Nov 9, 2012, 11:17:38 AM11/9/12
to publice...@googlegroups.com
Gracias miltonvas por la ayuda.
Para poder hacer lo que me sugieres debería saber cuál es la columna del precio y eso es lo que no se sabe hasta que el usuario lo indica luego de visualizar la tabla a importar en un grid para ese fin.
Si supiese de antemano cuál es la columna del precio declararía como N(10,2) el campo del cursor que recibe la tabla importada, pero como no lo sé todas las columnas de ese cursor son de tipo character.
Recién aplico round luego de que el usuario indica la columna del precio y recién ahí hago los procesos que tenga que hacer.
Gracias nuevamente por la sugerencia.
Saludos cordiales.
Javier.

Marlon Cabrera

unread,
Nov 9, 2012, 3:23:37 PM11/9/12
to publice...@googlegroups.com
Declara todos los campos con 254 caractares lo máximo,  para que entre todo el valor si sin importar la cantidad de decimales.
 
Saludos


--
 
 
 



--
Marlon Cabrera

FidelJ

unread,
Nov 9, 2012, 3:51:47 PM11/9/12
to publice...@googlegroups.com
Puedes utilizar la función TestNumero() que acompaño con una rutina como esta:

select mITabla
SCAN
FOR i=1 to Fcount()
LcCampo=Fields(i)
lncValor=ALLTRIM(Eval(lcCampo))
if TestNumero(lncValor)
nValor=ROUND(VAL(lncValor),2)
replace (lcCampo) with Transform(nvalor,"999,999.99")  && aquí escribe el formato ok.
endif
NEXT
ENDSCAN
GO TOP
BROWSE
**************************
function TEstNumero(xcValor)
**************************
* xcValor es un String que puede ser un número
* Devuelve Verdadero ó Falso
***********************************************
local nlen,i_,lNumero
if vartype(xcValor)#"C".or.empty(xcValor)
return .f.
endif
nlen=len(xcValor)
* Posible Numero negativo
if nlen>1
if left(xcValor,1)="-"
xcValor=substr(xcValor,2)
nlen=len(xcValor)
endif
endif
* Se acepta un solo punto decimal
if Occurs(".",xcValor)>1
return .f.
endif
lNumero=.t.
for i_ =1 to nlen
if !inlist(substr(xcValor,i_,1),"0","1","2","3","4","5","6","7","8","9",".")
lNUmero=.f.
exit
endif
next

return lNumero
ENDFUNC

FidelJ

unread,
Nov 9, 2012, 5:23:06 PM11/9/12
to publice...@googlegroups.com
En esta variante, siempre que el append from lo hagas sobre una Tabla (no un cursor), la rutina detecta qué columnas contienen números, agrega columnas con N(12,2) y elimina las columnas originales.
La determinación de qué columnas contienen números se hace con la función TestNumero()

* Nota; ver el path de la tabla para ALTER TABLE addbs(ruta)+mitabla
**********************************************************************************
LOCAL lcnValor,lcCampo,i,cAdd,cDrop
select mITabla
APPEND FROM etc

LOCAL ARRAY gacol(1)  && en el Array indico qué columnas contienen números.
nc=0
select mITabla
SCAN
FOR i=1 to Fcount()
LcCampo=Fields(i)
lncValor=ALLTRIM(Eval(lcCampo))
if TestNumero(lncValor)
IF ASCAN(gacol,i)=0
nc=nc+1
DIMENSION gacol(nc)
gacol[nc]=i
ENDIF
nValor=ROUND(VAL(lncValor),2)
replace (lcCampo) with LTRIM(STR(nValor,14,2))  
endif
NEXT
ENDSCAN
IF nc#0
        Store "" TO cAdd, cDrop

FOR i=1 TO ALEN(gacol)
cAdd=cAdd+[ADD COLUMN "NWCAMPO]+LTRIM(STR(I))+[" N(12,2)]
cDrop=cDrop+[DROP COLUMN ]+FIELDS(gacol[i])+" "
NEXT
IF !EMPTY(cAdd)
SELECT mitabla
USE
ALTER TABLE mitabla &cAdd
SELECT mitabla
SCAN
FOR i=1 TO ALEN(gacol)
lcCampo="NwCampo"+LTRIM(STR(i))
nFields=gacol[i]
lcValor=ALLTRIM(EVALUATE(Fields(nFields)))
replace (lcCampo) WITH VAL(lcValor)
NEXT
ENDSCAN
ENDIF
IF !EMPTY(cDrop)
SELECT mitabla
USE
ALTER table mitabla &cDrop
endif
ENDIF
SELECT MITABLA

ultraton500

unread,
Nov 10, 2012, 12:43:51 AM11/10/12
to publice...@googlegroups.com
Qué tal Marlon, los campos están declarados con 80 caracteres y son muchos menos los decimales que aparecen (unos 14).
De todas formas lo que busco es que solo se muestren dos dígitos decimales, el problema no es que no se alcanzan a mostrar todos.
Gracias de todas formas.
Saludos,
Javier.

Walter R. Ojeda Valiente

unread,
Nov 10, 2012, 12:45:53 AM11/10/12
to publice...@googlegroups.com
¿Y no puedes obtener más datos de las celdas?

Por ejemplo, con la función VARTYPE() podrás saber si es de tipo caracter o de tipo numérico.

Saludos.

Walter.

"Si puedes razonar con gente religiosa, no son gente religiosa". Dr. House




Date: Fri, 9 Nov 2012 21:43:51 -0800
From: ultra...@gmail.com
To: publice...@googlegroups.com
Subject: Re: [vfp] Re: Problemas con decimales en importación desde Excel
--
 
 
 

ultraton500

unread,
Nov 10, 2012, 12:52:00 AM11/10/12
to publice...@googlegroups.com
Hola Fidel, gracias por la rutina y la función.
Como uso un cursor probé las primeras pero el problema persiste.
No he tenido tiempo de investigar al respecto pero en cuanto lo vea te comento.
Agradezco el tiempo dedicado a ayudarme.
Saludos ocrdiales,
Javier.

ultraton500

unread,
Nov 10, 2012, 1:01:40 AM11/10/12
to publice...@googlegroups.com
Hola Walter, hago la importación desde una tabla de Excel a un cursor creado en el Init cuyos campos son todos de tipo character. Por lo tanto los valores numéricos quedan expresados como character y ahí es donde algunos de ellos pasan de tener 2 decimales en la tabla de Excel a tener unos 13 o 14 en el cursor.
Lo que no entiendo es porqué la mayoría conserva los 2 decimales y otros lo extienden a muchos mas.
Saludos y gracias por la sugerencia.
Javier.

FidelJ

unread,
Nov 10, 2012, 7:46:44 AM11/10/12
to publice...@googlegroups.com
De acuerdo. 
Puedes utilizar igualmente el cursor. Hay un Warning en la ayuda al respecto, de dice que respecto de cursores creados con CREATE CURSOR, puede producir resultados no consistentes.
En la prueba que realizo para testear la rutina, funciona con cursor sin inconvenientes.
"Therefore, you should generally avoid using ALTER TABLE with Visual FoxPro cursors unless you have tested and understood the outcome." O sea, hay que testear el caso particular. 

Walter R. Ojeda Valiente

unread,
Nov 10, 2012, 7:52:06 AM11/10/12
to publice...@googlegroups.com
Vaya, en todas mis aplicaciones uso mucho CREATE CURSOR y también ALTER TABLE y jamás encontré algún inconveniente.


Saludos.

Walter.

"Si puedes razonar con gente religiosa, no son gente religiosa". Dr. House




Date: Sat, 10 Nov 2012 04:46:44 -0800
From: fjch...@gmail.com
To: publice...@googlegroups.com
Subject: [vfp] Re: Problemas con decimales en importación desde Excel
--
 
 
 

ultraton500

unread,
Nov 11, 2012, 1:52:07 PM11/11/12
to publice...@googlegroups.com


El viernes, 9 de noviembre de 2012 14:51:47 UTC-6, FidelJ escribió:

ultraton500

unread,
Nov 11, 2012, 2:08:15 PM11/11/12
to publice...@googlegroups.com
Hola Fidel, sin querer abusar de tu generosidad quisiera pedirte si me puedes hacer el favor de hacer la prueba con la misma tabla que intento importar.
Para eso te adjuinto la tabla, el form y la función para que, en solo un par minutos, puedas comprobar si las columnas 3,4 y 5 contienen o no algunos valores con mas de 2 decimales como me sucede a mi.
De mas está decir que te agradeceré mucho el favor.
Saludos,
Javier.
IMPORTAR LISTA.rar

Jhonny Zambrana

unread,
Nov 11, 2012, 8:18:09 PM11/11/12
to publice...@googlegroups.com
Por alguna arzon la funcion TestNumero siempre devuelve F. seguire viendo y haber como te ayudo...

Jhonny Zambrana

unread,
Nov 11, 2012, 8:55:57 PM11/11/12
to publice...@googlegroups.com
Hola nuevamente Yo, haber si esto te sirve, logre que todos ingresen en modo texto con tres decimales, lo hice con tres por que algunos precios en la tabla excel trae tres decimales.
No es de lo mas ortodoxo pero creo que sirve..
 
Un abrazo
IMPORTAR LISTA1.rar

Jhonny Zambrana

unread,
Nov 11, 2012, 11:29:39 PM11/11/12
to publice...@googlegroups.com
Bueno ahora si creo que ya quedo espero te sirva, de seguro hay muchas cosas que cambiar y mejorar.
 
Un abrazo y que estes bien..
IMPORTAR LISTA2.rar

ultraton500

unread,
Nov 12, 2012, 1:09:17 AM11/12/12
to publice...@googlegroups.com
Que tal Johny, valoro y agradezco mucho tu esfuerzo para darme una mano con esto.
Veo que lo que haces es cambiar el tipo de dato a los campos que el usuario identifica como numéricos. 
La intención del form es que el usuario seleccione el archivo a importar y luego lo visualice para identificar e indicar (mediante unos combos) cuál es la columna del código, de la descripción, del costo y del precio.
Una vez indicadas puede clickear el botón que actualiza la tabla de artículos del sistema, en donde una de las 1ras. cosas que se hace es convertir los campos del costo y del precio a N(12,2).

Por lo que la idea es mostrarle al usuario la tabla a importar con el problema ya corregido en lugar de darle la forma de corregirlo. Por eso es que la función de Fidel detecta cuáles son los campos numéricos para cambiarles el formato sin intervención del usuario.
Te agradezco nuevamente por la ayuda.
Saludos cordiales,
Javier.

Robert Martínez

unread,
Nov 12, 2012, 8:58:02 AM11/12/12
to publice...@googlegroups.com
Saludos,

Prueba ese procedimiento, solo tienes que pegarlo en un prg vacio y ejecutarlo, si crees que te puede ser util es facil de adaptar a tu formulario.


*** Inicio Procedimiento
Local xlsName, dbfname, cpNum

*** Seleccionar Archivo XLS
xlsName = Getfile('XLS','Seleccionar')
If Empty(xlsName)
    Return .F.
Endif

Local cConn, cTAbla, cCursor

*** Preparar el Driver ODBC
cConn = "Driver={Microsoft Excel Driver (*.xls)};"+;
    "DriverId=790;Dbq="+xlsName+;
    ";DefaultDir="+Justpath(xlsName)+";"

*** Conectando al Libro de XLS
nH = Sqlstringconnect(cConn)

*** Cargando las hojas que tiene el libro
SQLTables(nH,"", "SheetNames")

** Selecciono la primera hoja del Libro XLS
Select SheetNames
If Reccount()>0
    Go Top
Endif

** Cargar filas y columnas de la hoja seleccionada
cTAbla = Trim(SheetNames.Table_Name)
cCursor = Chrtran(cTAbla," $","_")
lok = SQLExec(nH,'Select * From ['+cTAbla+']','curTMPXLS') > 0


If lok
    ** Desconectar del libro XLS
   SQLDisconnect(nH)

    Use In  SheetNames
    ** Rehacer cursor XLS con Número de Fila.
    Select Recno() As fila, * From curTMPXLS Into Cursor curTMPXLS

    ** Convertir algunos campos memos del cursor a Caracter
    Select curTMPXLS

    Afield[campos]
    For N=1 To Alen(campos,1)
        If campos[n,2]= 'M'
            cmdExec = Textmerge("CALCULATE MAX( LEN(<<campos[n,1]>>)) TO llong")
            &cmdExec
            campos[n,2]='C'
            campos[n,3]=lLong
            campos[n,4]=0
        Endif
    Endfor
    Create Cursor curImported From Array campos

    Select curImported
    Append From Dbf('curTMPXLS')
    GO top
    Use In curTMPXLS
    Release campos
   
   
    Select curImported
    BROWSE NOWAIT

ELSE
    SQLDisconnect(nH)
    Messagebox(aErrorArray[2],16,'Error..')
    RETURN .f.
Endif

*** Fin Procedimiento
Message has been deleted

Jhonny Zambrana

unread,
Nov 12, 2012, 10:36:40 AM11/12/12
to publice...@googlegroups.com
Ok. no hay problema, solo como comentario decirte que ami en muchas pruebas el TestNumero me salta o pasa por alto en especial en las columnas 4 y 5, asi que seria bueno enfatizar unpoco en eso.
 
Un abrazo y que estes bien.
 
El lunes, 12 de noviembre de 2012 02:09:17 UTC-4, ultraton500 escribió:

FidelJ

unread,
Nov 12, 2012, 10:51:20 AM11/12/12
to publice...@googlegroups.com

Ultraton:
Te envío tu formulario con algunas modificaciones. Ahora TestNUmero es un método del form. Thisform.TestNUmero(), por lo que ya no necesitas la función. 
Corregí los NwCampo y el único problema es el número de BarCode que se podría filtrar o no.
Fijate que Valor como Variable pública no vale la pena. Generé una propiedad llamada valor y la puse como controlSource dele text1, que también lo puse como Enabled=.f.

Suerte.

El jueves, 8 de noviembre de 2012 16:09:18 UTC-3, ultraton500 escribió:
IMPORTAR.ZIP

ultraton500

unread,
Nov 13, 2012, 11:13:55 AM11/13/12
to publice...@googlegroups.com
Hola Robert, claro que me es útil, funciona perfectamente. Lo voy a revisar con mas detalle para adaptarlo a mi formulario.
Te agradezco mucho por por tu ayuda.
Saludos,
Javier.

ultraton500

unread,
Nov 13, 2012, 12:12:07 PM11/13/12
to publice...@googlegroups.com
Fantástico Fidel, tengo para aprender mucho de las mejoras que has hecho. Ahora si me funciona bien, solo le haré una pequeña reforma para evitar que convierta a números el campo del código.
Te estoy muy agradecido por tu ayuda.
Saludos,
Javier.
Reply all
Reply to author
Forward
0 new messages