Zum Inhalt springen
SheetForge

Quellen, Export & Push

Es gibt drei Schreibpfade, jeder mit einem anderen Ziel:

  • Übernehmen schreibt das Authoring-Staging in die Quelle.
  • Export schreibt per Bake erzeugte SO-Werte zurück in Tabellendateien.
  • Push schreibt per Bake erzeugte SO-Werte zellweise in die Live-Google-Tabelle.

Importquellen

Die Importquelle ist eine gleichberechtigte Wahl im Settings-Asset. Jede Quelle deklariert ihre eigene Authoring-Fähigkeit (CanAuthor):

QuelleWas sie liestAuthoring (Rückschreiben)
LocalFileEin Ordner mit .tsv- / .csv- / .xlsx-Dateien (nur unmittelbare untergeordnete Elemente; eine Datei = ein Tab, xlsx-Arbeitsmappen steuern ihre Sheets bei)Vollständig — Übernehmen, Strukturbearbeitung, Umbenennen von Schlüssel/Tab
GoogleSheet · SheetsApiEine private/geteilte Tabelle via Service-Account-JWT-Authentifizierung (Einrichtungsanleitung)Vollständig — chirurgisch präzise Zellschreibvorgänge, Struktur-Rewrite, Push
GoogleSheet · ExportUrlEine per Link geteilte Tabelle über ihre Export-URL — keine Authentifizierung nötigSchreibgeschützt (CanAuthor = false) — Push/Übernehmen/Strukturbearbeitung/Löschen sind deaktiviert, mit Erklärung
Benutzerdefinierte ProviderAlles, was ein Plugin registriert (ISheetSourceProvider — DB, REST, unternehmensinterne Formate)Entscheidung des Providers über sein CanAuthor-Flag

Hinweise:

  • ExportUrl erfordert eine Gid-Map (Tab-Name → #gid=-Wert) — eine Export-URL ohne Gid liefert stillschweigend nur den ersten Tab zurück, daher wird die Map erzwungen (GoogleSheetGidMapMissing, doppelte Gids werden abgelehnt). Der SheetsApi-Modus entdeckt Tabs automatisch und benötigt keine Map.
  • Der eingebaute xlsx-Reader/-Writer ist handgeschriebenes OOXML (nur System.IO.Compression + System.Xml — kein NPOI/ClosedXML, kein Fremdcode), sodass er keine DLLs hinzufügt, die mit anderen Assets in Ihrem Projekt kollidieren könnten. Es ist ein einziger, gemeinsam genutzter Codec: Derselbe Reader läuft im Unity-Editor und — zu WebAssembly kompiliert — in der Web-App, sodass die beiden Hosts bei einer Zelle nie uneins sein können. Er ist bewusst minimal gehalten und ehrlich darüber — nur Werte, keine Neuberechnung:
    • Eine Formelzelle liefert den in der Datei zwischengespeicherten Wert. Eine Formel ohne zwischengespeicherten Wert sowie eine Fehlerzelle (#REF!, #DIV/0!) werden abgelehnt (UnsupportedXlsxCell) — speichern Sie die Arbeitsmappe einmal in Excel, um Werte zwischenzuspeichern, oder materialisieren Sie Formeln.
    • Eine datumsformatierte Zelle wird als ihr Datum gelesen, ausgegeben als yyyy-MM-dd — sowohl der ISO-Zelltyp als auch eine reine Zahl, deren Format ein Datumsformat ist, wobei sowohl das 1900- als auch das 1904-Datumssystem berücksichtigt werden — statt der rohen Seriennummer, die die Datei speichert. Andere Zahlenformate, verbundene Zellen und Diagramme werden nicht importiert.
    • Diese Interpretationen — zwischengespeicherte Formelwerte, Daten als Anzeigetext, ignorierte Formatierung — sind die feste Richtlinie des Readers in beiden Hosts, und der Import-Dialog der Web-App benennt zusätzlich, welche davon tatsächlich vorkamen, in einem Hinweis „Wie diese Arbeitsmappe gelesen wurde".
    • Ein Tabulatorzeichen oder Zeilenumbruch innerhalb einer Zelle wird abgelehnt (UnsupportedCellCharacter) — verwenden Sie ; für Listen.
    • Zelltyp-Codes, die der Reader nicht erkennt, werden als roher gespeicherter Text gelesen, nicht abgelehnt.
  • Lokale Dateien müssen Unicode sein. Ein UTF-8-BOM oder ein UTF-16-BOM (LE oder BE) wird respektiert; ohne BOM wird die Datei als striktes UTF-8 dekodiert. Eine ältere Einzelbyte-Kodierung wie CP949 oder Shift-JIS wird abgelehnt (UnsupportedEncoding), nicht erraten — ein Raten würde auf verschiedenen Maschinen unterschiedlich dekodieren und die Daten stillschweigend beschädigen. Speichern Sie die Datei erneut als UTF-8.
  • Eine Quelle kann Teilausgaben zurückgeben — eine fehlerhafte Datei verwirft nicht die lesbaren Tabs; die Probleme kommen als Diagnosen an.
  • Benutzerdefinierte Source-Provider werden automatisch entdeckt und erscheinen im selben Settings-Dropdown — siehe Plugin-Erstellung.
  • Das Studio sagt Ihnen Bescheid, wenn sich die Quelle ohne Ihr Zutun weiterentwickelt hat. Beim Fokussieren des Fensters — oder auf Anfrage über das ⋯-Menü — liest das Studio die Quelle erneut ein und vergleicht sie mit dem Schnappschuss Ihres letzten Imports, und zeigt nur dann ein Badge, wenn sich die Daten tatsächlich unterscheiden: Eine lediglich erneut gespeicherte oder nur umformatierte Tabelle bleibt still, weil der Vergleich auf dem Inhalt beruht, nicht auf Zeitstempeln. Ein Klick auf das Badge bietet an, den Import auszuführen; nichts fragt per Timer ab, nichts importiert von selbst, und offline oder ohne Berechtigung zu sein bedeutet schlicht: kein Badge. Es funktioniert für jede Art von Quelle auf dieselbe Weise — lokale Dateien, Export-URL-Tabellen und die Sheets API gleichermaßen.

Export — die Rückweg-Hälfte des Round-Trips

⋯ ▸ Export ausführen in der Symbolleiste des Data Studio schreibt per Bake erzeugte SO-Werte zurück in Tabellendateien.

  • Die Struktur stammt aus der Baseline, die Werte aus den SOs. Export tauscht die aktuellen Werte in den Baseline-Schnappschuss der Struktur Ihrer Tabelle ein — Markierungszeilen, Spaltenreihenfolge, Kommentare und von Menschen geschriebener Text bleiben zu 100 % erhalten.
  • Semantischer Wert-Round-Trip: Die Normalisierung 1.01 ist zulässig (identischer Wert); Fließkommazahlen verwenden das kürzeste round-trip-fähige Format; immer . als Dezimaltrennzeichen.
  • Formate: Tsv / Csv / Xlsx / Json / MatchSource — jeder Tab kehrt in das Format zurück, aus dem er importiert wurde; bei Google-Ursprung oder unbekanntem Ursprung erfolgt ein Fallback auf Tsv. Json ist ein reines Ausgabeformat für Maschinen statt für Tabellenkalkulationen: eine Datei pro Tab, Datensätze als Objekte, int / float / bool als echte JSON-Zahlen und -Booleans, und jeder andere Wert — Referenzen, Listen, Farben, Kurven, benutzerdefinierte Typen — im exakten kanonischen Zelltext, den die Tabelle hält, sodass ein Server oder ein externes Tool Spieldaten konsumieren kann, ohne Tabellentext zu parsen. JSON ist keine Importquelle, und eine JSON-Datei trägt keine Tabellenstruktur, die einen Round-Trip durchlaufen könnte — die Tabelle bleibt kanonisch. TSV und CSV schreiben eine Datei pro Tab; Xlsx schreibt jeden exportierten Tab in eine einzige Arbeitsmappe (SheetForge.xlsx), jeder Tab als eigenes Sheet in Tab-Reihenfolge — eine Arbeitsmappe ist das Format, das dafür gemacht ist, mehrere Sheets zu fassen, und sie zusammenzuhalten ist auch das, was Referenz-Dropdowns erlaubt, über Sheets hinweg zu zeigen (unten). Unter MatchSource sammeln sich die Tabs mit xlsx-Ursprung in dieser einen Arbeitsmappe, während die anderen in ihre eigenen Dateien zurückkehren. Ein Sheet-Name, den die Regeln der Arbeitsmappe nicht fassen können (zu lang, oder ein verbotenes Zeichen), wird angepasst und namentlich gemeldet — niemals stillschweigend umbenannt.
  • Aktualität wird erzwungen: Der Export mit einem veralteten Bake nach einer Schema-Änderung schlägt mit ExportSchemaMismatch fehl (der per Bake erzeugte SchemaFingerprint muss mit dem der Baseline übereinstimmen) — führen Sie zuerst einen Import aus.
  • Asset-Referenzen werden als der Adresstext zurückexportiert, den die Tabelle verwendet — der Schlüssel, oder parent[sub] bei einem Sub-Asset; die Gruppe ist die der Spalte — niemals als GUIDs. Typisierte Spalten (AssetRef@Group<Type>) durchlaufen den Round-Trip auf dieselbe Weise. Color-, AnimationCurve- und Gradient-Werte kommen in ihrer kanonischen Textform zurück (siehe Tabellensyntax); eine Kurve ohne Schlüsselpunkte wird als leere Zelle exportiert, und eine Farbe wird auf 0…1 begrenzt (kein HDR).

Push — zellweises Rückschreiben zu Google Sheets

⋯ ▸ Zu Google Sheet pushen in der Symbolleiste des Data Studio sendet per Bake erzeugte SO-Werte Zelle für Zelle an die Live-Tabelle. Der Menüpunkt ist deaktiviert, mit ausgeschriebenem Grund, sofern die aktive Quelle nicht Google Sheets im API-Modus ist. Es ist so konzipiert, dass es niemals eine Live-Tabelle beschädigt, die gerade jemand anderes bearbeitet.

Drei Zusicherungen ergeben sich aus dieser Kette:

  • Nichts wird ohne Ihre Bestätigung eines zellweisen Plans gesendet.
  • Eine Zelle, die sich nach Ihrem Import in der Live-Tabelle geändert hat, wird übersprungen, nie überschrieben.
  • Eine Zeilenlöschung wird nur gesendet, wenn die Live-Tabelle diesen Schlüssel noch genau in dieser Zeile zeigt — alles, was sich verschoben hat, wird mit einem Hinweis übersprungen, niemals erraten.

Die Sicherheitskette, der Reihe nach:

  1. SheetsApi-Zugangsdaten erforderlich — Push im ExportUrl-Modus wird abgelehnt, noch bevor irgendein Netzwerkaufruf stattfindet (GooglePushRequiresSheetsApi).
  2. Pro gepushtem Tab ist eine Schlüsselspalte erforderlich — Push lokalisiert jede Zeile in der Live-Tabelle anhand des Schlüssels neu, sodass es eine verschobene Zeile erkennen und diesen Schreibvorgang sicher überspringen kann (nie an die falsche Zeile gesendet). Ein schlüsselloser Tab mit Änderungen wird abgelehnt (PushKeylessTabUnsupported).
  3. Plan + Bestätigung: Ein zellweises Diff (Baseline vs. aktuelles SO) wird als Plan berechnet — Schreibvorgänge, Anhänge, Zeilenlöschungen — und zur expliziten Bestätigung angezeigt, bevor irgendetwas gesendet wird; Löschungen stehen in einem eigenen Abschnitt, jede benannt nach dem Schlüssel, der verschwinden wird. Ablehnen = null gesendete Zellen.
  4. Erneutes Abrufen der Live-Daten vor dem Senden: Unmittelbar vor dem Senden wird die Live-Tabelle erneut abgerufen und verglichen. Widersprüchliche Zellen werden übersprungen, nicht überschrieben (als Warnungen gemeldet):
    • PushConflictCellChanged — ein Dritter hat diese Zelle bearbeitet.
    • PushConflictRowMoved — der Schlüssel wurde in einer anderen Zeile gefunden, als es Ihr Import gesehen hat, sodass der Schreibvorgang übersprungen wird (nie an die falsche Zeile gesendet). Importieren Sie erneut, um neu zu synchronisieren, und pushen Sie dann erneut.
    • PushConflictRowMissing — die Zeile wurde extern gelöscht.
    • PushConflictDuplicateLiveKey / PushConflictAppendKeyExists — mehrdeutige Ziele.
  5. Zeilenlöschungen werden vor dem Senden per Schlüssel abgeglichen. Ein von Ihnen gelöschter Datensatz wird erst dann aus der Live-Tabelle entfernt, wenn der Abruf vor dem Senden bestätigt hat, dass sein Schlüssel noch genau in der Zeile sitzt, die Ihr Import gesehen hat: Eine bereits verschwundene Zeile gilt als erledigt (ein erneuter Push löscht nichts doppelt), und ein auf einer anderen Zeile gefundener Schlüssel — die Tabelle hat sich verschoben — wird mit einem Hinweis übersprungen, niemals anhand der Position gelöscht. Löschungen werden zuletzt gesendet, innerhalb jedes Tabs von unten nach oben, sodass frühere Entfernungen die Koordinaten späterer nicht verschieben können. Eine Quelle, die keine Zeilen löschen kann (ein benutzerdefinierter Provider ohne diese Fähigkeit), fällt ehrlich auf das alte Verhalten zurück: Die Löschung wird gemeldet, und die Live-Zeile bleibt für Sie übrig.

Prüfen Sie nach einem Push die Anzahl der angewendeten/übersprungenen Zellen im Bericht; wurden Zellen übersprungen, importieren Sie erneut, um abzugleichen, und pushen Sie erneut.

Strukturänderungen zu Google

Strukturbearbeitungen (Spalten, Markierungen, Neuanordnung, Umbenennungen) schreiben bei einer Google-Quelle den gesamten Ziel-Tab neu — zunächst mit einer Live-Diff-Prüfung und expliziter Bestätigung, bevor irgendetwas überschrieben wird, das sich seit Ihrem letzten Import in der Tabelle geändert hat. Wertbearbeitungen bleiben chirurgisch präzise (pro Zelle); nur die Struktur nutzt den Rewrite-Pfad.

Addressables-Registrierungen durch ein Übernehmen

Ein Asset im Data Studio auf eine AssetRef@Group-Zelle zu ziehen, oder eines aus dem Projekt auszuwählen, kann neben der Tabelle auch eine Änderung am Projekt vormerken: das Hinzufügen des Assets zur Gruppe, das Verschieben aus einer anderen Gruppe, oder das Erstellen der Gruppe. Diese Registrierungen sind Teil des Übernehmens und laufen an einer festen Stelle der Kette — derselben Stelle für einen lokalen Ordner, ein Google Sheet und einen benutzerdefinierten Source-Provider:

  1. Vorab-Validierung validiert den gesamten projizierten Zustand, wobei die vorgemerkten Registrierungen als vorhanden gezählt werden, sodass eine Zelle, die auf ein noch nicht registriertes Asset zeigt, kein Fehler ist.
  2. Die Tabelle wird geschrieben. Wird das Schreiben abgebrochen oder schlägt es fehl, läuft nichts von dem Folgenden: Die Addressables-Einstellungen bleiben unangetastet, und die Registrierungen bleiben für den nächsten Versuch vorgemerkt. Ein Übernehmen, das keinen Tab schreiben konnte, weil jeder betroffene Tab übersprungen wurde (zum Beispiel wenn nur Tabs aus einer Arbeitsmappe betroffen waren), führt sie ebenfalls nicht aus. Ein Übernehmen, das überhaupt nichts in die Tabelle zu schreiben hat — die einzige vorgemerkte Änderung ist eine Registrierung —, führt sie sehr wohl aus und importiert erneut; keine andere vorgemerkte Bearbeitung wird von diesem Durchlauf committet, sodass sie rückgängig machbar bleibt.
  3. Die Registrierungen laufen der Reihe nach: Zuerst werden Gruppen erstellt (mit dem Standard-BundledAssetGroupSchema und ContentUpdateGroupSchema), dann werden Einträge hinzugefügt oder verschoben und erhalten ihre Adresse, und die Einstellungen werden einmal gespeichert. Jedes Element wird unmittelbar vor der Ausführung erneut geprüft und eher übersprungen als erzwungen, wenn das Asset inzwischen gelöscht wurde, wenn die Adresse inzwischen von einem anderen Asset in dieser Gruppe belegt ist, wenn die Gruppe nicht erstellt oder gefunden werden konnte, und wenn keine Zelle die Adresse mehr referenziert (eine Registrierung erstellt nie einen Eintrag, auf den nichts zeigt, und eine Gruppe, deren sämtliche Einträge übersprungen wurden, wird ebenfalls nicht erstellt). Besitzt das Projekt noch kein Addressables-Einstellungs-Asset, wird eines zu diesem Zweck erstellt.
  4. Die vorgemerkte Liste wird geleert — angewendete wie übersprungene gleichermaßen —, und der automatische erneute Import folgt, sodass der Bake die neuen Einträge sieht. Eine übersprungene Registrierung wird daher bei diesem erneuten Import ehrlich als UnknownAssetKey auf der Zelle gemeldet, die sie benötigt hat.

Die Konsole trägt eine Zeile pro Ergebnis — Addressables: 'address' → group 'Group' für jedes angewendete Element, Addressables: skipped 'address' (reason) als Warnung für jedes übersprungene — sowie eine Zusammenfassungszeile Addressables: N registered, M skipped. Bei einer Quelle aus einem lokalen Ordner endet der Abschlussdialog des Übernehmens mit derselben Zusammenfassungszeile.

Ins Sheet geschriebene Dropdowns

Spalten, deren Auswahlmöglichkeiten endlich sind, erhalten eine an die Tabelle angehängte Datenvalidierungsregel, sodass die Person, die in Google Sheets oder Excel bearbeitet, aus einer Liste wählt, statt sich Schreibweisen zu merken. Nichts muss dafür eingeschaltet werden: Die Regeln werden bei jedem Export, Push und Authoring-Rückschreiben neu berechnet und überall dort angewendet, wo das Ziel sie tragen kann.

SpalteRegel
Enum<T>-SkalarEine feste Liste der Member dieses Enums.
Referenz-Skalar (RecordId@Tab, sowie ein benutzerdefinierter Typ mit Referenz-Parität — §4.4a)Ein Bereich über die Schlüsselspalte des Ziel-Tabs, nach oben offen, sodass Datensätze, die dem Ziel-Tab hinzugefügt werden, von selbst der Liste beitreten.
List<>, Wrapper-Spalten, die Schlüsselspalte selbstKeine Regel — dort trägt eine Zelle mehrere Werte, oder es gibt keine Zielliste.
  • Orientierung, niemals Erzwingung. Jede Regel ist nicht strikt (Google strict:false, xlsx showErrorMessage="0"): Ein Wert außerhalb der Liste wird mit einem Warnmarker gekennzeichnet, aber dennoch akzeptiert. Eine harte Ablehnung würde den gewöhnlichen Arbeitsablauf „die Referenz jetzt schreiben, den Datensatz später definieren" brechen und den eigenen Vorschlägen für die nächstliegende Übereinstimmung des Imports zuwiderlaufen.
  • Die Regeln sind Anzeigemetadaten, keine Werte. Sie erscheinen nie in einer Zelle, daher bleibt der Round-Trip unberührt, und ein Export ohne Regeln ist byte-identisch mit einem, der vor deren Existenz erzeugt wurde.
  • Unabhängig von den Werten angewendet. Das Anhängen von Regeln ist ein eigener Schritt statt eines Nebeneffekts beim Schreiben von Zellen — der häufigste Ablauf (ein Enum-Member hinzufügen, keine Daten ändern) sendet null Zellen, sodass ein Nebeneffekt nie liefe. Es ist idempotent, ein erneuter Lauf ändert also nichts.
  • Ein Fehlschlag ist eine Warnung, kein gescheiterter Push. Wenn die Werte hinausgingen und nur die Regeln nicht angehängt werden konnten, ist der Push dennoch geglückt; führen Sie ihn erneut aus, und nur die Regeln werden erneut angewendet.

Was jedes Format tragen kann:

ZielMechanismusHinweise
Google Sheets (Push / Rückschreiben)setDataValidation, in einer Anfrage gebündeltBeide Regelarten. Der Referenzbereich lässt seine Endzeile offen, sodass er mit dem wachsenden Ziel-Tab mitwächst.
xlsx (Export)dataValidations nach den Sheet-DatenBeide Regelarten. Da der Export eine einzige Arbeitsmappe ist, zeigt ein Referenzbereich auf die Schlüsselspalte des Ziel-Sheets innerhalb derselben Datei, nach unten offen — dieselbe Bedeutung, die der Google-Bereich hat. Eine Regel wird weiterhin übersprungen, und in der Warnung genannt, in drei ehrlichen Fällen: ein Member, der ein Komma enthält (der Inline-Trenner würde ihn aufspalten), eine Inline-Liste über dem Spezifikationslimit von 255 Zeichen (die gesamte in Anführungszeichen gesetzte Liste, die das Format begrenzt), und ein Bereich, dessen Ziel-Tab nicht in der Arbeitsmappe ist.
TSV / CSV (Export)Reiner Text hat keinen Platz dafür.
JSON (Export)Eine Datendatei, keine Tabellenkalkulation — es gibt keine Zelle, an die ein Dropdown angehängt werden könnte.

Alles Ausgelassene wird ehrlich als eine einzige Warnung DropdownNotSupportedByFormat pro Lauf gemeldet — sie nennt jede betroffene Spalte, sodass die Antwort auf „warum gibt es Dropdowns bei Google, aber nicht in meiner Datei?" im Bericht steht statt ein Rätsel zu bleiben. Es ist eine Warnung und kein Fehler, weil die Werte selbst vollständig exportiert wurden; es fehlt nur der Bedienkomfort.

Die Gid-Map

Wird nur im ExportUrl-Modus verwendet. Jeder Eintrag ordnet einen Tab-Namen dem #gid=-Wert der Tabelle zu (sichtbar in der Browser-URL, wenn der Tab ausgewählt ist). Der Settings-Inspector zeigt die Map nur, wenn sie relevant ist.

Sie müssen diese Zahlen nicht einzeln aus dem Browser abschreiben. Der Inspector des Einstellungs-Assets besitzt einen Abschnitt Google Sheets, der die Map für Sie füllt.

  • Im ExportUrl-Modus liest Autofill gid from live die Tab-Liste der Live-Tabelle und schreibt die gesamte Map daraus neu, und speichert dann das Einstellungs-Asset.
  • Im SheetsApi-Modus bietet dasselbe Panel stattdessen Fetch live tab list an, das Ihnen lediglich die Tabs zeigt, die die Tabelle derzeit besitzt. Dieser Modus entdeckt Gids von selbst und benötigt überhaupt keine Map.

Ein Vorbehalt: Das automatische Ausfüllen spricht mit der Sheets-API, benötigt also einen konfigurierten Service-Account-Schlüssel, obwohl der ExportUrl-Import selbst keinen braucht. Ohne einen solchen bricht es ab und sagt dies, statt eine halb ausgefüllte Map zu schreiben.

Build-Aktualitäts-Hook — ein veralteter Bake lässt den Build fehlschlagen

Vor jedem Build prüft ein Pre-Build-Hook für jeden committeten generierten Database-Typ drei Dinge:

  • (i) das per Bake erzeugte SO existiert;
  • (ii) sein Schema-Fingerabdruck stimmt mit der Baseline überein;
  • (iii) seine Addressables-Registrierung existiert.

Jeder Fehlschlag bricht den Build mit einem umsetzbaren Hinweissatz ab (z. B. „Tools/SheetForge/Data Studio öffnen, dann ↓ Pull from source drücken, dann bauen"). Genau das macht „per Bake erzeugte SOs sind gitignored" sicher: Eine Klon- oder CI-Maschine kann keinen leeren Cache ausliefern.

Verwandte Seiten