Tablas desde datos
Un bloque :::csv no pega una copia de tus datos en el documento. Guarda una selección: qué archivo, qué columnas, qué filas. Cuando el CSV subyacente cambia, el siguiente render o exportación vuelve a leer el archivo y la tabla se actualiza sola. Nunca vuelves a copiar números, y el documento nunca se desincroniza de la hoja de cálculo que los produjo.
Sintaxis
Un bloque nombra el archivo y, opcionalmente, un selector de columnas y un selector de filas, cada uno agrupado entre paréntesis:
:::csv[Growth rates]
data.csv (A:B, D) (1:8, 12)
:::
El [Growth rates] opcional se convierte en el título de la tabla. data.csv se resuelve como un archivo del vault, de la misma forma en que la transclusión resuelve notas. (A:B, D) selecciona las columnas A, B y D; (1:8, 12) selecciona las filas de datos 1 a 8 más la fila 12.
Formas de selector
| Forma | Significado |
|---|---|
A:B | Un rango contiguo, con letras de hoja de cálculo o índices base 1 (A:B, 1:3) |
(A, C, F) | Una lista no contigua, agrupada entre paréntesis |
Nombre | Un nombre de encabezado, comparado sin distinguir mayúsculas contra la fila de encabezado del CSV |
1, 2, … | Un índice base 1: para columnas, posición en la hoja de cálculo; para filas, posición entre las filas de datos (la fila de encabezado no es la fila 1) |
1:8 o (1:3, 7) | Los rangos de filas funcionan igual que los de columnas, más agrupación no contigua |
| (omitido) | Omitir un selector por completo significa “todo”: data.csv solo selecciona todas las columnas y todas las filas |
(C, A) | El orden se conserva, así que esto reordena la tabla: la columna C va primero, la columna A segundo |
Una palabra suelta puede coincidir con una letra de hoja de cálculo o con un nombre de encabezado; el nombre de encabezado gana cuando ambos son posibles, así que un CSV con una columna literalmente llamada A se comporta como tú esperarías.
La forma legible de clave/valor es equivalente a la compacta, y se lee mejor cuando una selección se alarga:
:::csv[Growth rates]
file: data.csv
cols: A:B, D
rows: 1:8, 12
:::
Datasets con nombre
Cuando varios bloques necesitan el mismo recorte de un CSV, un bloque :::data{#data:growth} declara esa selección una sola vez y le da un nombre:
:::data{#data:growth}
growth.csv (A:D) (1:20)
:::
La declaración no imprime nada. Como una definición de macro, existe solo para que otros bloques apunten a ella: un :::csv cuyo origen es @data:growth renderiza esos datos como tabla, y un bloque de gráfica puede hacer lo mismo. La selección propia del bloque que la usa se aplica encima de la del dataset, así que @data:growth (A, C) significa “las columnas A y C de mi dataset growth”, no las columnas A y C del CSV completo:
:::csv[Cepas rápidas]
@data:growth (A, C)
:::
Un dataset es deliberadamente distinto de una figura, una ecuación o una tabla: no es un elemento numerado y nadie lo cita en prosa, así que no encontrarás un “ver Data 3”. Pero sí viaja en el mismo sistema de labels que el resto del editor: el panel de Labels reporta declaraciones duplicadas (dos bloques :::data con el mismo {#data:nombre}), referencias a datasets que no existen (@data:algo sin una declaración correspondiente) y datasets que nadie usa. El editor marca ambos problemas mientras escribes, no solo al abrir el panel.
Una tabla generada por :::csv también puede llevar su propio label, {#tbl:x}, y volverse citable con @tbl:x en la prosa, exactamente como una tabla escrita a mano. El dataset que la alimenta y la tabla que produce son dos cosas distintas: una no se numera ni se cita, la otra sí.
Analizando el CSV en sí
Los archivos se leen según RFC 4180: campos entre comillas, comillas escapadas, y campos que contienen el delimitador o saltos de línea incrustados se manejan correctamente. El delimitador en sí no se asume como coma: ComdTeX lo detecta contando candidatos en la primera línea, eligiendo entre coma, punto y coma, tabulador y barra vertical. Un CSV exportado desde una hoja de cálculo europea con punto y coma, o un TSV, funcionan ambos sin ninguna configuración adicional.
Cuando falta algo
Un archivo faltante no falla en silencio. Si data.csv no se encuentra en el vault, el bloque se reemplaza por una nota visible que lo dice, en lugar de la tabla. Lo mismo ocurre con una selección que no resuelve a nada, o un archivo que no se puede leer como CSV. El silencio parecería un error de renderizado; una nota honesta te dice exactamente qué corregir.
Dónde se resuelve
Un bloque :::csv se resuelve de forma consistente en todas partes: la vista previa en vivo, “Compilar PDF”, “Exportar como .tex”, “Exportar PDF” y cualquier otra ruta de exportación. También se resuelve dentro de notas transcluidas: si la nota A incrusta la nota B con ![[B]], y B contiene un bloque :::csv, ese bloque igual se expande correctamente cuando A se renderiza o se exporta. Esto es deliberado: todas las rutas de exportación pasan por el mismo paso de resolución de documento, así que la tabla que ves en la vista previa es exactamente la tabla que llega al PDF, sin importar qué botón hayas presionado para llegar ahí.
Tables from data
A :::csv block does not paste a copy of your data into the document. It stores a selection: which file, which columns, which rows. When the underlying CSV changes, the next render or export reads the file again and the table updates on its own. You never re-copy numbers, and the document never drifts from the spreadsheet that produced them.
Syntax
A block names the file and, optionally, a column selector and a row selector, each grouped in parentheses:
:::csv[Growth rates]
data.csv (A:B, D) (1:8, 12)
:::
The optional [Growth rates] becomes the table’s caption. data.csv is resolved as a vault file, the same way transclusion resolves notes. (A:B, D) selects columns A, B and D; (1:8, 12) selects data rows 1 through 8 plus row 12.
Selector forms
| Form | Meaning |
|---|---|
A:B | A contiguous range, spreadsheet letters or 1-based indices (A:B, 1:3) |
(A, C, F) | A non-contiguous list, grouped in parentheses |
Name | A header name, matched case-insensitively against the CSV’s header row |
1, 2, … | A 1-based index: for columns, spreadsheet position; for rows, position among the data rows (the header row is not row 1) |
1:8 or (1:3, 7) | Row ranges work the same way as column ranges, plus non-contiguous grouping |
| (omitted) | Leaving a selector out entirely means “everything”: data.csv alone selects every column and every row |
(C, A) | Order is preserved, so this reorders the table: column C comes first, column A second |
A bare word can match either a spreadsheet letter or a header name; the header name wins when both are possible, so a CSV with a column literally named A behaves the way you would expect.
The readable key/value form is equivalent to the compact one, and reads better when a selection gets long:
:::csv[Growth rates]
file: data.csv
cols: A:B, D
rows: 1:8, 12
:::
Named datasets
When several blocks need the same slice of a CSV, a :::data{#data:growth} block declares that selection once and gives it a name:
:::data{#data:growth}
growth.csv (A:D) (1:20)
:::
The declaration prints nothing. Like a macro definition, it exists only so other blocks can point at it: a :::csv block whose source is @data:growth renders that data as a table, and a plot block can do the same. The referencing block’s own selection applies on top of the dataset’s, so @data:growth (A, C) means “columns A and C of my growth dataset”, not columns A and C of the whole CSV:
:::csv[Fast strains]
@data:growth (A, C)
:::
A dataset is deliberately different from a figure, an equation or a table: it is not a numbered element and nobody cites it in prose, so you will never find a “see Data 3”. But it does ride the same label system as the rest of the editor: the Labels panel reports duplicate declarations (two :::data blocks with the same {#data:name}), references to datasets that do not exist (@data:something with no matching declaration), and datasets nobody uses. The editor flags both mistakes while you write, not only when you open the panel.
A table generated by :::csv can also carry its own label, {#tbl:x}, and become citable with @tbl:x in prose, exactly like a hand-written table. The dataset that feeds it and the table it produces are two different things: one is never numbered or cited, the other is.
Parsing the CSV itself
Files are read as RFC 4180: quoted fields, escaped quotes, and fields containing the delimiter or embedded newlines are all handled correctly. The delimiter itself is not assumed to be a comma: ComdTeX sniffs it by counting candidates in the first line, choosing among comma, semicolon, tab and pipe. A CSV exported from a European spreadsheet with semicolons, or a TSV, both work without any extra configuration.
When something is missing
A missing file does not fail silently. If data.csv cannot be found in the vault, the block is replaced with a visible note saying so, in place of the table. The same happens for a selection that resolves to nothing, or a file that cannot be read as CSV. Silence would look like a rendering bug; an honest note tells you exactly what to fix.
Where it resolves
A :::csv block resolves consistently everywhere: the live preview, “Compile PDF”, “Export as .tex”, “Export PDF”, and every other export path. It also resolves inside transcluded notes: if note A embeds note B with ![[B]], and B contains a :::csv block, that block still expands correctly when A is rendered or exported. This is deliberate: every export path calls through the same document-resolution step, so a table you see in the preview is exactly the table that reaches the PDF, regardless of which button you pressed to get there.