Verwenden von Abfrage mit Spaltenüberschriften anstelle von Spaltenbuchstaben

7

Ich habe eine Formel, mit der ich den Spaltenbuchstaben für ein eindimensionales Array, das die Spaltenüberschriften eines Blattes sind, dynamisch abrufe. Um QUERY () mit Spaltennamen anstelle von Buchstaben zu verwenden.

SUBSTITUTE(ADDRESS(1,MATCH("Weight", Headers, 0),4), "1", "")

Die Syntax nimmt ziemlich viel Platz ein und kann für die Augen schwierig sein, wenn die Abfragen lang werden. Ein Beispiel:

=QUERY(A3:F13, "select "&SUBSTITUTE(ADDRESS(1,MATCH("Type", Headers, 0),4), "1", "")&" where ("&SUBSTITUTE(ADDRESS(1,MATCH("Version", Headers, 0),4), "1", "")&" = 'Version 1') and ("&SUBSTITUTE(ADDRESS(1,MATCH("Type", Headers, 0),4), "1", "")&" <> 'Type')")

Tut das gleiche wie

=QUERY(A3:F13, "select E where (A = 'Version 1') and (E <> 'Type')")

Mit dem Vorteil, immer die Zeile auszuwählen, möchte ich, egal in welcher Reihenfolge sie sind.

Ist es möglich, eine Funktion zu erstellen, die wie folgt funktioniert, ohne das Rad im Apps-Skript neu zu erstellen?:

GetHeaders(range, string)

=QUERY(A3:F13, "select "&GetHeader(Headers, "Type")&" where ("&GetHeader(Headers, "Version")&" = 'Version 1') and ("&GetHeader(Headers, "Type")&" <> 'Type')")
Douglas Gaskell
quelle
Wie @Normal Human in einem Kommentar in seiner Antwort erklärt hat, besteht die einzige Möglichkeit, eine benutzerdefinierte Funktion zu erstellen , in der Verwendung von Apps Script. Wenn Sie Antworten ohne deren Verwendung benötigen, sollte "Funktion erstellen" umformuliert werden (dh "Formel erstellen") und erwähnen, dass die Verwendung benutzerdefinierter Funktionen nicht erwünscht ist.
Rubén

Antworten:

4

Ohne Apps-Skript

Ohne Apps Script kann man keine neue Funktion erstellen. Die einzige Möglichkeit, den Prozess zu rationalisieren, besteht darin, mehr Zellen irgendwo zu platzieren und auf diese zu verweisen.

Beispiel: Geben Sie unter jeder Überschrift wie "Gewicht" den Befehl ein

=regexextract(address(1, column()), "[A-Z]+")

Dadurch werden die Spaltenbuchstaben unter die Überschriften gesetzt. Fügen Sie die Zeile mit Buchstaben in den Bereich "Überschriften" ein. Verwenden Sie in der Abfragezeichenfolge

hlookup("Weight", Headers, 2, 0)

Das ist leichter für die Augen als

SUBSTITUTE(ADDRESS(1,MATCH("Weight", Headers, 0),4), "1", "")

Mit Apps Script

Wenn Sie einen Bereich (benannt oder anderweitig) an eine benutzerdefinierte Funktion übergeben, werden die Werte übergeben , ohne dass Informationen zu ihrer Position im Blatt vorliegen. Aber ich habe eine Lösung gefunden: Leiten Sie die Position der Header aus dem ersten Argument von ab query. Es ist nicht erforderlich, "Header" einzuschließen, was sich selbst wiederholte.

Version 1: Header im Abfragebereich enthalten

Ich bevorzuge es, die Kopfzeilen in den an die Abfrage übergebenen Bereich aufzunehmen und die Anzahl der Kopfzeilen als drittes Argument von anzugeben query. Dies vermeidet eine Fehlinterpretation von Daten als Header oder umgekehrt. Zum Beispiel:

=QUERY(A1:F13, "select "&GetHeader("Type")&" where ("&GetHeader("Version")&" = 'Version 1') and ("&GetHeader("Type")&" <> 'Type')", 2) 

Hier ist die benutzerdefinierte Funktion, die mit der obigen Abfrage verwendet werden soll:

function getHeader(name) {
  var sheet = SpreadsheetApp.getActiveSheet();
  var formula = SpreadsheetApp.getActiveRange().getFormula();
  var args = formula.match(/\w+:\w+(?=[ ,])/);
  var range = sheet.getRange(args[0]);
  var firstRow = range.offset(0, 0, 1, range.getWidth());
  var headers = firstRow.getValues();
  for (var i = 0; i < headers[0].length; i++) {
    if (headers[0][i] == name) {
      var notation = range.getCell(1, i+1).getA1Notation();
      var column = notation.replace(/\d/, '');
      return column;
    }
  }
  return 'Not found';
}

Die Funktion erhält die Formel aus der Zelle, aus der sie aufgerufen wurde. Es extrahiert das erste Bereichsargument der Formel mit einem regulären Ausdruck. Dann durchsucht es die erste Zeile dieses Bereichs , vorausgesetzt, es ist die Kopfzeile, auf der Suche nach der angegebenen Zeichenfolge. Es erhält die A1-Notation der Zelle mit der Zeichenfolge, entfernt den Zeilenteil davon und gibt das Ergebnis zurück.

Version 2: Header aus Zeile 1

Eine alternative Version, bei der die Überschriften unabhängig von den Zeilen im Abfrageargument aus der ersten Zeile des Blattes stammen. Einfach ersetzen

  var firstRow = range.offset(0, 0, 1, range.getWidth());

mit

  var firstRow = sheet.getRange(1, range.getColumn(), 1, range.getWidth());

Mit dieser Version können Sie verwenden

=QUERY(A3:F13, "select "&GetHeader("Type")&" where ("&GetHeader("Version")&" = 'Version 1') and ("&GetHeader("Type")&" <> 'Type')")  

quelle
Danke normaler Mensch! Ich wollte jedoch die Verwendung von Apps Script vermeiden, da benutzerdefinierte Funktionen in der Regel nur zeitweise funktionieren, wenn sie in Massen verwendet werden. Ich benötige etwas, das jedes Mal funktioniert, und meiner Erfahrung nach funktionieren benutzerdefinierte Funktionen nicht jedes Mal (das fortwährende Loading...Problem, das gelöst werden kann) Löschen und erneutes Einfügen der Funktion).
Douglas Gaskell
1
Sie haben gefragt, ob Sie eine Funktion erstellen möchten. Die Verwendung von Apps Script ist die einzige Möglichkeit, eine neue Funktion zu erstellen. Ansonsten gibt es nichts anderes als das Kopieren und Einfügen derselben Kombination von integrierten Funktionen. Ich verstehe die Bedenken hinsichtlich der Leistung, aber normalerweise ist die Anzahl der Abfragen nicht sehr groß, oder Sie haben Leistungsprobleme im Zusammenhang mit Abfragen selbst.
1
Trotzdem habe ich meinen Vorschlag hinzugefügt, ohne Skript zu handeln.
0

Ich mag die Antwort von user79865 sehr. Wenn Sie es verwenden möchten und ein anderes Gebietsschema als US haben (wie mein polnisches), haben Sie möglicherweise ein anderes Trennzeichen für Funktionsargumente in Sheets. Und statt:

=QUERY(A3:F13, "select "&GetHeader("Type")&" where ("&GetHeader("Version")&" = 'Version 1') and ("&GetHeader("Type")&" <> 'Type')", 2)

Sie könnten haben ( ;anstelle von ,):

=QUERY(A3:F13; "select "&GetHeader("Type")&" where ("&GetHeader("Version")&" = 'Version 1') and ("&GetHeader("Type")&" <> 'Type')"; 2)

In diesem Fall sollte der reguläre Ausdruck in Funktion (Version 1), Zeile 4, geändert werden von:

var args = formula.match(/\w+:\w+(?=[ ,])/);

zu:

var args = formula.match(/\w+:\w+(?=[ ;])/);


Wenn sich Ihre Daten in einem separaten Blatt befinden (aber in derselben Tabelle), können Sie den regulären Ausdruck ändern, um nach dem Blattnamen zu suchen und ihn zur Suche nach Spaltennamen zu verwenden:

function getHeader( name ) {
  var sheet = SpreadsheetApp.getActiveSheet();
  var formula = SpreadsheetApp.getActiveRange().getFormula();
  var args = formula.match(/\((\'*(.+(?=[!']))\'*!)*(\w+:\w+(?=[ ;]))/); // 1: "'sheet name'!", 2:"sheet name", 3:"A1:D100"
  if( args[2] ) 
    sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(args[2]);
  var range = sheet.getRange(args[3]);
  var firstRow = range.offset(0, 0, 1, range.getWidth());
  var headers = firstRow.getValues();
  for (var i = 0; i < headers[0].length; i++) {
    if (headers[0][i] == name) {
      var notation = range.getCell(1, i+1).getA1Notation();
      var column = notation.replace(/\d/, '');
      return column;
    }
  }
  return 'Not found';
}


Ich möchte einen Kommentar hinzufügen, aber als Anfänger kann ich keinen Kommentar abgeben ...

Piotr Machowski
quelle