Search function data entry form - google-apps-script

With some help from here i've made a data form, whereby data is put from an input sheet to a data sheet and then the input sheet is emptied again.
Now I want to be able to find the data back in the input sheet when I put the right code.
How do I do this?
This is the script to put data from the input sheet towards the data sheet.
function Process() {
const ss = SpreadsheetApp.getActive();
const dataSheet = ss.getSheetByName('NIEUW Invoerbestand');
const inputSheet =ss.getSheetByName('Input')
const idCell = ss.getRangeByName('Barcode');
const id = idCell.getValue();
const cellFound = dataSheet.getRange('A:A')
.createTextFinder(id)
.matchCase(true)
.matchEntireCell(true)
.findNext()
if (!cellFound) return;
const fieldRange = inputSheet.getRange('Input!E4:E231');
const fieldValues = [fieldRange.getValues().flat()];
dataSheet
.getRange(cellFound.getRow(), 6)
.offset(0, 0, fieldValues.length, fieldValues[0].length)
.setValues(fieldValues);
fieldRange.clearContent();
idCell.clearContent();
}
I've tried this script, but this gives the error 'forEach is not a function'
const searchCell = inputSheet.getRange ("B2")
const searchValue = searchCell.getValue()
const data = dataSheet.getRange ("A4:HY").getValues()
const recordsFound = data.filter( r => r[0] == searchValue)
if(recordsFound.lenght === 0) return
fieldRange.forEach ((f,i) => inputSheet.getRange(f).setValue(recordsFound[0][i+6]))
}

Related

The number of columns in the data does not match the number of columns in the range

im fairly new to this so please excuse me if the problem isn't clear enough. I’m trying to make an input sheet with a barcode, where the data gets put in the row with the right barcode. the code works fine when I put the fieldrance cells like "D4", "D5", etc
const fieldRange = ["D4","D5","D6","D7","D8"]
const id = IDcell.getValue()
const cellFound = DataWS.getRange ("A:A")
.createTextFinder(id)
.matchCase(true)
.matchEntireCell(true)
.findNext()
if (!cellFound) return
const row = cellFound.getRow()
const fieldValues = fieldRange.map(f => InputWS.getRange(f).getValue())
DataWS.getRange(row,6,1,5).setValues([fieldValues])
fieldRange.forEach (f => InputWS.getRange(f).clearContent())
IDcell.clearContent()
}
But whenever I want to add more cells, (cause the actual document i want to use this code for has 241 cells) I would like to change the fieldrange to ["D4:D8"]instead of adding all the cells themselves.
This throws an error
Exception: The number of columns in the data does not match the number of columns in the range. The data has 1 but the range has 5.
How do I fix this error?
The full script I have now is:
function Process(){
const ss = SpreadsheetApp.getActiveSpreadsheet()
const InputWS = ss.getSheetByName ("Input")
const DataWS = ss.getSheetByName ("NIEUW Invoerbestand")
const IDcell = ss.getRangeByName("Barcode")
const fieldRange = ["D4:D8"]
const id = IDcell.getValue()
const cellFound = DataWS.getRange ("A:A")
.createTextFinder(id)
.matchCase(true)
.matchEntireCell(true)
.findNext()
if (!cellFound) return
const row = cellFound.getRow()
const fieldValues = fieldRange.map(f => InputWS.getRange(f).getValue())
DataWS.getRange(row,6,1,5).setValues([fieldValues])
fieldRange.forEach (f => InputWS.getRange(f).clearContent())
IDcell.clearContent()
}
Use Range.offset(), like this:
function process() {
const ss = SpreadsheetApp.getActive();
const dataSheet = ss.getSheetByName('NIEUW Invoerbestand');
const idCell = ss.getRangeByName('Barcode');
const id = idCell.getValue();
const cellFound = dataSheet.getRange('A:A')
.createTextFinder(id)
.matchCase(true)
.matchEntireCell(true)
.findNext()
if (!cellFound) return;
const fieldRange = inputSheet.getRange('Input!D4:D8');
const fieldValues = [fieldRange.getValues().flat()];
dataSheet
.getRange(cellFound.getRow(), 6)
.offset(0, 0, fieldValues.length, fieldValues[0].length)
.setValues(fieldValues);
fieldRange.clearContent();
idCell.clearContent();
}

Import Data From multiple sheet with a list of ID and specifics column

I have about many spreadsheet work with my partners and each partner use 1 spreadsheat for manage data.
I using a table to store all ID, Sheet name and column store data I need to import to my master sheet.
This is my Spreadsheet:
Link here
I using Appscript to do import data by read values in this table with 2 loop, I see it work to slow How could I speed up it?
this is my script
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Source Link');
var master = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Master') ;
const dstLr = getLastPopulatedRow(ss); //get last row of Source Link
const target_sheet_name = ss.getRange(2,6,dstLr-1,1).getValues(); //Get data in Column F input to array
const ids = ss.getRange(2,1,dstLr-1,1).getValues(); //get data in column A input to array
const ebayID = ss.getRange(2,2,dstLr - 1,1).getValues(); //get cloumn index at Column B input to array
const team = ss.getRange(2,3,dstLr-1,1).getValues(); //get column containt team name at column C input to array
const linkOrder = ss.getRange(2,4,dstLr-1,1).getValues(); //get cloumn containt Link Order at column D input to array
const tracking = ss.getRange (2,5,dstLr-1,1).getValues(); //get column containt Tracking at column E input to array
const benCO = ss.getRange(2,7,dstLr,1).getValues();
ids.forEach((id, i) => {
const srcSheet = SpreadsheetApp.openById(id).getSheetByName(target_sheet_name[i]);
const lr = getLastPopulatedRow(srcSheet);
const srcCol = [ebayID[i], team[i], linkOrder[i],tracking[i]].flat();
for(var j = 0; j < srcCol.length; j++) {
const destCol = [1,2,3,4];
const destCol2 = [5];
destCols = destCol[j]
const srcRange = srcSheet.getRange(3, srcCol[j], lr); // Origin range to copy
const values = srcRange.getValues(); // Getting values from origin column
const destRange = master.getRange(2, destCols, lr);
master.clearContents;
destRange.setValues(values);
}
})
}
function getLastPopulatedRow(sheet) {
var data = sheet.getDataRange().getValues();
for (var i = data.length-1; i > 0; i--) {
for (var j = 0; j < data[0].length; j++) {
if (data[i][j]) return i+1;
}
}
return 0;
}
I also need add value of G column for each data I import from ID and Sheet name at colum A and column F, but when I try set value for column E at Master sheet I got error that "data have 1 but destination range have 582"
Could Some one give me advise
That's what I try
ids.forEach((id, i) => {
const srcSheet = SpreadsheetApp.openById(id).getSheetByName(target_sheet_name[i]);
const lr = getLastPopulatedRow(srcSheet);
const srcCol = [ebayID[i], team[i], linkOrder[i],tracking[i]].flat();
for(var j = 0; j < srcCol.length; j++) {
const destCol = [1,2,3,4];
const destCol2 = [5];
destCols = destCol[j]
const srcRange = srcSheet.getRange(3, srcCol[j], lr); // Origin range to copy
const values = srcRange.getValues(); // Getting values from origin column
const destRange = master.getRange(2, destCols, lr);
master.clearContents;
destRange.setValues(values);
}
const coName = [];
coName.push(benCO[i]);
master.getRange(2,5,lr,1).setValues(coName);
})
and this is error:
From your question and samples, how about the following sample script?
Sample script:
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sourceLink = ss.getSheetByName('Source Link');
const master = ss.getSheetByName('Master');
const srcValues = sourceLink.getRange("A2:G" + sourceLink.getLastRow()).getValues();
const header = ["Order ID", "Team", "ID", "ID TRACKING#"];
const values = [header, ...srcValues.flatMap(r => {
const sheet = SpreadsheetApp.openById(r[0]).getSheetByName(r[5]);
const [, h, ...v] = sheet.getDataRange().getValues();
const temp = h.map(e => e.trim());
const indexes = header.map(e => temp.indexOf(e));
return v.map(r => indexes.map(i => r[i]));
})];
master.clearContents().getRange(1, 1, values.length, values[0].length).setValues(values);
}
In this sample script, first, the header is declared and the values are retrieved using the header from each sheet. And, the populated values are put into the destination sheet.
In this sample script, the header is used from your sample Spreadsheet. So, when you change the header titles, the result values might not be able to be used. Please be careful about this.
Reference:
map()
Added:
From your following reply,
I got messenger error at this line: const temp = h.map(e => e.trim()); messenger said: TypeError: e.trim is not a function
My proposed script is for your provided Spreadsheet, and when I tested my proposed script no error occurs. From your reply, I guessed that your Spreadsheet might be different from your provided Spreadsheet. If my understanding is correct, from your error message, I'm worried that the header rows might be changed. In your provided Spreadsheet, 1st 2 rows are header rows. But, if the header row is only the 1st row, the error might occur because the row values include the date object in the 2nd row. If my understanding is correct, can you test the following sample script?
Sample script:
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sourceLink = ss.getSheetByName('Source Link');
const master = ss.getSheetByName('Master');
const srcValues = sourceLink.getRange("A2:G" + sourceLink.getLastRow()).getValues();
const header = ["Order ID", "Team", "ID", "ID TRACKING#"];
const values = [header, ...srcValues.flatMap(r => {
const sheet = SpreadsheetApp.openById(r[0]).getSheetByName(r[5]);
// const [, h, ...v] = sheet.getDataRange().getValues();
let h;
let [h1, h2, ...v] = sheet.getDataRange().getValues();
if (h2.some(e => e instanceof Date)) {
h = h1;
v = [h2, ...v];
} else {
h = h2;
}
const temp = h.map(e => e.trim());
const indexes = header.map(e => temp.indexOf(e));
return v.map(r => indexes.map(i => r[i]));
})];
master.clearContents().getRange(1, 1, values.length, values[0].length).setValues(values);
}
If the same error occurs and another error occurs, can you provide the sample Spreadsheet for correctly replicating the issue? By this, I would like to confirm it.

Is there an alternative to appendRow in AppsScript that only prints certain columns while leaving others in the row untouched

I'm building a calculator to use for pricing purposes. It has a primary "Calculator" sheet, where an admin can enter data and then generate a new result to the "DataLog" sheet. The "DataLog" sheet stores the results (columns A through X) and calculates the resulting price (columns Y through AO). There are also a few workflow columns that need to be present for each row (Columns AP through AS).
I am currently using appendRow() to print the data to the "DataLog" sheet. The issue is that appendRow() finds the first empty row, and since columns Y through AS are not empty because they contain necessary formulas/workflow, it prints to the bottom of the sheet. I am looking for a way to print the data where 1) it checks only a certain column for an empty row (column A or C, for example) and prints to that row, and 2) does not overwrite the formula/workflow columns (Y through AS).
Is there a way to do this using appendRow() or is there another function I should be using? Other than this one issue of where to print the results, everything works just as I want it to, but I cannot seem to find a way to resolve this issue.
EDIT: The reason the formula and workflow must be present within "DataLog" is that there are situations where after an entry has been filled out and printed changes need to be made to row, thereby changing the final price. So I cannot calculate the price within the function and print that as a static number.
Here is a copy of the calculator: https://docs.google.com/spreadsheets/d/1vsVZeOUUqhdiW1unz6dPuiP5yw24ENrv1-49kXqBnx4/edit#gid=0
Here is a copy of the code I am using:
function ClearCells() {
var sheet = SpreadsheetApp.getActive().getSheetByName('CALCULATOR');
sheet.getRange('G9:H9').clearContent();
sheet.getRange('G11').clearContent();
sheet.getRange('G14:H14').clearContent();
sheet.getRange('G6').clearContent();
sheet.getRange('I6').clearContent();
sheet.getRange('I17:I21').clearContent();
sheet.getRange('I24:I29').clearContent();
sheet.getRange('I32').clearContent();
sheet.getRange('K5').clearContent();
sheet.getRange('K15').clearContent();
}
function FinalizePrice() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sourceRangeFL = ss.getRangeByName('FirstLast');
const sourceValsFL = sourceRangeFL.getValues().flat();
const sourceRangeEN = ss.getRangeByName('EntityName');
const sourceValsEN = sourceRangeEN.getValues().flat();
const sourceRangeEP = ss.getRangeByName('EmailPhone');
const sourceValsEP = sourceRangeEP.getValues().flat();
const sourceRangeRT = ss.getRangeByName('ReturnType');
const sourceValsRT = sourceRangeRT.getValues().flat();
const sourceRangeRE = ss.getRangeByName('Returning');
const sourceValsRE = sourceRangeRE.getValues().flat();
const sourceRangeBQ = ss.getRangeByName('BasicQuestions');
const sourceValsBQ = sourceRangeBQ.getValues().flat();
const sourceRangeSEQ = ss.getRangeByName('SchEQuestions');
const sourceValsSEQ = sourceRangeSEQ.getValues().flat();
const sourceRangeEQ = ss.getRangeByName('EntityQuestions');
const sourceValsEQ = sourceRangeEQ.getValues().flat();
const sourceRangePYP = ss.getRangeByName('PYP');
const sourceValsPYP = sourceRangePYP.getValues().flat();
const sourceRangeADJ = ss.getRangeByName('Adjustment')
const sourceValsADJ = sourceRangeADJ.getValues().flat();
const sourceRangeAN = ss.getRangeByName('AdjustmentNote')
const sourceValsAN = sourceRangeAN.getValues().flat();
const sourceVals = [...sourceValsFL, ...sourceValsEN, ...sourceValsEP, ...sourceValsRT, ...sourceValsRE, ...sourceValsBQ, ...sourceValsSEQ, ...sourceValsEQ, ...sourceValsPYP, ...sourceValsADJ, ...sourceValsAN]
console.log(sourceVals)
const anyEmptyCell = sourceVals.findIndex(cell => cell === "");
if(anyEmptyCell !== -1){
const ui = SpreadsheetApp.getUi();
ui.alert(
"Input Incomplete",
"Please enter a value in ALL input cells before submitting",
ui.ButtonSet.OK
);
return;
}
const date = new Date();
const email = Session.getActiveUser().getEmail();
const data = [date, email, ...sourceVals];
const destinationSheet = ss.getSheetByName("DataLog");
destinationSheet.appendRow(data);
console.log(data);
sourceRangeFL.clearContent();
sourceRangeEN.clearContent();
sourceRangeEP.clearContent();
sourceRangeRT.clearContent();
sourceRangeRE.clearContent();
sourceRangeBQ.clearContent();
sourceRangeSEQ.clearContent();
sourceRangeEQ.clearContent();
sourceRangePYP.clearContent();
sourceRangeADJ.clearContent();
sourceRangeAN.clearContent();
ss.toast("Success: Item added to the Data Log!");
}
I know this is incomplete but for the purpose of discussion here's how I would clear content in your situation.
function ClearCells() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
sh.getRangeList(["G9", "G11", "G14:H14", "G6", "I6", "I17:I21", "I24:I29", "I32", "K5", "K15"]).getRanges().forEach(r => r.clearContent();)
}
If you wished to append the values of your individual ranges into a row you could do it like this:
function appendRangeValues() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
const osh = ss.getSheetByName('Sheet1')
const rgl = sh.getRangeList(["G9", "G11", "G14:H14", "G6", "I6", "I17:I21", "I24:I29", "I32", "K5", "K15"]);
const rglb = breakUpRangeList(ss,sh,rgl);
const vs = rglb.getRanges().map(r => r.getValue());
Logger.log(JSON.stringify(vs))
osh.getRange(osh.getLastRow() + 1, 1, 1, vs.length).setValues([vs]);
}
But I'm guessing that you want to skip over cell functions and other columns so let me know what you want and may be we can find a solution that fits your needs
The breakUpRangeList function is something I wrote a while back to break up ranges into their individual cells which I find easier to deal with.
function breakUpRangeList(ss=SpreadsheetApp.getActive(),sh=ss.getSheetByName("Sheet0"),rgl) {
let b = [];
rgl.getRanges().forEach(rg => {
rg.getValues().forEach((r,i) => {
let row = rg.getRow() + i;
r.forEach((c, j) => {
let col = rg.getColumn() + j;
b.push(sh.getRange(row, col).getA1Notation())
})
})
})
b = [...new Set(b)];
Logger.log(JSON.stringify(b));
return sh.getRangeList(b);
}
Try this:
function appendRangeValues() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
const osh = ss.getSheetByName('Sheet1')
const rgl = sh.getRangeList(["G9", "G11", "G14:H14", "G6", "I6", "I17:I21", "I24:I29", "I32", "K5", "K15"]);
const rglb = breakUpRangeList(ss,sh,rgl);
const vs = rglb.getRanges().map(r => r.getValue());
Logger.log(JSON.stringify(vs))
osh.getRange(getColumnHeight(3,osh,ss) + 1, 1, 1, vs.length).setValues([vs]);
}
function getColumnHeight(col, sh, ss) {
var ss = ss || SpreadsheetApp.getActive();
var sh = sh || ss.getActiveSheet();
var col = col || sh.getActiveCell().getColumn();
var rcA = [];
if (sh.getLastRow()){ rcA = sh.getRange(1, col, sh.getLastRow(), 1).getValues().flat().reverse(); }
let s = 0;
for (let i = 0; i < rcA.length; i++) {
if (rcA[i].toString().length == 0) {
s++;
} else {
break;
}
}
return rcA.length - s;
}

Copying a row from one sheet to another and deleting the original data

I am trying to copy the last populated row from one spreadsheet, to the first non populated row of another spreadsheet. And if possible delete the row that was copied from the source spreadsheet.
function moveRows () {
importRange(
"1PugO3VL8ZkGzA6stYfUkQK4WoU-FfRUBHUzRDTsEbYE",
"Sheet2!A:Z",
"1A2buwUnoDYVRILSETTFd_v6XGmrQtsGD-nT4P8Ufl_0",
"Sheet x!B1"
);
}
function importRange(sourceID,sourceRange,destinationID,destinationRangeStart) {
const sourceSS = SpreadsheetApp.openById(sourceID);
const sourceRng = sourceSS.getRange(sourceRange)
const sourceVals = sourceRng.getValues();
// console.log(sourceVals);
const destinationSS = SpreadsheetApp.openById(destinationID);
const destStartRange = destinationSS.getRange(destinationRangeStart);
const destSheet = destinationSS.getSheetByName(destStartRange.getSheet().getName());
const destRange = destSheet.getRange(
destStartRange.getLastRow() + 1 ,
destStartRange.getColumn(),
sourceVals.length,
sourceVals[0].length
);
destRange.setValues(sourceVals);
};
I found this online, but it copies the entire data from one sheet to another. It does the job, but not exactly what I need it to do.
This should work.
Instead of deleting a row from the original sheet, this will set a row of empty values into the copied range.
Just replace the sheet name of the oriSheet and tarSheet according your spreadsheet, should get the job done.
function moveRow() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const oriSheet = ss.getSheetByName('original');
const tarSheet = ss.getSheetByName('target');
const oriRange = oriSheet.getRange(oriSheet.getLastRow(),1,1,oriSheet.getLastColumn());
const values = oriRange.getValues();
tarSheet.getRange(tarSheet.getLastRow()+1,1,1,values[0].length).setValues(values);
oriRange.setValues([values[0].map(col => '')]);
}
Just realized that you are working on 2 spreadsheets...
const ssid_1 = '1PugO3VL8ZkGzA6stYfUkQK4WoU-FfRUBHUzRDTsEbYE';
const ssid_2 = '1A2buwUnoDYVRILSETTFd_v6XGmrQtsGD-nT4P8Ufl_0';
function moveRow() {
const oriSheet = SpreadsheetApp.openById(ssid_1).getSheetByName('original');
const tarSheet = SpreadsheetApp.openById(ssid_2).getSheetByName('target');
const oriRange = oriSheet.getRange(oriSheet.getLastRow(),1,1,oriSheet.getLastColumn());
const values = oriRange.getValues();
tarSheet.getRange(tarSheet.getLastRow()+1,1,1,values[0].length).setValues(values);
oriRange.setValues([values[0].map(col => '')]);
}
Just add the Spreadsheet IDs into the variables on top and it should work.

App Script: What's the shorter way to get the range of multiple cells

I am trying to copy the data from the Source sheet to my Target sheet. Is there a version where I can shorten this code? It seems to be that the .getRange can only accept one string.
When I try this line of code const sRange = sSheetDay.getRange('I4', '15', 'I6'); and so on, it always says it can't find the range. I know my questioning is not that good, especially I'm really a beginner at this. Hopefully someone has the same experience.
My main goal to this is to copy the data from a specific cell. And I can't seem to find the solution.
function copyDataFilters() {
const dTable = SpreadsheetApp.getActiveSpreadsheet();
const sSheetDay = dTable.getSheetByName('Day 1');
const sRange = sSheetDay.getRange('I4');
const sRange2 = sSheetDay.getRange('I5');
const sRange3 = sSheetDay.getRange('I6');
const sRange4 = sSheetDay.getRange('I7');
const sRange5 = sSheetDay.getRange('I8');
const sRange6 = sSheetDay.getRange('I9');
const sRange7 = sSheetDay.getRange('I12');
const sRange8 = sSheetDay.getRange('I13');
const sRange9 = sSheetDay.getRange('I16');
const sRange10 = sSheetDay.getRange('I17');
const sRange11 = sSheetDay.getRange('I20');
const sRange12 = sSheetDay.getRange('I21');
const sRange13 = sSheetDay.getRange('I24');
const sRange14 = sSheetDay.getRange('I25');
const sRange15 = sSheetDay.getRange('I27');
const sValue = sRange.getValues();
const sValue2 = sRange2.getValues();
const sValue3 = sRange3.getValues();
const sValue4 = sRange4.getValues();
const sValue5 = sRange5.getValues();
const sValue6 = sRange6.getValues();
const sValue7 = sRange7.getValues();
const sValue8 = sRange8.getValues();
const sValue9 = sRange9.getValues();
const sValue10 = sRange10.getValues();
const sValue11 = sRange11.getValues();
const sValue12 = sRange12.getValues();
const sValue13 = sRange13.getValues();
const sValue14 = sRange14.getValues();
const sValue15 = sRange15.getValues();
const targetSheet = dTable.getSheetByName('All filters report');
const targetRange = targetSheet.getRange('B4:C4');
const targetRange2 = targetSheet.getRange('B5:C5');
const targetRange3 = targetSheet.getRange('B6:C6');
const targetRange4 = targetSheet.getRange('B7:C7');
const targetRange5 = targetSheet.getRange('B8:C8');
const targetRange6 = targetSheet.getRange('B9:C9');
const targetRange7 = targetSheet.getRange('B11:C11');
const targetRange8 = targetSheet.getRange('B12:C12');
const targetRange9 = targetSheet.getRange('B14:C14');
const targetRange10 = targetSheet.getRange('B15:C15');
const targetRange11 = targetSheet.getRange('B17:C17');
const targetRange12 = targetSheet.getRange('B18:C18');
const targetRange13 = targetSheet.getRange('B20:C20');
const targetRange14 = targetSheet.getRange('B21:C21');
const targetRange315 = targetSheet.getRange('B24:C24');
targetRange.setValue(sValue);
targetRange2.setValue(sValue2);
targetRange3.setValue(sValue3);
targetRange4.setValue(sValue4);
targetRange5.setValue(sValue5);
targetRange6.setValue(sValue6);
targetRange7.setValue(sValue7);
targetRange8.setValue(sValue8);
targetRange9.setValue(sValue9);
targetRange10.setValue(sValue10);
targetRange11.setValue(sValue11);
targetRange12.setValue(sValue12);
targetRange13.setValue(sValue13);
targetRange14.setValue(sValue14);
targetRange315.setValue(sValue15);
}
Use getRangeList
From the references
// Get a list of ranges A1:D4, F1:H4.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var rangeList = sheet.getRangeList(['A1:D4', 'F1:H4']);
References
https://developers.google.com/apps-script/reference/spreadsheet/sheet?hl=en#getrangelista1notations
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet?hl=en#getrangelista1notations
function elfunko() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
//you can do this with values
const [v4,v5,v6,v7,v8,v9,,,v12,v13,,,v16,v17,v18,v19,v20,v21,,,v24,v25,v26,v27] = sh.getRange("I4:I27").getValues();
Logger.log(v4);
//unfortunatey you cannot do this with ranges. It resullts in an error
const [I4,I5,I6,I7,I8,I9,,,I12,I13,,,I16,I17,I18,I19,I20,I21,,,I24,I25,I26,I27] = sh.getRange("I4:I27");
Logger.log(I4.getValue());
}
So were stuck with handling multiple ranges with a rangelist as shown Ruben's answer
In the current stage, when the different values are trying to be got from and put to the scattered cells, the Spreadsheet service (SpreadsheetApp) has no methods for directly achieving this goal. So, in order to directly achieve this goal, as the current workaround, Sheets API can be used. When this is reflected in a sample script by including the goal of your script, it becomes as follows.
Sample script:
Before you use this script, please enable Sheets API at Advanced Google services.
function copyDataFilters2() {
const srcSheet = "Day 1";
const dstSheet = "All filters report";
const src = ["I4", "I5", "I6", "I7", "I8", "I9", "I12", "I13", "I16", "I17", "I20", "I21", "I24", "I25", "I27"].map(e => `'${srcSheet}'!${e}`);
const dst = ["B4:C4", "B5:C5", "B6:C6", "B7:C7", "B8:C8", "B9:C9", "B11:C11", "B12:C12", "B14:C14", "B15:C15", "B17:C17", "B18:C18", "B20:C20", "B21:C21", "B24:C24"].map(e => `'${dstSheet}'!${e}`);
const ssId = SpreadsheetApp.getActiveSpreadsheet().getId();
const values = Sheets.Spreadsheets.Values.batchGet(ssId, { ranges: src }).valueRanges.map(({ values }) => values ? [Array(2).fill(values[0][0])] : [[""]]);
const data = values.map((e, i) => ({ values: e, range: dst[i] }));
Sheets.Spreadsheets.Values.batchUpdate({ data, valueInputOption: "USER_ENTERED" }, ssId);
}
When this script is run, the values are retrieved from the cells "I4", "I5", "I6", "I7", "I8", "I9", "I12", "I13", "I16", "I17", "I20", "I21", "I24", "I25", "I27" of "Day 1" sheet, and the retrieved values are put to the cells of "B4:C4", "B5:C5", "B6:C6", "B7:C7", "B8:C8", "B9:C9", "B11:C11", "B12:C12", "B14:C14", "B15:C15", "B17:C17", "B18:C18", "B20:C20", "B21:C21", "B24:C24".
References:
map()
Method: spreadsheets.values.batchGet
Method: spreadsheets.values.batchUpdate