Fuentes, exportación y envío
Existen tres rutas de escritura, cada una con un destino distinto:
- reflejar escribe la preparación de creación en el origen.
- Export escribe los valores del SO generado mediante bake de vuelta en los archivos de la hoja.
- Push escribe los valores del SO generado mediante bake en la hoja de Google en vivo, celda por celda.
Orígenes de importación
El origen de importación es una opción de primera clase en el asset de ajustes. Cada origen declara su propia capacidad de creación (CanAuthor):
| Origen | Qué lee | Creación (escritura de vuelta) |
|---|---|---|
| LocalFile | Una carpeta de archivos .tsv / .csv / .xlsx (solo elementos hijos inmediatos; un archivo = una pestaña, los libros xlsx aportan sus hojas) | Completa — reflejo, edición de estructura, renombrado de clave/pestaña |
| GoogleSheet · SheetsApi | Una hoja de cálculo privada/compartida mediante autenticación JWT de cuenta de servicio (guía de configuración) | Completa — escrituras de celda quirúrgicas, reescritura de estructura, Push |
| GoogleSheet · ExportUrl | Una hoja compartida por enlace mediante su URL de exportación — sin necesidad de autenticación | Solo lectura (CanAuthor = false) — Push/reflejo/edición de estructura/eliminación se deshabilitan con una explicación |
| Proveedores personalizados | Cualquier cosa que registre un plugin (ISheetSourceProvider — DB, REST, formatos propios) | A elección del proveedor mediante su indicador CanAuthor |
Notas:
- ExportUrl requiere un mapa de gid (nombre de pestaña → valor
#gid=). Una URL de exportación sin gid devuelve silenciosamente solo la primera pestaña, por lo que el mapa se hace obligatorio (GoogleSheetGidMapMissing, los gid duplicados se rechazan). El modo SheetsApi descubre las pestañas automáticamente y no necesita ningún mapa. - El lector/escritor de xlsx integrado es OOXML escrito a mano (solo
System.IO.Compression+System.Xml— sin NPOI/ClosedXML, cero código de terceros), por lo que no añade DLLs que puedan chocar con otros assets de tu proyecto. Es un único códec, compartido: el mismo lector se ejecuta en el editor de Unity y — compilado a WebAssembly — en la app web, así que los dos hosts no pueden discrepar sobre una celda. Es deliberadamente mínimo y honesto al respecto — solo valores, sin recálculo:- Una celda de fórmula aporta el valor guardado en caché en el archivo. Una fórmula sin valor en caché, y una celda de error (
#REF!,#DIV/0!), se rechazan (UnsupportedXlsxCell) — guarda el libro una vez en Excel para que los valores queden en caché, o materializa las fórmulas. - Una celda con formato de fecha se lee como su fecha, mostrada
yyyy-MM-dd— tanto el tipo de celda ISO como un número simple cuyo estilo es un formato de fecha, respetando tanto el sistema de fechas de 1900 como el de 1904 — en lugar del número de serie en bruto que almacena el archivo. Otros formatos numéricos, las celdas combinadas y los gráficos no se importan. - Esas interpretaciones — valores de fórmula en caché, fechas como texto visible, formato ignorado — son la política fija del lector en ambos hosts, y el diálogo de importación de la app web además nombra las que realmente ocurrieron en una nota "Cómo se leyó este libro".
- Una tabulación o salto de línea dentro de una celda se rechaza (
UnsupportedCellCharacter) — usa;para las listas. - Los códigos de tipo de celda que el lector no reconoce se leen como su texto en bruto almacenado, no se rechazan.
- Una celda de fórmula aporta el valor guardado en caché en el archivo. Una fórmula sin valor en caché, y una celda de error (
- Los archivos locales deben estar en Unicode. Se respeta un BOM UTF-8 o un BOM UTF-16 (LE o BE); sin BOM, el archivo se decodifica como UTF-8 estricto. Una codificación heredada de un solo byte como CP949 o Shift-JIS se rechaza (
UnsupportedEncoding), no se adivina. Adivinar decodificaría de forma distinta en máquinas distintas y corrompería los datos en silencio. Vuelve a guardar el archivo como UTF-8. - Un origen puede devolver una salida parcial — un archivo dañado no descarta las pestañas legibles; los problemas llegan como diagnósticos.
- Los proveedores de origen personalizados se descubren automáticamente y aparecen en el mismo menú desplegable de ajustes — consulta Creación de plugins.
- El estudio te avisa cuando el origen ha seguido su camino sin ti. Al enfocar la ventana — o a petición desde el menú ⋯ — el estudio vuelve a leer el origen y lo compara con la instantánea de tu última importación, y muestra una insignia solo cuando los datos realmente difieren: una hoja que solo se volvió a guardar o simplemente se reformateó permanece en silencio, porque la comparación se basa en el contenido, no en las marcas de tiempo. Al hacer clic en la insignia se ofrece ejecutar la importación; nada consulta en un temporizador, nada importa por sí solo, y estar sin conexión o sin autorización simplemente significa que no aparece ninguna insignia. Funciona igual para todo tipo de origen — archivos locales, hojas de URL de exportación y la Sheets API por igual.
Exportación — la mitad de retorno del ciclo de ida y vuelta
⋯ ▸ Ejecutar exportación en la barra de herramientas de Data Studio escribe los valores del SO generado mediante bake de vuelta en los archivos de la hoja.
- La estructura viene del baseline, los valores vienen de los SO. La exportación intercambia los valores actuales dentro de la instantánea del baseline de la estructura de tu hoja. Las filas de marcador, el orden de columnas, los comentarios y el texto escrito por humanos se preservan al 100%.
- Ida y vuelta semántica de valores: la normalización
1.0↔1está permitida (el valor es idéntico); los floats usan el formato de ida y vuelta más corto; siempre con.decimal. - Formatos:
Tsv/Csv/Xlsx/Json/MatchSource— cada pestaña vuelve al formato desde el que se importó; el origen Google o un origen desconocido recurre a Tsv.Jsones un formato exclusivo de salida, pensado para máquinas y no para hojas de cálculo: un archivo por pestaña, los registros como objetos,int/float/boolcomo números y booleanos JSON reales, y todos los demás valores — referencias, listas, colores, curvas, tipos personalizados — en el texto de celda canónico exacto que guarda la hoja, de modo que un servidor o una herramienta externa pueda consumir los datos del juego sin analizar el texto de la hoja. JSON no es un origen de importación, y un archivo JSON no lleva ninguna estructura de hoja que hacer ida y vuelta — la hoja sigue siendo canónica. TSV y CSV escriben un archivo por pestaña;Xlsxescribe todas las pestañas exportadas en un solo libro (SheetForge.xlsx), cada pestaña como su propia hoja en el orden de las pestañas — un libro es el formato hecho para contener varias hojas, y mantenerlas juntas es también lo que permite que las listas desplegables de referencia apunten entre hojas (más abajo). BajoMatchSource, las pestañas de origen xlsx se agrupan en ese único libro mientras las demás vuelven a sus propios archivos. Un nombre de hoja que las reglas del libro no puedan admitir (demasiado largo, o con un carácter prohibido) se ajusta y se reporta por su nombre — nunca se renombra en silencio. - Se exige vigencia: exportar con un bake obsoleto después de un cambio de esquema falla con
ExportSchemaMismatch. ElSchemaFingerprintdel bake debe coincidir con el del baseline, así que ejecuta primero una importación. - Las referencias de asset se exportan de vuelta como el texto de dirección que usa la hoja — la clave, o
parent[sub]para un sub-asset; el grupo es el de la columna — nunca como GUID. Las columnas tipadas (AssetRef@Group<Type>) hacen round-trip de la misma manera. Los valoresColor,AnimationCurveyGradientvuelven en su forma de texto canónica (consulta Sintaxis de la hoja); una curva sin claves se exporta como una celda vacía, y un color se limita a 0…1 (sin HDR).
Push — escritura de vuelta a nivel de celda en Google Sheets
⋯ ▸ Hacer Push (Google Sheets) en la barra de herramientas de Data Studio envía los valores del SO generado mediante bake a la hoja en vivo, celda por celda. El elemento está deshabilitado, con el motivo explicado, a menos que el origen activo sea Google Sheets en modo API. Está diseñado para que nunca corrompa una hoja en vivo que alguien más esté editando.
Se derivan tres garantías de esta cadena:
- Nada se envía sin tu aprobación de un plan a nivel de celda.
- Una celda que cambió en la hoja en vivo después de tu importación se omite, nunca se sobrescribe.
- Una eliminación de fila solo se envía cuando la hoja en vivo todavía muestra esa clave exactamente en esa fila — cualquier cosa que se haya desviado se omite con un aviso, nunca se adivina.
La cadena de seguridad, en orden:
- Se requieren credenciales de SheetsApi — Push en modo ExportUrl se rechaza antes de cualquier llamada de red (
GooglePushRequiresSheetsApi). - Se requiere una columna clave por cada pestaña enviada mediante Push — Push vuelve a localizar cada fila por clave en la hoja en vivo. Así es como detecta una fila que se movió y omite esa escritura de forma segura, sin enviarla nunca a la fila equivocada. Una pestaña sin clave con cambios se rechaza (
PushKeylessTabUnsupported). - Plan + aprobación — se calcula un diff a nivel de celda (baseline frente al SO actual) como un plan: escrituras, adiciones, eliminaciones de fila. El plan se muestra para aprobación explícita antes de enviar nada; las eliminaciones aparecen en su propia sección, cada una identificada por la clave que desaparecerá. Rechazar = cero celdas enviadas.
- Nueva obtención en vivo antes del envío: inmediatamente antes de enviar, la hoja en vivo se vuelve a obtener y se compara. Las celdas en conflicto se omiten, no se sobrescriben (reportadas como advertencias):
PushConflictCellChanged— un tercero editó esa celda.PushConflictRowMoved— la clave se encontró en una fila distinta a la que vio tu importación, así que la escritura se omite (nunca se envía a la fila equivocada). Vuelve a importar para resincronizar, y luego haz Push de nuevo.PushConflictRowMissing— la fila se eliminó externamente.PushConflictDuplicateLiveKey/PushConflictAppendKeyExists— destinos ambiguos.
- Las eliminaciones de fila se emparejan por clave antes de enviarse. Un registro que eliminaste se quita de la hoja en vivo solo después de que la obtención previa al envío confirme que su clave todavía está en la fila exacta que vio tu importación: una fila que ya desapareció cuenta como hecha (un nuevo Push no elimina nada dos veces), y una clave encontrada en una fila distinta —la hoja se ha desviado— se omite con un aviso, nunca se elimina por posición. Las eliminaciones se envían al final, de abajo hacia arriba dentro de cada pestaña, así las eliminaciones anteriores no pueden desplazar las coordenadas de las posteriores. Un origen que no puede eliminar filas (un proveedor personalizado sin esa capacidad) recurre honestamente al comportamiento anterior: la eliminación se reporta y la fila en vivo se deja para que tú la quites.
Después de un Push, revisa los recuentos de aplicadas/omitidas del informe. Si se omitieron celdas, vuelve a importar para reconciliar y haz Push de nuevo.
Cambios de estructura en Google
Las ediciones de estructura (columnas, marcadores, reordenamiento, renombrados) en un origen de Google reescriben toda la pestaña de destino. Una comprobación de diff en vivo se hace primero, y se requiere aprobación explícita antes de sobrescribir cualquier cosa que haya cambiado en la hoja desde tu última importación. Las ediciones de valores siguen siendo quirúrgicas (por celda); solo la estructura usa la ruta de reescritura.
Registros de Addressables hechos por un reflejo
Soltar un asset sobre una celda AssetRef@Group en Data Studio, o elegir uno desde el proyecto, puede preparar un cambio en el proyecto además de en la hoja: añadir el asset al grupo, moverlo desde otro grupo, o crear el grupo. Esos registros son parte del reflejo y se ejecutan en un lugar fijo de la cadena — el mismo lugar para una carpeta local, una hoja de Google y un proveedor de origen personalizado:
- Validación previa valida todo el estado proyectado con los registros preparados contados como presentes, así que una celda que apunta a un asset todavía no registrado no es un error.
- Se escribe la hoja. Si la escritura se cancela o falla, nada de lo siguiente se ejecuta: los ajustes de Addressables quedan intactos y los registros permanecen preparados para el siguiente intento. Un reflejo que no pudo escribir ninguna pestaña porque todas las pestañas tocadas se omitieron (por ejemplo, cuando solo se tocaron pestañas respaldadas por libro) tampoco los ejecuta. Un reflejo que no tiene nada en absoluto que escribir en la hoja — el único cambio preparado es un registro — sí los ejecuta y reimporta; ese paso no confirma ninguna otra edición preparada, así que sigue siendo reversible con undo.
- Los registros se ejecutan, en orden: primero se crean los grupos (con los
BundledAssetGroupSchemayContentUpdateGroupSchemapredeterminados), luego se añaden o mueven las entradas y reciben su dirección, y los ajustes se guardan una sola vez. Cada elemento se vuelve a comprobar justo antes de ejecutarse y se omite en lugar de forzarse cuando el asset ya se eliminó, cuando la dirección ya la usa un asset distinto en ese grupo, cuando el grupo no se pudo crear o encontrar, y cuando ninguna celda hace referencia ya a la dirección (un registro nunca crea una entrada a la que nada apunta, y un grupo cuyas entradas se omitieron todas tampoco se crea). Si el proyecto todavía no tiene un asset de ajustes de Addressables, se crea uno para el propósito. - La lista preparada se limpia — tanto lo aplicado como lo omitido — y sigue la reimportación automática, así que el bake ve las entradas nuevas. Un registro omitido se reporta entonces con honestidad en esa reimportación como
UnknownAssetKeyen la celda que lo necesitaba.
La consola lleva una línea por resultado — Addressables: 'address' → group 'Group' por cada elemento aplicado, Addressables: skipped 'address' (reason) como advertencia por cada uno omitido — y una línea de resumen Addressables: N registered, M skipped. Para un origen de carpeta local, el diálogo de finalización del reflejo termina con esa misma línea de resumen.
Listas desplegables escritas en la hoja
Las columnas cuyas opciones son finitas reciben una regla de validación de datos adjunta a la hoja, para que la persona que edita en Google Sheets o Excel elija de una lista en lugar de recordar cómo se escribe cada valor. No hay que activar nada: las reglas se calculan en cada Export, Push y escritura de vuelta de creación, y se aplican dondequiera que el destino pueda llevarlas.
| Columna | Regla |
|---|---|
Escalar Enum<T> | Una lista fija con los miembros de ese enum. |
Escalar de referencia (RecordId@Tab, y un tipo personalizado con paridad de referencia — §4.4a) | Un rango sobre la columna clave de la pestaña destino, dejado abierto, así que los registros añadidos a la pestaña destino se suman a la lista por sí solos. |
List<>, columnas wrapper, la propia columna clave | Sin regla — ahí una celda contiene varios valores, o no hay un destino que listar. |
- Orientación, nunca imposición. Cada regla es no estricta (Google
strict:false, xlsxshowErrorMessage="0"): un valor fuera de la lista se marca con un indicador de advertencia pero se sigue aceptando. El rechazo estricto rompería el flujo habitual de "escribe la referencia ahora, define el registro después". También competiría con las propias sugerencias de coincidencia más cercana de la importación. - Las reglas son metadatos de visualización, no valores. Nunca aparecen en una celda, así que el ciclo de ida y vuelta no se ve afectado. Una exportación sin reglas es idéntica byte a byte a una producida antes de que esto existiera.
- Se aplican independientemente de los valores. Adjuntar reglas es un paso propio y no un efecto secundario de escribir celdas. El flujo más común — añadir un miembro de enum, sin cambiar ningún dato — envía cero celdas, así que un efecto secundario nunca se ejecutaría. Adjuntarlas es idempotente, así que volver a ejecutarlo no cambia nada.
- Un fallo es una advertencia, no un push fallido. Si los valores salieron y solo las reglas no se pudieron adjuntar, el push igualmente tuvo éxito; ejecútalo de nuevo y solo se vuelven a aplicar las reglas.
Lo que puede llevar cada formato:
| Destino | Mecanismo | Notas |
|---|---|---|
| Google Sheets (Push / escritura de vuelta) | setDataValidation, agrupado en una sola solicitud | Ambos tipos de regla. El rango de referencia omite su fila final, así que sigue a la pestaña destino a medida que crece. |
| xlsx (Export) | dataValidations después de los datos de la hoja | Ambos tipos de regla. Como la exportación es un solo libro, un rango de referencia apunta a la columna clave de la hoja destino dentro del mismo archivo, abierto hacia abajo en la hoja — el mismo significado que tiene el rango de Google. Una regla se sigue omitiendo, y se nombra en la advertencia, en tres casos honestos: un miembro de la lista que contiene una coma (el separador en línea lo dividiría), una lista en línea que supera el límite de la especificación de 255 caracteres (la lista completa entrecomillada es lo que limita el formato), y un rango cuya pestaña destino no está en el libro. |
| TSV / CSV (Export) | — | El texto plano no tiene dónde ponerlas. |
| JSON (Export) | — | Un archivo de datos, no una hoja de cálculo — no hay ninguna celda a la que adjuntar una lista desplegable. |
Todo lo que queda fuera se reporta honestamente como una sola advertencia DropdownNotSupportedByFormat por ejecución, nombrando cada columna afectada. La respuesta a "¿por qué hay listas desplegables en Google pero no en mi archivo?" está entonces en el informe en lugar de ser un misterio. Es una advertencia y no un error porque los valores en sí se exportaron completos; solo falta la comodidad de edición.
El mapa de gid
Solo se usa en modo ExportUrl. Cada entrada asocia un nombre de pestaña con el valor #gid= de la hoja (visible en la URL del navegador cuando la pestaña está seleccionada). El inspector de ajustes muestra el mapa solo cuando es relevante.
No tienes que copiar esos números del navegador uno por uno. El inspector del asset de ajustes tiene una sección de Google Sheets que rellena el mapa por ti.
- En modo ExportUrl, Autocompletar gid desde la hoja en vivo lee la lista de pestañas de la hoja de cálculo en vivo y reescribe todo el mapa a partir de ella, y luego guarda el asset de ajustes.
- En modo SheetsApi, el mismo panel ofrece en su lugar Obtener lista de pestañas en vivo, que simplemente te muestra las pestañas que la hoja tiene actualmente. Ese modo descubre los gid por sí solo y no necesita ningún mapa.
Una advertencia: el autorrelleno habla con la API de Sheets, así que necesita una clave de cuenta de servicio configurada aunque la propia importación en modo ExportUrl no la necesite. Sin una, se detiene y lo indica en lugar de escribir un mapa a medias.
Hook de vigencia de la build — un bake obsoleto hace fallar la build
Antes de cada build, un hook previo a la build verifica tres cosas para cada tipo de Database generado y confirmado:
- (i) el SO generado mediante bake existe;
- (ii) su huella de esquema coincide con el baseline;
- (iii) su registro de Addressables existe.
Cualquier fallo aborta la build con una frase accionable (por ejemplo, "abre Tools/SheetForge/Data Studio, pulsa ↓ Pull from source, y luego haz build"). Esto es lo que hace seguro que "los SO generados mediante bake estén en gitignore": una máquina clonada o de CI no puede enviar una caché vacía.
Páginas relacionadas
- Primeros pasos — configuración y seguridad de la clave de cuenta de servicio
- Conceptos fundamentales — los baselines y el modelo de ida y vuelta
- Data Studio — escrituras de creación frente a Push
- Capacidades y límites — la lista completa de límites de Google/xlsx