Acceso a base de datos SQLite desde Delphi Starter

Hola amigos,

En ésta entrada vamos a realizar la conexión con una base de datos SQLite utilizando Delphi Starter Edition, versión 10.2 Tokyo y como ya se habrán dado cuenta, ésta edición de Delphi no cuenta con los componentes necesarios para la conexión a bases de datos, sin embargo, si tenemos la posibilidad de instalar componentes de terceros para poder acceder a motores de base de datos y expandir las características de nuestra herramienta de desarrollo.

Los componentes que utilizaremos en éste tutorial son los componentes ZEOS que nos permitiran dar continuidad a ésta serie aprovechando las facilidades que nos ofrece Delphi Starter Edition.

Para realizar ésta entrada utilizaremos la aplicación que desarrollamos en el artículo anterior «Consumir un servicio web con Delphi 10.2 Starter y cURL« donde obtenemos información del tipo de cambio del día del peso mexicano contra monedas de otros países.

Una vez que obtenemos dicha información tendrémos la capacidad de almacenarla para efectos de mantener un histórico de «paridades» y poder consultar el valor de una moneda en un día determinado.

Para poder llevar a cabo éste tutorial necesitamos descargar el componente de acceso base de datos ZEOS el cual pueden descargar del siguiente enlace: ZeosLib versión 7.2.1 Release Candidate

El motor de base de datos que usarémos será SQLite donde crearemos dos tablas y una vista para utilizarlas en nuestra aplicación, dicha base de datos estará incluida en los archivos de descarga al final de éste tutorial, sin embargo, si deseas crearla tu mismo se entregarán los DDL para que las generes con el administrador SQLite de tu preferencia, si no conoces alguno puedes descargar SQLite Studio Database Manager que me parece un muy buen administrador.

Comenzaremos por instalar los componentes ZEOS versión 7.2.1 rc, el paquete que se usará para Delphi Starter es el contenido en el directorio DelphiXE10.

Carga el proyecto ZeosDbo.bpg en Delphi y compila todos los bpl’s en el siguiente orden:

• ZCore.bpl
• ZParseSql.bpl
• ZPlain.bpl
• ZDbc.bpl
• ZComponent.bpl

Para que puedan compilar los BPL’s es necesario agregar los siguientes directorios a la ruta de las librerias/bibliotecas que se localiza en el menu Tools -> Options -> Delphi Options -> Library -> Library Path.

C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\packages\DelphiXE10;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\component;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\dbc;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\parsesql;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\plain;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\Core

Una vez que compilamos correctamente el proyecto ZeosDbo aparecerá el grupo Zeos Access en la paleta de herramientas como se muestra en la siguiente imagen:

El siguiente paso es la creación de la base de datos SQLite que utilizaremos en ésta sección y como les comenté pueden usar la base de datos que está incluida en las descargas al final de éste tutorial o pueden crearla con el Lenguaje de Definición de Datos (DDL)  desde cualquier Administrador SQLite.

--
-- File generated with SQLiteStudio v3.1.1 on mar may 30 21:19:36 2017
--
-- Text encoding used: System
--
PRAGMA foreign_keys = off;
BEGIN TRANSACTION;

-- Table: TC_CATALOGO
DROP TABLE IF EXISTS TC_CATALOGO;

CREATE TABLE TC_CATALOGO (
    ID          INTEGER      NOT NULL
                             PRIMARY KEY AUTOINCREMENT,
    CLAVE       STRING (20)  NOT NULL,
    DESCRIPCION STRING (200) 
);


-- Table: TC_HISTORICO
DROP TABLE IF EXISTS TC_HISTORICO;

CREATE TABLE TC_HISTORICO (
    ID      INTEGER        NOT NULL,
    FECHA   DATE           NOT NULL,
    TIPCAMB DECIMAL (7, 4),
    PRIMARY KEY (
        ID,
        FECHA
    )
);


-- View: TC_LISTADO
DROP VIEW IF EXISTS TC_LISTADO;
CREATE VIEW TC_LISTADO AS
    SELECT CAT.CLAVE,
           HIST.FECHA,
           HIST.TIPCAMB,
           CAT.DESCRIPCION
      FROM TC_HISTORICO HIST
           INNER JOIN
           TC_CATALOGO CAT ON CAT.ID = HIST.ID;


COMMIT TRANSACTION;
PRAGMA foreign_keys = on;

Despues de crear las tablas vamos a inicializar el catálogo de monedas para que se tenga la información necesaria para enlazar la información que vamos a recibir del Servicio Web de Banxico.

INSERT INTO TC_CATALOGO (DESCRIPCION,CLAVE,ID)
VALUES	('Tipo de cambio pesos por dólar E.U.A. Fecha de liquidación.','DLL01',1),
		('Tipo de cambio Pesos por dólar E.U.A. Fecha de determinación (FIX)','DLL02',2),
		('Cotización de las divisas que conforman la canasta del DEG Respecto al peso mexicano Euro','EURO',3),
		('Cotización de la divisa Respecto al peso mexicano Dólar Canadiense','DLLCA',4),
		('Cotización de las divisas que conforman la canasta del DEG Respecto al peso mexicano Yen japonés','YEN',5),
		('Cotización de las divisas que conforman la canasta del DEG Respecto al peso mexicano Libra esterlina.','LIBRA',6);

En éste momento ya tenemos los componentes de acceso a base de datos y la base de datos listos, ahora comenzaremos a dar forma a nuestro proyecto.

Abra el proyecto wsStarter.dproj que se creo en el tutorial anterior (Si no lo has creado, puedes descargarlo siguiendo éste enlace).

Agregue los siguientes componentes a la forma principal.

• TButton
• TDataSource;
• TDateTimePicker
• TDBGrid
• TZConnection;
• TZQuery;

Después de organizar a tu gusto los componentes que se agregaron ya tendremos nuestra forma similar a la siguiente imagen:

Configuramos la conexión en el componente ZConnection1  asignando la ruta de la base de datos y el protocolo del motor de la base de datos que vamos a usar, en éste caso sqlite-3.

Ésta configuración de la base de datos está en tiempo de diseño pero lo recomendable es hacerlo en tiempo de ejecución ya que la base de datos puede ser colocada en cualquier lugar ya sea en la misma máquina o en otra máquina de la red. Para configurarla en tiempo de ejecución pueden hacer lo siguiente:

procedure TForm1.FormCreate(Sender: TObject);
begin
  ZConnection1.Database := ExtractFilePath(Application.ExeName) + 'base\TipoCambio.sqlite3';
end;

(También puede ser a través de la lectura de un archivo INI, XML o el mismo registro de windows, como mejor les parezca.)

Ahora vamos a decidir que vamos a hacer con la información que se reciba del Servicio Web de Banxico. Yo he decidido mostrar la información seleccionando la fecha deseada en el componente TDateTimePicker1 y mostrar los tipos de cambio de ese día (si ya se ha descargado), para ello utilizaremos la vista que previamente se creo en la base de datos llamada TC_LISTADO ejecutandola desde el componente ZQuery1 el cual ya debe estar enlazado al DataSource y a su vez el DataSource enlazado al DBGrid.

La consulta es muy simple y  es la siguiente:

select * from TC_LISTADO list
where list.FECHA = :fecha

Ya estamos listos para modifcar el proyecto y acceder a una base de datos. Comenzamos agregando las siguientes unidades a la sección USES de nuestra unidad uXMLclass.pas.

• ZDataset,
• ZAbstractConnection;

Posteriormente agregamos una variable y una propiedad a la clase TRequestResponse para la conexión con la base de datos.

• ZQryTC: TZQuery;

• Fconexion: TZAbstractConnection;

• property conexion: TZAbstractConnection read Fconexion write Fconexion;

Finalmente harémos una modificación al procedimiento TRequestResponse.BuscaTC() para leer el XML de Respuesta obteniendo la Moneda, la Fecha y el Tipo de Cambio y agregando ésta información a nuestra tabla de históricos para consultas posteriores.

function TRequestResponse.buscaTC(xml: IXMLDocument): TStrings;
var
  I: integer;
  nodoData: IXMLNode;
  Linea: string;
  valor: variant;
  moneda: integer;
begin
  Result := TStringList.Create;
  Result.Text := '';
  nodoData := xml.ChildNodes[1].ChildNodes[1];
  if nodoData <> nil then
  begin
    ZQryTC := TZQuery.Create(nil);
    ZQryTC.Connection := Fconexion;
    ZQryTC.SQL.Text := 'INSERT INTO TC_HISTORICO(ID, FECHA, TIPCAMB) ' + #13 +
                       'VALUES(:id, :periodo, :tc) ';
    for I := 0 to nodoData.ChildNodes.Count-1 do
    begin
      if nodoData.ChildNodes[I].NodeName = 'bm:Series' then
      begin
         if pos('FIX',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 2
         else
         if pos('Euro',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 3
         else
         if pos('Canadiense',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 4
         else
         if pos('Yen',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 5
         else
         if pos('Libra',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 6
         else
            ZQryTC.ParamByName('ID').Value := 1;

         moneda := ZQryTC.ParamByName('ID').Value;

         ZQryTC.ParamByName('PERIODO').AsString :=
                 nodoData.ChildNodes[I].ChildNodes[0].Attributes['TIME_PERIOD'];

         valor := NULL;
         if nodoData.ChildNodes[I].ChildNodes[0].Attributes['OBS_VALUE'] <> '' then
            ZQryTC.ParamByName('TC').AsString :=
                 nodoData.ChildNodes[I].ChildNodes[0].Attributes['OBS_VALUE']
         else
            ZQryTC.ParamByName('TC').Value := valor;

         ZQryTC.ExecSQL;

         Result.Add(Moneda.ToString + #9 +
                    nodoData.ChildNodes[I].ChildNodes[0].Attributes['TIME_PERIOD'] + #9 +
                    nodoData.ChildNodes[I].ChildNodes[0].Attributes['OBS_VALUE'] );

      end;
    end;
    ZQryTC.Free;
  end;
end;

Con el código anterior recorremos los nodos de XLM para obtener la información que necesitamos, la insertamos en la base de datos y finalmente regresamos un informe de lo descargado a la forma principal como se puede observar en las siguientes imagenes:

Pareciera que la información mostrada careciera de sentido, sin embargo, la parte final de éste tutorial es mostrar un listado de los tipos de cambio de una fecha dada utilizando la vista que creamos anteriormente la cual es disparada por la siguiente consulta.

select * from TC_LISTADO
where FECHA = :fecha

Para ejecutar la consulta utilizamos el evento OnClick del  botón [Listado] y escribimos el siguiente código:

procedure TForm1.Button3Click(Sender: TObject);
begin
  ZQuery1.Close;
  ZQuery1.ParamByName('FECHA').Value := DateTimePicker1.Date;
  ZQuery1.Open;
end;

Ya tenemos listo todo y solo presionamos el botón [Listado] para que la información sea presentada en el Grid de nuestra forma como se observa en la siguiente imagen.

Como pueden ver, acceder a una base de datos con Delphi Starter no tiene mayor complicación y las posibilidades que se nos presentan son muchas, solo recuerden, de acuerdo a la licencia de ésta edición de Delphi Starter se nos indica que si logran obtener una ganancia igual o mayor a 1,000 dólares deben de adquirir una versión de pago, los invito a que hagan el esfuerzo, les aseguro que no se arrepentiran.

Y bueno hemos llegado al final de éste tutorial, espero que sea de su agrado y sobre todo que sea de utilidad.

Hasta la próxima


Todo el código escrito aquí es de libre descarga y utilización solo te pido, si te parece correcto, que menciones su origen y claro cualquier mejora que le hagas publicala que se agradecerá enormemente.

Muchas gracias.

Consumir un servicio web con Delphi 10.2 Starter y cURL

Hola amigos,

En ésta entrada les hablaré acerca de la versión ‘gratuita’ de Delphi llamada Delphi Starter Edition, versión 10.2 Tokyo la cual nos permite, según su contrato de licencia, generar aplicaciones comerciales aunque con algunas limitaciones propias de éste tipo de ediciones.

Si quieren conocer acerca de éste producto, su licencia de uso y las limitaciones propias de la versión, les proporciono una lista de enlaces que me parecen muy interesantes.

Quiero mencionar que la intención de ésta entrada es la de mostrar que con ésta versión podemos comenzar a desarrollar soluciones reales y no solo el famoso «Hola Mundo». Por supuesto al ser un producto gratuito tiene algunas limitaciones pero nada que nos evite hacer uso de nuestras capacidades y dar forma a aplicaciones de alto rendimiento.

Para ésta entrada les sugiero que descarguen el programa soapUI el cual es open source  y que nos facilitará la vida al generar un cliente para el consumo de Servicios Web así como descargar e instalar Delphi 10.2 Tokio Starter.

Una de las limitantes de la versión Starter es que no cuenta con el asistente para la importación del archivo WSDL el cual genera la unidad que implementa los métodos del Servicio Web para su consumo y aunque ésta unidad se puede obtener vía línea de comandos he querido hacerlo con una solución alternativa a través de un proyecto llamado cURL el cual está orientado a la transferencia de archivos y que soporta varios protocolos como FTP, FTPS, HTTP, HTTPS, TFTP, SCP, SFTP, Telnet, DICT, FILE y LDAP entre otros.

Cabe mencionar que éste proyecto lo conocí hace unos años, para ser exactos el 14 de Marzo de 2011, cuando nuestro amigo Domingo Seaone  publicó en el foro delphiaccess punto com una implementación de ésta biblioteca desarrollando una unidad con Delphi y que me ha permitido dar solución a varios requerimientos de clientes a lo largo de éstos 6 años que han pasado.

Pues bien, comenzaremos por obtener los archivos XML de Request y Response del Servicio Web a través de la aplicación soapUI, para ello usaremos el Servicio Web del Banco de México para consultar el tipo de cambio del peso frente al Dólar, el Euro, la Libra Esterlina y el Yen. La url del servicio web es la siguiente:

http://www.banxico.org.mx/DgieWSWeb/DgieWS?WSDL

Creamos un nuevo proyecto SOAP seleccionamos el método tiposDeCambioBanxico y enviamos la petición, el Servicio Web nos regresará la información en un archivo soap XML conteniendo los diferentes tipos de cambio como se muestra en la imagen siguiente:

La versión Starter de Delphi tampoco incluye el asistente XML Data Binding por lo que tenemos que construir el REQUEST y el RESPONSE de forma manual, bueno, no todo en la vida es fácil, pero veamos la situación como una buena oportunidad para aprender algo nuevo. 🙂

Ya estamos listos para comenzar nuestro tutorial, como primer paso vamos a crear una clase que generará la estructura del mensaje de petición SOAP para enviarla a través de cURL al servidor del Servicio Web y serializar la respuesta SOAP para obtener (en este caso)  los tipos de cambio disponibles del peso mexicano contra otras monedas.

La clase contendrá las propiedades, variables y métodos necesarios para el consumo del Servicio Web como se muestra a continuación.

TRequestResponse = class

type

  TRequestResponse = class
  private
    xmlArch: IXMLDocument;
    envelopeSOAP: IXMLNode;

    Curl: TCURL;
    curlResult: CURLcode;
    curlError: string;

    Stream: TMemoryStream;
    StreamOut: TMemoryStream;

    function creaRequest: IXMLDocument;
    function enviaRequest(url, Post: AnsiString; out Reply: AnsiString): Boolean;
    function RecursiveFindNode(ANode: IXMLNode; const SearchNodeName: string): IXMLNode;
    function buscaTC(xml: IXMLDocument): TStrings;

  public
    function ConsultaTipoDeCambio(endPoint: AnsiString): TStrings;

  end;

El método creaRequest genera el mensaje de petición SOAP utilizando el objeto IXMLDocument el cual se encargará de dar el formato adecuado para poder enviarlo al servidor donde está alojado el Servicio Web que queremos consumir.

function TRequestResponse.creaRequest: IXMLDocument;

function TRequestResponse.creaRequest: IXMLDocument;
begin
  xmlArch := NewXMLDocument;
  xmlArch.Encoding := 'UTF-8';
  envelopeSOAP := xmlArch.AddChild('soapenv:Envelope');
  with envelopeSOAP do
  begin
    Attributes['xmlns:ws'] := 'http://ws.dgie.banxico.org.mx';
    Attributes['xmlns:soapenv'] := 'http://schemas.xmlsoap.org/soap/envelope/';
    Attributes['xmlns:xsd'] := 'http://www.w3.org/2001/XMLSchema';
    Attributes['xmlns:xsi'] := 'http://www.w3.org/2001/XMLSchema-instance';
    AddChild('soapenv:Header');
    with AddChild('soapenv:Body') do
    begin
      with AddChild('ws:tiposDeCambioBanxico') do
      begin
        Attributes['soapenv:encodingStyle'] := 'http://schemas.xmlsoap.org/soap/encoding/';
      end;
    end;
  end;
  Result := xmlArch;
end;

Con éste código se genera el mensaje SOAP necesario para realizar la petición al Servicio Web y que será enviado por medio de cURL.

Por supuesto que habrá formas más efectivas de hacer esto, sin embargo ésta me parece a mi la más simple y controlada.

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.dgie.banxico.org.mx">
	<soapenv:Header/>
	<soapenv:Body>
		<ws:tiposDeCambioBanxico soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
	</soapenv:Body>
</soapenv:Envelope>

A continuación agregaremos la unidad creada por mi amigo Domingo Seoane la cual encapsula el método para enviar la petición al Servicio Web, dicha unidad se llama uCurl.pas la cual publicó en DelphiAccess.

A continuación agregamos la función para realizar la llamada a dicha unidad y que llamaremos enviaRequest. En ésta función necesitaremos la URL del Servicio Web y el Request que hemos creado con la función creaRequest, dicha función regresará dos valores, uno de tipo out donde obtendrémos el Response del Servicio Web y un boolean que nos indicará si la función fué procesada correctamente o no.

function TRequestResponse.enviaRequest(url, Post: AnsiString; out Reply: AnsiString): Boolean;

function TRequestResponse.enviaRequest(url, Post: AnsiString; out Reply: AnsiString): Boolean;

//******************************************************************************
      function ReadFromStream(Buffer: PAnsiChar; Size, Count: Integer;
        Stream: TStream): Integer; cdecl;
      begin
        Result:= Stream.Read(Buffer^,Size*Count) div Size;
      end;

      function SaveToStream(Buffer: PAnsiChar; Size, Count: Integer;
        Stream: TStream): Integer; cdecl;
      begin
        Result:= Stream.Write(Buffer^,Size*Count) div Size;
      end;

      function MemoryStreamToString(M:TMemoryStream): AnsiString;
      begin
        SetString(Result, PAnsiChar(M.Memory), M.Size);
      end;

      procedure ErrorCurl(const mensaje: string);
      begin
        raise Exception.Create(mensaje);
        exit;
      end;
//******************************************************************************

begin
  Result:= false;
  Curl:= curl_easy_init;
  if Curl <> nil then
  try
    if curl_easy_setopt(Curl, CURLOPT_VERBOSE, TRUE) <> CURLE_OK then
      ErrorCurl('No se pudo asignar CURLOPT_VERBOSE.');
    if curl_easy_setopt(Curl, CURLOPT_USE_SSL, CURLUSESSL_ALL) <> CURLE_OK then
      ErrorCurl('No se pudo asignar CURLOPT_USE_SSL.');
    if curl_easy_setopt(Curl, CURLOPT_SSL_VERIFYPEER, FALSE) <> CURLE_OK then
      ErrorCurl('No se pudo asignar CURLOPT_SSL_VERIFYPEER.');
    if curl_easy_setopt(Curl, CURLOPT_URL, PAnsiChar(url)) <> CURLE_OK then
      ErrorCurl('No se pudo asignar CURLOPT_URL.');
    if curl_easy_setopt(Curl, CURLOPT_POST, 1) <> CURLE_OK then
      ErrorCurl('No se pudo asignar CURLOPT_POST.');
    if curl_easy_setopt(Curl, CURLOPT_READFUNCTION, @ReadFromStream) <> CURLE_OK then
      ErrorCurl('No se pudo asignar CURLOPT_READFUNCTION.');
    if curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, @SaveToStream) <> CURLE_OK then
      ErrorCurl('No se pudo asignar CURLOPT_WRITEFUNCTION.');

    Stream    := TMemoryStream.Create;
    StreamOut := TMemoryStream.Create;

    try
      with TStringList.Create do
      try
        Add(unicodeString(Post));
        SaveToStream(Stream);
      finally
        Free;
      end;
      Stream.Position:= 0;
      if curl_easy_setopt(Curl, CURLOPT_INFILE, Stream) <> CURLE_OK then
        ErrorCurl('No se pudo asignar CURLOPT_INFILE.');
      if curl_easy_setopt(Curl, CURLOPT_POSTFIELDSIZE, Stream.Size) <> CURLE_OK then
        ErrorCurl('No se pudo asignar CURLOPT_POSTFIELDSIZE.');
      Header := nil;
      Header := curl_slist_append(Header, 'SOAPAction: ""');
      Header := curl_slist_append(Header, 'Accept-Encoding: gzip, deflate');
      Header := curl_slist_append(Header, 'Content-Type: text/xml;charset=UTF-8;');
      Header := curl_slist_append(Header, 'User-Agent: Apache-HttpClient/4.1.1 (java 1.5)');
      try
        if curl_easy_setopt(Curl, CURLOPT_FILE, StreamOut) <> CURLE_OK then
          ErrorCurl('No se pudo asignar CURLOPT_FILE.');
        if curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, Header) <> CURLE_OK then
          ErrorCurl('No se pudo asignar CURLOPT_HTTPHEADER.');

        curlResult := curl_easy_perform(Curl);

        if curlResult = CURLE_OK then
        begin
          Reply := MemoryStreamToString(StreamOut);
          curlError := '';
          result := true;
        end
        else begin
               curlError := curl_easy_strerror(curlResult);
               result := false;
        end;

      finally
        curl_slist_free_all(Header);
      end;
    finally
      Stream.Free;
      StreamOut.Free;
    end;
  finally
    curl_easy_cleanup(Curl);
  end;
end;

Ya estamos a punto de terminar la clase que consumirá el Servicio Web, solo nos falta serializar el Response del Servicio Web lo cual harémos manualmente debido a que tenemos ciertas limitantes al no tener disponible el asistente XML Data Binding en el IDE de nuestro Delphi Starter. Cabe mencionar que si ustedes tienen una forma más elegante de hacerlo, no duden en retroalimentarnos para enriquecer éste tutorial.

Para ello vamos a utilizar dos funciones, una que tome prestada del sitio  stackoverflow y una que escribiremos nosotros mismos, dichas funciones son

function RecursiveFindNode(ANode: IXMLNode; const SearchNodeName: string): IXMLNode;

{
   Función basada en la original que se tomó del siguiente enlace
   http://stackoverflow.com/questions/28901757/delphi-find-xml-node
}
function TRequestResponse.RecursiveFindNode(ANode: IXMLNode; const SearchNodeName: string): IXMLNode;
var
  I: Integer;
begin
  if CompareText(ANode.NodeName, SearchNodeName) = 0 then
      Result := ANode
  else if not Assigned(ANode.ChildNodes) then
          Result := nil
       else begin
              for I := 0 to ANode.ChildNodes.Count - 1 do
              begin
                Result := RecursiveFindNode(ANode.ChildNodes[I], SearchNodeName);
                if Assigned(Result) then
                   Exit;
              end;
       end;
end;

function buscaTC(xml: IXMLDocument): TStrings;

function TRequestResponse.buscaTC(xml: IXMLDocument): TStrings;
var
  I: integer;
  nodoData: IXMLNode;
  Linea: string;
begin
  Result := TStringList.Create;
  Result.Text := '';
  nodoData := xml.ChildNodes[1].ChildNodes[1];
  if nodoData <> nil then
  begin
    for I := 0 to nodoData.ChildNodes.Count-1 do
    begin
      if nodoData.ChildNodes[I].NodeName = 'bm:Series' then
      begin
         Result.Add(nodoData.ChildNodes[I].Attributes['TITULO'] + #9 +
                    nodoData.ChildNodes[I].Attributes['BANXICO_UNIT_TYPE'] + #9 +
                    nodoData.ChildNodes[I].ChildNodes[0].Attributes['TIME_PERIOD'] + #9 +
                    nodoData.ChildNodes[I].ChildNodes[0].Attributes['OBS_VALUE'] );
      end;
    end;
  end;
end;

Por último vamos a ewscribir el código de la función principal de nuestra clase llamado ConsultaTipoDeCambio y que requiere de la URL del Servicio Web la cual enviaremos desde la forma principal.

function TRequestResponse.ConsultaTipoDeCambio(endPoint: AnsiString): TStrings;

function TRequestResponse.ConsultaTipoDeCambio(endPoint: AnsiString): TStrings;
var
  nodoBody: IXMLNode;
  nodoResult: IXMLNode;
  xml: IXMLDocument;
  response: AnsiString;

begin
  xml := creaRequest;
  xml.XML.SaveToFile(ExtractFilePath(Application.ExeName) + 'request_' +
                               formatDateTime('yyyymmdd_hhnnss',now) + '.xml' );
  if sendRequest(endPoint, AnsiString(xml.XML.Text), response) then
  begin
    try
      xmlArch := NewXMLDocument;
      xmlArch.XML.Text := response;
      xmlArch.Active := true;
      nodoBody := xmlArch.ChildNodes[1].ChildNodes[1];
      if nodoBody <> nil then
      begin
        nodoResult := RecursiveFindNode(NodoBody, 'result');
        if nodoBody <> nil then
        begin
          xml := TXMLDocument.Create(nil);
          xml.XML.Text := nodoResult.ChildNodes[0].NodeValue;
          xml.Active := true;
          xml.XML.SaveToFile(ExtractFilePath(Application.ExeName) +
                                                'response.xml', TEncoding.ANSI);
          Result := BuscaTC(xml);
        end
        else begin
               Result.Text := 'ERROR: No se pudo acceder al nodo "Result"';
        end;
      end
      else begin
             Result.Text := 'ERROR: No se pudo acceder al nodo "Body"';
      end;
    except
      on e: exception do
         Result.Text := 'ERROR: ' + e.Message;
    end;
  end;

end;

Ya tenemos nuestra unidad uXMLClass.pas la cual contiene la clase TRequestResponse completa y lista para ser usada por el programa principal.

En la forma principal vamos a agregar dos componentes TButton y un componente TMemo. Perdón pero suelo ser minimalista 😀

Acomodamos los componentes a nuestro gusto y escribiremos el siguiente código en el evento OnClick del componente TButton.

procedure TForm1.Button1Click(Sender: TObject);
var
  ReqResp: TRequestResponse;
  retorno: TStrings;
begin
  ReqResp := TRequestResponse.Create;
  retorno := TStringList.Create;
  retorno := ReqResp.ConsultaTipoDeCambio(AnsiString('http://www.banxico.org.mx/DgieWSWeb/DgieWS'));
  Memo1.Lines := retorno;
end;

Finalmente ejecutamos nuestra aplicación y deberíamos obtener la siguiente respuesta.

Con ésto concluimos éste pequeño tutorial donde pretendemos mostrar que se puede trabajar con ésta edición de Delphi y crear aplicaciones listas para dar solución a requerimientos reales. Por supuesto que hay de requerimientos a requerimientos pero la idea es comenzar nuestro «propio negocio» y poder obtener ingresos suficientes para adquirir una de las versiones de pago y dar el siguiente paso para que nuestro negocio se reafirme y podamos dar soluciones completas y mas profesionales.

Antes de despedirme les quiero decir que vamos a estar desarrollando algunos temas con Delphi Starter con lo que pretendemos aportar nuestro granito de arena, si tienen algún tema que pueda ser creado con ésta versión con gusto lo intentaremos desarrollar.

Les agradeceré que dejen sus comentarios, críticas y/o palabras de aliento que me darán el oxígeno necesario para continuar con ésta serie. 🙂

Hasta la próxima


Todo el código escrito aquí es de libre descarga y utilización solo te pido, si te parece correcto, que menciones su origen y claro cualquier mejora que le hagas publicala que se agradecerá enormemente.

Muchas gracias.

Delphi 10.2 Tokio

Hola amigos,

Después de un par de semanas donde tuve algunos problemas con mi sitio, hemos regresado con una nueva imagen y no encontré mejor forma que hablando de la característica más esperada de Delphi.

En efecto, la posibilidad de desarrollar aplicaciones que corran en Linux se ha hecho realidad, se está hablando por todo el mundo y mi bitácora no iba a ser la excepción.

Para poder generar mi primer aplicación he seguido el video tutorial de mi buen amigo Luis Felipe González quien de una forma sencilla y muy didáctica muestra como instalar una máquina virtual con Ubuntu Server 16.04.2 para desarrollar aplicaciones Delphi.

No voy a repetir lo que nuestro amigo amablemente nos ha proporcionado para respetar su trabajo y darle los créditos que merece, así que pueden acceder al video tutorial dando clic en el siguiente enlace:

Delphi 10.2 Tokyo. Configurar el Ambiente Linux usando Ubuntu 16.04.2 LTS

Siguiendo el video tendremos lo necesario para crear nuestra primer aplicación en Linux, sin embargo, ésta entrada mostrará la instalación de Delphi 10.2 Tokio y para poder realizarla he utilizado el Trial que está disponible en la página de Embarcadero y que puedes descargar desde el siguiente enlace Start for free.

Una vez descargado el instalador procedemos a ejecutarlo para iniciar el proceso.

 

 

Para iniciar nos muestra la pantalla de selección de las plataformas que se desean instalar, para éste ejercicio solo he seleccionado Delphi con todas las plataformas disponibles, Windows 64 bits, Windows 32 bits, OS X, iOS, Android y el ya famoso Linux 64 bits.

 

 

Posteriormente tenemos que seleccionar opciones adicionales, para éste ejercicio solo vamos a seleccionar solo unas cuantas, una vez que estén instalado nuestra herramienta podrán seleccionar de nuevo las que se deseen tener instaladas como lo veremos mas adelante.

Damos clic en el botón Install para continuar.

 

 

A continuación nos pide leer cuidadosamente las licencias de cada uno de las dependencias involucradas. Si están de acuerdo con las licencias presione el botón Agree all para continuar.

 

 

Con ésto terminamos el proceso de instalación de la herramienta. Presionamos el botón START WORKING para que se muestre el IDE de Delphi 10.2 Tokio.

 

 

El IDE de Delphi 10.2 Tokio no sufrió cambios aparentes en comparación con Delphi 10.1 Berlín, sin embargo, se reorganizaron algunos elementos del menú para un mejor manejo y una navegación más rápida como lo podemos observar en la siguiente lámina obtenida del Webinar del lanzamiento de Delphi 10.2 Tokio.

 

En éste punto ya tenemos listo nuestro Delphi para comenzar a experimentar, pero antes procederemos a configurar nuestro ambiente de desarrollo que es el que nos permitirá acceder a Linux desde Delphi.

Lo primero que necesitamos es transferir el archivo LinuxPAServer19.0.tar.gz que se localiza en el directorio PAServer de nuestra instalación a Linux utilizando un cliente de ftp, en mi caso Bitvise SSH Client que es el que utilizo como Terminal SSH y FTP.

Ya teniendo nuestro PAServer en Linux procederemos a descompactarlo con la instrucción que nos mostró Luis Felipe en su video, ejecutamos el paserver, no asignamos contraseña y ya tenemos nuestro ambiente de trabajo en linux listo para aceptar llamadas desde Delphi.

tar -xvzf LinuxPAServer19.0.tar.gz

 

 

Solo nos falta crear el perfil de la conexión con el PAServer que está corriendo en la maquina remota Linux, para ello damos clic en el Menu ToolsOptions y seleccionamos la opción SDK Manager, damos clic en el boton Add… y nos pedirá tres datos IP Remota, Puerto y Contraseña, en éste caso la IP de mi Servidor Linux es 192.168.1.67, el puerto es el asignado por el PAServer 64211 y no asigné contraseña. Presionamos el botón de Test Connection. y si se siguió paso a paso el tutorial de Luis Felipe verémos la confirmación de que la conexión con el servidor Linux a sido satisfactoria.

 

 

 

Ya está todo listo para comenzar a escribir código y para ello crearemos un nuevo proyecto de tipo consola dando clic en la opción Create a new project… – Delphi Projects ó a través del Menú File – New – Other – Delphi Projects

 

Asignamos la plataforma de Linux 64-bits, escribimos nuestro mensaje en el bloque correspondiente, ejecutamos y listo, ya hemos generado nuestro primer «Hola Mundo» corriendo en Linux como se puede observar en la siguiente imagen.

 

 

Con ésto hemos terminado éste pequeño ejercicio pero muy esperanzador en cuanto al potencial que tenemos con ésta nueva versión de Delphi.

Quiero finalizar parafraseando a Neil Armstrong.

«Es un pequeño paso para el programador, pero un gran paso para la comunidad»

 

 

 

 

 

 

Hasta la próxima


Formas Incrustadas FMX

Ésta entrada está basada en el ejemplo FMXEmbeddedForm (Delphi) localizado en la wiki de documentación de Embarcadero donde nos muestra como incrustar una forma dentro de otra y la intención de la presente entrada es desarrollar paso a paso la forma como hacerlo con Delphi XE7.

Y sin más preambulo comenzaremos creando una aplicación multi-dispositivo, para ello seleccionaremos en los proyectos de Delphi la opción Multi-Device Application.

FI-01

 

Posteriormente seleccionamos el tipo de aplicación multi-dispositivo, personalmente utilizo una aplicación en blanco.

FI-02

A continuación agregamos una nueva forma multi-dispositivo desde el menú File –> new –> Multi-Device Form – Delphi como se muestra en la siguiente figura.

FI-03

Elegimos el tipo de Forma HD y presionamos el botón OK.

FI-04

Antes de continuar guardamos nuestro proyecto, la unit1 la guardamos como uFormaPadre y la unit2 como uFirmaIncrustada, al proyecto le pueden asignar el nombre que deseen.

FI-05

Agramos a nuetra formaPadre dos componentes, 1 ToolBar con la propiedad Align = Top y 1 Panel con la propiedad Align = Client como se muestra en la siguente figura.

FI-06

En la formaIncrustada agregamos tres componentes, 1 TabControl con la propiedad Align = Client donde agregué 3 Tabs y dos TButton, ustedes pueden agregar los componentes que deseen, la idea es mostrar la forma con algunos componentes para poder observar fácilmente el efecto deseado.

FI-07

El siguiente paso es agregar la unidad uFormaIncrustada en nuestra formaPadre, para ello pueden hacerlo presionando Alt-F11 o en el menu File –> Use Unit o escribiendo manualmente la unidad en una sección Uses de la formaPadre.

FI-08

Adicionalmente agregamos un procedimiento llamado EmbeddedForm() en la sección Private de la clase Tfrm_Padre (TForm1 si no cambiaron el nombre de la forma) como se muestra en la siguente imagen, a continuación presionamos Ctrl + Shift + C para agregar nuestro procedimiento en la sección de implementación y escribimos el código que se realizará cuando se llame a dicho procedimiento.

FI-09

Ahora ya podemos hacer la llamada a  nuestro procedimiento, en éste caso  se ha decidido seguir el ejemplo de la Wiki de Embarcadero utilizando el evento OnCreate de la formaPadre, en la siguente figura se muestra dicha llamada.

Podemos observar que el procedimiento va a incrustar la formaIncrustada en el objeto Panel de la formaPadre en el momento que la aplicación se crea, ustedes pueden jugar con la formaPadre para ejecutar el procedimiento en el momento que lo deseen, incluso pueden agregar código a la formaIncrustada para que ejecute lo que deseen una vez que ya está incrustada en la formaPadre.

FI-10

En éste momento nuestra aplicación ya está lista para ser ejecutada en cualquiera de los dispositivos que desee y que están disponibles en DelphiXE7 , en mi caso lo hice para Android y para Windows 32Bits, pero se puede compilar sin problema para los demás y utilizando el mismo código por supuesto.

A continuación pueden ver la imagen en los dós dispositivos compilados.

FI-11
Android teléfono LG-P880
FI-12
Windows 32 Bits

Descargas


Si lo deseas puedes descargar el código fuente de ésta entrada, espero sea de utilidad.

Ésta entrada y el código fuente son libres para su uso y publicación, lo único que te pido, si te parece justo, es mencionar la fuente de donde se obtuvo.

Primer «vistazo» a RAD Studio XE6

 

RAD_icons2

Ayer 17 de Abril, ya he instalado RAD Studio XE6 y quiero mostrarles mi primer contacto con ésta versión «cero kilometros».

Cabe mencionar que contiene muchos componentes por demás interesantes y requerirá de estudiarlos.

Pues bien, mi primer impresión es que ha tenido cambios a nivel visual, incluyendo desde el instalador del producto hasta el menú del mismo, el cual ya no es el mismo en 3D que estabamos acostumbrados a utilizar, ahora tiene un estilo METROPOLIS, que en lo personal me agrada, no tengo problema por eso, algunos dirían que es igual que Visual Studio, pero bueno, al final el estilo RETRO pareciera que llegó para quedarse.

RADXE6_1

RADXE6

También, incluye muchas funcionalidades y características de actualidad, como lo es la forma Google Glass, aunque poco a poco iremos descubriendo más características, como primer vistazo, no he visto todo por supuesto.

googleGlass

Y bueno, antes de pensar en hacer algo y ver que hace RAD Studio XE6, he tomado uno de sus ejemplos para compilarlo y ejecutarlo en mi teléfono Android. Cabe mencionar que sólo abrí el proyecto SQLite del directorio de ejemplos, el cual permite crear tareas y las almacena en una base de datos SQLite llamada «tasks.s3db», pues bien, ejecuté el proyecto y el resultado fué el siguiente:

tasks

Hasta aquí mi primer contacto con RAD Studio XE6, aunque hay muchas cosas realmente buenas, estoy particularmente interesado en utilizar y aprender Tethering. Ya veremos en las próximas semanas que haremos con todo ésto, son demasiadas cosas por explorar pero poco el tiempo disponible.

Nos leemos.

«Happy Coding»

Construir una App iOS paso a paso

Hola amigos, en ésta ocasión vamos a desarrollar una aplicación para iOS paso a paso, para éste artículo usaremos la interfaz de un iPhone5, pero bien pueden hacerlo para iPhone estándar y/o para iPad.

Antes de comenzar éste tutorial, quiero comentar, que es requisito contar con una MAC o al menos un servicio como el macincloud para poder compilar y ejecutar nuestra aplicación móvil.

Como ya es mi costumbre, vamos a desarrollar un cliente que consuma un Servicio Web pero desde un dispositivo móvil, vamos a tomar el ejemplo que publiqué hace unos meses (Probando Delphi for iOS) del cual no pude hablar más a fondo debido a que aún era un producto beta pero que me sirvió mucho para aprender un poco de ésta nueva característica que cuenta la más reciente versión de Delphi.

Lo primero que vamos a hacer es crear una aplicación Delphi para Móvil con Firemonkey como se muestra en la siguiente imagen:

Acto seguido, Delphi nos muestra una ventana con diferentes  plantillas de aplicaciones móviles con FireMonkey, donde elegiremos para efectos de éste ejercicio, la plantilla que contiene encabezado y pié de página.

Posteriormente y antes de comenzar a desarrollar nuestra aplicación,  Delphi nos muestra un experto que  nos ayudará a configurar el ambiente de desarrollo para la construcción de aplicaciones móviles para iOS, es decir, como configurar la MAC y RAD Studio para trabajar en conjunto.

Pueden seguir éste excelente artículo de mi buen amigo Germán Estévez (Neftalí) para configurar el entorno de trabajo iOS.

Minimizamos o cerramos el experto y tendremos ya nuestra forma lista para comenzar a escribir nuestra primera aplicación móvil para iOS.

Comenzamos por elegir el dispositivo para el cual vamos a desarrollar nuestra aplicación móvil. En mi caso elegí el iPhone5.

También colocamos un texto en el encabezado de nuestra forma, éste ejemplo será un conversor de monedas a través del consumo de un Servicio Web creado por el Banco de México, el cual nos proporciona el tipo de cambio de algunas monedas.

Ahora necesitamos decidir que objetos vamos a colocar en nuestra forma, en mi caso decidí colocar los siguientes:

  • 1 TListBox
  • 7 TListBoxItem’s
  • 2 TListBoxGroupHeader’s
  • 5 TLabel’s
  • 2 TEdit’s

También conseguí 6 banderas de los países que vamos (en éste ejemplo) a disponer de paridad cambiaria contra el peso mexicano.

Después de agregar los objetos y acomodarlos según me pareció adecuado, nos ha quedado como se muestra en la imagen.

  El primer paso es agregar el TListBox a nuestra forma y configuramos las siguientes propiedades:

  • GroupingKind = gsGrouped
  • StyleLookup = transparentlistboxstyle

Damos clic derecho del mouse en el ListBox donde nos mostrará un menú emergente donde seleccionaremos la opción AddItem y agregamos:

  • 7 TListBoxItem’s
  • 2 TListBoxGroupHeader’s

Continuamos agregando imágenes a los TListBoxItem; en éste ejemplo utilizaremos banderas de cada país del cual se tiene paridad cambiaria con el Peso mexicano, damos clic en la propiedad ItemData del TListBoxItem, damos clic en la propiedad BitMap y nos mostrará una ventana donde podrémos seleccionar la imagen que deseamos. También editamos el texto que se va a mostrar en la propiedad Text.

Adicionalmente colocamos los 2 TEdit y las 5 TLabel como se muestra en la imagen siguiente:

El siguiente paso es  generar nuestra clase que consumirá el Servicio Web del Banco de México y que nos proporcionará las paridades o tipos de cambio de las monedas que vamos a utilizar en nuestra aplicación, el WSDL de éste servicio web es el siguiente:

http://www.banxico.org.mx/DgieWSWeb/DgieWS?WSDL

Vamos a utilizar la forma tradicional de importar el WSDL a nuestra aplicación con el importador de WSDL como se muestra a continuación:

Éste importador genera el código necesario para poder consumir el servicioWeb y ya sólo nos resta escribir el código para que nuestra aplicación se conecte y nos muestre las paridades para cada una de las monedas seleccionadas y usarlas para convertir la cantidad de la moneda extranjera al peso mexicano. Por supuesto, ustedes pueden utilizar otro proveedor de paridades para ajustarlo a su moneda.   Ya tenemos todo para comenzar a escribir nuestro código.

Y como todo lo nuevo, hay algunos detalles que hay que tomar en cuenta a la hora de escribir nuestro código,

por ejemplo:

¿Cómo hacer que nuestra aplicación se ajuste en la pantalla para que no se encime en los contoles donde vamos a capturar el monto a convertir?.

La solución la encontré en uno de los ejemplos que vienen con delphi y se llama «ScrollableForm» el cual se encuentra en el directorio «RAD Studio\11.0\Samples\FireMonkeyMobile».

Se requirió de agregar dos componentes más, un TVertScrollBox y un TLayout para poder ajustar la pantalla cuando se intenta escribir en los controles sin que interfiriera el teclado numérico.

 

{******************************************************************************}
{  código para ajustar los objetos cuando se muestra el teclado en la pantalla }
{******************************************************************************}

procedure THeaderFooterForm.RestorePosition;
begin
  VertScrollBox1.ViewportPosition := PointF(VertScrollBox1.ViewportPosition.X, 0);
  Layout1.Align := TAlignLayout.alClient;
  VertScrollBox1.RealignContent;
end;

procedure THeaderFooterForm.UpdateKBBounds;
var
  LFocused : TControl;
  LFocusRect: TRectF;
begin
  FNeedOffset := False;
  if Assigned(Focused) then
  begin
    LFocused := TControl(Focused.GetObject);
    LFocusRect := LFocused.AbsoluteRect;
    LFocusRect.Offset(VertScrollBox1.ViewportPosition);
    if (LFocusRect.IntersectsWith(TRectF.Create(FKBBounds))) and
       (LFocusRect.Bottom > FKBBounds.Top) then
    begin
      FNeedOffset := True;
      Layout1.Align := TAlignLayout.alHorizontal;
      VertScrollBox1.RealignContent;
      Application.ProcessMessages;
      VertScrollBox1.ViewportPosition :=
        PointF(VertScrollBox1.ViewportPosition.X,
               LFocusRect.Bottom - FKBBounds.Top);
    end;
  end;
  if not FNeedOffset then
    RestorePosition;
end;

procedure THeaderFooterForm.FormCreate(Sender: TObject);
begin
  VertScrollBox1.OnCalcContentBounds := CalcContentBoundsProc;
end;

procedure THeaderFooterForm.FormVirtualKeyboardHidden(Sender: TObject;
  KeyboardVisible: Boolean; const Bounds: TRect);
begin
  FKBBounds.Create(0, 0, 0, 0);
  FNeedOffset := False;
  RestorePosition;
end;

procedure THeaderFooterForm.FormVirtualKeyboardShown(Sender: TObject;
  KeyboardVisible: Boolean; const Bounds: TRect);
begin
  FKBBounds := TRectF.Create(Bounds);
  FKBBounds.TopLeft := ScreenToClient(FKBBounds.TopLeft);
  FKBBounds.BottomRight := ScreenToClient(FKBBounds.BottomRight);
  UpdateKBBounds;
end;

procedure THeaderFooterForm.CalcContentBoundsProc(Sender: TObject;
  var ContentBounds: TRectF);
begin
  if FNeedOffset and (FKBBounds.Top > 0) then
  begin
    ContentBounds.Bottom := Max(ContentBounds.Bottom,
                                2 * ClientHeight - FKBBounds.Top);
  end;
end;
{******************************************************************************}

Scroll Vertical para reajustar la pantalla

Otro detalle era pasar el monto, la bandera y el texto de cada moneda, lo cual fué algo simple de resolver pasando las propiedades al seleccionar la moneda deseada hacia el objeto destino.

 
procedure THeaderFooterForm.lbDolarUSAClick(Sender: TObject); 
begin 
  TC := StringReplace(label1.Text,'

Escribimos el código necesario en el evento OnExit del Edit donde capturamos la cantidad a convertir para que nos muestre el valor en peso de acuerdo a la moneda seleccionada.

 
procedure THeaderFooterForm.Edit2Exit(Sender: TObject);
begin
  valorME := StringReplace(edit2.Text,'

Compilamos y Delphi XE4 hace su trabajo generando todo lo necesario para que nuestra aplicación sea ejecutada en el simulador.

Convertimos dólares a pesos

Convertimos Euros a pesos

Con ésto hemos terminado el primer artículo de una serie que intentará demostrar que se puede desarrollar 4 aplicaciones diferentes utilizando los mismo componentes y el mismo código, espero no defraudarlos 🙂

Los otros tres artículos son:

Happy coding!!!!

Descargas


Si lo deseas puedes descargar el código fuente de ésta entrada, espero sea de utilidad.

Ésta entrada y el código fuente son libres para su uso y publicación, lo único que te pido, si te parece justo, es mencionar la fuente de donde se obtuvo.


Lanzamiento RAD Studio XE4

2013-05-21 08.59.40

Hola,

El día de ayer (21 Mayo 2013) estuve en el lanzamiento de RAD Studio XE4 en la Ciudad de México. Una presentación que me ha dejado muy satisfecho con lo que los chicos de Embarcadero han hecho para proporcionarnos la opción de crear aplicaciones para dispositivos móviles iOS.

En ésta ocasión el encargado de darnos los pormenores de ésta nueva versión de RAD Studio fué Anders Ohlsson a quien podemos ver preparando su equipo antes de iniciar el evento, cabe mencionar que tuve la oportunidad de charlar un poco con él (mi inglés es muy pobre :)) y puedo asegurarles que es una persona muy agradable y atenta.

2013-05-21 08.34.11

Dió inicio la presentación de RAD Studio XE4 «la primera solución de desarrollo de aplicaciones nativas multi-dispositivo»

2013-05-21 09.18.26

Las ventajas de contar con una sólo herramienta de desarrollo son enormes ya que se traduce en un sólo código base, un sólo equipo y una sóla agenda, aúnado a la reducción de gastos que serían mucho más altos si se tuviera que desarrollar con diferentes herramientas para diferentes dispositivos.

2013-05-21 09.21.50

2013-05-21 09.25.58

Y ésto se logra con Firemonkey, la plataforma para la creación de aplicaciones de múltiples dispositivos realmente nativas para iOS, Windows y Mac que usa un solo código base y que de acuerdo a su arquitectura podrá acceder al popular sistema operativo Android, algo muy esperado por muchos….

2013-05-21 09.24.35

Algunas de las caracteristicas más relevantes de RAD Studio:

2013-05-21 09.28.18     2013-05-21 09.35.23

2013-05-21 09.32.42     2013-05-21 12.04.21   2013-05-21 10.02.55

2013-05-21 09.35.37

La asistencia fué de 100 personas exactamente, aunque es un buen número, seguimos extrañando aquellas presentaciones con mas de 200 asistentes, estoy seguro que la presentación de Android regresará esos números.

2013-05-21 09.36.25

En general la presentación fué muy interesante y algo peculiar en ésta ocasión fué que hubo pocas caras conocidas y muchas caras nuevas, algo que pudiera tener dos aristas, sin embargo, me reservo el comentario hasta ver la respuesta de la comunidad cuando Android salte a escena.

Hasta pronto

Consumir un Servicio Web de terceros

A petición de uno de mis lectores, he creado un pequeño cliente que consume un servicio web de terceros, en éste caso el mismo que usé para mi entrada anterior Probando Delphi for iOS  pero en una aplicación de escritorio.

El proceso es muy simple.

– Creamos una nueva aplicación VCL.

– Importamos el WSDL del Servicio Web en éste caso de Banxico.

Éste importador nos genera una clase con la definición del Servicio Web lista para ser consumida, como lo podemos apreciar en la siguiente imagen.

– Agregamos los objetos que deseamos para que nuestra interfáz gráfica se vea un poco decente 🙂

– Agregamos el código necesario para consumir el método que obtiene el tipo de cambio de las diferentes monedas y ejecutamos nuestra aplicación.

Cabe mencionar que por el poco tiempo que dispongo no pude utilizar el XML Data Binding para crear las clases que representan el esquema del documento XML por lo que tuve que «trabajar» con algo más simple para serializar el XML que nos regresa el Servicio Web.

Enjoy!!!

Nota: Desarrollado con Delphi XE2


Ésta entrada y el código fuente son libres para su uso y publicación, lo único que te pido, si te parece justo, es mencionar la fuente de donde se obtuvo.

Probando Delphi for iOS

Logo Delphi MVP

Como algunos saben, estoy muy involucrado en la creación y consumo de servicios web y desde hace tiempo había querido desarrollar un cliente que consumiera un servcio web desde dispositivos móviles tal y como lo hago en las aplicaciones de escritorio y puedo asegurarles que Delphi for iOS es inigualable, estoy muy entusiasmado por la rapidéz, facilidad y poderío al hacerlo con mi herramienta preferida.

Pues bien, he desarrollado un pequeño cliente para consumir un servicio web que nos proporciona el tipo de cambio de algunas monedas (USD Dólar, Dólar Canadiense, Euro, Yen y Libra Esterlina) con relación al peso mexicano y con ello poder hacer la conversión ya sea de pesos mexicanos a monedas extranjeras o al contrario.

El desarrollo de ésta app fué muy simple.

  • Importamos el wsdl de servicio web, en éste caso del Banco de México (http://www.banxico.org.mx/DgieWSWeb/DgieWS?WSDL)
  • Colocamos los componentes visuales necesarios.
  • Consumimos el método «tiposDeCambioBanxicoRequest» del servicio Web para mostrar los diferentes valores en pesos de las monedas extranjeras.
  • Escribimos las operaciones básicas para realizar la conversión de divisas.
  • Compilamos y ejecutamos la App en el simulador de iPhone instalado en mi MacBook Air.

 

vcl

La App funciona muy bien en el simulador de iPhone, se puede seleccionar la moneda que se deseé y se puede ingresar la cantidad que quieres convertir ya sea en pesos o en la moneda extranjera seleccionada. Como un pequeño detalle, la bandera de la moneda extranjera cambia de acuerdo a la moneda seleccionada en la parte superior.

iOS

Como ven es una App muy básica, pero las opciones son inmensas, por supuesto que no estoy descubriendo el hilo negro, ya hay muchas aplicaciones de éste tipo para dispositivos móviles, sin embargo, como prueba inicial, puedo asegurar que Delphi for iOS no me decepcionó, al contrario, me ha despertado un interés muy fuerte y sólo estoy en espera de que sea liberado.

Por hoy es todo, espero que ésta App les haya sido interesante e ilustrativa como lo fué para mi. Seguiremos probando Delphi for iOS, aún hay muchas cosas que quiero ver y el tiempo es poco 🙂

Hasta la próxima.

Importante: Considere que todo lo que se expresa en ésta publicación es acerca de un producto Beta por lo que los detalles finales pueden llegar a cambiar en el lanzamiento oficial.

Los únicos medios oficiales acerca de éste producto se encuentran en el sitio de embarcadero, puede acceder a los detalles en los siguientes enlaces :

Develop iOS applications with Delphi y en su mapa de ruta.

Ésta entrada sólo intenta mostrar de forma simple y sin entrar en detalles técnicos las facilidades que nos podría proporcionar el nuevo Delphi for iOS

Consumir WebService con acceso a Base de Datos

Hace un tiempo que publiqué un tutorial para  Crear y Consumir un WebService con las 4 funciones aritméticas básicas (suma, resta, multiplicación y división).

He creado un nuevo tutorial para  Consumir un Web Service con acceso a Base de Datos en la comunidad DelphiAccess.

El temario del tutorial es el siguiente.
Capítulo 1. Crear nuestra base de datos
Capítulo 2. Crear el Web Service

Capítulo 2.1 Creamos un Nuevo Proyecto
Capítulo 2.2 Creamos la Conectividad con la Base de Datos
Capítulo 2.3 La Clase TRemotable
Capítulo 2.4 Creando las funciones del ABM

Capítulo 3. Registrar el Web Service en el IIS
Capítulo 4. Crear la aplicación Cliente
Apéndice I

Espero que sea de ayuda y sobre todo que les de las bases para desarrollar aplicaciones robustas.

Salud OS