Hi I have a list of data in Google Sheets that I want to use to extract certain names based upon another list.
Following code works to point me out on what row the search_string is:
function searchString(){
var sheet = SpreadsheetApp.getActiveSheet()
var search_string = "searchname1"
var textFinder = sheet.createTextFinder(search_string)
var search_row = textFinder.findNext().getRow()
var ui = SpreadsheetApp.getUi();
ui.alert("search row: " + search_row)
}
I want to find out how I can add multiple search_strings like below. Its quite a list.
I tried array brackets but that gives me an error of NULL.
function searchString(){
var sheet = SpreadsheetApp.getActiveSheet()
var search_string = ("searchname1","searchname2")
var textFinder = sheet.createTextFinder(search_string)
var search_row = textFinder.findNext().getRow()
var ui = SpreadsheetApp.getUi();
ui.alert("search row: " + search_row)
}
Then instead of showing me an alert I want to copy the rows that are found to a new sheet.
In the subsequential order of the array of search_strings.
Explanation:
Your goal is to copy the rows where the strings appear (for the first time) in the source sheet to a target sheet.
You can include all the strings you want to search in the search_strings array.
Iterate over each string to find the first row it appears and add that row to the rows array.
Then you can get all the data from the source sheet and filter only the rows that are part of the rows list:
var data = source_sheet.getDataRange()
.getValues().filter((_,i)=>rows.includes(i+1));
Finally copy the data to the target sheet.
Solution:
function searchString(){
const ss = SpreadsheetApp.getActive();
const source_sheet = ss.getSheetByName('Sheet1'); // change the name
const target_sheet = ss.getSheetByName('Sheet2'); // change the name
const search_strings = ["searchname1","searchname2"]; // add your strings to search
const rows = [];
search_strings.forEach(search_string=>{
let textFinder = source_sheet.createTextFinder(search_string);
try{
let search_row = textFinder.findNext().getRow();
rows.push(search_row);
} catch(e){}
});
const data = source_sheet.getDataRange()
.getValues().filter((_,i)=>rows.includes(i+1));
if(data.length>0){
target_sheet.getRange(1,1,data.length,data[0].length).setValues(data);
}
}
Related
Good health to all! In this case, the row contains 136 columns, we filter by the 8th column, then we need to copy and paste into another file, for example, columns 134-136. I set the range var rng = sht.getRange(3,134,10000,3), I thought it would be similar to the FILTER() function, but no - the script works only if the range contains a column by which we filter... There was also a decision to insert all 136 columns and delete unnecessary 133, but this is generally, as it seems to me, inhumane.
Can you tell me what needs to be changed in the existing code so that you can copy and paste a filtered range that does not contain the column that is being filtered?
How can the script be modified so that it can be filtered by two or more columns?
Here I found a piece of code that filters the Google table by value and inserts the selected rows into the specified sheet.
I would be grateful for a tip on the optimal solutions for each issue
function CopyPaste()
{//the quantity is written
const SOURCE1 = SpreadsheetApp.openById("Here is the Google table ID");
const sht = SOURCE1.getSheetByName("Sales");
var ss = SpreadsheetApp.getActive();
var sheet2 = ss.getSheetByName("Monitor"); //settings sheet
var diap = sheet2.getRange("A1").getValue(); //value for the filter
var rng = sht.getRange(3,1,10000,136);// filtered range
var PasteSht = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet 3');// sheet for inserting data in the current workbook
var rngA = rng.getValues();//this is where a fragment of someone else's code came from (I didn't rename variables)
var yesesA = []
for(var i=0;i<rngA.length;i++)
{
if(rngA[i][7]==diap)
{
yesesA.push(rngA[i])
}
}
var yesesRng = PasteSht.getRange(3, 1, yesesA.length, yesesA[0].length);
yesesRng.setValues(yesesA);
}
Try this
Code.gs
function CopyPaste() { //the quantity is written
const SOURCE1 = SpreadsheetApp.openById("Here is the Google table ID");
const sht = SOURCE1.getSheetByName("Sales");
var ss = SpreadsheetApp.getActive();
var sheet2 = ss.getSheetByName("Monitor"); //settings sheet
var diap = sheet2.getRange("A1").getValue(); //value for the filter
var rng = sht.getDataRange(); // filtered range
var PasteSht = ss.getSheetByName('Sheet 3');// sheet for inserting data in the current workbook
var rngA = rng.getValues();//this is where a fragment of someone else's code came from (I didn't rename variables)
var yesesA = rngA.filter( row => row[7] === diap ); // filter out all rows including diap
ysesA = yesesA.map( row => row.slice(132,136) ); // Array.slice(from,to(not including)) columns 133-136
var yesesRng = PasteSht.getRange(3, 1, yesesA.length, yesesA[0].length);
yesesRng.setValues(yesesA);
}
Reference
Array.filter()
Array.map()
Arrow function expression
I've been looking on this website and others for an answer but can't find anything relevant and was wondering if someone could help please.
I've using Apps Script - Google Sheets.
The main sheet was called "M-Front". So it got quotation number with revision number. If new quotation, the revision will be zero. If we revise the quotation once, the revision number will be 1.
For example, GE-2108-0271-Rev.0 is new quotation.
If we revise once, it would be GE-2108-0271-Rev.1.
I have other sheet called "M-Items".
Let say for GE-2108-0271-Rev.0, we have three rows for that quotation number represent three items for that quotation.
My intention is , if new revision was made in "M-Front". It will be GE-2108-0271-Rev.1. But how to detect the last row from "M-Front" quotation number and in "M-Items" we copy and paste the rows. In this case, 3 rows/items. and make the quotation in "M-Items" from GE-2108-0271-Rev.0 to GE-2108-0271-Rev.1.
M-Front
M-Items
The Script i've stuck
function CopyRange() {
var sourcespread = SpreadsheetApp.openById('1Zgs1jzjIeaBpd5Ms7emQgxhVJBMtlEOlDNDfxlhSRiY'); //replace with source ID
var sourcesheet = sourcespread.getSheetByName('M-Front'); //replace with source Sheet tab name
var destspread = SpreadsheetApp.openById('1Zgs1jzjIeaBpd5Ms7emQgxhVJBMtlEOlDNDfxlhSRiY'); //replace with destination ID
var destsheet = destspread.getSheetByName('M-Items'); //replace with destination Sheet tab name
var testrange = sourcesheet.getRange('M:M').getLastRow;
var testvalue = (testrange.getValues());
var data = [];
var j =[];
for (i=0;i<testvalue.length;i++) {
if (testvalue[i] /= 0) {
data.push.apply(data,sourcesheet.getRange('A:A').getValues());
//Copy matched ROW numbers to j
j.push(i);
}
}
//Copy data array to destination sheet
destsheet.getRange(destsheet.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}
You might want to try the below script:
function CopyRange() {
var sourcespread = SpreadsheetApp.openById('1Zgs1jzjIeaBpd5Ms7emQgxhVJBMtlEOlDNDfxlhSRiY'); //replace with source ID
var sourcesheet = sourcespread.getSheetByName('M-Front'); //replace with source Sheet tab name
var destsheet = sourcespread.getSheetByName('M-Items'); //replace with destination Sheet tab name
var mcol= sourcesheet.getRange('M1:M').getValues();
var acol = sourcesheet.getRange('A1:A').getValues();
var ccol = destsheet.getRange('C1:C').getValues();
var acol2 = destsheet.getRange('A1:A').getValues();
var mvalues = mcol.filter(String);
var avalues = acol.filter(String);
var cvalues = ccol.filter(String);
var avalues2 = acol2.filter(String);
for (let i=1; i<mvalues.length; i++) {
if (mvalues[i][0] != 0) {
if (avalues[i][0] == avalues2[i][0] && mvalues[i][0] == cvalues[i][0] - 1)
var valuescopy = sourcesheet.getRange("RANGE_FOR_THE_VALUES_TO_COPY").getValues();
destsheet.getRange("RANGE_WHERE_TO_PASTE").setValues(valuescopy);
cvalues[i][0]++;
}
}
}
It is important to note the following points:
getLastRow will return the last row for the entire range - this means that the rows which have no values are also included this;
In order to retrieve the rows which contain a value, the filter has been used.
getValues method will return a 2D array, so you will have to access an element in this way array[i][j].
Moreover, please bear in mind that you will have to adjust the ranges properly such that they match your needs accordingly; more specifically, the range from where you want to copy the values and also the destination range.
Reference
getLastRow();
getValues();
getRange(row, column, numRows, numColumns).
In my Spreadsheet I have a column of data with book titles, and a column data with of URLS in it, about 5000 rows. I would like to use appscript to make a new column of data with those same titles hyperlinked using the URLS in the other column.
I'm trying to do this with arrays and the map function but I'm not sure how to use the map function so that the titles become hyperlinked. I'm very new at this so need a bit of help. Here's what I'm doing so far, the "????" in the MakeURL function is placeholder for the fix. Any suggestions?
Thank you for helping!
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet=ss.getActiveSheet();
function mainfunction() {
//Get both non-contiguous values into separate arrays.
var titles = activeSheet.getRange('E:E').getValues();
var theURLS = activeSheet.getRange('Q:Q').getValues();
//Put both values into a single unified array
var unified=[];
for (var i=0;i<titles.length;i++){
unified.push(titles[i],theURLS[i])
}
//Run a transformation on the values of the unified array and output it into newTitles array
var newtitles = unified.map(makeURL);
//write the new hyperlinked titles into a range(column).
activeSheet.getRange('Z:Z').setValues(newtitles);
};
function makeURL(row){ return ?????; };
I believe your goal as follows.
You want to retrieve the values from the columns "E" and "Q".
The columns "E" and "Q" are the title and the hyperlink, respectively.
You want to create the hyperlink value using the title and hyperlink, and want to put the values to the column "Z".
You want to achieve this using Google Apps Script.
In this case, I would like to propose to use RichTextValues. When this is reflected to your script, please modify as follows.
Modified script:
When you run the function of the modified mainfunction, the hyperlink values created from the columns "E" and "Q" are put to the column "Z".
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
function mainfunction() {
//Get both non-contiguous values into separate arrays.
var lastRow = activeSheet.getLastRow();
var titles = activeSheet.getRange('E1:E' + lastRow).getValues();
var theURLS = activeSheet.getRange('Q1:Q' + lastRow).getValues();
var richTextValues = titles.map(([e], i) => [SpreadsheetApp.newRichTextValue().setText(e).setLinkUrl(theURLS[i][0]).build()]);
activeSheet.getRange('Z1:Z' + richTextValues.length).setRichTextValues(richTextValues);
}
Note:
If you will achieve your goal using the built-in formula, I thought that you can also use the following formula. In this case, please put it to the cell "Z1".
=ARRAYFORMULA(HYPERLINK(Q:Q,E:E))
If you want to put the formulas using Google Apps Script, I thought that you can also use the following script.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
function mainfunction() {
//Get both non-contiguous values into separate arrays.
var lastRow = activeSheet.getLastRow();
var titles = activeSheet.getRange('E1:E' + lastRow).getValues();
var theURLS = activeSheet.getRange('Q1:Q' + lastRow).getValues();
var formulas = titles.map(([e], i) => [`HYPERLINK("${theURLS[i][0]}","${e}")`]);
activeSheet.getRange('Z1:Z' + formulas.length).setFormulas(formulas);
}
References:
Class RichTextValueBuilder
setRichTextValues(values)
Ok, title might be confusing. I mean, I'm confused just trying to make this work.
I essentially have 3 sheets.
The Search Sheet - Has a search box & macro button.
The Data Sheet - self explanatory.
The Target Sheet - Sorted into columns.
So, what I'm needing to happen is: when a user enters a value in the Search Sheet & hits the "go" button, it searches the Data sheet for any cells in column B that match. On a match, it modifies the matched cell so it won't match on another search, then copies the adjacent cell 'A' value into the first column of the Target Sheet, contuingin down the sheet & adding each match to the same column.
On a new search, the results will show in the 2nd column, etc...
Search1 = "L1" | Search 2 = "L3"
Data Sheet:
DataSheet
Result Sheet:
Result Sheet
Here's my shitty attempt at scripting it. I probably defined the wrong things & didn't define right things. I'm trying to wrap my head around it, but I think I've gotten into the deep end too fast.
function moveTest() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); //Spreadsheet
var source = ss.getSheetByName("Close"); //Input Sheet
var sourceData = ss.getSheetByName("Raw_Data"); //Data Sheet (List of all data)
var target = ss.getSheetByName("Pallet_Data"); //Target Sheet
var dataRange = data.getRange("B:B").getValues; //Range To Search on Data Sheet
var lastcolumn = target.getLastColumn(); //Last Column of Target
var searchval = [[source.getRange("A2").getValue()]]; //Search String
var targetRange = target.getRange("A"+(lastcolumn+1)+":C"+(lastcolumn+1)); //Define New Range n+1
//var rIndex = getRowIndex(); //row index of Data
//var cIndex = getColumnindex(); //column index of Data
while (dataRange has_data) { // For each row that has data in column B...
if (Bn = searchval) { // If B in row 'n' matches the search value
var rIndex = sourceData.getRowIndex(); // Define that row
var match = sourceData.getActiveCell // Defines B of matched row
var firstcell = rIndex.getRange(??) // Define cell A of that row
match.setValue('Moved'); // Change value of B in matched row so it won't match on new search
firstcell.copyTo(lastcolumn) //Copy Cell A of defined row into last column of target sheet
//Add next match to bottom of SAME Column then start NEW Column when function is run again.
}
}
Thanks
Solution:
Your script could look like this:
function cellMatch() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Data");
var sheet2 = ss.getSheetByName("Result");
var sheet3 = ss.getSheetByName("Search");
var lr = sheet1.getLastRow();
var data = sheet1.getRange(2,1,lr-1,2).getValues();
var lc = sheet2.getLastColumn()+1;
var key = sheet3.getRange("B1").getValue();
var matched = [["Search "+lc]];
for (var i=0; i<lr-1; i++) {
if (data[i][1] == key) {
var temp = [];
temp.push(data[i][0]);
matched.push(temp);
}
}
var result = sheet2.getRange(1,lc,matched.length);
result.setValues(matched);
}
This should take the search key from Search sheet, compare it with the Data sheet, and place the results into Result sheet.
Sample Data:
This is the result after executing the script twice, for L1 and L3.
I need to apply a filter on a spreadsheet and then apply the filter on the active spreadsheet.
Tried using the Filter Class but not sure what is incorrect
'''
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("main sheet");
var dataMatrix1 = activeSheet.getRange(1, 1, activeSheet.getLastRow(), activeSheet.getLastColumn());
function applyFilter(){
Logger.log("mark1");
var filteredData = dataMatrix1.createFilter(); //filter created
var a = 'a';
filteredData.sort(1, false);
filteredData.setColumnFilterCriteria(1 , a);
Logger.log("Mark2");
}
'''
The spreadsheet has 2 rows with value = 'a' in the first column. Need to apply a filter to the sheet and filter out rows with value = 'a'.
You are very close to accomplish your request; you only need to create a filter criteria instead of using the a variable. You can see exactly which methods to use on the following code. Also, the filtered string must be inside of an array, so I sightly modified your a variable.
function applyFilter() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
"main sheet");
var dataMatrix1 = activeSheet.getRange(1, 1, activeSheet.getLastRow(),
activeSheet.getLastColumn());
var filteredData = dataMatrix1.createFilter(); //filter created
var a = ['a'];
filteredData.sort(1, false);
var filterCriteria = SpreadsheetApp.newFilterCriteria().setHiddenValues(a)
.build();
filteredData.setColumnFilterCriteria(1, filterCriteria);
}
Please, do not hesitate to ask for more help if you keep having problems.