3

I have one spreadsheet with multiple tabs, e.g.

"Summary"
"Week 1"
"Week 2"
"Backlog"

The number of Weeks is not fixed. In the future, I may add more tabs as time goes on, for example
"Week 3"
"Week 4"
...

In the "summary" tab, I want to list all the data from Column A (remove title) from all "Week" tabs. Currently, I have to add all the tab names of "Week" manually in the query range parameter, e.g.

=query({'Week 1'!A2:A; 'Week 2'!A2:A}, "select *")

But I want to make it automatically if I add more tabs in the future by doing something like this:

=query({"Week *"}!A2:A, "select *")

How do I do that?

TheMaster
  • 45,448
  • 6
  • 62
  • 85
raywang
  • 33
  • 3

2 Answers2

4

An option would be to get rid of the QUERY formula altogether and use an Apps Script Custom Function instead.

First, open a bound script by selecting Tools > Script editor, and copy the following functions to the script:

function SUMMARIZE_WEEKTABS() {
  const ss = SpreadsheetApp.getActive();
  const weekSheets = ss.getSheets().filter(sheet => sheet.getName().startsWith("Week "));
  const summarySheet = ss.getSheetByName("Summary");
  let weekData = weekSheets.map(weekSheet => {
    return weekSheet.getRange(2, 1, weekSheet.getLastRow()).getValues().flat();    
  });
  weekData = weekData[0].map((_, colIndex) => weekData.map(row => row[colIndex]));
  return weekData;
}

The function SUMMARIZE_TABS returns the data from column A from all sheets whose name starts with "Week ". Once it is defined in your script, you can use it the same way you would use any sheets built-in function. See, for example, this:

enter image description here

Update:

If you want all data to be written on the same column, use this instead:

function SUMMARIZE_WEEKTABS() {
  const ss = SpreadsheetApp.getActive();
  const weekSheets = ss.getSheets().filter(sheet => sheet.getName().startsWith("Week "));
  const summarySheet = ss.getSheetByName("Summary");
  let weekData = weekSheets.map(weekSheet => {
    return weekSheet.getRange(2, 1, weekSheet.getLastRow() - 1).getValues();    
  }).flat();
  return weekData;
}

Reference:

Iamblichus
  • 18,540
  • 2
  • 11
  • 27
  • Thank you @Iamblichus Just one more question. I notice that all the results are placed in each column for each "Week" tab, how to place all the results in just one column instead of in multiple columns? Big thanks – raywang Sep 23 '20 at 09:31
  • @raywang I updated my answer with this option. Let me know if that works for you. – Iamblichus Sep 23 '20 at 10:11
  • Hi @lamblichus, Big thanks for the update, it's almost there. The results returned and placed in a row but not in a column. I have zero knowledge about the script programing, thank you so much for another update. – raywang Sep 25 '20 at 06:52
  • @raywang I tested it, all data is placed in a column, not in a row. Did you copy this function as it is? – Iamblichus Sep 25 '20 at 07:03
  • 1
    Hi @lamblichus, my bad, your code works. Thanks a million! – raywang Sep 28 '20 at 07:52
  • @lamblichus is there a tweak to populate only unique values? (I too need this, sorry for the bump) – Nix Dec 08 '20 at 11:34
  • @Nix There are many ways to do this, probably the easiest would be using Set and the spread syntax to remove the duplicates from the returned array, as shown in [this answer](https://stackoverflow.com/a/9229821): `weekData = [...new Set(weekData)]`. If this is not what you want, or if you need more details, I'd suggest posting a new question. – Iamblichus Dec 08 '20 at 11:47
  • @lamblichus Thanks for the reply! I did raised a similar [question](https://stackoverflow.com/questions/65195498/script-to-summary-unique-column-from-multiple-tabs-google-sheets-then-if-possibl) that needed two part and this is the first part solution. I found after 2 days... I added this code before last line and it worked `unique=getUnique_(weekData).map(e=>[e]); returnunique;` I've no idea what I did – Nix Dec 08 '20 at 11:55
2

Explanation:

You can use Google Apps Script to accomplish this task.

The following script:

  • gets all the sheets of your spreadsheet file that contain the name Week,
  • iterates over these sheets and construct a string object which can be used inside the query formula,
  • sets the resulting formula to cell A1 of the Summary sheet. Feel free to modify A1 in the code below.

I also added a function that creates a macro button on top of your sheet, so you can use this functionality from the sheet itself (see instructions below).


Solution:

Please follow the instructions (gif) on how to use the following code:

function getQuery() {
  const ss = SpreadsheetApp.getActive();
  const summary_sheet = ss.getSheetByName('Summary');
  const sheet_names = ss.getSheets().filter(fsh=>fsh.getName().includes("Week")).map(sh=>sh.getName())
  var weeks = [];
  sheet_names.forEach(wk => 
                      weeks.push(`'${wk}'!A2:A`)
                     )
  summary_sheet.getRange('A1').setFormula(`=query({${weeks.join(";")}}, "select *")`)

}

function onOpen() {
  SpreadsheetApp.getUi()
  .createMenu('Macros')
  .addItem('Get Query', 'getQuery')
  .addToUi();
}

Instructions:

After you save the code snippet in the script editor, refresh your sheet/browser.

steps


References:

Google Apps Script libraries:

JavaScript libraries:

Marios
  • 26,333
  • 8
  • 32
  • 52
  • Thank you so much for your solution and code, really appreciated. I think it does inspire me on how to do this! FWIW, I don't know why, but your code only returns the content of A2:A from the first "Week" tab, and ignore the results of the rest of the "Week" tabs. – raywang Sep 18 '20 at 09:04
  • @raywang the query works. It does not ignore the results of the other week tabs. In your query, you say A2:A. Which means that you are getting all the empty cells of each week tab. If you scroll down the summary tab, you will see the data of the other weeks too. Accept the answer if it solved your question by clicking on the ✅ button to the left of the answer. – Marios Sep 18 '20 at 09:19