martes, 19 de diciembre de 2017

Gestor de archivos con excel. Buscar, encontrar, coincidir. Nuestro propio filtro avanzado en excel. Preliminar




Sigo sin ideas. El otro día hablando con un amigo me comentó que el utiliza un programa que le permite seleccionar fotos según unos atributos que el mismo les asigna. Además de arquitecto, diseña y construye muebles. A cada mueble construido le saca varias fotos para documentar el trabajo y, como es lógico, le interesa poder consultar en sus archivos por tipo de mueble, no solo por fecha o nombre. Asigna un tipo de mueble a cada foto, pueden ser varios atributos los asignados, tantos como se consideren necesarios para poder buscarlos por tipo de mueble.

Voy a hacer un gestor similar, solo con excel. Tengo, como muchísima gente, miles de fotos digitales en origen y unos cuantos cientos escaneadas. En las fotos digitales la fecha en la que se hicieron suele coincidir con la fecha que aparece en los listados. En las escaneadas no, la fecha de escaneo normalmente es muy posterior a la de realización de la foto. Podemos asignar un atributo "fecha de la foto" distinto al de fecha de los listados. Podemos asignar atributos tales como lugar, como familia, como amigos, etc...

Fase 1: Llevar a excel los nombres de las fotos:
  • Recupero el viejo D.O.S. Con el viejo comando dir obtengo un fichero con todos los "jpg" que tengo en mi directorio "Fotos", redireccionando la salida a un fichero de texto.
  • Creo un fichero ejecutable ".bat" (con notepad) con la siguiente instrucción: dir c:\DiscoWindowsXp\fotos\*.jpg /s /o /-C  > Imagenes.txt
  • Si quisiese añadir otro tipo de fichero añadiría una línea por tipo de fichero (dir c:\DiscoWindowsXp\fotos\*.gif /s /o /-C >> Imagenes.txt)
  • Esto nos da, me da en mi instalación, un fichero de texto con la siguiente estructura:



 Directorio de c:\DiscoWindowsXp\fotos\20121201 Confirmacion


01/12/2012  21:44           1407193 IMG_5543.JPG
01/12/2012  21:44           1467596 IMG_5544.JPG
              42 archivos 

En esta estructura  aparece una línea con el directorio y n líneas con el nombre, y otros atributos, de los ficheros. Debemos pasar de esta estructura a otra en la que en cada línea aparezca, además, el directorio, y que además elimine las líneas vacías.

  • Abro  excel. Desde excel abro el fichero de texto. En el momento de la apertura seleccionamos "Ancho fijo" y en origen del archivo "MS-DOS".
  • En la siguiente pantalla eliminamos todas las posibles divisiones. Vamos a importar los datos sin dividir.
  • En la tercera pantalla importamos los datos como "Texto". Finalizamos.
Adición del directorio al resto de las líneas:

  • La cosa consiste en identificar las líneas que empiezan por "Directorio ".
  • En el caso de que empiece por "Directorio" obtenemos el nombre del directorio y, si no, mantenemos el nombre obtenido anteriormente. 
  • Nos situamos en b2 y escribimos =SI(IZQUIERDA($A2;10)="Directorio";EXTRAE($A2;15;200);$B1)
  • Como quiero filtrar los directorios, en c2 ponemos y arrastramos la siguiente instrucción: =SI(IZQUIERDA($A2;10)="Directorio";$C1+1;$C1) Si los 10 caracteres de las izquierda son iguales a directorio, suma uno al valor anterior, si no mantén el valor anterior
  • Con esa instrucción pongo un número a cada directorio. 
  • Para numerar las fotos utilizamos la siguiente fórmula, en D2: =SI(MINUSC(DERECHA($A2;4))=".jpg";$D1+1;$D1)
  • Numeramos todas las líneas en E. Ponemos un 1 en E1, un dos en E2, seleccionamos ambas celdas y arrastramos.
Solo imágenes:
  • Insertamos una nueva hoja, "JPG" Copiamos la columna E en "JPG" A1, de momento no vamos a colocar cabeceras. 
  • Con el administrador de nombres creamos el rango con nombre "Datos". Con este nombre haremos referencia a al rango utilizado en la hoja "Imagenes", =Imagenes!$A:$E
  • Ya en JPG colocamos en b1 =COINCIDIR(JPG!$A1;Imagenes!D:D;0) Es decir buscamos el valor A1 en la columna D de Imagenes. Casi deberíamos incluir la gestión de errores pero de momento no es imprescindible. Arrastramos hasta el final.
  • En C1, en la columna C, situamos el directorio utilizando =SI.ERROR(INDICE(Datos;$B1;2);""). En este caso además controlamos el posible error con la función SI.ERROR() Si se produjera un error devuelve "". Arrastramos.
  • En D, utilizando =SI.ERROR(INDICE(Datos;$B1;1);"") traemos los nombres de los ficheros y su fecha y tamaño.
  • Esto es un paso intermedio, podemos separar fecha y nombre sin realizar este paso pero queda mas claro si se hace este paso intermedio. Evitemos, en lo posible, formulones.
  • En E1 situamos la fecha del fichero con =IZQUIERDA($D1;17). Arrastramos
  • Por último en F separamos el nombre y limpiamos de los espacios que preceden al nombre con =ESPACIOS(EXTRAE($D1;19;255)). Arrastramos
  • Podemos, si así lo consideramos, separar el año, el mes y el día de la fecha. Como, de momento la fecha está en modo texto, podemos convertirla a modo fecha. Basta sumarle 0 para convertirla. Gestionando el posible error, =SI.ERROR(E1+0;"")
  • Tanto si hemos pasada la fecha de texto a número como si no podemos utilizar las funciones DIA(E1), MES(E1), Año(G1), Hora(G1) y Minuto(G1). Gestionamos el posible error con SI.Error(). Arrastraríamos para completar la página.
Nombre de los directorios.
  • Insertamos una nueva hoja, la hoja "Dir".
  • Copiamos o llenamos la columna A con los 500 primeros números (+-)
  • Buscamos la primera ocurrencia del ordinal de la columna a en la columna C de "Imagenes" con =SI.ERROR(COINCIDIR(JPG!$A1;Imagenes!C:C;0);""). Esta vez si gestionamos el posible error. Arrastramos.
  • Obtenemos el nombre con =SI.ERROR(INDICE(Datos;$B1;2);"").
  • Vemos que como partimos de de un comando DOS tenemos problemas con la Ñ,ñ y con alguna vocal acentuada. 
  • Copiamos el carácter que sustituye a la Ñ (en "Imagenes" y procedemos a reemplazar en la hoja "Imagenes", columna A, ese carácter por "ñ".
  • Repetimos la operación para los otros posibles caracteres mal representados.
  • Ya tenemos separados, por columnas los atributos que nos interesan, pero, tenemos un libro excel cargadísimo de fórmulas que nos pueden causar problemas en un futuro.
Por tanto creo que debemos pasar los datos separados, copiando los valores solamente, a un nuevo libro
  • Creamos un nuevo libro.
  • Añadimos las hojas "JPG" y "Dir"
  • Vamos al libro procesado y copiamos los datos que nos interesen de los datos  obtenidos. En mi caso lo copio todo, ya eliminaré lo que tenga que eliminar. 
  • Copio JPG. Voy a la imagen, selecciono A1 y elijo "pegado especial". Seleccionamos "Valor".
  • Damos formato de fecha a la columna fecha
  • Lo mismo para Dir.
  • Insertamos una línea para incluir cabeceras. Eliminamos si fuese preciso alguna columna o alguna fila con errores.

¡Bien! ya tenemos importados a nuestra aplicación los datos que queremos gestionar. Ahora viene el pesadisimo  trabajo manual en el que tendríamos que poner, foto a foto, aquellos atributos que definen cada foto. Como tenemos agrupadas las fotos por directorio y es muy probable que todas las fotos de un mismo directorio tengan los mismos atributos, dividimos los atributos en "atributos del directorio" y "atributos de la foto". Los atributos del directorio los añadimos en la hoja de directorios y los otros en la hoja de JPG. Como hemos asignado unos atributos genéricos al directorio que afectan a todos los ficheros puede que resulte interesante definir un "no atributo" con el fin de excluir alguno de de los atributos de directorio de algún ficheros en concreto. 
A partir de aquí deberíamos de cambiar de plataforma, pasar los datos a una base de datos y trabajar con access en vez de excel, pero aun se pueden obtener resultados aceptables en excel.
  • Los atributos, en este caso, son texto separado por comas. Se puede hacer de otra manera, que cada cual se lo piense. 
  • Como estoy escribiendo un "preliminar" y veo que además el libro excel se está volviendo demasiado pesado, hay miles y miles de formulas,  no voy a desarrollar completamente la idea Me voy a limitar a encontrar un par de textos diferentes dentro del nombre del directorio y/o dentro de los atributos de directorio. De momento no voy a buscar ni por fechas ni por tamaños ni por atributos de fichero. Quizás lo desarrolle posteriormente
  • Asigno los atributos de algunos directorios en la página "Dir". Texto separado por comas. Estos atributos son texto del tipo "montaña", "vacaciones", "móvil", nombre de algún amigo, etc...
  • En la página "Buscar" dedicamos las celdas A2 y A3 para introducir los textos a buscar. En A5 indicamos si queremos que los textos buscados estén los dos en los atributos o con que este uno solo de ellos basta. Tiene dos valores válidos, "S" o "N", si o no.
  • Creamos un par de variables con nombre, Busca1 y Busca2, textos a buscar, referentes a Buscar!A2 y Buscar!A3.
  • Volvemos a la página "Dir". Como la segunda cadena de búsqueda es opcional, si no existiese la igualo a la primera., ver las celdas C1 y C2. Como puede hacerse directamente con variables con nombre creo la variable Busca3 y trabajo con ella =SI(Busca2<>"";MINUSC(Busca2);MINUSC(Busca1)).
  • Con este sencillo truco me evito varias columnas de fórmulas. Además trato las cadenas de texto en minúsculas, también facilita mucho la vida.
  • En las columnas C y D buscamos en la concatenación del nombre del directorio y de los atributos el primer y segundo texto a localizar con =SI.ERROR(ENCONTRAR( Busca1;MINUSC($A4 & "," & $B4 & ",");1);0).
  • En las columnas E y F utilizamos las funciones Y() y O() para conocer si al menos uno de los textos buscados esta presente o si ambos lo están.
  • Como ya he comentado, una vez que tenemos importados y procesados los datos a la hoja excel deberíamos continuar pasando los datos a una base de datos, tipo access,  y continuar el trajo con la B.D. En este punto debemos hacer un "JOIN" con los directorios y los ficheros JPG. Entre la hoja Dir y la hoja JPG.
  • Primero buscamos, y encontramos, el directorio de JPG en la relación de directorios de Dir con =COINCIDIR(JPG!B2;Dir!A:A;0) en la columna K. 
  • El valor encontrado nos permite pasar de Dir a JPG los distintos campos del JOIN con =INDICE(Dir!B:B;$K2)
  • En la columna P numeramos los registros que cumplen la/las condiciones pedidas con =SI(SI(AmbosN="S";$O2;$N2);P1+1;P1).
  • Volvemos a la hoja "Buscar". En la columna B hemos copiado la numeración de uno a n, donde n es el número máximo de registros esperados. Si nos hubiésemos quedado cortos ampliamos numeración y arrastramos las formulas
  • Buscamos el ordinal (1,2,3,4...) en la columna P de JPG. Con este número obtenemos los distintos campos a presentar con =SI.ERROR(INDICE(JPG!B:B;Buscar!$C2) & "\";"")
  • Tanto la columna P de JPG, como el área de datos de JPG deberíamos referenciarlas con una variable con nombre. 
  • Para terminar escribimos un código html que lo podemos pasar a una página htm.
  • =SI(E2<>"";"<br><a href=" &CARACTER(34) & D2& E2 &CARACTER(34)& " target=foto>"  & D2& E2 & "</a>";"")
  • Pasamos este código, es un copia-pega manual, abrimos la página y ya tenemos un enlace a todas las fotos que cumplen las condiciones pedidas. 
  • Si queremos completar, dar un acabado perfecto, ya tendríamos que pasar a programación.






jueves, 7 de diciembre de 2017

Automatizar respuestas a un formulario de Google con Excel. Preliminar.

En un principio la idea de automatizar respuestas a un formulario de google me surgió en uno de mis trabajos con Arduino Yun. Parto del supuesto de que necesito medir remotamente unos determinados parámetros. Leo, envío a la nube los valores medidos y puedo consultarlos desde cualquier sitio (incluido mi móvil).
Me quedé sin ideas y dejé de hacer cosas con arduino. El otro día en una sobremesa estuvimos hablando de IPs estaticas e IPsdinámicas, si se podía hacer esto o no hacerlo, que si te cambia la IP no puedes pensar en establecer tu propia red, etc...

Me surgió la pregunta ¿puedo conocer remotamente la IP dinámica de mi instalación desde cualquier sitio? Después de pensarlo, después de hacer unas cuantas  pruebas recuperé la vieja idea de automatizar respuestas a un formulario.
  • Obtengo la IP. Es fácil. De momento, estoy en los preliminares, la leo de una de las páginas web que me dan ese servicio (www.cualesmiip.com). 
  • Esta lectura la puedo hacer automaticamente abriendo www.cualesmiip.com desde vbasic como si fuera un libro excel mas.
  • Workbooks.Open Filename:="http://www.cualesmiip.com/"
  • Hecho esto, en principio, la dirección IP aparece en la celda A31.
  • Esto no quiere decir que siempre vaya a ser así, la página web puede ser modificada en cualquier momento.
Creo un formulario google, con salida a una hoja de cálculo:


Si quiero automatizar el envío de un formulario necesito conocer tanto la acción que se ejecuta al pulsar "Envío" como el nombre de los distintos campos de pregunta. Son nombres internos que hay que buscar en el código fuente del formulario:
  • El la inmensa sopa de letras que supone el código fuente de un formulario encontrar la acción y los nombres de las preguntas parece imposible pero es relativamente sencillo. 




Una vez encontrados acción y preguntas lo llevamos un código vbasic, como el siguiente:



Sub DireccionIP()

Dim IP, NL, Accion, Prg1, Prg2, Lin

'
' Abrimos y obtenemos IP de www.cualesmiip
'
    Workbooks.Open Filename:="http://www.cualesmiip.com/"
  IP = ActiveSheet.Range("a31").Value
    ActiveWindow.Close
'Preparamos respuesta al formulario
Accion = "https://docs.google.com/forms/d/e/1FAIpQLScChBMMMdog1LT4leKk2WF0DDd32-aeWLll57YjVVjvBvJGhw/formResponse?"
Prg1 = "entry.1464650708=" & IP
Prg2 = "entry.1464650708=" & Now()


Lin = Accion & Prg1 & "&" & Prg2

'enviamos la acción

    Workbooks.Open Filename:=Lin
  ActiveWindow.Close
    
End Sub


  • Ya solo queda comprobar que el envío se ha realizado. Voy a mi google drive, abro la hoja de cálculo que he creado para contener las repuestas y veo que si se ha producido el envío. 
  • Por triplicado, de momento no se por que, pero ahí está la dirección IP pedida.
  • Como estoy en los preliminares, me doy casi por satisfecho, aunque el resultado presente varios defectos y falte casi totalmente el desarrollo de la idea, he conseguido enviar vía excel la dirección IP obtenida en www.cualesmiip.com a mi google drive. Ya la tengo en red, ya puedo consultarla desde cualquier sitio. De momento se que se puede hacer de un modo relativamente sencillo.