¿Cómo leer un fichero de Excel en ASP clásico?

Pues me encontraba estos días trabajando con una aplicación web antigua en ASP clásico que requería una nueva funcionalidad: importar datos que el cliente recibiría en una hoja de Excel, una hoja que en principio siempre tendrá el mismo formato. La duda era ¿cómo hago para leer el fichero de Excel con el viejo VBScript? Pues en este caso he usado el motor de Access 2010 (puede descargarse desde la web de Microsoft) y su conector OLEDB para tratar la hoja de Excel como si fuera una tabla SQL. Aquí os dejo un ejemplo del código:

Declare ExcelFile, Consulta, ExcelConnection, RSDatos
ExcelFile = "C:\Users\MiUsuario\MiCarpeta\MiExcel.xls"

Consulta= "SELECT [Campo1], [Campo2],[Campo3] FROM [Hoja1$]"
Set ExcelConnection = Server.createobject("ADODB.Connection")
ExcelConnection.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelFile & ";Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";"
SET RSDatos= Server.CreateObject("ADODB.Recordset")
RSDatos.Open Consulta, ExcelConnection

En resumen: creo una consulta para sacar los datos como si fuera un SQL, creo un objeto de conexión ADODB, me sirvo del motor de Access para pasarle como fuente de datos la ruta del fichero excel, creo un recordset y guardo los datos de la consulta en el mismo. Ahora ya puedo usar a mi gusto los datos almacenados en el recordset.

Javascript: sobreescribir el comportamiento del botón derecho del ratón en una web.

A veces, por lo que sea, en una aplicación web necesitamos sobreescribir el comportamiento standar del click derecho del ratón, que en lugar de abrirnos el menú contextual abra algo personalizado. Veamos lo básico ¿Cómo hacemos que en lugar del comportamiento por defecto ejecute el código que queramos? Pues recogiendo el evento y escribiendo nuestro propio código:

if (document.addEventListener) {
    document.addEventListener('contextmenu', function(e) {
        alert("NANAY DE ABRIR!!!!!"); //Aquí iría el código que quieres ejecutar en lugar del comportamiento por defecto
        e.preventDefault(); //esta línea evita el comportamiento por defecto
     }, false);
 } else {
    document.attachEvent('oncontextmenu', function() {
        alert("NANAY DE ABRIR"); ///aquí una alternativa
        window.event.returnValue = false;
    });
}

Visual Studio Code: seleccionar bloques de código encolumnados

Seguimos con consejillo para usar más cómodamente el Visual Studio Code. Vamos a imaginar que tenemos un bloque de código tal que así:

<input type="hidden" name="IdUsuario" id="IdUsuario" value="35" />
<input type="hidden" name="IdHuella" id="IdHuella" value="4667"/> 
<input type="hidden" name="IdMonos" id="IdMonos" value="99"  /> 
<input type="hidden" name="IdClase" id="IdClase" value="tr1" /> 

Ahora imaginemos que queremos seleccionar todas las ocurrencias de type=»hidden», si te fijas el código está redactado de tal forma que forman una columna. ¿Cómo podríamos seleccionar este bloque encolumnado? Pues bastaría con pulsar las teclas Shift+Alt y arrastrar con el ratón para hacer la selección encolumnada desde el inicio de la columna hasta el final, de esta forma podemos coger el bloque verticalmente.

Otra opción sería seleccionar la primera ocurrencia de type=»hidden» y después pulsar Ctrl+Shift+Alt y con la flecha abajo del teclado ir seleccionando las siguientes ocurrencias (o seleccionar la última ocurrencia e ir seleccionando hacia arriba con la flecha arriba, claro)

Visual Studio Code: Seleccionar varios elementos

Si trabajando con Visual Studio Code queremos modificar todas las ocurrencias de una cadena de texto en principio nos bastaría con pulsar Ctrl+H, que es el comando para buscar y reemplazar, ahí tenemos tanto la opción de modificar todas como la de ir saltando de una en una ocurrencia. ¿Y si no queremos recorrer todo? Podemos seleccionar un elemento y pulsar después Ctrl+D, lo que irá añadiendo a nuestra selección una por una todas las ocurrencias de esa cadena, cuando hayamos seleccionado las que queremos bastará con editar una para que se editen todas.

Otra opción es mantener pulsada la tecla ALT mientras hacemos click sobre las cadenas que queremos seleccionar, al que además nos permitirá seleccionar diferentes elementos si queremos y no solo los que coincidan con la cadena que buscamos.

Visual Studio Code: comentar y descomentar varias líneas

Llevo una temporadita que trabajo principalmente con Visual Studio Code (como sabréis por aquel meme) así que de vez en cuando puede que deje por aquí algún truquillo-consejo (que seguramente ya hayan comentado mil blogs más). Empecemos por este ¿Cómo se puede comentar rápidamente un montón de líneas?

Pues para comentar en Windows o en Linux primero seleccionamos las líneas que queremos comentar, después pulsamos la tecla CTRL y mientras la mantenemos pulsada también pulsamos primero la tecla K y luego la tecla C. En caso de que trabajéis con uno de esos equipos propiedad de Apple entonces tendréis que cambiar la tecla CTRL por la tecla CMD.

Pues para descomentar en Windows o en Linux es similar, primero seleccionamos las líneas que queremos comentar, después pulsamos la tecla CTRL y mientras la mantenemos pulsada pulsamos primero la tecla K y luego la tecla U. De nuevo en caso de que trabajéis con uno de esos equipos propiedad de Apple, tendréis que cambiar la tecla CTRL por la tecla CMD.

Crear una tabla HTML con cabecera fija, usando CSS3

Si bien los elementos table suenan a cosa del pasado, a aquellos tiempos en los que todo se hacía con tablas y de vez en cuando algo de flash o similar, todavía siguen utilizándose tablas en el mundo de la programación y diseño web, ya no como elemento central y básico de la maquetación, pero sí para por ejemplo presentar datos en ese formato de filas/columnas.

Si tenemos una tabla muy larga la solución tradicional ha sido siempre la paginación, que con el tiempo fue sustituída por elementos que van insertando nuevas filas de forma asíncrona mientras hacemos scroll. En estos casos puede pasar que hayamos bajado mucho, la cabecera ya no esté visible y no tengamos muy claro a qué corresponde cada columna. Una solución podría ser repetir la cabecera cada x filas, pero se puede hacer visualmente incómodo. Otra posibilidad es hacer fijas estas cabeceras de forma que siempre estén visibles en pantalla y bajen mientras hacemos scroll.

Parece que lo lo lógico sería que pudiésemos hacer fijos los elementos thead o tr, ya que queremos que toda la línea quede fijada, pero aunque nos parezca lo elemental no será posible. Para fijar un elemento de esta forma tenemos que ponerle position:relative y esta característica no se aplica a esos elementos, esto implica que tendremos que usarlo obligatoriamente sobre las celdas, sobre los elementos th o td.

Supongamos que tenemos una tabla como esta (bueno, con cientos de registros para que tenga sentido la cabecera fija):

<table>
  <thead>
    <tr>
       <th>Nombre</th>
       <th>Edad</th>
       <th>Salario</th>
       <th>Rango</th>
       <th>Area</th>
     </tr>
    </thead>
   <tbody>
    <tr>
       <td>Manuela Z.</td>
       <td>43</td>
       <td>24000</td>
       <td>Analista</td>
       <td>Big Data</td>
     </tr>
  </tbody>
</table>

Si queremos fijar la cabecera el CSS, lo más básico posible, sería tal que así:

table {
  position: relative;
  border-collapse: collapse; 
}
th, td {
  padding: 6%;
}

th {  
  position: sticky;
  top: 0; 
}

Hay tres puntos clave en ese CSS: el position:relative de la tabla, el position:sticky del elemento th y la posición top:0 también del elemento th. De esta forma le decimos que todas las celdas de la cabecera se queden fijas en la parte superior de la tabla, así al bajar el scroll estas bajarán con él.

Generar un fichero de EXCEL con ASP

Una entrada rápida: queremos que una página ASP en lugar de mostrarnos la información en el navegador lo que haga sea generar un fichero de EXCEL y que se descargue en nuestro equipo ¿Es posible? Sí.

Solo necesitamos añadir dos cabeceras al inicio del documento:

Response.ContentType="application/vnd.ms-excel"
Response.AddHeader "Content-Disposition", "attachment; filename=NombreFichero.xls"

PostgreSQL: Instrucciones básicas de gestión de tablas

Una entrada básica de SQL ¿Cuáles son las instrucciones básicas de gestión de tablas en el SGBD PostgreSQL? Veámoslas:

Crear tabla (para el ejemplo crearemos una tabla de de tres columnas, con un id autonumérico, una columna de texto que no admite nulos y una columna para números decimales con un valor por defecto de 0):

CREATE TABLE t (
  id SERIAL PRIMARY KEY,
  columna1 VARCHAR NOT NULL,
  columna2 NUMERIC(10,2) DEFAULT 0
);

Para borrar una tabla tenemos dos opciones, la primera de ella será hacerlo con el parámetro RESTRICT o sin ningún parámetro, pues esta es la opción por defecto. Si hay objetos que dependan de esa tabla, como vistas o claves externas, no borrará la tabla y nos devolverá un mensaje de error informándonos:

DROP TABLE laTablaQueSea RESTRICT;

La otra opción es borrar en casacada, con el parámetro CASCADE. En este caso borra la tabla y todos los objetos que dependan de la misma.

DROP TABLE laTablaQueSea CASCADE

Si lo que queremos es añadir una columna entonces tenemos que usar ALTER TABLE seguida de la instrucción ADD COLUMN especificando el nombre de columna, el tipo de datos y las restricciones que se aplicarán sobre la misma.

ALTER TABLE laTablaQueSea
ADD COLUMN nombreDeColumna tipoDeDatos constraint;

Si queremos añadir varias columnas solo tenemos que repetir la instrucción ADD COLUMN separada por comas:

ALTER TABLE laTablaQueSea
ADD COLUMN nombreDeColumna tipoDeDatos constraint,
ADD COLUMN nombreDeColumna2 tipoDeDatos constraint,
ADD COLUMN nombreDeColumna3 tipoDeDatos constraint;

En cambio si queremos borrar una columna tenemos que usar DROP COLUMN seguido del nombre de la columna:

ALTER TABLE laTablaQueSea DROP COLUMN nombreDeColumna;

Para deshabilitar los triggers vinculados a una tabla tenemos que usar también ALTER TABLE:

ALTER TABLE laTablaQueSea DISABLE TRIGGER ALL;

Para volver a habilitar estos triggers sería lo mismo pero con el parámetro ENABLE:

ALTER TABLE laTablaQueSea ENABLE TRIGGER ALL;

Para añadir alguna restricción a la tabla también usamos ALTER TABLE, en ese caso seguido de ADD y de la restricción que sea.

ALTER TABLE laTablaQueSea ADD laRestriccionQueQuieras;

Para borrar una restricción sobre una tabla utilizamos ALTER TABLE, pero ahora con DROP:

ALTER TABLE laTablaQueSea DROP laRestriccionQueQuieras;

Para renombrar una tabla tenemos que usar RENAME después del ALTER TABLE:

ALTER TABLE laTablaQueSea RENAME TO otroNombreDeTabla;

Y para renombrar una columna es similar:

ALTER TABLE laTablaQueSea RENAME columna1 TO columna2 ;

Finalmente si queremos borrar todos los datos de una tabla sin borrar la tabla, nuestra opción es la instrucción TRUNCATE TABLE:

TRUNCATE TABLE laTablaQueSea CASCADE;

Búsqueda binaria o dicotómica

Durante el corto tiempo que tuve cuenta en CuriousCat (lo borré porque para recibir insultos anónimos ya me llega con Tweeter y los comentarios de este blog) alguien me pidió que escribiera sobre la diferencia entre una búsqueda binaria y una búsqueda dicotómica. Eso se lo contesté rápidamente allí: búsqueda dicotómica y búsqueda binaria son sinónimos, no hay diferencia.

¿En qué consiste la búsqueda binaria?

Cuando hablamos de búsqueda binaria hablamos de un algoritmo, una serie de instrucciones para que un programa informático realice una tarea. Concretamente de un algoritmo de búsqueda, es decir, la serie de instrucciones necesarias para encontrar un valor dentro de una colección de valores. La búsqueda binaria está pensada para buscar un elemento dentro de una colección ordenada. Vamos a explicar cómo funciona con un ejemplo: imagínate que tuvieras una lista con todos los habitantes de Barcelona ordenada por la primera letra de su apellido, tienes que buscar a alguien que se apellida «Martínez» ¿te pondrías a mirar la lista desde el principio hasta llegar a ese nombre? Son millones de comprobaciones. Ese procedimiento sería el de una búsqueda lineal: comprobar todos los valores hasta encontrar el deseado, funciona pero es muy lento, tiene utilidad cuando no queda más remedio (una colección desordenada) pero es demasiado ineficiente para una lista ordenada.

Aplicando una búsqueda binaria a ese ejemplo lo que haríamos sería encontrar primero el valor del medio de la lista, dividir la lista en dos mitades y comprobar si el valor intermedio es el que buscamos, es menor o es mayor. Si se diera la casualidad de que es el que buscamos la búsqueda ya estaría finalizada, si el valor intermedio es menor descartaríamos la mitad inferior de la lista y si es mayor descartaríamos la mitad superior. Ahora que localizamos en qué mitad tiene que estar nuestro valor repetimos el procedimiento sobre esa mitad, creando otras dos mitades y de nuevo repitiendo el procedimiento hasta dar con nuestro valor. En cada iteración descartamos la mitad de los datos que teníamos, lo que reduce el tiempo de búsqueda respecto a la lineal.

¿Se usa este algoritmo?

La mayoría de lenguajes de programación o frameworks ya tienen funciones de búsquea integradas muy bien optimizadas, así que no es habitual que alguien tenga que escribir una función de búsquea binaria, excepto en ejercicios académicos para aprender algoritmia. Yo personalmente he utilizado este método para buscar entre conjuntos de datos manualmente, cuando no disponía de un índice. Aquí abajo os dejo una implementación del algoritmo en Javascript:

function buscaDicotomica(valor, conjunto) {
    //valor es lo que vamos a buscar, cojunto es el array donde lo buscamos
    var ini = 0;    //inicio del array
    var fin = conjunto.length - 1;   //fin del array
    var pos = -1;
    var finaliza = false;
    var media;
 
    while (finaliza === false && ini<= fin) {
        media= Math.floor((ini+ fin)/2);
        if (conjunto[media] == valor) {
            finaliza = true;
            pos  = media;
        } else if (conjunto[media] > valor) {  //si está en la mitad inferior
            fin= media - 1;
        } else {  //si está en la mitad superior
            ini= media+ 1;
        }
    }
    return pos;
}

Script de PowerShell para enviar un correo con Gmail

Un compañero necesitaba un script de PowerShell que enviase un correo con un texto concreto desde su dirección de email a otra dirección fija, pero no lograba que funcionase correctamente utilizando su cuenta de Gmail. En su día por aquí, ya hace años, hablamos sobre cómo enviar correos desde una cuenta de Gmail usando PHPMailer, así que durante la hora de comer le he echado una mano y he hecho algo sirviéndome del cmdlet Send-MailMessage:

$username   = 'tucorreo@gmail.com'
$password   = 'tupassword'
$secstr     = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}

$brocolharum = @{
    from       = "tucorreo@gmail.com"
    to         = "correoquerecibe@gmail.com"
    subject    = "Danger Danger, high voltage!"
    smtpserver = "smtp.gmail.com"
    port       = "587"
    body       = "Si te estás leyendo esto me debes un capuccino con licor de avellana"
    credential = New-Object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
    usessl     = $true
    verbose    = $true
    DeliveryNotificationOption = "OnFailure"
}

Send-MailMessage @brocolharum

Se trata de un ejemplo muy básico, después podéis adaptarlo a vuestras necesidades.