Plantilla de jerarquía padre-hijo desde CSV (catálogo de productos)
Un export de PIM o de BOM nombra el padre de cada fila, así que sus flechas apuntan hacia arriba. La columna Línea a nombra a los hijos, así que apuntan hacia abajo. Esta plantilla es esa inversión dibujada: cinco niveles y siete hojas.
¿Qué es plantilla de jerarquía padre-hijo desde CSV (catálogo de productos)?
Un export de catálogo de productos y una lista de materiales llegan con la misma forma. Una fila por artículo, una columna de id, una columna de nombre, y una columna que nombra al padre de esa fila: parent_id, parent_sku, belongs_to, o como lo llame el sistema que escribió el archivo. La jerarquía está entera ahí. Sencillamente está guardada apuntando en el sentido equivocado para un diagrama: cada fila nombra a la única fila que tiene encima, y ninguna fila nombra a las filas de debajo. Ese es el diseño correcto para una base de datos, donde una celda guarda un valor y nunca una lista, y el equivocado para un diagrama, donde una flecha sale de un padre y llega a un hijo. Tampoco es un archivo que hayas construido tú. Un CSV es lo que sale de un sistema, ya aplanado: no quedan fórmulas que recalculen la búsqueda por ti, no hay una segunda hoja con la tabla de variantes, no hay colores que digan qué filas eran los productos terminados.
La hoja de QueryChart guarda la relación contraria. Línea a guarda las filas a las que apunta esta fila (sus hijos) como una lista de números de fila separados por comas, y Texto de línea guarda las etiquetas de los conectores en el mismo orden. Así que la traducción es una única inversión, hecha una sola vez. Agrupa el export por su columna de padre, y cada grupo se convierte en el valor de Línea a de la fila que ese grupo nombra. Un padre con cuatro hijos acaba con cuatro números en una sola celda; cada hijo acaba sin nada en su propio Línea a y con su posición contada en la de su padre. Las filas cuya celda de padre está vacía son las raíces, y quieres exactamente una: tres padres vacíos son tres árboles, y tres árboles son tres diagramas.
Hay dos cosas que despistan. Línea a guarda posiciones, no identificadores: el valor es el número de la fila dentro de la hoja, así que un padre SKU-1042 hay que resolverlo al número de la fila que lleva ese código, y meter una fila renumera todo lo que hay debajo. Un número que no nombra ninguna fila se descarta al dibujar el diagrama, y nada te avisa. La segunda es que la profundidad no es una columna: se obtiene recorriendo la cadena de padres hacia arriba hasta llegar a un vacío, y por eso el mismo tipo de registro puede estar a profundidades distintas en ramas distintas del mismo archivo. El diagrama de abajo es un pequeño catálogo de muebles de exterior dibujado exactamente así: diecinueve filas repartidas en cinco columnas de profundidad y cuatro carriles de registro, una raíz, siete hojas, y cinco decisiones en los puntos donde un catálogo se bifurca de verdad: si una categoría vuelve a anidarse, si un producto lleva filas de variante, si un artículo es de stock o bajo pedido, y si un componente se compra o se fabrica.
Qué cubre este diagrama de flujo
En esta plantilla
- Cinco columnas de profundidad: «Raíz (padre vacío)» y del «Nivel 1» al «Nivel 4», cruzadas con cuatro carriles de registro: «Registro de categoría», «Registro de producto», «Registro de variante» y «Registro de componente», de modo que la columna de tipo del export pasa a ser una posición en la página mientras que la cadena de padres pasa a ser la columna.
- Una única raíz, «Catálogo de exterior», que en el archivo es la única fila cuya celda de padre está vacía, y que se abre hacia las dos categorías de nivel 1, «Asientos» y «Sombra y refugio».
- El motivo por el que la profundidad y el tipo de registro nunca acaban de cuadrar: «¿La categoría se sigue anidando?» separa una subcategoría anidada de «Juego de cojines para banco», un producto vendible situado a la misma profundidad que una categoría, así que «Banco de jardín de 3 plazas» acaba un nivel más abajo que «Parasol de brazo 3 m» aunque los dos sean productos.
- «¿El producto tiene variantes?» respondido igual que lo responde el archivo: un sí produce «Juego de cojines, natural», una fila de variante que lleva el código pedible, y un no produce «Juego de cojines para banco, SKU único», donde la fila de producto es la fila vendible y no tiene ningún hijo.
- La rama de lista de materiales, a la que solo se llega por «¿De stock o bajo pedido?»: un artículo de stock termina en «Banco de jardín de 3 plazas, roble», mientras que uno bajo pedido continúa hacia «¿Comprado o fabricado en casa?» y baja hasta «Juego de listones de madera dura» y «Estructura de banco de hierro fundido».
- Siete filas hoja, cada una con la celda de Línea a vacía, separadas por la forma y no por la profundidad: hojas vendibles como «Tela de repuesto 3 m» frente a hojas internas como «Conjunto de varillas del parasol», que es lo que decide «¿El recambio se vende por separado?».
Cuándo usar esta plantilla
- Alguien te ha mandado un export de catálogo (un CSV salido de un PIM, de un ERP o del back office de una tienda) y te ha preguntado qué contiene realmente la gama.
- Una lista de materiales llega a varios cientos de líneas y nadie ve a qué artículos terminados llega un componente sin filtrar el archivo a mano.
- Dos sistemas no se ponen de acuerdo sobre la estructura del catálogo, y quieres los dos exports dibujados como dos árboles en lugar de comparados fila a fila en un diff.
- El export tiene huérfanos dentro, filas cuyo id de padre no aparece en ninguna parte del archivo, y necesitas encontrarlos antes de cargar la jerarquía en cualquier otro sitio.
- Vas a entregar la gama a un proveedor, a un auditor o a alguien que acaba de entrar, y una columna de ids junto a otra columna de ids de padre no es algo que nadie pueda leer.
El CSV que produce este diagrama
Una fila por paso. Los números de Línea a son números de fila: son los que dibujan los conectores, y es la columna que falta en casi todos los archivos.
| # | Forma | Texto de la caja | Línea a | Texto de línea | Carril horizontal | Carril vertical |
|---|---|---|---|---|---|---|
| 1 | Start | Catálogo de exterior | 2, 3 | Raíz (padre vacío) | Registro de categoría | |
| 2 | Process | Asientos | 4 | Nivel 1 | Registro de categoría | |
| 3 | Process | Sombra y refugio | 7 | Nivel 1 | Registro de categoría | |
| 4 | Decision | ¿La categoría se sigue anidando? | 5, 6 | Subcategoría, Producto vendible | Nivel 1 | Registro de categoría |
| 5 | Process | Bancos | 10 | Nivel 2 | Registro de categoría | |
| 6 | Process | Juego de cojines para banco | 8 | Nivel 2 | Registro de producto | |
| 7 | Process | Parasol de brazo 3 m | 9 | Nivel 2 | Registro de producto | |
| 8 | Decision | ¿El producto tiene variantes? | 11, 12 | Sí: una fila por variante, No: la fila de producto es el SKU | Nivel 2 | Registro de producto |
| 9 | Decision | ¿El recambio se vende por separado? | 13, 14 | Se vende suelto, Solo para servicio técnico | Nivel 2 | Registro de producto |
| 10 | Process | Banco de jardín de 3 plazas | 15 | Nivel 3 | Registro de producto | |
| 11 | Success | Juego de cojines, natural | Nivel 3 | Registro de variante | ||
| 12 | Success | Juego de cojines para banco, SKU único | Nivel 3 | Registro de producto | ||
| 13 | Success | Tela de repuesto 3 m | Nivel 3 | Registro de variante | ||
| 14 | End | Conjunto de varillas del parasol | Nivel 3 | Registro de componente | ||
| 15 | Decision | ¿De stock o bajo pedido? | 17, 16 | De stock, Bajo pedido | Nivel 3 | Registro de producto |
| 16 | Decision | ¿Comprado o fabricado en casa? | 18, 19 | Comprado, Fabricado en casa | Nivel 3 | Registro de componente |
| 17 | Success | Banco de jardín de 3 plazas, roble | Nivel 4 | Registro de variante | ||
| 18 | End | Juego de listones de madera dura | Nivel 4 | Registro de componente | ||
| 19 | End | Estructura de banco de hierro fundido | Nivel 4 | Registro de componente |
#,Forma,Texto de la caja,Línea a,Texto de línea,Carril horizontal,Carril vertical
1,Start,Catálogo de exterior,"2, 3",,Raíz (padre vacío),Registro de categoría
2,Process,Asientos,4,,Nivel 1,Registro de categoría
3,Process,Sombra y refugio,7,,Nivel 1,Registro de categoría
4,Decision,¿La categoría se sigue anidando?,"5, 6","Subcategoría, Producto vendible",Nivel 1,Registro de categoría
5,Process,Bancos,10,,Nivel 2,Registro de categoría
6,Process,Juego de cojines para banco,8,,Nivel 2,Registro de producto
7,Process,Parasol de brazo 3 m,9,,Nivel 2,Registro de producto
8,Decision,¿El producto tiene variantes?,"11, 12","Sí: una fila por variante, No: la fila de producto es el SKU",Nivel 2,Registro de producto
9,Decision,¿El recambio se vende por separado?,"13, 14","Se vende suelto, Solo para servicio técnico",Nivel 2,Registro de producto
10,Process,Banco de jardín de 3 plazas,15,,Nivel 3,Registro de producto
11,Success,"Juego de cojines, natural",,,Nivel 3,Registro de variante
12,Success,"Juego de cojines para banco, SKU único",,,Nivel 3,Registro de producto
13,Success,Tela de repuesto 3 m,,,Nivel 3,Registro de variante
14,End,Conjunto de varillas del parasol,,,Nivel 3,Registro de componente
15,Decision,¿De stock o bajo pedido?,"17, 16","De stock, Bajo pedido",Nivel 3,Registro de producto
16,Decision,¿Comprado o fabricado en casa?,"18, 19","Comprado, Fabricado en casa",Nivel 3,Registro de componente
17,Success,"Banco de jardín de 3 plazas, roble",,,Nivel 4,Registro de variante
18,End,Juego de listones de madera dura,,,Nivel 4,Registro de componente
19,End,Estructura de banco de hierro fundido,,,Nivel 4,Registro de componenteCómo funciona
Encuentra las dos columnas que llevan la jerarquía
Para esto, todo lo demás del export es decoración. Necesitas la columna que guarda el identificador propio de cada fila y la columna que nombra a su padre. Rara vez se llaman id y parent_id: busca parent_sku, belongs_to, category_path o assembly. Si el padre es una ruta y no un código, del tipo Inicio > Asientos > Bancos, el último segmento es el padre y el resto es la profundidad. Si el export no tiene ninguna columna de padre pero sí un número de nivel, mira más abajo la nota sobre las listas de materiales indentadas.
Invierte la columna de padre para convertirla en Línea a
Este es todo el trabajo. Ordena o agrupa el export por su columna de padre de modo que los hijos de cada padre queden juntos, y después escribe los números de fila de esos hijos en la celda de Línea a del padre, separados por comas. Aquí se invierte el sentido: el export decía que el hijo nombra al padre, la hoja dice que el padre nombra a los hijos. Merece la pena decir en voz alta una consecuencia: la columna de padre tiene un valor por fila y Línea a tiene tantos valores como hijos tenga esa fila, así que la información se traslada de muchas filas a menos filas.
Numera las filas al final, y solo cuando el orden ya sea definitivo
Línea a guarda la posición de la fila dentro de la hoja, no su identificador, así que SKU-1042 tiene que convertirse en el número de la fila que lo lleva. Inserta una fila después y todos los números por debajo del punto de inserción se quedan desviados en uno. Deja primero las filas en su orden definitivo y después resuelve los ids a números de una sola pasada. Un valor de Línea a que nombra una fila inexistente se descarta en silencio al dibujar el diagrama, y eso parece una caja que sencillamente se olvidó de conectarse con algo.
Entrecomilla la celda de Línea a y confirma el delimitador
Línea a y Texto de línea guardan listas separadas por comas, así que en un archivo delimitado por comas esas celdas tienen que ir entre comillas dobles («4,5» y «Sí,No») o la fila gana un campo y todas las columnas siguientes se corren una posición a la izquierda. Los exports europeos suelen estar delimitados por punto y coma, lo que vuelve inofensivas las comas dentro de las celdas pero obliga a leer el archivo entero como delimitado por punto y coma. Los nombres de producto traen sus propios problemas de entrecomillado: una coma en Banco, 3 plazas o un símbolo de pulgada en un mástil de 3" hay que escaparlos igual. Si una columna parece ignorada al importar, mira el primer nombre de encabezado, porque un archivo escrito como UTF-8 con marca de orden de bytes lleva tres bytes invisibles delante.
Fija Forma según lo que es la fila, y los dos carriles según dónde está
Una fila recibe Inicio: la que tiene el padre vacío. Las filas con Línea a vacío son hojas, y una hoja necesita una forma terminadora (Fin, Éxito o Rechazo), porque una fila no terminal sin conector de salida es un callejón sin salida. Usa la división que usa esta plantilla si te sirve: Éxito para las filas que un cliente puede pedir, Fin para las que solo existen dentro de un conjunto. Después rellena Carril horizontal con la profundidad que has recorrido y Carril vertical con la propia columna de tipo del export. Un nombre de forma no reconocido se normaliza a Proceso sin protestar, así que revisa sobre todo cómo has escrito Decisión.
Limpia los huérfanos, las raíces de más y los bucles antes de importar
Tres comprobaciones, cada una con un síntoma distinto. Todos los valores de la columna de padre tienen que aparecer en la columna de id; los que no, son huérfanos, normalmente porque el export se filtró a una categoría mientras que los padres viven por encima. Solo una fila debería tener el padre vacío, y si hay varias es que estás mirando varios árboles. Y ninguna fila puede llegar a sí misma a través de sus padres, algo que ocurre tras una fusión mal hecha y que, una vez invertido, dibuja un conector que vuelve sobre sí mismo.
Preguntas frecuentes
¿Cómo se convierte una columna de padre e hijo en un diagrama de flujo?
Invirtiendo la relación y numerándola después. El export te da hijo nombra a padre; la hoja quiere padre nombra a hijos. Agrupa las filas por la columna de padre y, para cada padre, escribe los números de fila de sus hijos en la celda de Línea a de ese padre, separados por comas. Cada fila cuya celda de padre está vacía es una raíz y toma la forma Inicio; cada fila que no aparece en la columna de padre de nadie es una hoja, tiene el Línea a vacío y toma una forma terminadora. Rellena Texto de la caja desde la columna de nombre, Carril horizontal desde la profundidad que obtienes recorriendo la cadena de padres, y Carril vertical desde la columna de tipo que el export ya tiene. Después suelta el .csv sobre el área de hoja de cálculo del editor, o pega ahí directamente el texto CSV. La importación empareja por nombres de encabezado, así que el orden de las columnas de tu archivo da igual y las que no reconoce viajan con él y se ignoran.
¿Qué diferencia hay entre una columna de padre y una columna Línea a?
El sentido, la cardinalidad y a qué se refiere el valor. Una columna de padre apunta hacia arriba: cada fila nombra a la única fila que tiene encima, así que hay exactamente un valor por fila y las hojas son las filas que no nombra nadie. Una columna Línea a apunta hacia abajo: cada fila nombra a las filas que tiene debajo, así que un padre con cuatro hijos guarda cuatro valores en una celda y las hojas son las filas cuya celda está vacía. Y los valores son de distinta naturaleza. Una columna de padre guarda un identificador, algo como SKU-1042 que acompaña a la fila se mueva a donde se mueva. Línea a guarda una posición, el número de la fila contando desde 1 dentro de la hoja, que cambia en cuanto se inserta una fila por encima. Por eso los identificadores hay que resolverlos a números después de fijar el orden de las filas y no antes.
Mis columnas se desplazaron a mitad del archivo. ¿Qué ha pasado?
Casi siempre una coma sin entrecomillar. Una fila de CSV se parte por el delimitador antes de que nada más la mire, así que una celda de Línea a que contiene 4,5 en un archivo delimitado por comas se lee como dos campos, la fila acaba con un campo más que el encabezado, y todas las columnas posteriores a Línea a caen bajo el encabezado de su vecina. Envuelve esas celdas en comillas dobles y el analizador las vuelve a juntar. Lo mismo vale para Texto de línea, que también es una lista separada por comas, y para cualquier nombre de producto con una coma dentro. Si en cambio el desplazamiento empieza en la primerísima columna, la causa suele ser el problema contrario: el archivo está delimitado por punto y coma, como la mayoría de los exports europeos, y se está leyendo como delimitado por comas, o un desajuste de codificación ha pegado una marca de orden de bytes al primer nombre de encabezado, de modo que ya no empareja.
¿Qué pasa con una fila cuyo padre no está en el export?
Se convierte en un huérfano, y es el defecto más habitual de un export filtrado. Le pediste al sistema una categoría, o solo los artículos activos, y te dio exactamente esas filas, con sus ids de padre incluidos, que apuntan a filas que el filtro excluyó. Nada en el archivo está marcado como incorrecto. Cuando se invierte la jerarquía, esa fila sencillamente no aparece nunca en el Línea a de nadie, así que se dibuja como una caja a la que no llega nada, fuera del árbol. Decide fila por fila cuál es el caso antes de importar: una fila cuyo padre quedó fuera del filtro debería volver a colgar del antepasado incluido más cercano, y una fila cuyo padre ya no existe en el sistema de origen es un error de datos que hay que devolver, no que dibujar.
¿Puedo usar una lista de materiales que tiene columna de nivel en vez de columna de padre?
Sí, y se convierte en lo mismo, pero la conversión depende del orden de las filas y no de ningún valor de la fila. Una lista de materiales indentada repite los niveles 1, 2, 2, 3, 1 a lo largo del archivo, y la regla es que el padre de una fila es la fila más cercana por encima cuyo nivel es exactamente uno menor. Eso significa que el orden original del export es determinante: ordena el archivo por número de pieza y la jerarquía desaparece, sin error y sin nada de lo que recuperarla. Recorre el archivo de arriba abajo guardando la última fila vista en cada nivel, asigna los padres según avanzas, y solo entonces inviértelo a Línea a. Las cantidades, las unidades y los códigos de proveedor pueden quedarse donde están en sus propias columnas, que viajan con la importación y se ignoran, o pasar a la columna de notas si los quieres visibles.
