2012-12-15 22 views
7

Ich möchte mit Google Apps Script benutzerdefinierte Funktionen für eine Tabelle erstellen. Ich habe eine sehr einfache Funktion:Dienst zu oft aufgerufen (Google Apps Script)

function foo(){ 
    return "bar"; 
}; 

Das Problem ist, dass ich diese Funktion in ein paar hundert Zellen brauche. Wenn ich die Funktion =foo() in alle diese Zellen einfügen, funktioniert die Funktion in einigen Zellen, aber in den meisten bekomme ich diesen Fehler: "Dienst zu oft aufgerufen: Tabelle. Versuchen Sie Utilities.sleep(1000) zwischen Anrufen."

[Screenshot here]

Ich glaube, ich verstehe nicht, warum diese Funktion, einfach, wie es ist, einen Aufruf des Tabellenkalkulations-Dienstes angesehen wird. Ich ersuche nicht einmal irgendwelche Daten (außer für die Funktion selbst). Ist das das Problem? Und wenn ja, gibt es einen Workaround? Benutzerdefinierte Funktionen können Google Spreadsheets erheblich leistungsfähiger machen. Dieses Problem führt jedoch dazu, dass eine benutzerdefinierte Funktion in mehreren Zellen verwendet werden kann. Vorschläge?

(PS - Die Verwendung der Utilities.sleep() Funktion wie von der Fehlermeldung vorgeschlagen, hilft überhaupt nicht, wenn alle Zellen ihre Funktionen gleichzeitig aufrufen; es verlangsamt nur die Rate, mit der einzelne Zellen die Funktion wiederholt aufrufen.)

Antwort

1

Durch Aufrufen der Funktion in der Tabelle rufen Sie den Tabellenkalkulationsdienst auf, indem Sie ihn auffordern, zum Server zu gelangen, um die Ergebnisse Ihrer Funktion auszuführen. Als Ergebnis haben Sie in kurzer Zeit einige hundert Anfragen gestellt.

Ein Work around könnte sein, Ihre Funktion ein paar Zellen gleichzeitig hinzuzufügen. Wenn Sie das Blatt später erneut öffnen, stoßen Sie wahrscheinlich auf das gleiche Problem.

Je nachdem, was Ihre Funktion zu erreichen versucht, sollten Sie die integrierten Tabellenfunktionen verwenden. Da ist viel Kraft. Das Schreiben einer Funktion, die auf eine Reihe von Werten anstatt auf eine einzelne Zelle wirkt, könnte eine andere, bessere Option sein. Es könnte durch ein benutzerdefiniertes Menüelement oder mithilfe des Skriptmanagers ausgelöst werden.

Denken Sie daran, Batch-Aktionen sind Ihr bester Freund, wenn es um die Arbeit mit Tabellen geht.

+0

Ich denke, Ich hätte mehr über mein endgültiges Ziel in meiner Frage erfahren sollen. Kurz gesagt, ich habe eine Funktion geschrieben, die eine "3D" Summe (eine Summe über die Blätter) macht.Während ich weiß, dass Sie dies mit den integrierten Funktionen tun können, ist das Problem, dass ich Blätter wöchentlich hinzufüge, was bedeutet, dass ich diese Funktionen wieder aufnehmen und aktualisieren muss, um die neuen Blätter aufzunehmen. Was ich wollte, war nur eine Funktion, die iterativ Werte von ALLEN Blättern abholte und ihre Summe zurückgab, ohne dass ich die Funktion jede Woche aktualisieren musste. – jrc03c

+0

Und ich habe eine andere Frage: Warum ist ein SERVER für eine einfache Funktion wie die in meiner Frage notwendig? Warum können solche einfachen Dinge nicht clientseitig berechnet und dann in die Zellen hineingeschoben werden (oder zumindest wie ein HUD über der Tabelle angezeigt werden)? Ich bin mir bewusst, dass dieser Vorgang alle Arten von Berechtigungen und Sicherheitsfragen aufwirft. Aber haben Google Apps Scripts nicht bereits die Möglichkeit, vor dem Hantieren mit Benutzerdaten um Erlaubnis zu bitten? – jrc03c

+0

Bitte geben Sie weitere Details zur Art dieser "3D" -Summe oder einen Beispielcode für weitere Unterstützung an. Der Code, den Sie im Google Apps-Skript schreiben, ist im Wesentlichen serverseitiger Code. Es ist nicht Teil der Tabelle. Ich wette, dass es sich wie ein Dienst verhält. Jedes Skript hat seine eigene kleine Datenbank, es hat CPU-Berechtigungen, Timeout-Beschränkungen usw. Es gibt viel mehr zu tun als nur "" = "bar" 'als Tabellenkalkulation zu verwenden. Egal, ich bin mir sicher, dass es einen Weg gibt Um eine Summe zu erreichen, ohne diese Einschränkungen zu erfüllen – fooby

9

Nach dem Optimization section auf dem Apps Script Funkt.führer:

Each time a custom function is used in a spreadsheet, Google Sheets makes a separate call to the Apps Script server. If your spreadsheet contains dozens (or hundreds, or thousands!) of custom function calls, this process can be quite slow.

Consequently, if you plan to use a custom function multiple times on a large range of data, consider modifying the function so that it accepts a range as input in the form of a two-dimensional array, then returns a two-dimensional array that can overflow into the appropriate cells.

Um dies zu tun, in einem Eingang übergeben, die die Größe des Arrays repräsentiert Sie zurückgeben möchten. Wenn Sie mit der Ausführung Ihrer Funktion beginnen, prüfen Sie, ob der Eingabeparameter ein Array mit input.map ist. Wenn dies der Fall ist, können Sie die Funktion für jedes Element aufrufen und die gesamte Sammlung zurückgeben.

Also in Ihrem Fall wie folgt aus:

function foo(){ 
    return "bar"; 
}; 

Sie können die Funktion wie folgt aktualisiert:

function foo(input){ 
    if (input.map) {   // Test whether input is an array. 
    return input.map(foo); // Recurse over array if so. 
    } else { 
    // do actual function work here 
    return "bar"; 
    } 
}; 

Und es dann so nennen:

screenshot

+0

Wenn die 'foo'-Funktion mehrere Argumente akzeptiert, aber nur das erste Argument ein Array sein kann, gibt es eine ähnliche Methode, um erneut zu arbeiten e über das Array auch? – Argyll

Verwandte Themen