30 de agosto de 2010

Formas de conectarse a un Servidor SQL

La primera, según mi experiencia, es la forma mas rápida de conectarse, también depende como esten planteando el sistema. Ésta al ser la "mas rápida", puede usarse para que cada vez haga una consulta.
La segunda puede plantearse al iniciar el programa, y las consultas se hacen sobre esa conexión pero no se vuelve a crear por cada consulta

La tercera, igual que la segunda, la ventaja de esta es que no es necesario declarla en ODBC

La primera
***************************
oConn  = createobject('ADODB.Connection')
cConnString="Provider=SQLOLEDB.1;Persist Security Info=False;User ID="+ALLTRIM(lc_usuario_)+";Pwd="+ALLTRIM(lc_password)+";Initial Catalog="+ALLTRIM(lc_nombre)+";Data Source="+ALLTRIM(lc_sname)
oConn.Open(cConnString)
oRS = CREATEOBJECT("ADODB.Recordset")
oRS.ActiveConnection = oConn
oCA=CREATEOBJECT("CursorAdapter")
oCA.DataSourceType = "ADO"
oCA.DataSource = oRS
oCA.MapBinary = .T.
oCA.MapVarchar = .T.
oCA.SelectCmd = "select * from empleados"  && ejemplo
IF !oCA.CursorFill()
  LOCAL laError
  DIMENSION laError[1]
  AERROR(laError)
  MESSAGEBOX(laError[2])
ELSE
  ********** lo "capturo" en un cursor para manipularlo en modo local
  loAlias=ALIAS()
  cMacro1="SELECT * FROM "+loAlias+" INTO CURSOR "+ loCursor +" readwrite"
  &cMacro1
  WAIT windows "Procesado "+loCursor NOWAIT
ENDIF 
*****************************************************************

La segunda, Atravez de ODBC
lc_sql=SQLCONNECT("localdb","simio","fantasiA") && localdb tiene que estar creado en odbc solapa usuarios
if m.lc_con < 0
  nopc=MESSAGEBOX("No se pudo conectar , talvez ODBC no este configurado",0+48,"Error")
  RETURN .f.
endif 
****************************************

La tercera, conectar usando los drivers de ODBC (no es necesario crear una conexion en ODBC)
lcStringConn="Driver={SQL Server}"+";Server="+lc_IPSQL+";Database="+lc_nombre+";Uid="+lc_usuario_+";Pwd="+lc_password
***Evitar que aparezca  la ventana de login 
SQLSETPROP(0,"DispLogin",3)
SQLSETPROP(0,"IdleTimeout",0)
lc_con=SQLSTRINGCONNECT(lcStringConn)
if m.lc_con < 0  &&  nose pudo conectar
  wait windows "no conecta"
endif 
****************************************

Carlos [caremi66]

28 de julio de 2010

Autogenerar Report mejorando presentacion

En muchas ocasiones me surgía la necesidad de realizar un listado sencillo, a partir de una pequeña tabla o cursor, lo que me obligaba a diseñar e incluir en mis proyectos, numerosos 'reports', cuya utilidad no era excesivamente importante.

Siempre había descartado la opcion "CREATE REPORT FROM 'filename' ", porque el resultado tenía una apariencia demasiado rustica.

Todo esto me terminó por decidir a intentar desarrollar una rutina que, tras generar un report automático desde una tabla o cursor, mejorase algo su presentación. No pretendo obtener un resultado espectacular ni incluir un monton de opciones y posibilidades, sino solo conseguir un report con un aspecto presentable.

A la rutina siguiente, solo es necesario pasarle 2 parametros, el nombre de la tabla o cursor, a partir de la cual se generará el report, y un título para el listado.

Los campos se presentarán en el orden en que aparezcan en la tabla o cursor.

Esta es la rutina:
**************************************************************
* Autogeneracion de un listado (report rapido) partiendo de un
* cursor o tabla.
* Se autoajusta fuente, tamaño y nº de columnas a mostrar
*
* Parametros: cCursor --> Nombre del cursor/tabla origen
*                    cTitulo --> Titulo para el listado
*
* Ej: do autorepo with "micursor", "Titulo del Listado"
*
****************************************************************
LPARAMETERS cCursor, cTitulo
*
LOCAL cRepo, nLong, sFont, cFont, cCampos, nMaxCol, sExtra

cRepo = SYS(2015) + '.frx'
*
IF VARTYPE(cCursor) # 'C'
  WAIT WINDOW "Faltan Datos"
ENDIF
IF VARTYPE(cTitulo) # 'C'
  cTitulo = ''
ENDIF

cFont = 'Calibri'  && Fuente de letra a usar
nMaxCol = 225      && Nº máximo de columnas (depende de fuente)
nLong = 0
cCampos = ''

* Establecer anchura, limites y tamaño fuente
nCampos = AFIELDS(aCampos, cCursor)
FOR xx = 1 TO nCampos
  nLong = nLong + aCampos(xx, 3)
  IF nLong > nMaxCol
    cTitulo = cTitulo + '    ***'
    EXIT
  ELSE
    IF EMPTY(cCampos)
      cCampos = cCampos + aCampos(xx,1)
    ELSE
      cCampos = cCampos + ', ' +aCampos(xx,1)
    ENDIF
  ENDIF
ENDFOR

* Ajusto tamaño de fuente depende long. datos
* 'sExtra' para ajustar campos (depende de ver. VFP)
DO CASE
  CASE nLong > 190
    sFont = 7
    sExtra = IIF(VERSION(5) / 100 = 9, 120, -320)

  CASE nLong > 160
    sFont = 8
    sExtra = IIF(VERSION(5) / 100 = 9, 200, -170)

  CASE nLong > 135
    sFont = 9
    sExtra = IIF(VERSION(5) / 100 = 9, 360, -110)

  OTHERWISE
    sFont = 10
    sExtra = IIF(VERSION(5) / 100 = 9, 450, 180)
ENDCASE

* Crear un report y pasar a realizar ajustes
CREATE REPORT (cRepo) FROM DBF(cCursor) FIELDS &cCampos COLUMN WIDTH 256
*
USE (cRepo) IN 0 ALIAS mirepor EXCL
SELECT mirepor
*
* Cambiar texto 'Page' por 'Página' en caso de runtime en ingles
REPLACE EXPR WITH ["Página "] FOR ALLTRIM(EXPR) = ["Page "] IN mirepor
*
* Cambiar la fuente para todos 'labels' y 'campos'
REPLACE ALL fontface WITH cFont FOR INLIST(objtype, 5, 8)

* Cambiar tamaño fuente y estilo para 'labels' encabezado columnas
REPLACE ALL FONTSIZE WITH sFont, fontstyle WITH 3  FOR objtype=5 AND Vpos=0 IN mirepor

* Reducir tamaño fuente para todos 'campos'
REPLACE ALL FONTSIZE WITH sFont - 1  FOR objtype = 8

* Cambiar tamaño fuente y estilo para 'labels' y 'campos' del pie de pagina
REPLACE FONTSIZE WITH sFont - 1, fontstyle WITH 2 FOR ALLTRIM(EXPR) = [DATE()] IN mirepor
REPLACE FONTSIZE WITH sFont - 1, fontstyle WITH 2 FOR ALLTRIM(EXPR) = ["Página "] IN mirepor
REPLACE FONTSIZE WITH sFont - 1, fontstyle WITH 2 FOR ALLTRIM(EXPR) = [_PAGENO] IN mirepor
*
* Añadir línea separación en pie de pagina
GOTO TOP
LOCATE FOR ALLTRIM(mirepor.EXPR) = [_PAGENO]
miW = mirepor.hpos + mirepor.WIDTH + 100
miV = mirepor.Vpos -100
*
APPEND BLANK IN mirepor
REPLACE mirepor.objtype WITH 6
REPLACE mirepor.Vpos WITH miV
REPLACE mirepor.WIDTH WITH miW
REPLACE mirepor.HEIGHT WITH 105
REPLACE mirepor.penpat WITH 8
REPLACE mirepor.supalways WITH .T.
REPLACE mirepor.platform WITH 'WINDOWS'
*
* Añadir línea separación en encabezado
GOTO TOP
LOCATE FOR mirepor.objtype=5 AND mirepor.Vpos=0
*
miV = mirepor.Vpos + mirepor.HEIGHT
*
APPEND BLANK IN mirepor
REPLACE mirepor.objtype WITH 6
REPLACE mirepor.Vpos WITH miV
REPLACE mirepor.WIDTH WITH miW
REPLACE mirepor.HEIGHT WITH 105
REPLACE mirepor.penpat WITH 8
REPLACE mirepor.supalways WITH .T.
REPLACE mirepor.platform WITH 'WINDOWS'
*
* Mover todo hacia abajo, para colocar titulo
IF !EMPTY(cTitulo)
  *
  extra = 4000 && Altura para el titulo
  GOTO TOP
  REPLACE ALL Vpos WITH Vpos + extra FOR INLIST(objtype, 5, 6, 8) IN mirepor
  REPLACE ALL HEIGHT WITH HEIGHT + extra FOR objcode = 1 IN mirepor
  *
  * Añadir Titulo
  APPEND BLANK IN mirepor
  REPLACE mirepor.platform WITH 'WINDOWS'
  REPLACE mirepor.objtype WITH 5
  REPLACE mirepor.hpos WITH 100
  REPLACE mirepor.fontface WITH cFont
  REPLACE mirepor.fontstyle WITH 4
  REPLACE mirepor.FONTSIZE WITH 16
  REPLACE mirepor.WIDTH WITH 70000
  REPLACE mirepor.HEIGHT WITH 2800
  REPLACE mirepor.supalways WITH .T.
  REPLACE mirepor.EXPR WITH ["&cTitulo"]
  REPLACE mirepor.mode WITH 1
  *
ENDIF
*
* Ajustar 'labels' columnas segun version VFP
REPLACE ALL mirepor.Vpos WITH mirepor.Vpos - sExtra FOR mirepor.objtype=5 AND mirepor.Vpos = extra
*
DELETE ALL FOR objtype = 26 IN mirepor
PACK
*
USE IN mirepor
*
* Mandar impresion
oForm = CREATEOBJECT("Form")
WITH oForm
  .CAPTION = "Vista Previa "
  .WINDOWTYPE = 1
  .WIDTH = _SCREEN.WIDTH - 16
  .HEIGHT = _SCREEN.HEIGHT - 16
  *
  SELECT &cCursor
  GOTO TOP
  REPORT FORM (cRepo) PREVIEW WINDOW (.NAME)
  REPORT FORM (cRepo) TO PRINTER PROMPT NOCONSOLE NOEJECT
  *
  .RELEASE()
ENDWITH
*
* Borrar Report autogenerado
DELETE FILE (JUSTSTEM(cRepo) + '.frx')
DELETE FILE (JUSTSTEM(cRepo) + '.frt')
*
RETURN
Jose Antonio Blasco

17 de julio de 2010

Calculo de cuotas por el sistema francés

Con esta rutina podemos calcular el valor de la cuota, cuota capitalizada e interés según el sistema francés.
*-- Sistema Frances 
*-- Datos a Cargar 
Capital = 10000 
CantidadCuotas = 36 
TasaAnual = 22  && Porcentaje 
TasaMensual = TasaAnual/12/100 
*-- Listado 
? "    Nro.Cuota        Cuota             Cuota Capitalizada             Interes" 
? REPLICATE("-",80) 
FOR NroCuota = 1 TO CantidadCuotas 
  Cuota = Capital * (TasaMensual/(1-(1+TasaMensual)^-CantidadCuotas)) 
  CuotaCapitalizada = Cuota * (1-TasaMensual*(1-(1+TasaMensual)^-(CantidadCuotas-NroCuota+1))/TasaMensual ) 
  Interes = TasaMensual * Cuota * (1-(1+TasaMensual)^-(CantidadCuotas-NroCuota+1))/TasaMensual 
  ? NroCuota, ROUND(Cuota,2), ROUND(CuotaCapitalizada,2), ROUND(Interes,2) 
ENDFOR 

Luis María Guayán

26 de mayo de 2010

Un sencillo método para validar que no se dejen determinados datos vacíos en un formulario.

Primeramente coloca un * (asterisco) en la propiedad Comment a los objetos que deseas validar.

Posteriormente coloca el siguiente código en el borón Grabar del formulario.

LOCAL lnObjecto,lcContenido,lcNombre,lcFoco
FOR lnObjecto = 1 TO THISFORM.OBJECTS.COUNT
  IF THISFORM.OBJECTS(lnObjecto).COMMENT = "*"
    lcNombre = THISFORM.OBJECTS(lnObjecto).NAME
    lcContenido = "ThisForm." + lcNombre + ".Value"
    IF EMPTY(&lcContenido)
      MESSAGEBOX("Es necesario capturar el dato " + ;
        SUBSTR(lcNombre,4), 16, "No es posible")
      lcFoco = "ThisForm." + lcNombre + ".SetFocus"
      &lcFoco
      RETURN
    ENDIF
  ENDIF
ENDFOR

Saludos.

Jesus Caro V.

6 de abril de 2010

Menú desplegable en un CommandButton

Esta es una clase simple para mostrar un menú desplegable bajo un CommandButton. El menú se muestra al hacer click sobre el botón, o pulsando la barra espaciadora, F4 o ALT+DOWN sobre el mismo.

Espero les sea de utilidad
* Menú en commandbutton
WITH NEWOBJECT("xForm")
  .SHOW(1)
ENDWITH
RETURN

DEFINE CLASS xForm AS FORM
  ADD OBJECT cmdMenu1 AS xCommandButton WITH ;
    CAPTION = "Menu 1", TOP = 10, LEFT = 10,;
    MenuOptions = "Opcion 1 . \<1,Opcion 1 . \<2,Opcion 1 . \<3"

  ADD OBJECT cmdMenu2 AS xCommandButton WITH ;
    CAPTION = "Menu 2", TOP = 10, LEFT = 120,;
    MenuOptions = "Opcion 2 . \<1,Opcion 2 . \<2"

  ADD OBJECT cmdClose AS xCommandButton WITH ;
    CANCEL = .T., CAPTION = "Cerrar", TOP = 10, LEFT = 240

  PROCEDURE cmdClose.CLICK
    THISFORM.HIDE()
  ENDPROC
ENDDEFINE

DEFINE CLASS xCommandButton AS COMMANDBUTTON
  HEIGHT = 25

  MenuOptions = ""

  PROCEDURE MOUSEMOVE (nButton, nShift, nXCoord, nYCoord)
    IF nButton==1 AND ! EMPTY(THIS.MenuOptions)
      THIS.ShowPopupMenu()
      NODEFAULT
    ENDIF
  ENDPROC

  PROCEDURE KEYPRESS(nKeyCode, nShiftCtrlAlt)
    #DEFINE K_DOWN 160
    #DEFINE K_ALT 4
    #DEFINE K_F4 -3

    * WAIT WINDOW TRANSFORM(nKeyCode) + " " + TRANSFORM(nShiftCtrlAlt) NOWAIT

    DO CASE
      CASE nKeyCode==K_DOWN AND nShiftCtrlAlt==K_ALT
        NODEFAULT
        THIS.ShowPopupMenu()
      CASE nKeyCode==K_F4
        NODEFAULT
        THIS.ShowPopupMenu()
    ENDCASE
  ENDPROC

  PROCEDURE CLICK
    NODEFAULT
    THIS.ShowPopupMenu()
  ENDPROC

  * Armo y muestro el menú
  PROCEDURE ShowPopupMenu()
    LOCAL nOp, sOp, nY, nX, nRatio

    TRY
      RELEASE POPUP _Popup_Menu
    CATCH
    ENDTRY

    WITH THIS
      THISFORM.ADDPROPERTY("ActivePopupMenu", THIS)

      * Convierto de pixels a foxels
      nRatio = FONTMETRIC(1)
      nY = (.TOP + .HEIGHT) / nRatio

      nRatio = FONTMETRIC(6)
      nX = .LEFT / nRatio

      DEFINE POPUP _Popup_Menu FROM nY, nX SHORTCUT

      FOR nOp = 1 TO GETWORDCOUNT(.MenuOptions, ",")
        sOp = GETWORDNUM(.MenuOptions, nOp, ",")
        DEFINE BAR (nOp) OF _Popup_Menu PROMPT (sOp)
        sOp = TRANSFORM(nOp)
        ON SELECTION BAR (nOp) OF _Popup_Menu _SCREEN.ACTIVEFORM.ActivePopupMenu.AfterClick( &sOp )
      NEXT
    ENDWITH

    ACTIVATE POPUP _Popup_Menu
  ENDPROC

  * Borro el menú luego del click y llamo al handler
  PROCEDURE AfterClick(nOption)
    THISFORM.ActivePopupMenu = NULL
    * RELEASE POPUP _Popup_Menu
    THIS.OnMenu (nOption)
    THISFORM.REFRESH()
  ENDPROC

  PROCEDURE OnMenu (nOption)
    WAIT WINDOW "Seleccionó opcion " + TRANSFORM(nOption) + " del botón " + PROPER(THIS.NAME) NOWAIT
  ENDPROC
ENDDEFINE

Mario Lopez