I need to get & combine values of some specific columns (Name, Age, Phone) from a raw sheet to another sheet but I don't know how to do it with the google app script.
the workflow looks like as below:
First, I need to get values of only Name, Age, Phone columns from the raw sheet, I don't want to collect the region column. The raw sheet looks like as an image here:
Then I think I have to push it to an array and paste it to the result sheet which contains 3 columns: Name, Age, Phone
In query function I can do it with this statement:
=query("raw sheet","select Col1, Col3, Col4")
but I don't know how to do it with google app script.
If you use to try it with google app script, please share with me the reference code to do it, thank you so much!
I believe your goal is as follows.
You want to retrieve the specific columns from a source sheet, and want to put the retrieved columns to the destination sheet using Google Apps Script.
In this case, how about the following sample script?
Sample script:
Please copy and paste the following script and set the variables of sourceAndDestinationSheet and dstHeader and run the function with the script editor.
function myFunction() {
const sourceAndDestinationSheet = ["source sheet name", "destination sheet name"]; // Please set the source sheet name and destination sheet name to the 1st and 2nd element.
const dstHeader = ["Name", "age", "phone"]; // This is the header of the destination values.
// 1. Retrieve values from the source sheet.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [srcSheet, dstSheet] = sourceAndDestinationSheet.map(s => ss.getSheetByName(s));
const [header, ...values] = srcSheet.getDataRange().getValues();
// 2. Create an array of destination values.
const colIndexes = dstHeader.map(h => header.indexOf(h));
const dstValues = [dstHeader, ...values.map(r => colIndexes.map(i => r[i]))];
// 3. Put the destination values to the destination sheet.
dstSheet.getRange(1, 1, dstValues.length, dstValues[0].length).setValues(dstValues);
}
Note:
If you want to use this script as a custom function, how about the following script? In this case, please put a custom formula of =SAMPLE(Sheet1!A1:D, "Name,age,phone") (It supposes that the source sheet and range are "Sheet1" and "A1:D") to the destination sheet.
function SAMPLE(v, h) {
const dstHeader = h.split(",").map(e => e.trim());
const [header, ...values] = v;
const colIndexes = dstHeader.map(h => header.indexOf(h));
return [dstHeader, ...values.map(r => colIndexes.map(i => r[i]))];
}
In this sample script, it is required to be the same between dstHeader and the actual header name of the source sheet. Please be careful this.
References:
map()
Custom Functions in Google Sheets
Try
=query('raw_2'!A1:D,"select A,B,D where A is not null",1)
Related
I have a google doc urls column within a google sheets
https://docs.google.com/spreadsheets/d/id
I want to display another column next to that to display google docs latest modified date? Is it possible to achieve that using google sheets formulas or apps script?
About Is it possible to achieve that using google sheets formulas or apps script?, in this case, the custom function cannot be used. But, when the Google Apps Script is run with the script editor, custom menu, button and so on, your goal can be achieved. In your situation, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet and run the function with the script editor. By this, the script is run.
function myFunction() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); // Please set your sheet name.
const range = sheet.getRange("A2:A" + sheet.getLastRow());
const values = range.getValues()
.map(([a]) => {
if (a.toString() == "") return [null];
const id = a.split("/")[5];
return [id ? DriveApp.getFileById(id).getLastUpdated() : null];
});
range.offset(0, 1).setValues(values);
}
In this sample script, first, the URLs are retrieved from the column "A" and the last updated date is retrieved using the file ID retrieved from URL. And, the retrieved values are put to the column "B".
Note:
In this sample, it supposes that the format of your URL is like https://docs.google.com/spreadsheets/d/id. Please be careful about this.
At the above sample script, it supposes that the URLs like https://docs.google.com/spreadsheets/d/id are directly put into the column "A". But, if the URLs are put to the column "A" as the hyperlink of a text like "DOC", please test the following script.
function myFunction() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); // Please set your sheet name.
const range = sheet.getRange("A2:A" + sheet.getLastRow());
const values = range.getRichTextValues()
.map(([a]) => {
const link = a.getLinkUrl();
if (!link) return [null];
const id = link.split("/")[5];
return [id ? DriveApp.getFileById(id).getLastUpdated() : null];
});
range.offset(0, 1).setValues(values);
}
As another approach, for example, if the number of URLs is large, I thought that the following sample script might be useful as the low process cost. This script retrieves the last updated date using Drive API with batch requests. When you use this script, please install a Google Apps Script library and please enable Drive API at Advanced Google services, and test it.
function myFunction() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); // Please set your sheet name.
const range = sheet.getRange("A2:A" + sheet.getLastRow());
const requests = {
batchPath: "batch/drive/v3",
requests: range.getValues().map(([a]) => ({ method: "GET", endpoint: `https://www.googleapis.com/drive/v3/files/${a.split("/")[5]}?fields=modifiedTime` })),
};
const values = BatchRequest.EDo(requests).map(({ modifiedTime }) => [modifiedTime ? new Date(modifiedTime) : null]);
range.offset(0, 1).setValues(values);
}
In this script, as a sample, it supposes that the column "A" has the URLs like https://docs.google.com/spreadsheets/d/id. Please be careful about this.
References:
getLastUpdated()
map()
I have 25 tabs in a Google Spreadsheet, but this number slowly grows as more data is added. The importrange function that we are provided by default requires the specification of which sheets to import data from using something like what was outlined here: Combining multiple spreadsheets in one using IMPORTRANGE. However, is there a way (using a default function or the Apps Script) to do this for all tabs in the Google Spreadsheet, without specifying each one individually?
I believe your goal is as follows.
You want to retrieve the values from all sheets in a Google Spreadsheet and want to put the values to a sheet of the destination Spreadsheet. In this case, you want to set a range you want to retrieve.
You want to achieve this using Google Apps Script.
Sample script:
Please copy and paste the following script to the script editor of Google Apps Script, and set the variables. And, run the function.
function myFunction() {
const range = "A1:E3"; // Please set the range you want to retrieve.
const srcSpreadsheetId = "###"; // Please set source Spreadsheet ID.
const dstSpreadsheetId = "###"; // Please set destination Spreadsheet ID.
const dstSheetName = "Sheet1"; // Please set destination sheet name.
const values = SpreadsheetApp.openById(srcSpreadsheetId).getSheets().flatMap(s => s.getRange(range).getValues());
const dstSheet = SpreadsheetApp.openById(dstSpreadsheetId).getSheetByName(dstSheetName);
dstSheet.clearContents().getRange(1, 1, values.length, values[0].length).setValues(values);
}
When this script is run, the values are retrieved from the specific range of all sheets from the source Spreadsheet, and the values are put to the destination sheet.
In the above script, the retrieved values to "A1" of the destination sheet. If you want to append the values, please modify as follows.
From
dstSheet.clearContents().getRange(1, 1, values.length, values[0].length).setValues(values);
To
dstSheet.getRange(dstSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
Unfortunately, I'm not sure whether I could correctly understand your question. So, for example, if you want to retrieve the values from all sheets except for multiple sheets, and you want to put the retrieved values to the specification sheet in the same Spreadsheet, how about the following sample script? In this case, you can use this script as a custom function. So, when you use this script, please put a custom function of =SAMPLE("A1:E3", "Sheet2,Sheet3") to a cell. In this sample arguments, the values are retrieved from the range of "A1:E3" of all sheets except for "Sheet2" and "Sheet3".
function SAMPLE(range, exclude) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const excludeSheets = [ss.getActiveSheet().getSheetName(), ...exclude.split(",").map(e => e.trim())];
return ss.getSheets().flatMap(s => {
if (!excludeSheets.includes(s.getSheetName())) {
return s.getRange(range).getValues();
}
return [];
});
}
As another pattern, if you want to retrieve the values from all sheets in a source Spreadsheet to a sheet of destination Spreadsheet, how about the following sample script? In this sample, please copy and paste the following script to the script editor of the destination Spreadsheet. And, please set the variables of source Spreadsheet ID and range you want. When this script is run, a formula is put to the cell "A1" of the destination sheet. The formula is from this thread. By this, you can see the values from all sheets in the source Spreadsheet at the destination sheet.
function myFunction2() {
const range = "A1:E3"; // Please set the range you want to retrieve.
const srcSpreadsheetId = "###"; // Please set source Spreadsheet ID.
const srcSs = SpreadsheetApp.openById(srcSpreadsheetId);
const url = srcSs.getUrl();
const values = srcSs.getSheets().map(s => `IMPORTRANGE("${url}","'${s.getSheetName()}'!${range}")`);
const formula = `={${values.join(";")}}`;
const dstSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); // Please set the destination sheet name.
dstSheet.clearContents().getRange(1, 1).setFormula(formula);
}
References:
getSheets()
getValues()
setValues(values)
Added:
About your following reply,
I'm using the first block of code that you sent, and it works. However, I want to copy the entire cell so that it also transfers the cell color, in addition to the text content of the cell. How would I modify the first block of code you sent to do that?
Unfortunately, from your question, I couldn't notice that you wanted to copy both the values and the background color of the cells. To achieve this request, the modified script of my 1st script is as follows.
Sample script:
function myFunction() {
const range = "A1:E3"; // Please set the range you want to retrieve.
const srcSpreadsheetId = "###"; // Please set source Spreadsheet ID.
const dstSpreadsheetId = "###"; // Please set destination Spreadsheet ID.
const dstSheetName = "Sheet1"; // Please set destination sheet name.
const { values, backgroundColors } = SpreadsheetApp.openById(srcSpreadsheetId).getSheets().reduce((o, s) => {
const r = s.getRange(range);
o.values = [...o.values, ...r.getValues()];
o.backgroundColors = [...o.backgroundColors, ...r.getBackgrounds()];
return o;
}, { values: [], backgroundColors: [] });
const dstSheet = SpreadsheetApp.openById(dstSpreadsheetId).getSheetByName(dstSheetName);
dstSheet.clearContents().clearFormats().getRange(1, 1, values.length, values[0].length).setValues(values).setBackgrounds(backgroundColors);
}
I have a column with strings containing a name and an ID concatenated. How can I extract just the name part of the string and use that for filtering a dataset and copying it over to another worksheet in the google sheets file using the google apps script? The main thing I'm having difficulty with is just extracting the names from the column since they can vary in length. Additionally, I'm trying to perform automation using google apps script, so I want to avoid making a column manually and use something like regex.
Below is an example of how the column values look:
Identity
Jane100
Adam500
Adam500
Erica234
Jessica8
We can use regular expressions here:
var input = "Adam500";
var regExp = new RegExp("([a-z]+)", "i")
var name = regExp.exec(input)[1];
Logger.log(name); // Adam
I believe your goal is as follows.
You want to copy the following values on a column of the source sheet.
Identity
Jane100
Adam500
Adam500
Erica234
Jessica8
And, you want to paste the following values to a column of the destination sheet (in the same Spreadsheet) by converting from the above values.
Identity
Jane
Adam
Adam
Erica
Jessica
You want to achieve this using Google Apps Script.
In this case, how about the following sample script?
Sample script 1:
function sample1() {
const srcSheetName = "Sheet1"; // Please set the source sheet name.
const dstSheetName = "Sheet2"; // Please set the destination sheet name.
const srcColumn = 1; // Values are retrieved from column "A".
const dstColumn = 1; // Values are put to the column "A".
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [srcSheet, dstSheet] = [srcSheetName, dstSheetName].map(e => ss.getSheetByName(e));
const srcValues = srcSheet.getRange(1, srcColumn, srcSheet.getLastRow()).getValues();
const dstValues = srcValues.map(([a], i) => [i == 0 || !a.toString() ? a : a.replace(/\d+/g, "")]);
dstSheet.getRange(1, dstColumn, dstValues.length).setValues(dstValues);
}
In this sample script, the values are retrieved from the column of the source sheet, and the converted values are put on the destination sheet.
Sample script 2:
function sample2() {
const srcSheetName = "Sheet1"; // Please set the source sheet name.
const dstSheetName = "Sheet2"; // Please set the destination sheet name.
const srcColumn = 1; // Values are retrieved from column "A".
const dstColumn = 1; // Values are put to the column "A".
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [srcSheet, dstSheet] = [srcSheetName, dstSheetName].map(e => ss.getSheetByName(e));
const last = srcSheet.getLastRow();
const dstRange = dstSheet.getRange(1, dstColumn);
srcSheet.getRange(1, srcColumn, last).copyTo(dstRange);
dstRange.offset(1, 0, last - 1).createTextFinder("\\d+").useRegularExpression(true).replaceAllWith("");
}
In this sample script, the values are copied from the column of the source sheet to the destination sheet. And, the copied values are converted. In this case, the text styles can be copied.
References:
getValues()
setValues(values)
createTextFinder(findText)
SpreadsheetApp how to return unique values from an array
in this post how to count a duplicate values and show theme in sheetname('test2') Range ('B2:B7')
here my google sheet https://docs.google.com/spreadsheets/d/1HN0XCLrEzlRkInIv6xFnhCFnhZabu7Y-Tz1dvYvsGQM/edit?usp=sharing
In your situation, how about the following sample script?
Sample script:
function myFunction() {
const srcSheetName = "test"; // Please set the source sheet name.
const dstSheetName = "test2"; // Please set the destination sheet name.
// Retrieve source and destination sheets.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [srcSheet, dstSheet] = [srcSheetName, dstSheetName].map(s => ss.getSheetByName(s));
// Retrieve source values and create an object for putting to the destination sheet.
const srcValues = srcSheet.getRange("A2:A" + srcSheet.getLastRow()).getValues();
const obj = srcValues.reduce((o, [a]) => (o[a] = o[a] ? o[a] + 1 : 1, o), {});
// Retrieve the values of column "A" from the destination sheet and create an array for putting to Spreadsheet.
const dstRange = dstSheet.getRange("A2:A" + dstSheet.getLastRow());
const dstValues = dstRange.getDisplayValues().map(([a]) => [obj[a] || 0]);
// Put the result values to the column "B" of the destination sheet.
dstRange.offset(0, 1).setValues(dstValues);
}
From your provided Spreadsheet, the sample sheet names are test and test2. Please modify this for your actual situation.
When you run this script, the values are retrieved from the source sheet and the count of each value is calculated. And, the result values are put to the column "B" of the destination sheet.
Note:
This sample script is for your provided Spreadsheet. When you change the structure of the Spreadsheet, this script might not be able to be used. Please be careful about this.
References:
reduce()
map()
I have bill of materials report where the data is double stacked when exported from database.
Original data:
Sheet is very large, but I want to format the data like this
Still a noob with appscript, but how would i script this to do that?
Thanks in advance.
I believe your goal as follows.
You want to achieve the following conversion on Google Spreadsheet using Google Apps Script.
From: Source sheet
To: Destination sheet
Flow:
In this case, I would like to propose the following flow of the sample script.
Retrieve values from the source sheet.
Create values for putting to the destination sheet an 2 dimensional array.
In this case, in the following sample script, the value of column "A" is checked. When the value of column "A" is not empty, the values of columns "A" to "D" is set to temp array. And when the next row of it has no value of column "A", the value of row is added to temp. By this, 0,123-00000-00,Test Assembly,,ABC Inc,abc123 is created. When the next row has no value of column "A", the value is added to ar by adding 4 empty values. By this, ,,,,XYZ Inc,abc234 is created. By this flow, the destination values are created.
Put the created value to the destination sheet.
Sample script:
When you use this script, please copy and paste the following script to the container-bound script of the Spreadsheet. And please set the source sheet name and destination sheet name.
function myFunction() {
const srcSheetName = "Sheet1"; // Please set the source sheet name.
const dstSheetName = "Sheet2"; // Please set the destination sheet name.
// 1. Retrieve values from the source sheet.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [header1, [,subHead1, subHead2], ...srcValues] = ss.getSheetByName(srcSheetName).getDataRange().getValues();
// 2. Create values for putting to the destination sheet an 2 dimensional array.
let temp = [];
const dstValues = srcValues.reduce((ar, [a,b,c,d]) => {
if (a.toString() != "") {
if (temp.length == 4) ar.push(temp.concat("",""));
temp = [].concat(a,b,c,d);
} else {
ar.push(temp.length == 4 ? temp = temp.concat(b,c) : Array(4).fill("").concat(b,c));
}
return ar;
}, [header1.concat(subHead1, subHead2)]);
// 3. Put the created value to the destination sheet.
ss.getSheetByName(dstSheetName).getRange(1, 1, dstValues.length, dstValues[0].length).setValues(dstValues);
}
When you run the function of myFunction(), the values are put to the destination sheet.
Note:
Please use this script with enabling V8.
If you want to use the script as the custom function, you can also use the following script. When you use this script, for example, when your sample input sheet is used, please put a custom function of =CUSTOMSAMPLE(A1:D12).
function CUSTOMSAMPLE(values) {
// 1. Retrieve values from the source sheet.
const [header1, [,subHead1, subHead2], ...srcValues] = values;
// 2. Create values for putting to the destination sheet an 2 dimensional array.
let temp = [];
const dstValues = srcValues.reduce((ar, [a,b,c,d]) => {
if (a.toString() != "") {
if (temp.length == 4) ar.push(temp.concat("",""));
temp = [].concat(a,b,c,d);
} else {
ar.push(temp.length == 4 ? temp = temp.concat(b,c) : Array(4).fill("").concat(b,c));
}
return ar;
}, [header1.concat(subHead1, subHead2)]);
// 3. Put the created value to the destination sheet.
return dstValues;
}
This sample script is for your sample input and output values in your question. When the cell structure in your actual sheet is different from them, the script might not be able to be used. Please be careful this.
References:
getValues()
reduce()
setValues(values)