¿Cómo autocompletar una columna de un archivo Excel incrementando un código numérico desde Batch?

Llevo un tiempo investigando para resolver un problema que tengo y haber si algún experto me puede echar una mano.

Tengo un archivo de Excel con una serie de columnas con datos, necesito de alguna forma poder ejecutar un archivo .bat para que me rellene la columna I-3. Dicha columna contendrá siempre un código numérico incremental donde yo decidiré con que numeración debe de comenzar ese código.

El formato del código es así: MM22000001

  [MM] nunca cambia

  [22] hace referencia al año, debe de generarse automáticamente

  [000000] estos dígitos deben de ir incrementando en cada fila de la columna

Al final lo que necesito que el .bat me pregunte por el código inicial, le pongo por ejemplo MM22000120, y si tengo en el Excel 5 filas de registros me tiene que rellenar la columna I-3 de la siguiente forma:

MM22000120

MM22000121

MM22000122

MM22000123

MM22000124

1 Respuesta

Respuesta
1

Me sorprende un poco que quieras modificar un archivo Excel con un bat cuando a mi entender, aunque no sea experto en Excel, el propio Excel tiene muchas posibilidades para hacer algo como lo que dices. Por otra parte para intentar tratar con un bat un libro Excel habría que aclarar de que tipo de archivos Excel estamos hablando porque no creo que fuera lo mismo un XLS que un XLSX

Hola gggirald, entiendo que te pueda sorprender lo que quiero hacer pero dentro de un contexto si que tiene sentido al menos para mi. Te cuento.

Tengo un script en .bat que utilizo para lanzar consultas de sql automatizadas en una base de datos, con estas consultas exporto los datos a un archivo excel que funciona como un archivo temporal, por eso no quiero realizar ningun cambio de manera manual en este excel.

Por otro lado tengo un software que genera pegatinas y se nutre de los datos del excel, entonces yo para imprimir pegatinas solo ejecuto el .bat y se me generan pegatinas sin necesidad de editar el excel. Los únicos datos que necesito generar de forma independiente son los códigos que te comenté.

Como alternativa podría generar el código en sql en tabla virtual y exportarlo, pero de igual forma necesito insertarlo en el excel.

Por si te preguntas por que no uso otro método para transferir los datos sin usar hojas de calculos, pues realmente los excel después de usarlos los voy archivando en un histórico en formato pdf, además hay mas datos que uso a modo de consulta

En principio uso formato xlsx, aunque no me importaría usar csv

Gracias

Con el formato CSV sí que creo que podría hacer algo, pero acabo de caer, cuando he empezado a "diseñar" el bat, que no entiendo que quieres decir con la columna I-3, tal vez te refieras a la columna I a partir de la fila 3, pero no estoy muy seguro de que sea eso.

Hola de nuevo, si en efecto quiero completar la columna I empezando en la fila 3, de ahí hacia abajo hasta el ultimo registro que tenga.

Gracias.

Muy bien. Ya he preparado un bat para tratar CSV según tus necesidades. Supongo que el separador de campos es el ";" como es habitual en los CSV para la "región" de España. Si fuera la coma, típico de los países angloparlantes, y como indican las siglas CSV ("Comma Separated Values"), habría que cambiar el bat:

@echo off
Setlocal EnableDelayedExpansion
set fila=3
set carpeta=d:\carpeta prueba
set archivo=kkk.csv
set /p valor=Introduce el valor a asignar inicialmente: 
pushd %carpeta%
del /q temp.csv>nul 2>&1
for /f "usebackq tokens=1-8,9,* delims=;" %%a in ("%archivo%") do (
   if !fila! neq 1 (echo %%a;%%b;%%c;%%d;%%e;%%f;%%g;%%h;%%i;%%j>>temp.csv&set /a fila-=1
      ) else (set val=%%i
              set val=!val:~0,4!
              if !valor! lss 10 (set val=!val!00000!valor!
                 )else if !valor! lss 100 (set val=!val!0000!valor!
                 )else if !valor! lss 1000 (set val=!val!000!valor!
                 )else if !valor! lss 10000 (set val=!val!00!valor!
                 )else if !valor! lss 100000 set val=!val!0!valor!
              echo %%a;%%b;%%c;%%d;%%e;%%f;%%g;%%h;!val!;%%j>>temp.csv
              set /a valor+=1
              )
      )
Popd

La variable FILA indica a partir de que fila se empieza el tratamiento. La variable CARPETA indica la carpeta/directorio en la que se encuentra el CSV a tratar. La variable ARCHIVO indica el nombre del archivo a tratar.

El bat es un poco rígido, en el sentido de que parte de que la columna a tratar es la "I", es decir, la novena columna. De momento no he conseguido "parametrizar" esta situación porque está implicada en el número de variables del bucle FOR a tener en cuenta para cada fila leída. Supongo que se podría conseguir, pero complicando considerablemente el código, creo yo.

Tal como está el BAT el archivo de salida es el TEMP. CSV, que debe haber incorporado los cambios solicitados, y solo esos, aunque seguro que elimina las líneas en blanco del archivo de entrada, si las hubiera.

Prueba y nos cuentas.

Tal como está el valor que pide es, solo, el de la parte secuencial. Pero no sería muy complicado que admitiera toda la cadena con la que se quiere rellenar la columna I.

Esta podría ser la solución para toda la cadena:

@echo off
Setlocal EnableDelayedExpansion
set fila=3
set carpeta=d:\carpeta prueba
set archivo=kkk.csv
set /p dato=Introduce el valor a asignar inicialmente: 
set fijo=%dato:~0,4%
set valor=%dato:~4% 
set /a valor=%valor:0=%
pushd %carpeta%
del /q temp.csv>nul 2>&1
for /f "usebackq tokens=1-8,9,* delims=;" %%a in ("%archivo%") do (
   if !fila! neq 0 (echo %%a;%%b;%%c;%%d;%%e;%%f;%%g;%%h;%%i;%%j>>temp.csv&set /a fila-=1
      ) else (if !valor! lss 10 (set val=%fijo%00000!valor!
                 )else if !valor! lss 100 (set val=%fijo%0000!valor!
                 )else if !valor! lss 1000 (set val=%fijo%000!valor!
                 )else if !valor! lss 10000 (set val=%fijo%00!valor!
                 )else if !valor! lss 100000 set val=%fijo%0!valor!
              echo %%a;%%b;%%c;%%d;%%e;%%f;%%g;%%h;!val!;%%j>>temp.csv
              set /a valor+=1
              )
      )
Popd

Hola muy buenas, lo he probado y la lógica principal funciona perfectamente , pero tiene algun detalle, te cuento:

1.cuando lo ejecuto me genera datos de manera correcta en la columna I y en la fila que yo le especifico, el primer problema que veo es que la primera fila que me genera no incluye dígito, en la imagen que te pongo como ejemplo debería de comenzar con el código MM22000001 en la celda que te señalo

Para ver si hay algún problema hice un pause en el bat y me arroja el siguiente mensaje "Falta un operando." , no se si esto tiene que ver con ese problema.

2. el otro detalle que me ocurre es que el código no se "genera" de la manera que yo espero, creo que me explique mal, necesito que la parte del código "MM22" sea siempre fija, (la MM nunca cambia y el 22 hace referencia al año), si el año se puede colocar para que se genere dinámicamente pues bien y si no pues cada año tendría que actualizarlo en el bat. Por otro lado cuando el programa me pregunta por el valor inicial lo que necesito es que me modifique la parte numeral final, te pongo un ejemplo: 

Si en 2023 ejecuto el bat y cuando me pregunte por el valor inicial coloco el valor "120", el csv se rellenaría así:

MM23000120

MM23000121

MM23000122

MM23000121

...

El tema de que la fila queda de manera rígida no me importa, siempre van a ir los datos que necesito generar.

Muchas gracias por la ayuda.

Disculpa en el ejemplo del código me equivoqué, al final en vez de MM23000121 es MM23000123

Para el punto 1 la explicación es de interpretación incorrecta por mi parte: creía que había que respetar 3 filas pero en realidad era "empezar en la tercera" (y, por tanto, respetar 2). Basta con cambiar el valor de la variable FILA, aunque también había un error en el IF que la trata.

En cuanto a la generación de las partes fija y anual no hay problema, claro.

Mira a ver si esta versión ya cumple como se espera:

@echo off
Setlocal EnableDelayedExpansion
set fila=2
set carpeta=d:\carpeta prueba
set archivo=kkk.csv
set /p valor=Introduce el valor a asignar inicialmente: 
set fijo=MM
set aa=%Date:~8% 
pushd %carpeta%
del /q temp.csv>nul 2>&1
for /f "usebackq tokens=1-8,9,* delims=;" %%a in ("%archivo%") do (
   if !fila! neq 0 (echo %%a;%%b;%%c;%%d;%%e;%%f;%%g;%%h;%%i;%%j>>temp.csv&set /a fila-=1
      ) else (if !valor! lss 10 (set val=00000!valor!
                 )else if !valor! lss 100 (set val=0000!valor!
                 )else if !valor! lss 1000 (set val=000!valor!
                 )else if !valor! lss 10000 (set val=00!valor!
                 )else if !valor! lss 100000 set val=0!valor!
              echo %%a;%%b;%%c;%%d;%%e;%%f;%%g;%%h;%fijo%%aa%!val!;%%j>>temp.csv
              set /a valor+=1
              )
      )
Popd

Bien perfecto ahora ya funciona como se espera, sólo hay un pequeño detalle, se me genera un espacio entre la parte fija y la numeral y deberia quedar todo junto, la verdad no se de donde sale, se me queda así "MM22 000001"

Ahora que ha quedado automatizado el valor del año he llegado a la conclusión de que puedo prescindir de la introducción del valor inicial. Voy a complicar un poco esto y voy a intentar automatizar el dato numeral para no tener siempre que apuntar e introducir ese valor en la linea de comandos.

Mi código debe de resetearse cada año, por lo que si en diciembre de este año va por el MM22000730, el 1 de enero debe de comenzar de nuevo tal que así MM23000001.

Para dar solución a esto se me ocurre generar un archivo de configuración que me permita consultar y guardar la numeración y el año actual en un fichero config.ini, por ejemplo:

code=25

year=2022

Imagino que tendría que confirmar siempre si el año actual coincide con el que hay escrito en el archivo config.ini, si coincide entonces debe de tomarse el valor que aparece en la variable code como valor inicial: "MM22000025, MM22000026 ..."

Pero si por el contrario el año actual no coincide con el del config.ini, deberia de actualizarse la variable year a "2023" y la variable code se resetearia colocando el valor a "1" "MM23000001, MM23000002 ..."

No se si esta es la forma más elegante de resolver, pero en mi cabeza parece que encaja, en principio yo se guardar una variable cogiendola de un documento, lo que tengo que ver como implementar la lógica de comparación, cualquier avance voy contando.

Muchas gracias por toda la ayuda

La separación tiene que ser porque la incluye la variable "aa", es decir que hay un espacio al final de la línea:

set aa=%Date:~8%

(de hecho, he comprobado que lo había). No me parece mal lo que sugieres de usar un config.ini para guardar el último código utilizado y el año actual. Si te supone algún problema me encantará ayudarte

Vale genial, en cuanto tenga algo de tiempo me pondré a intentar hacer la mejora y comentaré cualquier avance.

Por cierto tengo un proyecto muy interesante creado en batch relacionado con consultas automatizadas, cuando disponga de tiempo si quieres puedo mostrarte mis avances y dudas. Lo dicho muchas gracias y un saludo!!

Muy bien. Espero tus noticias. Seguramente sería más razonable abrir una nueva consulta para lo que fuera.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas