Excel-Automatisierung

Entwicklungsprotokoll: Was eine Tabelle mit 120.000 Zeilen tatsächlich kaputt macht

Eine Arbeitssitzung an einer Tabelle mit 121.254 Zeilen und 1,8 Millionen Zellen und den fünf einzelnen Dingen, die sich ändern mussten, bevor eine große tabellenübergreifende Analyse abgeschlossen, ihre Ausgabe überprüft und ein verwendbarer formatierter Bericht zurückgegeben werden konnte.

Die meisten Tabellenkalkulationsfunktionen werden anhand von Daten getestet, die auf einen Bildschirm passen. Dieses Protokoll umfasst eine Arbeitssitzung an einer Verkaufsarbeitsmappe mit 121.254 Zeilen in 15 Spalten – ungefähr 1,8 Millionen Zellen – und eine Anfrage, die gewöhnlich klingt: Kombinieren Sie die Produkt-, Kunden-, Bestell- und Verkaufstabellen und kennzeichnen Sie dann rückläufige Produkte, Wiederauffüllungsrisiken und Kunden mit geringem Wert.

Nichts an dieser Anfrage ist exotisch. Es scheiterte trotzdem mehrmals, und zwar aus Gründen, die fast nichts mit der Analyse selbst zu tun hatten. Was folgt, ist, was tatsächlich kaputt gegangen ist und was sich geändert hat.

Eine Plattformbeschränkung, keine langsame Abfrage

Der erste Fehler schien ein Fehler im dauerhaften Jobsystem zu sein. Die eigentliche Ursache war eine Regel in Google Apps Script: Ein Editor-Add-on darf keinen zeitgesteuerten Trigger erstellen, der öfter als einmal pro Stunde ausgelöst wird.

Das Design des Hintergrundjobs ging von einem einminütigen Auslöser aus. Diese Annahme galt während der Entwicklung, wo ein Container-gebundenes Skript frei geplant werden konnte, und hörte auf zu gelten, sobald derselbe Code als installiertes Add-on ausgeführt wurde. Die Anforderung, den Trigger zu installieren, wurde nicht beeinträchtigt – sie löste einen Fehler aus, und der Job wurde erstellt, sodass die Arbeit nie begann.

Es folgten zwei Änderungen. Die Installation eines Auslösers ist jetzt die beste Lösung: Es wird eine einminütige Trittfrequenz versucht, dann wird auf stündlich zurückgegriffen und schließlich wird überhaupt kein Auslöser mehr ausgelöst, und es wird nie ausgelöst. Und der erste Verarbeitungsschritt wird jetzt in derselben Ausführung ausgeführt, die die Aufgabe erstellt hat, und nicht in einem zweiten Aufruf, der die Aufgabe erneut nachschlagen muss.

Dieses zweite Detail war wichtiger als es klingt. Bei Apps Script-Eigenschaften handelt es sich nicht um zuverlässige Lese-/Schreibzugriffe über alle Ausführungen hinweg, sodass eine kurz zuvor geschriebene Aufgabe beim nächsten Aufruf möglicherweise als „Aufgabe nicht gefunden“ zurückgegeben wird.

Das Melden des Fortschritts ist nicht dasselbe wie das Fertigstellen

Obwohl der Job endlich gestartet wurde, wurde er immer noch nicht beendet. Das Tool hat einen Schritt ausgeführt und dann einen Status zurückgegeben, der besagt, dass die Arbeit „im Hintergrund fortgesetzt“ wird.

Dieser Satz war falsch. Da kein unterstündlicher Auslöser verfügbar ist, läuft im Hintergrund nichts weiter. Der Assistent las den Status, übermittelte dem Benutzer einen Prozentsatz und stoppte – ein Job blieb auf unbestimmte Zeit bei 34.000 von 121.253 Zeilen geparkt.

Die Laufzeit führt den Job nun selbst zum Abschluss, innerhalb eines begrenzten Budgets, und jeder nachfolgende Statusaufruf treibt die Arbeit voran, anstatt sie nur zu lesen. Ist das Budget ausgeschöpft, heißt es im Statustext deutlich, dass die Aufgabe noch nicht erledigt ist und nichts anderes sie voranbringt.

Das Prinzip ist es wert, direkt erwähnt zu werden: Ein Fortschrittsbericht ist kein Liefergegenstand. Ein Benutzer hat nach einer Tabelle gefragt, nicht nach einem Prozentsatz.

Eine Anfrage kann nur von Tools bedient werden, die das Modell sehen kann

Um die Werkzeugauswahl korrekt zu halten, legt GetSheetAI auf der Grundlage der Anfrage eine Teilmenge seiner Werkzeuge pro Runde offen. Dieser Mechanismus basiert auf dem Toolset Excel, und das Add-on Google Sheets registriert 22 Tools, die nur dort vorhanden sind. Diese Tools wurden aus jeder Anfrage herausgefiltert.

Der Effekt war spezifisch und leicht zu übersehen. Bei der Anfrage nach einem Balkendiagramm wurden 6 von 44 Tools angezeigt, wobei das Diagrammtool zu den versteckten gehörte. Die Aufforderung, einen Bereich zu sortieren, ergab 5 von 44, ohne das Sortierwerkzeug. Der Assistent weigerte sich nicht – er konnte das Werkzeug, das die Aufgabe erledigt, tatsächlich nicht erkennen.

Sheets verfügt jetzt über eine eigene Tool-zu-Bundle-Zuordnung, die jedes Excel-Gegenstück widerspiegelt, und der Filter durchläuft jedes Tool, zu dem er keine Meinung hat, anstatt es zu verwerfen. Ein Test liest jetzt die registrierten Werkzeugnamen direkt aus der Quelle, sodass das Hinzufügen eines Werkzeugs ohne Klassifizierung zum Fehlschlagen des Builds führt, anstatt es stillschweigend unerreichbar zu machen.

Die gleiche Art von Lücke trat in der Phrasierung auf. Eine chinesische Anfrage mit der Bedeutung „Neues Blatt erstellen“ entsprach keiner Regel, da das Muster nur eines der beiden gebräuchlichen Wörter für ein Blatt erkannte. Das Tool zur Blatterstellung blieb ausgeblendet und der Assistent meldete, dass das Erstellen eines Arbeitsblatts nicht möglich sei. Das war es nicht.

Fehlermeldungen sind Teil des Produkts

Mehrere Fehler führten zu einer Meldung, die ein Problem angab, ohne den Ausweg anzugeben.

Beim Schreiben in ein Blatt, das nicht existiert, wurde „Die angeforderte Ressource existiert nicht.“ zurückgegeben. Das liest sich wie ein defektes Add-In. Jetzt heißt es, dass das Blatt nicht existiert, dass das Schreibtool keine Blätter erstellt und dass dies bei zwei Aufrufen der Fall ist.

Die Ablehnung der Klassifizierung auf Zeilenebene für einen sehr großen Bereich führte zu einer bloßen Ablehnung. Das Beschriften eines aggregierten Ergebnisses funktioniert bei jeder Größe, daher benennt die Nachricht jetzt diesen Pfad: Zuerst die Gruppe und dann die Klassifizierungsregeln auf das gruppierte Ergebnis anwenden.

Ein Überschreibschutz hat nichts als blocked: true zurückgegeben, was als Fehler angezeigt wird. Es wird nun erklärt, dass das Ziel bereits Daten enthält und wie es weitergeht.

Keines davon ist kosmetisch. In jedem Fall beendete die vorherige Nachricht eine Aufgabe, die noch erledigt werden konnte.

Deterministische Ausdrücke erforderten mehr Arithmetik

Die Ableitung eines Jahr-Monats-Werts wie 201707 aus einem ganzzahligen Datumsschlüssel wie 20170702 erfordert entweder floor(x / 100) oder ein Modulo. Beides existierte nicht. Zwei Versuche schlugen fehl und die abgeleitete Kolumne wurde aufgegeben.

Die Ausdrucksebene umfasst jetzt floor, round, abs und mod, und der Fehler „Nicht unterstützte Funktion“ listet den vollständigen Satz auf und gibt genau diesen Ausdruck an, anstatt nur zu benennen, was abgelehnt wurde.

Wo es steht

In derselben Arbeitsmappe ist der dauerhafte Pfad nun abgeschlossen: Alle 121.253 Zeilen werden verarbeitet, gruppiert, geschrieben und formatiert, wobei jeder Ergebnisblock überprüft wird. Bei Excel führte dieselbe Anfrage zu einer Klassifizierung aller 397 Produkte – 132 ohne aktuelle Verkäufe, 101 mit einem Wiederauffüllungsrisiko gekennzeichnet, 99 rückläufig, 65 normal – berechnet mit nativem SUMIFS anhand der Quelltabelle, anstatt die Daten irgendwohin zu verschieben.

Die wissenswerten Betriebswerte:

  • dauerhafter Routing-Schwellenwert: mehr als 100.000 Zellen;
  • Quell-Chunking: begrenzte Lesevorgänge, pro Block beim Zurückschreiben überprüft;
  • Regressionsabdeckung: 826 Tests über die gemeinsame Laufzeit;
  • Hintergrundausführung bei Google Sheets-Add-ons: bestenfalls stündlich, sodass die Seitenleiste lange Jobs ausführt, während sie geöffnet ist.

Der letzte Punkt ist eher eine echte als eine vorübergehende Grenze. Ein installiertes Add-on kann die Arbeit nicht häufiger planen, sodass ein großer Auftrag ausgeführt wird, während die Seitenleiste geöffnet ist. Das dauerhafte Checkpointing bedeutet, dass beim Schließen keine abgeschlossene Arbeit verloren geht. Die ehrliche Beschreibung lautet jedoch, dass die Arbeit gesteuert und nicht geplant ist.

Bei der umfassenderen Lektion dieser Sitzung ging es nicht um die Skalierung. Bei jedem dieser Fehler wusste das System etwas, das der Benutzer nicht sehen konnte: eine Plattformregel, ein verstecktes Tool, einen unterstützten Pfad, der im Fehler nirgendwo genannt wurde. Die Größe machte sie alle auf einmal sichtbar.