21/2/18

Variables en SqlServer

En ocasiones es cómodo almacenar en una variable un valor si se van a hacer varias consultas. Siempre se puede repetir la consulta original pero a veces no tiene sentido.

Para hacer esto en SqlServer...

declare @idDeTrabajo int;
select @idDeTrabajo = (select id from nuestraTabla where claveAlternativa like 'ED820');--sin paréntesis falla

select * from Telefono where idTrabajo = @idDeTrabajo;
select * from DireccionPostal where idTrabajo = @idTrabajo;

Subtabla separada por comas.

Si queremos facilitar la visualización desde sqlpuro de una relación de uno a muchos, en ocasiones, es conveniente mostrar los datos de esa "subtabla" en un campo. Físicamente se almacena en una tabla separada pero, para visualizar la visualización, la mostramos como un campo.
Explico el ejemplo:
  • Tenemos una relación de muchos a muchos (Productos, Categorias)
  • La pasamos a una relación de uno (Productos) a muchos (Categorías unida con ProductosCategorias)
  • Mostramos la lista de productos con un campo que se extrae de la tabla de la parte muchos.
Con SqlServer se podría hacer como muestra el ejemplo:
SELECT Productos.Nombre, 
 STUFF(
    (SELECT ', '  + Categorias.Categoria
    FROM Categorias
    INNER JOIN ProductosCategorias ON ProductosCategorias.idCategoria = Categorias.idCategoria
    WHERE ProductosCategorias.idProducto = Productos.idProducto
    FOR XML PATH('')),
    1, 2, '') As Categorias
FROM Productos

1/2/18

Powershell. Problema al instalar paquetes npm que incluyen "@" arroba.

npm install @types/chai --save-dev

El comando powershell superior da un error "Símbolo (token) no reconocido en el texto de origen."

El problema está en la "@". En powershell el símbolo @ se usa para definir cosas que siguen como arrays, literales de más de una línea, etc. por lo que no funciona tal y como funcionaría en cmd.exe o shells de linux

Para solucionarlo en Powershell, hemos de poner entre comillas el paquete que incluya la @

npm install "@types/chai" --save-dev

9/1/18

Powershell. Que no trunque las propiedades al mostrarlas.

En ocasiones cuando mostramos algo en powershell, si la propiedad es muy grande la trunca y muestra "..." al final de la misma y perdemos esa parte del dato. Para evitar esto, por ejemplo con rutas largas podemos hacer lo siguiente.
Buscar todos los directorios y ficheros que contengan "Test" y guarda la ruta completa.
dir -Recurse *Test* | select fullname  |Out-File -width 230 .\borrame.test.txt
Los pasos son:

  1. Buscar Test
  2. Selecciona el nombre completo
  3. Lo pasa a un fichero "borrame.test.txt" con una anchura de 230 caracteres (donde en principio suponemos que entrará la cadena)
Si no ponemos el -width 230 se truncaría en el ancho por defecto.

Me edito a mi mismo. Hay una solución mejor.

Si en lugar de "select fullname" escribirmos "% fullname", pasa a la línea siguiente sin problemas. tendríamos:
dir -recurse *.* | % fullname
Nos mostrará todos los ficheros, con la ruta completa y uno por línea, si se pasa de una línea lo pone en 2.
Además si al final ponemos " | clip ". Nos lo copiará al portapapeles.
dir -recurse *.* | % fullname | clip

27/11/17

Scrapping con C#. Listas de Contratación Temporal de la Xunta.

url es la variable con la url a scrapear //valga el palabro

"//td[@align='left']" es una expresión xpath que devolvería los TD con alineación izquierda

Para hacer el scrapping con cSharp usamos ScrapySharp

Hay ejemplo completo en GitHub aquí

Código:

ScrapingBrowser Browser = new ScrapingBrowser();
Browser.UserAgent = new FakeUserAgent("primero", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0");
Browser.AllowAutoRedirect = true; // Browser has settings you can access in setup
Browser.AllowMetaRedirect = true;
WebPage PageResult = await Browser.NavigateToPageAsync(new Uri(url));
IEnumerable TDs = PageResult.Html.SelectNodes("//td[@align='left']");
this.lNombre.Clear();
foreach (HtmlNode item in TDs) {
    this.lContenidosTDs.Add(item.InnerText);
}

22/11/17

Comprobación de Consulta das Listas de Vinculación Temporal Decreto 37/2006. Javascrip

Está también en Github

const fileName = "./personas.json";
const Horseman = require("node-horseman");
const cheerio = require('cheerio')
const fs = require('fs');

var horseman = new Horseman();

var Personas = [];
var PersonasAnteriores;
var grabarFichero = false;

function GestionDeParametros(params){
if(params.length == 3){// así es que se envía un parámetro
grabarFichero = true;
}
}
function getPersonas(body) {
var $ = cheerio.load(body);
//$(".taboadatos TD");
var columna = 0;
$('.taboadatos TD').each(function () {
columna++;
if (columna === 1) {
Personas.push($(this).text());
}
if (columna === 4) {
columna = 0;
}

});
if(grabarFichero){
fs.writeFileSync(fileName,JSON.stringify(Personas),'utf-8');
}
var i = 0;
console.log("LISTA DE CAMBIOS DE LAS LISTAS DEL B SEGÚN FICHERO: " + fileName);
console.log("===================================================");
Personas.forEach(element => {
if (element === PersonasAnteriores[i]) {
console.log("" + (i + 1) + ": (IGUALES) " + element);
} else {
console.log("" + (i + 1) + ": (DIFERENTES) " + element + '///' + PersonasAnteriores[i]);
}
i++;
});
}

function ShowPersonas(per) {
console.log(per);
}

function CargarPersonasAnteriores() {
try {
PersonasAnteriores = JSON.parse(fs.readFileSync(fileName, 'utf-8'));
} catch (err) {
console.error(err);
console.error("No existe el fichero generelo con: ***");
}
}

GestionDeParametros(process.argv);
CargarPersonasAnteriores();

horseman
.userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0")
.open('http://www.xunta.es/rcp/listas/rcp_li05/li05_lista_ambito_sel.jsp?rcpCOD_LISTA=76&rcpCOD_AMBITO=U0000&rcpDES_AMBITO=AMBITO%20AUTON%D3MICO&lang=gl')
.waitForSelector("TD")
.html()
.then(function (body) {
getPersonas(body)
horseman.close();
})
;

20/11/17

Test. Clase de ayuda para envío de pulsaciones de teclas.

SSk: Static Send Keys.

Es un envoltorio para facilitar el uso de la función "SendKeys.SendWait(string keys)" y algunas utilidades más como introducir un tiempo de espera entre pulsación y pulsación. También permite generar apropósito tiempo de espera (Tread.Sleep(miliseconds)) y facilita el envío de algunas teclas especiales.

Se encuentra en github como parte del proyecto Utils pero es, de momento, muy independiente y no necesita nada del resto del proyecto.

https://github.com/IvanCruzFraguela/UtilNs/blob/master/Test/SSk.cs

28/9/17

SqlServer. Asociar usuarios de Directorio Activo a Base de Datos.

Hay que estar en la Base de Datos:

use DatabaseName;
Luego hay que crear el usuario para la base de datos:
create user [dominio\usuarioOGrupo];

Se me hace extraña la notación entre corchetes pero es así. Hay que poner el corchete, dominio, barra invertida, usuario o grupo AD y corchete.

Una vez que el usuario ya lo tiene en cuenta SqlServer, hay que decirle para qué lo vamos a usar. Se pueden dar todo tipo de permisos por tabla y/o columna pero lo típico será asignarlo a uno de los roles que tenga la Base de datos.

alter role [db_datareader,db_datawriter,...] add member [dominio\usuarioOGrupo];

En este caso los primeros corchetes no se ponen, son para definir que hay que elegir alguno de los roles. Por ejemplo:

alter role db_datawriter add member [empresa\vendedores];

Esto daría permiso de escritura en la Base de Datos activa a los pertenecientes al grupo vendedores en nuestro dominio (empresa)

Con esto, los pertenecientes a un grupo de Directorio Activo podrán, por ejemplo, escribir en una base de datos. Una vez que a ese usuario de dominio se le quita del grupo, ya no podrá hacerlo.

21/9/17

Operaciones con campos Identity (SqlServer)

Muchas de las tablas que uso tienen campos autonuméricos, llamados Identity, en SqlServer.

Si necesitamos introducir un número específico en esos campos, por ejemplo, porque estemos copiando una tabla de otra base de datos, o queramos tener unos valores específicos en algunos registros, tenemos que parar esa inserción antes de hacerlo.
Para ello usamos el comando:
set identity_insert [tabla] off;
set identity_insert [tabla] on; // Para dejarlo como estaba
Es importante tener en cuenta que SqlServer solo permite parar una inserción a la vez por Base de Datos. No podríamos tener dos tablas con la inserción parada. Habría que parar una, hacer las operaciones correspondientes, dejarla con la inserción activa de nuevo, y entonces parar la siguiente.
Tras esto, para fijar el valor en el que queramos que siga la inserción (normalmente igual al mayor número insertado hasta ahora) habría que ejecutar el comando:
DBCC CHECKIDENT ('[tabla]', RESEED,[numeroapartirdelcualsumar1]);

20/6/17

SqlServer. Lista de tablas y tablas relacionadas (Foreing key)

Lista de tablas
select * from sys.all_objects where type like 'U'

Tablas relacionadas con una dada.
SELECT   
   distinct OBJECT_NAME (f.referenced_object_id) AS referenced_object  
   FROM sys.foreign_keys AS f  
   WHERE f.parent_object_id = OBJECT_ID('[Nombre_tabla]');

15/5/17

Otro de envío de teclas.

Ejecuta un chrome y le envía las teclas para probar la página

Parece funcionar. Habría luego que comprobar que la página ha hecho lo que se le ha pedido



Process p = new Process();
p.StartInfo.FileName = @"C:\Program Files (x86)\Google\Chrome\Application\Chrome.exe";
p.StartInfo.Arguments = @"file:///C:/Users/usuario/Desktop/borrame.html";//html que se quiere probar
p.Start();
p.WaitForInputIdle();
Thread.Sleep(1000);
SendKeys.SendWait("{TAB}");
SendKeys.SendWait("hola a todos");
SendKeys.SendWait("{Tab}");
SendKeys.SendWait("{Enter}");
Thread.Sleep(1000);
p.CloseMainWindow();

Lectura de datos de usuario de directorio activo a un fichero.

Está también en github aquí
using System;

using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.IO;

namespace udaExe {
    class Program {
        static void Main(string[] args) {
            string ldapEntry;
            string fileName;
            int cantUsuarios = 0;
            if (!GetParameters(args, out ldapEntry, out fileName)) {
                Console.Out.WriteLine("uso: udaExe ldap fichero");
                Console.Out.WriteLine("Ejemplo: udaExe \"LDAP://OU=Users,dc=microsoft,dc=local\" \"c:\\usuarios.txt\"");

            } else {
                Console.Out.WriteLine("Buscando usuarios:");

                using (StreamWriter sw = File.CreateText(fileName)) {
                    try {
                        DirectoryEntry directoryObject = new DirectoryEntry(ldapEntry);
                        foreach (DirectoryEntry child in directoryObject.Children) {
                            string displayName = GetProperty(child, "displayName");
                            string distinguishedName = GetProperty(child, "distinguishedName");
                            string samAccountName = GetProperty(child, "samAccountName");
                            child.Close();
                            child.Dispose();
                            sw.WriteLine($"{displayName}#{samAccountName}#{distinguishedName}");
                            cantUsuarios++;
                        }
                        directoryObject.Close();
                        directoryObject.Dispose();
                    } catch (DirectoryServicesCOMException ex) {
                        Console.Error.WriteLine("Error: " + ex.Message.ToString());
                    }
                }
                Console.Out.WriteLine(cantUsuarios.ToString() + " usuarios encontrados, fichero generado: " + fileName);
            }
        }

        public static string GetProperty(DirectoryEntry de, string PropertyName) {
            if (de.Properties.Contains(PropertyName)) {
                return de.Properties[PropertyName][0].ToString();
            } else {
                return string.Empty;
            }
        }

        public static bool GetParameters(string[] args, out string ldap, out string fileName) {
            ldap = String.Empty;
            fileName = @"c:\users.txt";
            if (args.Length < 1) {
                return false;
            }
            ldap = args[0];
            if (args.Length >= 2) {
                fileName = args[1];
            }
            return true;
        }
    }
}

30/3/17

Disposición típica en HTML con etiquetas semánticas.

Está sacado de:
https://www.w3.org/TR/css-flexbox-1/



<!DOCTYPE html>
<header>...</header>
<main>
   <article>...</article>
   <nav>...</nav>
   <aside>...</aside>
</main>
<footer>...</footer>

3/2/17

Ordenar tablas de una base de datos para que las referenciadas estén antes de las que referencian

public void OrdenaTablas() {
    List listaOrdenada = new List();
    while (this.lTable.Count > 0) {//mientras haya elementos
        ColocaTablaEnOrden(this.lTable, this.lTable[0], listaOrdenada);
    }
    foreach (var item in listaOrdenada) {
        lTable.Add(item);
    }
}
private void ColocaTablaEnOrden(List listaOriginal, CTableM cTableM, List listaOrdenada) {
    listaOriginal.Remove(cTableM);
    foreach (CRelationM relacion in cTableM.lRelation) {
        string NombreTablaConLaQueSeRelaciona = relacion.tableDestination;
        CTableM tablaRelacionada = listaOriginal.Find(x => x.Name.Equals(NombreTablaConLaQueSeRelaciona));
        if (tablaRelacionada != null) {//Si la tabla relacionada aún está en la lista de tablas a ordenar
            //Meter antes en la lista de ordenadas
            ColocaTablaEnOrden(listaOriginal, tablaRelacionada, listaOrdenada);
        }
    }
    listaOrdenada.Add(cTableM);
}

14/9/16

Crear servicio en Windows:

1 - Nuevo proyecto de tipo: Installed → Visual C# → Classic Desktop → Windows Service.
2 - Saca un editor en donde poner componentes pero lo más importante es poner la propiedad (F4) “ServiceName”. Esta propiedad será el nombre que tiene el servicio en Windows. No será el nombre del ejecutable.
3 - Añadir un “Instalador” se hace con “Add Instaler” en la parte baja de la pestaña de propiedades. No sé exáctamente para qué sirve, pero ahí podremos poner una descripción del servicio y algunas propiedades interesantes más, pero si no se añade esto, luego no se “Instala” el servicio.
4 - “Instalar el Servicio”. No se puede ejecutar directamente, hay que instalarlo y luego iniciarlo. Para instalarlo hay que ejecutar: InstallUtil con el nombre del fichero ejecutable.
c:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe .\PCSService.exe

5 - “Arrancar el Servicio”. Se hace con net start y el nombre del servicio que hemos puesto en el paso 2.
net start XviConSl

Nota final:
Si en las propiedades del Servicio hemos puesto "AutoLog" a true (que viene por defecto) podremos ver con el visor de eventos (ejecutar "eventvwr" en cmd) mensajes del servicio al instalarse, iniciar, parar tanto en la parte de "sistema" como en la de "aplicaciones".

 

24/8/16

Html y css. Esqueleto página centrada horizontalmente

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml">
 <head> 
  <style> 
   div.clBloqueEncabezado{ 
                  background-color: cyan; 
    text-align: center; 
   } 
   div.clEncabezado{
    display:inline-block;
    background-color:green; 
    padding:0.5em; 
   } 
   div.clCuerpo { 
    text-align: center; 
   } 
   div.clMenu { 
    display: inline-block; 
    background-color: lightblue; 
   } 
   div.clPanelPrincipal { 
    display: inline-block; 
    background-color: lightcoral; 
   } 
   div.clBloquePie { 
    background-color: aquamarine; 
    text-align: center; 
   } 
   div.clPie{ 
    display:inline-block; 
    background-color:green; 
    padding:0.5em; 
   } 
  </style> 
 </head> 
 <body> 
  <div class="clBloqueEncabezado"> 
   <div class="clEncabezado"> 
    Encabezado 
   </div>
  </div> 
  <div class="clCuerpo"> 
   <div class="clMenu"> 
    <h2>Menú</h2> 
    <ul> 
     <li>Uno</li> 
     <li>Dos</li> 
     <li>Tres</li> 
    </ul> 
   </div> 
   <div class="clPanelPrincipal">panelPrincipal</div> 
  </div> 
  <div class="clBloquePie">
   <div class="clPie">Pie</div> 
  </div> 
 </body> 
</html>

19/8/16

Buscar con grep

grep -l -r -i --include="*.cs" "tExto a buscar" .
(Ojo que hay un punto al final)
  • -l que muestre solo el nombre
  • -r que busque en los directorios recursivamente.
  • -i CaseInsensitive. Que no distinga mayúsculas de minúsculas.
  • --include="*.cs". Tipos de fichero a buscar.
  • El punto al final es "Donde" buscar. En este caso en el directorio actual.

    (Si no se pone da un error extraño)

    grep: (entrada estándar): Not enough space

Para windows se consigue aquí


29/6/16

Hola mundo con C# Interactive de Visual Studio 2015

> #r "System.Windows.Forms" //Cargar el ensamblado
> using System.Windows.Forms; //Usar el Namespace
> MessageBox.Show("Hola"); //Mostrar el mensaje

9/6/16

Incluir fichero css en código con JSF.

Definiendo en el código xhtml la etiqueta h con
xmlns:h="http://java.sun.com/jsf/html"

Escribimos:

<h:outputStylesheet library="css" name="Estilos.css"  />

En cualquier parte del código

Lo que genera incluye en la cabecera, y con la ruta adecuada, y ... con parámetros que no entiendo un enlace
<link type="text/css" rel="stylesheet"
href="/proyecto/javax.faces.resource/Estilos.css.xhtml?ln=css" />
Pero el caso es que funciona. Si se usa algún estilo en la página lo usa.
Ejemplo:
<p:panelGrid columns="2" columnClasses="alinearArriba">