lunes, 22 de abril de 2019

Google - reCAPTCHA v3

Google ha lanzado reCAPTCHA v3 para evitar los robots de spam sin la interacción del usuario. reCAPTCHA v3 nos devuelve el puntaje de spam que se puede utilizar para realizar diversas acciones en su aplicación web.

reCAPTCHA v3. olvídate de “No soy un robot”

Google ha presentado el nuevo reCAPTCHA v3, la evolución del método de identificación en la web más popular. Gracias a él millones de páginas web pueden saber que en ella está entrando un ser humano, y no un robot que pueda tener oscuras intenciones. Este CAPTCHA fue creado para poder cribar a aquellos usuarios que funcionaran de una manera mecánica, y poder distinguirlos de meras máquinas. Ahora con esta nueva versión, el método se ha vuelto más inteligente, y necesita de menos interacción por parte del usuario para que la web sepa que no es un proceso automático. Las siglas CAPTCHA quieren decir “Completely Automated Public Turing test to tell Computers and Humans Apart” ("Prueba de Turing pública completamente automatizada para diferenciar a las computadoras y los humanos") un proceso que hasta ahora necesitaba de que superáramos ciertas pruebas, como reconocer objetos, resolver fórmulas matemáticas sencillas, o bien seleccionar con un aspa el texto de “no soy un robot” algo que con la nueva versión se elimina por completo. Ya no tendremos que superar este tipo de pruebas para demostrar que somos una persona en lugar de un robot. Todo gracias a un nuevo algoritmo que es capaz de saber si estamos comportándonos como lo haría una persona, o bien como una máquina. Ahora, si el algoritmo nota algún tipo de anomalía en la actitud de quien está entrando en la web, activará de nuevo estas pruebas. De esta manera se evita ralentizar el proceso de visitar las páginas. En este algoritmo entran variables como el movimiento de nuestro ratón, o los tiempos entre las pulsaciones al ratón que hemos hecho en nuestras visitas a distintas webs, para valorar si somos una persona o una máquina. Google le ha declarado la guerra al bot, y este es uno gran ejemplo.


Registre su sitio web y obtenga clave secreta
Lo primero que debe hacer es registrar su sitio web en Google reCAPTCHA para hacerlo, haga clic aquí.

Inicie sesión en su cuenta de Google y cree la aplicación rellenando el formulario. Seleccione el reCAPTCHA v3 y en esa opción de casilla de verificación "No soy un robot".

Credenciales
Una vez enviado, Google le proporcionará la siguiente información.

Clave del sitio
Llave secreta

Integra Google reCAPTCHA en tu sitio web.
Para integrarlo en su sitio web, debe colocarlo tanto en el lado del cliente como en el lado del servidor. En la página HTML del cliente, debe integrar esta línea antes de la etiqueta.

Nota:

Google reCAPTCHA v3 es invisible. No verás una forma de captcha de ningún tipo en tu página web. Necesitas capturar la respuesta de google captcha en tu código JavaScript. Aquí hay un pequeño fragmento.

Ícono reCAPTCHA
Esto generará un formulario y si se da cuenta, en la esquina derecha, verá un ícono reCAPTCHA de Google.

Como no tenemos un estilo de casilla de verificación, debemos capturar la respuesta de Google reCAPTCHA y enviarla al back-end para su verificación.

En el código, en el formulario de envío, obtenemos el token utilizando la función execute () de reCAPTCHA y pasamos el token junto con el correo electrónico y el comentario al código PHP, ASP mediante la función jQuery Ajax.

En el lado del servidor, vamos a usar PHP o ASP por ahora. Entonces, en la solicitud de envío de formulario, verificaremos la variable POST.

Ejecuta el código y rellena el formulario. Si Google no lo reconoce como un spammer, verá un cuadro de alerta que muestra el siguiente mensaje.

Respuesta API


Realice la solicitud para verificar el token de respuesta como con reCAPTCHA v2 o Invisible reCAPTCHA. La respuesta es un objeto JSON:

{
  "success": true|false,
  "challenge_ts": timestamp,  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
  "hostname": string,         // the hostname of the site where the reCAPTCHA was solved
  "error-codes": [...]        // optional
}

ASP


namespace Clase.Object
{
    public class ObjCaptcha
    {
        private string apiAddress = "https://www.google.com/recaptcha/api/siteverify";

        private string recaptchaSecret = Properties.Settings.Default.RecaptchaPrivateKey;

        public string RecaptchaVerify(string recaptchaToken)
        {
            string url = $"{apiAddress}?secret={recaptchaSecret}&response={recaptchaToken}";
            using (var httpClient = new HttpClient())
            {
                try
                {

                    string responseString = httpClient.GetStringAsync(url).Result;
                    return responseString;

                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }

}
        public class ResponseToken
        {

            public DateTime challenge_ts { get; set; }
            public float score { get; set; }
            public List<string> ErrorCodes { get; set; }
            public bool Success { get; set; }
            public string hostname { get; set; }
        }

 
}


Llamado ASP


<script src="https://www.google.com/recaptcha/api.js?render=token_key"></script>
    <script>
        grecaptcha.ready(function () {
            grecaptcha.execute(token_key, { action: 'homepage' }).then(function (token) {
                var recaptchaResponse = document.getElementById('recaptchaResponse');
                recaptchaResponse.value = token;
                $.ajax({
                    type: 'POST',
                    url: 'Captcha',
                    data: "{'token':'" + token + "'}",
                    contentType: 'application/json; utf-8',
                    dataType: 'json',
                    success: function (data) {
                        if (data.d != null || data.d.Estatus != false) {
                            if (data.d.Estatus != false) {
                            }
                        } else {
                        }
                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                    }
                });
            });
        });
    </script>

ObjCaptcha objCaptchas         = new ObjCaptcha();
            var responseString             = objCaptchas.RecaptchaVerify(token);
            ResponseToken response         = new ResponseToken();
            response = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseToken>(responseString.Result);


PHP


$email;$comment;$captcha;
  $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
  $comment = filter_input(INPUT_POST, 'comment', FILTER_SANITIZE_STRING);
  $captcha = filter_input(INPUT_POST, 'token', FILTER_SANITIZE_STRING);
  if(!$captcha){
    echo '<h2>Please check the the captcha form.</h2>';
    exit;
  }
  $secretKey = "-----put your secret here------";
  $ip = $_SERVER['REMOTE_ADDR'];

  // post request to server
  $url = 'https://www.google.com/recaptcha/api/siteverify';
  $data = array('secret' => $secretKey, 'response' => $captcha);

  $options = array(
    'http' => array(
      'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
      'method'  => 'POST',
      'content' => http_build_query($data)
    )
  );
  $context  = stream_context_create($options);
  $response = file_get_contents($url, false, $context);
  $responseKeys = json_decode($response,true);
  header('Content-type: application/json');
  if($responseKeys["success"]) {
    echo json_encode(array('success' => 'true'));
  } else {
    echo json_encode(array('success' => 'false'));
  }

Llamado PHP


<html>
  <head>
    <title>Google recapcha v3 demo - Codeforgeek</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <script src="https://www.google.com/recaptcha/api.js?render=put your site key here"></script>
  </head>
  <body>
    <h1>Google reCAPTHA Demo</h1>
    <form id="comment_form" action="form.php" method="post" >
      <input type="email" name="email" placeholder="Type your email" size="40"><br><br>
      <textarea name="comment" rows="8" cols="39"></textarea><br><br>
      <input type="submit" name="submit" value="Post comment"><br><br>
    </form>
      <script>
       // when form is submit
    $('#comment_form').submit(function() {
        // we stoped it
        event.preventDefault();
        var email = $('#email').val();
        var comment = $("#comment").val();
        // needs for recaptacha ready
        grecaptcha.ready(function() {
            // do request for recaptcha token
            // response is promise with passed token
            grecaptcha.execute('put your site key here', {action: 'create_comment'}).then(function(token) {
                // add token to form
                $('#comment_form').prepend('<input type="hidden" name="g-recaptcha-response" value="' + token + '">');
                    $.post("form.php",{email: email, comment: comment, token: token}, function(result) {
                            console.log(result);
                            if(result.success) {
                                    alert('Thanks for posting comment.')
                            } else {
                                    alert('You are spammer ! Get the @$%K out.')
                            }
                    });
            });;
        });
  });
  </script>
  </body>
</html>



Interpretando la partitura

reCAPTCHA v3 devuelve una puntuación (1.0 es muy probable que sea una buena interacción, 0.0 es muy probable que sea un bot). En función de la puntuación, puede realizar acciones variables en el contexto de su sitio. Cada sitio es diferente, pero a continuación hay algunos ejemplos de cómo los sitios usan la puntuación. Como en los ejemplos a continuación, actúe entre bastidores en lugar de bloquear el tráfico para proteger mejor su sitio.

Use caseRecomendación
homepageVea una vista coherente de su tráfico en la consola de administración mientras
filtra los raspadores.
loginCon puntajes bajos, se requiere autenticación de 2 factores o verificación por
correo electrónico para evitar ataques de relleno de credenciales.
socialLimite las solicitudes de amigos sin respuesta de usuarios abusivos y envíe
comentarios riesgosos a la moderación.
e-commercePonga sus ventas reales por delante de los robots e identifique las transacciones de
riesgo.



martes, 2 de abril de 2019

C# - Global.asax

El global.asax es el archivo de aplicación para todo proyecto ASP.NET, se encuentra en la raíz del proyecto. En él se declaran todos los eventos a nivel de aplicación como el inicio y fin de la misma, las peticiones web, etc... Es la evolución del antiguo global.asa existente en entornos de ASP clásico.
Se compila cada vez que inicia la aplicación. Cualquier modificación del archivo es detectada y origina el reinicio de la misma.

Eventos del global.asax

Entre todos los eventos global.asax, cabe destacar como principales los siguientes:
  • Application_Init: Inicio de la aplicación
  • Application_Disposed: Se dispara justo antes de que una aplicación sea destruida. Este método es ideal para limpiar anteriormente recursos que fueron utilizados.
  • Application_Start: Se dispara cuando se ha creado la primera instancia de la clase HttpApplication. Esto permite crear objetos que son accesibles a las todas las instancias de HttpApplication.
  • Application_End: Último evento lanzado antes de finalizar por completo la aplicación.
  • Application_Error: Se ejecuta cuando salta un error no controlado dentro de la aplicación.
  • Application_BeginRequest: Evento lanzado por cada petición de un cliente, ya sea el acceso a una url, una imagen, etc...
  • Application_EndRequest: Último evento antes de dar finalizada una petición.
  • Session_Start: Nueva sesión iniciada por un usuario. Muy usado junto al session_end para establecer contadores de usuarios activos.
  • Session_End: Fin de sesión para un usuario.

Usos del global.asax

Puede ser usado para múltiples tareas de gestión de las aplicaciones. Unos ejemplos pueden ser:
  • Declaración de filtros globales en el global.asax.
  • Interactuar con todas las peticiones. Puede usarse para gestionar las peticiones, modificar variables de app, crear un log de las mismas, etc...
  • Declarar modulos como el propio enrutado de asp.net.
  • Gestionar los errores de la aplicación. Recogiendo los mismos dentro del evento onApplicationError, se puede establecer un control de estos, guardando un log y gestionando las redirecciones según el tratamiento deseado

using System;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.SessionState;

namespace WebApplication1
{
    public class Global : System.Web.HttpApplication
    {

        void Application_Start(object sender, EventArgs e)
        {
            // Código que se ejecuta al iniciarse la aplicación

        }

        void Application_End(object sender, EventArgs e)
        {
             //  Código que se ejecuta cuando se cierra la aplicación

        }

        void Application_Error(object sender, EventArgs e)
        {
             // Código que se ejecuta al producirse un error no controlado

        }

        void Session_Start(object sender, EventArgs e)
        {
             // Código que se ejecuta cuando se inicia una nueva sesión

        }

        void Session_End(object sender, EventArgs e)
        {
             // Código que se ejecuta cuando finaliza una sesión.
            // Nota: el evento Session_End se desencadena sólo cuando el modo sessionstate
            // se establece como InProc en el archivo Web.config. Si el modo de sesión se establece como StateServer 
            // o SQLServer, el evento no se genera.

        }

    }
}

viernes, 29 de marzo de 2019

Paginas Web - Tipos MIME

 Hay dos tipos primarios de MIME son importantes para el rol de tipos por defecto:

  1. text/plain es el valor por defecto para los archivos textuales. Un archivo textual debe ser legible y no puede contener datos binarios.
  2. application/octet-stream es el valor por defecto para todos los demás casos. Un tipo de archivo desconocido debe usar este tipo. Los navegadores tienen un cuidado particular cuando manipulan estos archivos, tratando de proteger al usuario previéndo comportamientos peligrosos.

IANA es el registro oficial de los tipos de media MIME y mantiene una lista oficial de todos los tipos de MIME. Esta tabla, lista algunos de los tipos de MIME importantes para la web:

Extensión Tipo de documento Tipo de MIME
.aac Archivo de audio AAC audio/aac
.abw Documento AbiWord application/x-abiword
.arc Documento de Archivo (múltiples archivos incrustados) application/octet-stream
.avi AVI: Audio Video Intercalado video/x-msvideo
.azw Formato  eBook Amazon Kindle  application/vnd.amazon.ebook
.bin Cualquier tipo de datos binarios application/octet-stream
.bz Archivo BZip application/x-bzip
.bz2 Archivo BZip2 application/x-bzip2
.csh Script C-Shell application/x-csh
.css Hojas de estilo (CSS) text/css
.csv Valores separados por coma (CSV) text/csv
.doc Microsoft Word application/msword
.epub Publicación Electrónica (EPUB) application/epub+zip
.gif Graphics Interchange Format (GIF) image/gif
.htm Hipertexto (HTML) text/html
.html
.ico Formato Icon image/x-icon
.ics Formato iCalendar text/calendar
.jar Archivo Java (JAR) application/java-archive
.jpeg Imágenes JPEG image/jpeg
.jpg
.js JavaScript (ECMAScript) application/javascript
.json Formato JSON application/json
.mid Interfaz Digital de Instrumentos Musicales (MIDI) audio/midi
.midi
.mpeg Video MPEG video/mpeg
.mpkg Paquete de instalación de Apple application/vnd.apple.installer+xml
.odp Documento de presentación de OpenDocument application/vnd.oasis.opendocument.presentation
.ods Hoja de Cálculo OpenDocument application/vnd.oasis.opendocument.spreadsheet
.odt Documento de texto OpenDocument application/vnd.oasis.opendocument.text
.oga Audio OGG audio/ogg
.ogv Video OGG video/ogg
.ogx OGG application/ogg
.pdf Adobe Portable Document Format (PDF) application/pdf
.ppt Microsoft PowerPoint application/vnd.ms-powerpoint
.rar Archivo RAR application/x-rar-compressed
.rtf Formato de Texto Enriquecido (RTF) application/rtf
.sh Script Bourne shell application/x-sh
.svg Gráficos Vectoriales (SVG) image/svg+xml
.swf Small web format (SWF) o Documento Adobe Flash application/x-shockwave-flash
.tar Aerchivo Tape (TAR) application/x-tar
.tif Formato de archivo de imagen etiquetado (TIFF) image/tiff
.tiff
.ttf Fuente TrueType font/ttf
.vsd Microsft Visio application/vnd.visio
.wav Formato de audio de forma de onda (WAV) audio/x-wav
.weba Audio WEBM audio/webm
.webm Video WEBM video/webm
.webp Imágenes WEBP image/webp
.woff Formato de fuente abierta web (WOFF) font/woff
.woff2 Formato de fuente abierta web (WOFF) font/woff2
.xhtml XHTML application/xhtml+xml
.xls Microsoft Excel application/vnd.ms-excel
.xml XML application/xml
.xul XUL application/vnd.mozilla.xul+xml
.zip Archivo ZIP application/zip
.3gp Contenedor de audio/video 3GPP video/3gpp
audio/3gpp if it doesn't contain video
.3g2 Contenedor de audio/video 3GPP2 video/3gpp2
audio/3gpp2 if it doesn't contain video
.7z Archivo 7-zip application/x-7z-compressed

miércoles, 13 de marzo de 2019

iTextSharp - NET. C#

iText es una biblioteca de PDF que le permite CREAR, ADAPTAR, INSPECCIONAR y MANTENER documentos en el Formato de Documento Portátil (PDF), lo que le permite agregar la funcionalidad de PDF a sus proyectos de software con facilidad. Incluso tenemos documentación para ayudarle a obtener la codificación.

Actualmente contamos con dos versiones compatibles: iText 5 e iText 7. Ambas están disponibles bajo AGPL y licencia comercial.


iText 5 es una biblioteca de una solución que es compleja, pero está bien documentada para ayudarlo a crear sus soluciones.

iText 7 es una reescritura completa de iText 5, que le permite elegir su aventura con complementos, todo basado en una estructura de código modular simple, fácil de usar y bien documentada.

Ambas versiones le permiten:
- Genere documentos e informes basados ​​en datos de un archivo XML o una base de datos
- Crea mapas y libros, explotando numerosas funciones interactivas disponibles en PDF
- Agregue marcadores, números de página, marcas de agua y otras características a documentos PDF existentes
- Dividir o concatenar páginas de archivos PDF existentes
- Rellenar formularios interactivos.
- Servir documentos PDF generados o manipulados dinámicamente en un navegador web

iText 7 incluye pdfDebug, la primera herramienta de depuración que le brinda una visión general clara de sus flujos de contenido y estructura de documentos, así como pdfCalligraph, que le permite aprovechar la tipografía avanzada.

iText está disponible para Java, .NET en ambas versiones, y Android y GAE para iText 5 solamente.

iTextSharp es el puerto .NET de iText 5.

martes, 12 de marzo de 2019

Entity Framework - Caracteristicas

Características de Entity Framework


Multiplataforma: EF Core es un marco multiplataforma que puede ejecutarse en Windows, Linux y Mac.

Modelado: EF (Entity Framework) crea un EDM (Entity Data Model) basado en entidades POCO (Plain Old CLR Object) con propiedades get / set de diferentes tipos de datos. Utiliza este modelo al consultar o guardar datos de la entidad en la base de datos subyacente.

Consultas: EF nos permite usar consultas LINQ (C # / VB.NET) para recuperar datos de la base de datos subyacente. El proveedor de la base de datos traducirá estas consultas LINQ al lenguaje de consulta específico de la base de datos (por ejemplo, SQL para una base de datos relacional). EF también nos permite ejecutar consultas de SQL sin procesar directamente en la base de datos.

Seguimiento de cambios: EF realiza un seguimiento de los cambios ocurridos en instancias de sus entidades (valores de propiedad) que deben enviarse a la base de datos.

Guardar: EF ejecuta los comandos INSERT, UPDATE y DELETE en la base de datos en función de los cambios ocurridos en sus entidades cuando llama al método SaveChanges() . EF también proporciona el SaveChangesAsync() asíncrono SaveChangesAsync() .

Concurrencia: EF usa concurrencia optimista de forma predeterminada para proteger los cambios de sobrescritura realizados por otro usuario desde que se obtuvieron los datos de la base de datos.

Transacciones: EF realiza la administración automática de transacciones al consultar o guardar datos. También proporciona opciones para personalizar la gestión de transacciones.

Almacenamiento en caché: EF incluye el primer nivel de almacenamiento en caché fuera de la caja. Por lo tanto, las consultas repetidas devolverán datos del caché en lugar de golpear la base de datos.

Convenciones incorporadas: EF sigue las convenciones sobre el patrón de programación de la configuración e incluye un conjunto de reglas predeterminadas que configuran automáticamente el modelo EF.

Configuraciones: EF nos permite configurar el modelo EF utilizando atributos de anotación de datos o API Fluent para anular las convenciones predeterminadas.

Migraciones: EF proporciona un conjunto de comandos de migración que se pueden ejecutar en la Consola de NuGet Package Manager o la Interfaz de línea de comandos para crear o administrar un esquema de base de datos subyacente.

martes, 26 de febrero de 2019

Progress - comandos útiles

/* RECORRER TABLA*/
/*for each Endeds:
    display Endeds.
end.*/

/*BUSCAR PRIMER REGISTRO*/
/*find first Endeds
     no-lock no-error.*/

/*BUSCAR ULTIMO REGISTRO*/
/*find last Endeds
     no-lock no-error.*/


/*RECORRER TABLA CON CONDICION*/   
/*for each Endeds
    where Endeds.Ended = "1":
   
    display Endeds.Ended
            Endeds.Description.
end.           
*/


/*CREAR REGISTRO*/
/*create Endeds.
assign Endeds.Ended = "50"
       Endeds.Description = "prueba 50".     */


/*BUSCAR UN REGISTRO CONCRETO*/     
/*find Endeds
     where Endeds.ended = "50"
     no-lock no-error.
   
     display Endeds .
*/     


/*ELIMINAR REGISTRO*/   
/*   
find Endeds
     where Endeds.ended = "50"
     no-error.
   
     delete Endeds .
*/


/*ANIDAR TABLAS*/
/*for each TipFamiliy
    where TipFamiliy.tipFamiliy   = 1
    no-lock,
    each Families
    where Families.enterprise = 1 and
          Families.tipFamiliy  =   TipFamiliy.TipFamiliy
    no-lock:
   
    display TipFamiliy.Description
            Families.Description
            Families.Familiy.
   
end.   
*/         


/*CLAUSULAS BREAK BY*/
/*def var xcont as int.

for each TipFamiliy
    no-lock,
    each Families
    where Families.enterprise = 1 and
          Families.tipFamiliy  =   TipFamiliy.TipFamiliy
    no-lock
    break by Families.tipFamiliy:

    if first-of (Families.tipFamiliy) then
    do:
        XCONT = 0.
    end.
   
    XCONT = XCONT + 1.
   
    if LAST-OF (Families.tipFamiliy) then
    do:
        DISPLAY XCONT
                Families.tipFamiliy.
    end.
end.
*/


/*tablas temporales + exportaci¢n a fichero*/
def var xcont as int.

DEFINE TEMP-TABLE TMPJORDI
    FIELD TIPFAMILIA AS INT
    FIELD CONTADOR   AS INT
    INDEX IDX01
          TIPFAMILIA.


FOR EACH TMPJORDI:
    DELETE TMPJORDI.
END.

for each TipFamiliy
    no-lock,
    each Families
    where Families.enterprise = 1 and
          Families.tipFamiliy  =   TipFamiliy.TipFamiliy
    no-lock
    break by Families.tipFamiliy:

    if first-of (Families.tipFamiliy) then
    do:
        XCONT = 0.
    end.

    XCONT = XCONT + 1.

    if LAST-OF (Families.tipFamiliy) then
    do:
        CREATE TMPJORDI.
        ASSIGN TMPJORDI.TIPFAMILIA = FAMILIES.TIPFAMILIY
               TMPJORDI.CONTADOR = XCONT.
    end.
end.

output to "c:\tmp\datosjordi.txt".
FOR EACH TMPJORDI
    NO-LOCK:
    export TMPJORDI.
END.
output close.



&SCOPED-DEFINE TableToExport CatTipoTramiteIsai
output to "c:\tmp\ {&TableToExport}.txt".
FOR EACH {&TableToExport} NO-LOCK:
    EXPORT DELIMITER "|"   {&TableToExport}.
END.
output close.



output to "c:\tmp\CatalogoServicios.txt".
FOR EACH CatalogoServicios
    NO-LOCK:
    EXPORT DELIMITER "|"  CatalogoServicios.
END.
output close.


martes, 19 de febrero de 2019

Excel - Tips de Excel para Analisis de Datos

Tips de Excel

Buscar un Dato dentro de una columna( columna usada como vertor)

=BUSCARV(Reporte2!R110,Reporte1!$AD$11:$AD$620,1,FALSO)


Convertir una cadena con separador en columnas. (Texto en Columnas)

19.1000.1100.113.1131.9.5.1.1.1.13903
 =

|_____||_____||_____||_____||_____||_____||_____||_____||_____|

Quitar Duplicados por columna



Marcar los datos de una columna  con una segunda columna


Buscar un Dato dentro de una columna( columna usada como vertor)

=MATCH(A2,$B$2:$B$114,0)     Vs      =COINCIDIR(A2,$B$2:$B$114,0)

Concatenar columnas

=CONCATENAR(S11,".",T11,".",U11,".",V11,".",W11,".",X11,".",Y11,".",Z11,".",AA11,".",AB11,".",AC11)


Obtener el numero de apariciones de un caracter dentro de una cadena.

=LARGO(AF11)-LARGO(SUSTITUIR(AF11,".",""))



jueves, 14 de febrero de 2019

jQuery - Tips de jQuery

Mantener los selectores simples

Hasta hace poco, recuperar elementos DOM con jQuery era una combinación finamente coreografiada de cadenas de selector de análisis, bucles de JavaScript y API incorporadas como getElementById (), getElementsByTagName () y getElementsByClassName (). Pero ahora, todos los principales navegadores son compatibles con querySelectorAll (), que comprende los selectores de consultas CSS y aporta una importante ganancia de rendimiento.

Sin embargo, aún debe intentar optimizar la forma en que recupera los elementos. Sin mencionar que muchos usuarios todavía usan navegadores antiguos que obligan a jQuery a atravesar el árbol DOM, que es lento.

$('li[data-selected="true"] a')   // Fancy, but slow
$('li.selected a')  // Better
$('#elem')  // Best
Acceder al DOM siempre será la parte más lenta de cada aplicación de JavaScript, por lo que minimizarla es beneficioso. Una de las maneras de hacer esto, es almacenar en caché los resultados que jQuery le proporciona. La variable que elija tendrá un objeto jQuery, al que podrá acceder más adelante en su script.

var buttons = $('#navigation a.button');

// Some prefer prefixing their jQuery variables with $:
var $buttons = $('#navigation a.button');
('a.button:animated');   // Does not use querySelectorAll()
$('a.button').filter(':animated');  // Uses it
Deshabilitar el click derecho

Ya sea porque el cliente te lo solicite o tienes la necesidad de implementarlo, con JavaScript puedes deshabilitar facilmente el click derecho del mouse en una web. En esta pequeña entrada te enseño a hacerlo, simplemente tendrás que añadir la siguiente línea de código en al final de tu código html, antes del cierre de la etiqueta "body" de tu web, dentro de una etiqueta "script" como puedes ver a continuación.

<script type='text/javascript'>
 

document.oncontextmenu = function(){return false}
</script>


   También puedes hacerlo de otra manera si tienes implementada la librería de Jquery en tu web, con el siguiente código:
<script type='text/javascript'>
$(function(){
    $(document).bind("contextmenu",function(e){
        return false;
    });
});
</script>

Progress -Tips

dvc    + espacio         =        DEFINE VARIABLE  AS CHARACTER   NO-UNDO.

dvin   + espacio         =       DEFINE VARIABLE  AS INTEGER     NO-UNDO.

dvl     + espacio         =       DEFINE VARIABLE  AS LOGICAL     NO-UNDO.

MESSAGE 1 "cError". 

MESSAGE "cError" VIEW-AS ALERT-BOX INFO BUTTONS OK.


martes, 12 de febrero de 2019

Progress - Ejecutar Proceso

Un archivo .p

DEFINE INPUT  PARAMETER cvarcuentas    AS CHARACTER NO-UNDO.
DEFINE INPUT  PARAMETER iPer           AS INTEGER    NO-UNDO.
DEFINE INPUT  PARAMETER iYrP           AS INTEGER    NO-UNDO.
DEFINE INPUT  PARAMETER pctagsistema   AS CHARACTER  NO-UNDO.
DEFINE OUTPUT PARAMETER lError         AS LOGICAL INIT FALSE NO-UNDO.     
DEFINE OUTPUT PARAMETER cError         AS CHARACTER INIT "" NO-UNDO.


Llamando un archivo .r resultado, del archivo compilado .p.


RUN pCrea.r ON SERVER hAppsistem (INPUT   "19.1000",       
                                                 INPUT   28,                                           
                                                 INPUT   2019,                                           
                                                 INPUT   pcTagSistema,                                 
                                                 OUTPUT   plReturn,                                     
                                                 OUTPUT   pcReturn) NO-ERROR.                           

lunes, 11 de febrero de 2019

Progress - Using the CAN-FIND function



Using the CAN-FIND function



A menudo es necesario verificar la existencia de un registro sin recuperarlo para mostrarlo o actualizarlo. Por ejemplo, su lógica podría necesitar identificar a cada Cliente que tenga al menos un Pedido, pero es posible que no le importe recuperar ningún Pedido real. Para hacer esto, puede usar una alternativa a la declaración FIND que sea más eficiente porque solo verifica las entradas del índice siempre que sea posible para determinar si existe un registro, sin recurrir al trabajo adicional de recuperar el registro en sí. Esta alternativa es la función incorporada CAN-FIND. CAN-FIND toma un solo parámetro, que puede ser cualquier frase de selección de registro. La función CAN-FIND devuelve TRUE or FALSE dependiendo de si la frase de selección de registro identifica exactamente un registro en la base de datos.




Por ejemplo, imagine que desea identificar a todos los Clientes que hicieron pedidos desde 1997. No necesita recuperar o mostrar los Pedidos, solo necesita saber qué Clientes satisfacen este criterio de selección. El siguiente procedimiento simple logra esto:

FOR EACH Customer NO-LOCK WHERE Customer.Country = "USA":
  IF CAN-FIND(FIRST Order OF Customer WHERE Order.OrderDate < 1/1/98) THEN
    DISPLAY Customer.CustNum Customer.Name.
  ELSE
    DISPLAY Customer.CustNum "No 1997 Orders" @ Customer.Name.
END.


FOR EACH Customer NO-LOCK WHERE Customer.Country = "USA":
  FIND FIRST Order OF Customer NO-LOCK WHERE OrderDate < 1/1/98 NO-ERROR.
  IF AVAILABLE Order THEN
    DISPLAY Customer.CustNum Customer.Name Order.OrderDate.
  ELSE
    DISPLAY "No 1997 Orders" @ Customer.Name.
END.

Este procedimiento utiliza un pequeño truco de pantalla que no has visto antes. Si el cliente tiene pedidos para 1997, el procedimiento muestra el Customer name. De lo contrario, muestra la frase de texto No 1997Orders. Si incluye ese valor literal en la sentencia DISPLAY, se muestra en su propia columna como si fuera un campo o una variable. Para mostrarlo en lugar del campo Name, use el símbolo at-sign (@). La siguiente figura muestra el resultado.


Progress - CREATE BUFFER

CREATE BUFFER

Crea un objeto buffer dinámico.
Sintaxis

CREATE BUFFER handle FOR TABLE { table-name | table-handle | buffer-handle}
  [ BUFFER-NAME buffer-name ]
  [ IN WIDGET-POOL widget-pool-name ]


handle

Una variable de tipo HANDLE que representa el identificador del objeto de búfer.


FOR TABLE table-name|table-handle|buffer-handle


Una expresión de caracteres (table-name) que se evalúa como un nombre de tabla de base de datos único o un nombre de tabla temporal estática, un controlador de tabla temporal (table-handle) o un controlador de objeto de búfer existente (buffer-handle), cada uno de los cuales puede especificar el origen de registro para el que se crea el objeto de búfer.
Si el nombre de la tabla es ambiguo o existe, debe calificar el nombre de la tabla de la base de datos con un nombre de la base de datos o cambiar el nombre de la tabla temporal. De lo contrario, si la tabla de base de datos existe en varias bases de datos conectadas, el AVM crea el búfer en la primera base de datos conectada.

BUFFER-NAME buffer-name

Una expresión de tipo CHARACTER que evalúa, en tiempo de ejecución, el nombre del búfer dinámico que está creando. Esta opción permite que una consulta dinámica tenga múltiples buffers para la misma tabla.
IN WIDGET-POOL widget-pool-name
Una expresión de tipo CHARACTER que evalúa, en tiempo de ejecución, el nombre del grupo de widgets que contiene el búfer dinámico.
Nota: los nombres de grupos de widgets no distinguen entre mayúsculas y minúsculas.


DEFINE VARIABLE ix AS INTEGER NO-UNDO.
DEFINE VARIABLE qh AS HANDLE  NO-UNDO.
DEFINE VARIABLE bh AS HANDLE  NO-UNDO.
DEFINE VARIABLE fh AS HANDLE  NO-UNDO EXTENT 10.

CREATE BUFFER bh FOR TABLE "Customer".
CREATE QUERY qh.

qh:SET-BUFFERS(bh).
qh:QUERY-PREPARE("FOR EACH Customer").
qh:QUERY-OPEN().
qh:GET-FIRST().

DISPLAY bh:NAME.

REPEAT ix = 1 TO 10:
  fh[ix] = bh:BUFFER-FIELD(ix).
  DISPLAY fh[ix]:NAME STRING(fh[ix]:BUFFER-VALUE).
END.

qh:QUERY-CLOSE().
bh:BUFFER-RELEASE().
DELETE OBJECT bh.
DELETE OBJECT qh.