Como usar JavaScript o VBScript como lenguaje de "macros" en VFP

1,281 views
Skip to first unread message

Victor Espina

unread,
Feb 10, 2012, 9:38:14 AM2/10/12
to publice...@googlegroups.com
Hoy me encontre esto y me parecio super interesante. Es un articulo que explica como ejecutar codigo JScript o VBScript desde VFP, logrando incluso que ese codigo manipule objetos de VFP.

Lo interesante de esto es que si se abstrae el ambiente correctamente, es posible escribir un "macro" de JScript o VBScript que ejecute no solo en nuestra app VFP sino en cualquier otro lenguage donde podamos replicar el ambiente basico y ejecutar JScript o VBScript.

Aca les dejo el link:

Saludos

Victor Espina

Marco Plaza

unread,
Feb 10, 2012, 9:57:59 AM2/10/12
to Comunidad de Visual Foxpro en Español

Ciertamente Víctor, de hecho el Script Object permite obtener acceso a
todo el poder de JavaScript/VbScript desde Vfp. Se basa en mapear
objetos de Vfp al objeto de Javascript para luego ejecutar el código.

Aquí te paso un programa completamente funcional que te permite ver
como funciona el concepto. ( no es mío, no recuerdo de donde lo bajé )

http://db.tt/gpKipnRg

Saludos

Marco

Douglas Sánchez Guillén

unread,
Feb 11, 2012, 1:20:57 AM2/11/12
to publice...@googlegroups.com
Gracias Marcos esta deacachimba el ejemplo gracias por compartirlo funciona de pelos...
saludes
Douglas
--
Ing. Douglas Sánchez Guillén
      Consultor Informatico
Movistar: 505 8759 - 5342
Claro: 505 88495476

joaquinlr lopez

unread,
May 12, 2014, 12:07:14 PM5/12/14
to publice...@googlegroups.com
Marco, puedes enviarme el ejemplo, me gustaria ver un ejemplo concreto.
joaq...@hotmail.com
Gracias.

extremo

unread,
May 12, 2014, 12:21:48 PM5/12/14
to publice...@googlegroups.com
ejemplo de javascript en VFP

Local loScriptlcCode

* Instancio el Microsoft Script Control
loScript = CreateObject("MSScriptControl.ScriptControl.1")

* Indico que el script a ejecutar será en Javascript
loScript.Language = "Javascript"

* Agrego la referencia al desktop de VFP (objeto _Screen)
loScript.AddObject("VFPDesktop"_Screen)

* Escribo el código JScript en una variable
Text To lcCode Textmerge NoShow
    var i, cCaption = "Esto lo hizo Javascript";
    VFPDesktop.Caption = cCaption;
    VFPDesktop.Cls();
    for(i=1;i<=10;i++)
        VFPDesktop.Print( "Iteración FOR en Java Nº" + i + "\n\r" );

EndText

* Finalmente, ejecuto el script
loScript.ExecuteStatement(lcCode)

Bendiciones

Victor Espina

unread,
May 12, 2014, 12:50:16 PM5/12/14
to publice...@googlegroups.com
Excelente!!  No conocia el metodo AddObject().   Muy claro el ejemplo.  


Gracias

Victor Espina

Mario López

unread,
May 12, 2014, 8:12:37 PM5/12/14
to publice...@googlegroups.com
@Victor: yo uso algo bastante similar para Python, mi código VFP queda algo así como

DEFINE CLASS ActionDownloadFromFTP as xAction
    Description = "Descarga los archivos de lecturas desde el servidor FTP de <Empresa X>"

    PROCEDURE Do

    ClearStatus()
    AddStatus(This.Description + REPLICATE(CRLF, 2))

    Python
        import ftplib
        import config
        import os
        global f

        ftp = ftplib.FTP(config.ftp_server, config.ftp_user, config.ftp_pwd)
        ftp.cwd(config.ftp_dir_download_itin)
        for name in ftp.nlst():
            if name.startswith("."):
                continue

            self.report (name, nocrlf=True)
            # if re.match(config.ftp_itin_filter, name):
            if self.file_is_ok(name):
                self.report ("descargando...", nocrlf=True)

                if not config.ftp_no_download:
                    file_ = os.path.join(config.ftp_local_dir, name)
                    if not os.path.exists(file_):
                        f = open(file_, "wb")
                        ftp.retrbinary("RETR %s" % name, lambda block: f.write(block))
                        # self.report(f)
                        f.close()
                    else:
                        self.report ("ya descargado", nocrlf=True)
                else:
                    self.report ("ftp_no_dl", nocrlf=True)

                self.report()
            else:
                self.report("Of.Com %s no descargado" % name[:4] )

        ftp.quit()
    EndPython

    AddStatus("Descarga finalizada")

    ENDPROC
ENDDEFINE

Y todo lo que está entre Python / EndPython se envía a un servidor COM Python que se ejecuta
asincrónicamente y va reportando el estado de vuelta a VFP con self.report(xxx). De esta forma
puedo usar un montón de cosas de Python que vienen incluidas en la librería estándar o ya están
desarrolladas sin complicarme de más con VFP (ej: manejo de Bluetooth, FTP, archivos .ZIP,
servidor web, ... etc)


Saludos,
Mario
---

Victor Espina

unread,
May 13, 2014, 9:12:06 AM5/13/14
to publice...@googlegroups.com
Y como haces para que el compilador de VFP entienda el bloque PYTHON / ENDPYTHON ?

Mauricio R. Molinero

unread,
May 13, 2014, 3:03:31 PM5/13/14
to publice...@googlegroups.com
Modificando la rutina de errores supongo, porque mas, no hay.

Saludos!

Mauricio R. Molinero,

Mauricio R. Molinero

unread,
May 13, 2014, 3:24:00 PM5/13/14
to publice...@googlegroups.com
Lo mismo se podría haber hecho para simular TRY..ENDTRY no?

Saludos!

Mauricio R. Molinero,

Victor Espina

unread,
May 13, 2014, 4:24:14 PM5/13/14
to publice...@googlegroups.com
Justo por eso pregunte como lo hizo. :)

joaquinlr lopez

unread,
May 14, 2014, 3:12:06 AM5/14/14
to publice...@googlegroups.com
Es posible crear con javascript un metodo a un objeto Vfp y luego utilizar ese metodo en la secuencia de Vfp ?

Es decir:

1. En Vfp creo un objeto con sus propiedades, metodos y eventos
2. En un momento dado deseo agregar un metodo a ese objeto (al vuelo),
    Creo una rutina con MsScriptControl, agrego metodo con javascript y ejecuto
     el comando ExecuteStatement.
3. Ya esta creado el metodo en el objeto Vfp
4. Ahora quiero dejar en ejecucion ese metodo para el usuario (click, interactivechange, .. etc.)

Como hacerlo ?

Mario López

unread,
May 14, 2014, 8:38:32 AM5/14/14
to publice...@googlegroups.com
@Victor / Mauricio: esperé un poco para darle más suspenso al truco :)


#define Python        TEXT TO _PyExec.Text TEXTMERGE NOSHOW
#define EndPython    ENDTEXT

SET TEXTMERGE DELIMITERS TO "<<"">>"

CLEAR

* _Python = CREATEOBJECT("Python.PyServer1")        && Mi servidor COM Python
_PyExec = CREATEOBJECT("PyExec")            && El objeto "ejecutor", global

Python
    print("Hello from Python!!!!")
    self.report("Hello VFP <<_VFP.Version>> from Python")
EndPython

RETURN



DEFINE CLASS AssignExecutor AS Line
    Text = ""


    * El "truco": al asignar algo a _PyExec.Text se llama a _PyExec.Execute con
    * el texto como parámetro
    PROCEDURE Text_Assign(sText)
    This.Text = sText
    This.Execute(sText)
    RETURN This


    PROCEDURE Execute(sText)
    RETURN
ENDDEFINE


DEFINE CLASS PyExec AS AssignExecutor
    PROCEDURE Execute(sPyCode)
    ? "Acá ejecutaría:"
    ? sPyCode
    * _Python.execute(sPyCode)         && Llamo a mi servidor COM Python con el código a ejecutar
    ENDPROC
ENDDEFINE


***


Este "patrón" de ejecución lo uso bastante, incluso para instrucciones SQL VFP complejas, donde
con el debug activado guardo la instrucción SQL y el resultado de la misma para verificar posibles
errores.

Saludos,
Mario
---

Mauricio R. Molinero

unread,
May 14, 2014, 9:11:04 AM5/14/14
to publice...@googlegroups.com
Hola Mario,

Muy bueno el truco!, (siempre me olvido de las constantes esas..)

Para tener en cuenta la combinación del TEXTMERGE con el objeto publico.

Pregunta, tenes algún modulo compilado para poder usar Python fácil? o hay que instalarlo cada vez.
Pregunto por tema de distribución sobre todo.

Deberíamos trabajar esto un poco mas, (o compartir lo que tengas :D)

Saludos!

Mauricio R. Molinero,

Victor Espina

unread,
May 14, 2014, 9:12:09 AM5/14/14
to publice...@googlegroups.com
Mario, que manejo tan inteligente de las constantes.  Excelente!!!   No sabia que a una constante podia asignarsele una instruccion VFP.  En verdad, excelente idea.


Victor Espina

ZeRoberto

unread,
May 14, 2014, 9:53:49 AM5/14/14
to publicesvfoxpro
Veo que das muchas vueltas para algo simple.

Mario López

unread,
May 14, 2014, 9:54:06 AM5/14/14
to publice...@googlegroups.com
@Mauricio:


>> Pregunta, tenes algún modulo compilado para poder usar Python fácil? o hay que instalarlo cada vez.
>> Pregunto por tema de distribución sobre todo.

Si te referís a la instalación de Python, en general copio la carpeta PythonXX directamente y asocio los
archivos .py / .pyw con python.exe | pythonw.exe, por ejemplo, para Python 2.7 copio toda la carpeta
C:\Python27 de mi PC y asocio los archivos con:

assoc .py=pyfile
ftype pyfile=c:\Python27\python.exe %1
...

También se puede instalar directamente Python con el instalador .MSI de https://www.python.org/downloads/

Yo hago esto porque tengo las librerías estándar que uso en mi C:\Python27\..., en realidad con múltiples
proyectos y librerías muy distintas habría que usar virtualenv, pero eso es para un foro de Python :)


>> Deberíamos trabajar esto un poco mas, (o compartir lo que tengas :D)

En realidad crear un servidor COM en Python son 20 líneas, fijate en
http://showmedo.com/videotutorials/video?fromSeriesID=219&name=2190050

Básicamente mi servidor.COM es como el del ejemplo, solamente agrega métodos para reportar estados
a VFP vía un archivo intermedio, entonces cuando ejecuto self.report("algo") en Python lo agrega
al archivo .log que se levanta desde VFP. 

Cualquier duda puntual podés consultar en este thread o crear uno nuevo (me parece que no es del todo Off Topic
para VFP ya que estamos hablando de usar el servidor COM Python desde VFP).

Saludos,
Mario
---

Mario López

unread,
May 14, 2014, 10:35:52 AM5/14/14
to publice...@googlegroups.com
@Victor:

es que en realidad hay que tomar a define como #define una instrucción de preprocesador, si la vemos
solamente como una instrucción para definición de constantes este tipo de cosas no se podría hacer :)

SET NOSTALGIC MODE ON

De hecho sería muchísimo mejor si fuera como el preprocesador de Clipper, donde casí se podía
definir un lenguaje nuevo con el mismo:

---
#xcommand SELECT <fields,...> FROM <alias,...> ;
                [ ORDER BY <order,...> ];
                [ WHERE <join> ] ;
                [ HAVING <for> ] ;
                [ KEY <key,...> ] ;
                [ INTO ARRAY <array> [<add: ADDITIVE>] ]  => ;
                ;
          _SQLSelect ([@<array>], { <{fields}> }, { <"alias"> },;
                { || .T. [.AND. <for> ] [.AND. <join> ] }, { [ <{key}> ] }, ;
                { [ <order> ] }, <.add.> )
---

qué tiempos aquellos! :)

SET NOSTALGIC MODE OFF

Saludos,
Mario
---

ZeRoberto

unread,
May 14, 2014, 11:18:59 AM5/14/14
to publicesvfoxpro
Te refieres a la librería Class(y) que permitía manejar objetos en clipper?

Carlos Miguel FARIAS

unread,
May 14, 2014, 11:50:22 AM5/14/14
to Grupo Fox
Clipper es compilado, VFP es pseudocompilado, cuando toma una #DEFINE, reemplaza el rótulo por lo que tenga asociado.
De hecho, podrías tomar todas las sentencias de vfp, y asociandole un #DEFINE con la sentencia vfp que quieras y luego codificas usandos esos "alias" y no el código vfp original

#DEFINE SI IF
#DEFINE SINO ELSE
#DEFINE FINSI ENDIF

SI A>B
   bla bla
SINO
  bla bla
FINSI

Funciona!!!!
Saludos: Miguel, La Pampa (RA)

Victor Espina

unread,
May 14, 2014, 11:52:21 AM5/14/14
to publice...@googlegroups.com
Si, es cierto Mario.  Yo una vez "converti" a un fanatico de Clipper a VFP, y en lo unico que no pude ganarle fue en el tema del manejo de #DEFINE en clipper.  Increible las cosas que se podian hacer ahi con eso.


Victor 

ZeRoberto

unread,
May 14, 2014, 11:55:05 AM5/14/14
to publicesvfoxpro
La diferencia es que en clipper con Class(y) podías crear comandos nuevos, por ejemplo yo creaba mis DEFINE WINDOWS etc, etc pero acá en fox no tiene sentido solo es para cambiarle el nombre a los ya existentes.

Mario López

unread,
May 14, 2014, 2:06:16 PM5/14/14
to publice...@googlegroups.com
@Victor:

>> en lo unico que no pude ganarle fue en el tema del manejo de #DEFINE en clipper.  Increible las cosas que se podian hacer ahi con eso.

El manejo de arrays también era excelente (pero limitado en tamaño a arrays de 4096 elementos), también fué un lenguaje pionero en el uso de los codeblocks (en Python serían lambdas) y hasta soportaba una especie de programación orientada a objetos (no heredables, salvo con Class(y) si la memoria no me falla).

Lástima que -para mí- nunca tuvo nada que hacer al lado de FoxPro DOS con la velocidad de procesamiento de tablas, ni hablar de la falta de comandos SQL nativos (SELECT, DELETE, etc), solamente los comandos xBase. Aclaro que mi última experiencia fué con Clipper 5.2, apenas probé Harbour u otros compiladores, no sé cuál sea el estado actual de los mismos.

Saludos,
Mario
---

Mario López

unread,
May 14, 2014, 2:20:35 PM5/14/14
to publice...@googlegroups.com
@Ze Roberto:

no, me refería al preprocesador, el #xcommand que puse en mi post es de un programa mío real en Clipper,
y te permitía armar comandos como :

        SELECT PROPLAN->PLFECHA, PROPUESTA->PPNUMERO ,;
                PROPUESTA->PPFECHAI, PROPUESTA->PPGRUPO, PROPUESTA->PPORDEN,;
                PERSONA->CCNOMBRE, PADR(PROPUESTA->DEMARCA,8)+" "+PADR(PROPUESTA->DEMODELO,8),;
                PADR(UNIDAD->MOMARCA,8)+" "+PADR(UNIDAD->MOMODELO,8)+" "+UNIDAD->MOANIO,;
                PROPLAN->PLIMPORTE, ;
                ;
                PROPUESTA->PPTIPO ,;
                IIF(EMPTY(PROPLAN->PLFECHA),wdmaximo,PROPLAN->PLFECHA) ;
                ;
            FROM  PROPUESTA, PERSONA, PROPLAN, UNIDAD ;
            ;
                HAVING EVAL(wbfiltro);
            ;
                WHERE PROPUESTA->PPNUMERO==PROPLAN->PPNUMERO .AND.;
                        PERSONA->(CCTIPO+CCNUMERO)==PROPUESTA->(CCTIPO+CCNUMERO) .AND. ;
                        UNIDAD->(UNTIPO+STR(UNNUMERO,6))==PROPUESTA->(USTIPO+STR(USNUMERO,6)) ;
            ;
                KEY wslis_clave, PROPUESTA->(CCTIPO+CCNUMERO),;
                        STR(PROPUESTA->PPNUMERO,6), PROPUESTA->(USTIPO+STR(USNUMERO,6)) ;
            ;
                ORDER BY 10,11 ;
            ;
                INTO ARRAY vxarray

La librería Class(y) no la usé, solamente usé la OOP de Clipper en el sistema de Read/Get y en el Browse,
si me acuerdo bien.

Saludos,
Mario
----
Reply all
Reply to author
Forward
0 new messages