Choose Multiple Columns in Google Sheets Script - google-apps-script

I have a dataset of jobs for a gardening company with 50 or so columns.
status # ID Date Name Frequency Height Weight DOB...
☐ 4 340 09/06/20 Jack Once Off 175 100 11/1/60...
☐ 1 543 22/05/20 Sarah Weekly 170 201 12/2/87...
☐ 3 121 01/05/20 Emily Fortnightly 172 150 6/6/90...
☐ 3 577 11/06/20 Peter Once Off 165 165 31/1/89...
I have a custom script that recreates a new row when the checkbox is selected for weekly and fortnightly jobs and increases the # field by 1 and adds the appropriate date in the future for the date field. I also want it to copy all other data in the original row into the new row.
Currently it will copy up to column 9 but I have 50 columns that need the original data copied over. Is it possible to use more efficient code rather than using the below 50 times?
sheet.getRange(selectedRow,5).getValue(),
sheet.getRange(selectedRow,6).getValue(),
sheet.getRange(selectedRow,7).getValue(),
sheet.getRange(selectedRow,8).getValue(),
sheet.getRange(selectedRow,9).getValue(),
Here is the script:
function onEdit() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var checkbox = sheet.getActiveRange().getValue();
var selectedRow = sheet.getActiveRange().getRow();
var selectedFreq = sheet.getRange(selectedRow, 6).getValue();
//Run if selected cell has a checkbox and ticked
while(checkbox == true){
addValues(selectedRow, sheet, selectedFreq);
break;
}
}
//Function to process values based on frequency
function addValues(selectedRow, sheet, selectedFreq){
var number = sheet.getRange(selectedRow,2).getValue();
var date = new Date(sheet.getRange(selectedRow,4).getValue());
if(selectedFreq == "Fortnightly"){
//Insert a new row after the ticked checkbox, setup a new date with 14 days (or 2 weeks), increments the # with 1 & the rest of the data are copied
var newDate = new Date(date.setDate(date.getDate()+14));
sheet.appendRow(["",number+1,sheet.getRange(selectedRow,3).getValue(),newDate,
sheet.getRange(selectedRow,5).getValue(),
sheet.getRange(selectedRow,6).getValue(),
sheet.getRange(selectedRow,7).getValue(),
sheet.getRange(selectedRow,8).getValue(),
sheet.getRange(selectedRow,9).getValue()]);
sheet.getRange(sheet.getLastRow(),1).insertCheckboxes();
sheet.getRange(sheet.getLastRow(),4).setValue(sheet.getRange(sheet.getLastRow(),4).getValue()).setNumberFormat("dd/MM/yy");
}
if(selectedFreq == "Weekly"){
//Insert a new row after the ticked checkbox, setup a new date with 7 days (1 week), increments the # with 1 & the rest of the data are copied
var newDate = new Date(date.setDate(date.getDate()+7));
sheet.appendRow(["",number+1,sheet.getRange(selectedRow,3).getValue(),newDate,
sheet.getRange(selectedRow,5).getValue(),
sheet.getRange(selectedRow,6).getValue(),
sheet.getRange(selectedRow,7).getValue(),
sheet.getRange(selectedRow,8).getValue(),
sheet.getRange(selectedRow,9).getValue()]);
sheet.getRange(sheet.getLastRow(),1).insertCheckboxes();
sheet.getRange(sheet.getLastRow(),4).setValue(sheet.getRange(sheet.getLastRow(),4).getValue()).setNumberFormat("dd/MM/yy");
}
}

I suggest that you use Sheet.getRange(row, column, numRows, numColumns) and Range.getValues() to get the row values with multiple columns.
Sample:
var values = sheet.getRange(selectedRow,1,1,50).getValues();
values[0][1] = number+1;
sheet.appendRow(values.flat());
With this, you can get the values of your selected row, from column 1 to column 50.
Then you can just update specific index in your array values depending on your preference. Like values[0][1] = number+1
Lastly, you can use your array values in Sheet.appendRow(). You can use array.flat() to convert 2-d array to 1-d array
(UPDATE)
Your code must be something like this:
//Function to process values based on frequency
function addValues(selectedRow, sheet, selectedFreq){
var rowValues = sheet.getRange(selectedRow,1,1,50).getValues().flat();
var date = new Date(sheet.getRange(selectedRow,4).getValue());
if(selectedFreq == "Fortnightly"){
//Insert a new row after the ticked checkbox, setup a new date with 14 days (or 2 weeks), increments the # with 1 & the rest of the data are copied
var newDate = new Date(date.setDate(date.getDate()+14));
//Update column A,B and D
rowValues[0] = "";
rowValues[1] += 1;
rowValues[3] = newDate;
sheet.appendRow(rowValues);
sheet.getRange(sheet.getLastRow(),1).insertCheckboxes();
sheet.getRange(sheet.getLastRow(),4).setValue(sheet.getRange(sheet.getLastRow(),4).getValue()).setNumberFormat("dd/MM/yy");
}
}
I get the selected row values from column 1 to 50. Then use array.flat() to change the result from 2-d array to 1-d array
I changed column A, B and D based on your original code
appended the updated data in the sheet

Related

Paste to filtered rows only using google scripts

I have something like this on a sheet
NAME
POINTS
ELIGIBLE
FINAL
Alice
700
YES
Bob
500
NO
Carol
300
NO
Dave
200
YES
Eve
100
YES
I need to achieve the following in column D:
If it's a "NO", the final points will be the same as the original (like a placeholder) i.e. =B{row}
If it's a "YES", the final points will follow the same sequence as column B, except skipping all the "NO" in the list
so in this example, the output should be like this
NAME
POINTS
ELIGIBLE
FINAL
Alice
700
YES
700
Bob
500
NO
500
Carol
300
NO
300
Dave
200
YES
500
Eve
100
YES
300
When doing this manually, I just copy all values of B2:B, paste to D2, then apply filter "YES" to column C and paste to D2 once again. (this will paste some ugly trailing values to empty rows, but doesn't matter)
The current script
However, when doing this with script, I have to use a for loop to check column C of every row, then assign a =B{n} formula to column D, where n increases only when the current row is a YES
j = 2; //starting from the second row
for (var i = 0; i < lastRow - 1; i++) {
if (sheet.getRange(i+2,3).getValue() == "YES") {
sheet.getRange(i+2,4).setFormula(`B${j}`);
j++;
}
else {
sheet.getRange(i+2,4).setFormula(`B${j}`);
}
}
but this also means the processing time will scale with number of rows (10,000 - 20,000ms per ~100 row), all other actions I am doing only takes ~1000ms in total, which is why I'm looking for an option that does not need iterating to save a lot of time.
I don't mind not using formula in column D as long as the value is correct.
I have tried these
get B2:B as range, set filter (C1:C text equals to "YES"), then copyTo() D2:
seq = lbSheet.getRange(`B2:B${lastRow}`);
sheet.getRange("C1:C").createFilter();
filter = lbSheet.getFilter();
criteria = SpreadsheetApp.newFilterCriteria().whenTextEqualTo("YES").build();
filter.setColumnFilterCriteria(3,criteria);
seq.copyTo(sheet.getRange(`D2`),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
this does not paste to filtered cells only, but all cells
getValues(B2:B), set filter (C1:C text equals to "YES"), getRange(D2:D).setValues(B2:B):
seq = lbSheet.getRange(`B2:B${lastRow}`).getValues();
sheet.getRange("C1:C").createFilter();
filter = lbSheet.getFilter();
criteria = SpreadsheetApp.newFilterCriteria().whenTextEqualTo("YES").build();
filter.setColumnFilterCriteria(3,criteria);
sheet.getRange(`D2:D${lastRow}`).setValues(seq);
this gives range mismatch error
The problem with the OP script is that the target formula is always B${j}. But this is only true then the value is "Yes".
When the value is "No", the target formula references the same row; i.e. B${i+2}.
Lastly, the value results are pushed onto a temporary array, and setValues is only used once at the end of the script.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet()
var lastRow = sheet.getLastRow()
var tempArray = new Array
j = 2; //starting from the second row
for (var i = 0; i < lastRow - 1; i++) {
if (sheet.getRange(i+2,3).getValue() == "YES") {
// Logger.log("DEBUG: YES: i:"+i+", j:"+j+", range:"+sheet.getRange(i+2,3).getA1Notation()+", value = "+sheet.getRange(i+2,3).getValue()+", value range = "+sheet.getRange(i+2,4).getA1Notation()+" set value "+`B${j}`+" set value "+sheet.getRange(j,2).getValue())
tempArray.push([sheet.getRange(j,2).getValue()])
j++;
}
else {
// Logger.log("DEBUG: NO: i:"+i+", j:"+j+", range:"+sheet.getRange(i+2,3).getA1Notation()+", value = "+sheet.getRange(i+2,3).getValue()+", value range = "+sheet.getRange(i+2,4).getA1Notation()+" set value "+`B${i+2}`+" set value "+sheet.getRange(i+2,2).getValue())
tempArray.push([sheet.getRange(i+2,2).getValue()])
}
}
// update array values to column D
sheet.getRange(2,4,lastRow-1,1).setValues(tempArray)
}

Loop that finds duplicates, and deletes values after 1st instance of duplicate from a range of cells

Current Issue:
Hey everyone, appreciate any help here as I'm still beginning my journey in coding.
I'm trying to see if I can make a script that will:
Look for duplicates (in column D), and
delete any data from the following duplicates after the 1st match in columns E-L (see desired outcome if that doesn't make sense verbally).
The script would need to use the column header names (ex. "snacks") instead of hard-coded column references
*So for example, the script finds ABC001, deletes only the duplicates for ABC001 in the corresponding columns then moves on to ABC004 and performs the same action.
I'm not sure how to write a script that would do this, and keep going to find duplicates after the 1st set is found. I think I know how to do a for loop now, but it's not clear to me how to make it do a search loop and stop after it find the first match and keep going.
Current Data:
Desired Outcome:
Code so far below. I think I would need to incorporate something like JSmith showed in this example? Or would I need to incorporate some form of .length with the duplicate range in a for statement so that it can find the duplicates, get the # of them, and then only perform the action on everything past the 1st instance?
function duplicateRemoval() {
ss = SpreadsheetApp.getActive().getSheetByName('Sheet1');//gets sheet by name
const [aB,...cd] = ss.getDataRange().getValues();//literal assignment that assigns aB to the header array and the rest of the data to 'cd'
let column = {}
let iData = {};//index into the row array for each column header
aB.forEach((a,i)=>{column[a] = i+1;iData[a]=i});//building column and iData so that headers can move anywhere
}//let & forEach derived from (https://stackoverflow.com/questions/70101896/search-column-for-text-and-use-array-list-to-insert-text-in-another-cell) #Cooper
Raw Data:
Name
Owner
Snack
Transaction #
# of snacks requested
#2
#3
#4
#5
#6
#7
#8
Bill Example
Snacktown
celery
ABC001
4
1
2
3
4
5
6
4
Bill Example
Snacktown
celery
ABC001
4
1
2
3
4
5
6
4
Bill Example
Snacktown
celery
ABC001
4
1
2
3
4
5
6
4
Jane Doe
Snacktown
chips
ABC002
1
1
1
1
1
1
1
1
Jane Doe
Chipworld
chips
ABC003
1
1
1
1
1
1
1
1
Jane Doe
Chipworld
chips
ABC004
5
5
1
1
1
1
1
5
Jane Doe
Chipworld
chips
ABC004
5
5
1
1
1
1
1
5
Jane Doe
Chipworld
chips
ABC004
5
5
1
1
1
1
1
5
Jane Doe
Chipworld
chips
ABC004
5
5
1
1
1
1
1
5
Sources:
google app script array delete duplicate value from top
Google Script App Delete Duplicate Rows with a Specific Value in Specific Column in Google Sheet
How do I find and delete duplicate values in a range of cells while keeping the first occurrence of a duplicated value in Google Sheets?
Assuming transaction ids are always grouped, iterate through rows and delete all specified columns where previous transactionId is equal to current transactionId.
function duplicateRemovalOfColsToRemove() {
const transactionsHeader = 'Transaction #',
colsToRemoveHeaders = ['# of snacks requested', '#2'],//add column headers as necessary
ss = SpreadsheetApp.getActive().getSheetByName('Sheet1'), //gets sheet by name
range = ss.getDataRange(),
[headers, ...values] = range.getValues(),
colsToRemove = colsToRemoveHeaders.map((h) => headers.indexOf(h)),
transactionsIdx = headers.indexOf(transactionsHeader);
let currTransaction = '';
values.forEach((row) =>
row[transactionsIdx] === currTransaction
? colsToRemove.forEach((idx) => (row[idx] = ''))
: (currTransaction = row[transactionsIdx])
);
range.setValues([headers, ...values]);
}
It is unclear why you want to use a script here, as this seems doable with a plain vanilla spreadsheet formula. It is also unclear whether you really need to repeat the values in A2:D many times with nothing in columns E2:L.
To remove duplicate rows, and get just one copy of each unique transaction, choose Insert > Sheet and put this spreadsheet formula in cell A1:
=unique(Sheet1!A2:L)
To get the expected result you show, including rows that are mostly blank, use this:
=arrayformula(
{
Sheet1!A2:D,
array_constrain(
if(
Sheet1!D2:D <> Sheet1!D1:D,
Sheet1!E2:L,
iferror(1/0)
),
rows(Sheet1!E2:L), columns(Sheet1!E2:L)
)
}
)
To determine row uniqueness based on all columns A2:D instead of just the transaction ID in column D2:D, replace the if() condition with A2:A & B2:B & C2:C & D2:D <> A1:A & B1:B & C1:C & D1:D, inserting the proper sheet reference.
If you need a script you can try this:
function main() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
// get all data from the sheet
var data = range.getValues();
// get column headers
var headers = data.shift();
// get the list of transactions
var transactions = data.map(x => x[headers.indexOf('Transaction #')]);
// loop through all the transactions
for (let transaction of transactions) {
// get indexes of rows to process
var rows = transactions.map((t, row) => t === transaction ? row : '' ).filter(String).slice(1);
// process the rows
for (let r of rows) {
data[r][headers.indexOf('# of snacks requested')] = '';
data[r][headers.indexOf('#2')] = '';
data[r][headers.indexOf('#3')] = '';
data[r][headers.indexOf('#4')] = '';
data[r][headers.indexOf('#5')] = '';
data[r][headers.indexOf('#6')] = '';
data[r][headers.indexOf('#7')] = '';
data[r][headers.indexOf('#8')] = '';
}
}
// put the updated data back to the sheet
range.setValues([headers, ...data]);
}
Update
Here is the improved variant of the same code. It still loops through all the rows, but it skips already processed transactions:
function main() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
var [headers, ...data] = range.getValues();
var transactions = data.map(x => x[headers.indexOf('Transaction #')]);
var cols_to_clean = ['# of snacks requested','#2','#3','#4','#5','#6','#7','#8'];
var processed_transactions = [];
for (let transaction of transactions) {
// skip already processed transactions
if (processed_transactions.includes(transaction)) continue;
var rows_to_clean = transactions.map((t, row) => t === transaction ? row : '' )
.filter(String).slice(1);
for (let r of rows_to_clean) {
cols_to_clean.forEach(c => data[r][headers.indexOf(c)] = '');
}
processed_transactions.push(transaction);
}
range.setValues([headers, ...data]);
}
Thanks to #TheMaster for the noted deficiencies.
Update 2
Sorry for spamming, just figured out the final solution that has no redundant iterations (I hope):
function main() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
var [headers, ...data] = range.getValues();
var cols_to_clean = ['# of snacks requested','#2','#3','#4','#5','#6','#7','#8'];
// get all transactions (9 items for this data)
var all_transactions = data.map(x => x[headers.indexOf('Transaction #')]);
// get the short list of unique transaction (4 items for this data)
var uniq_transactions = [... new Set(all_transactions)];
for (let transaction of uniq_transactions) {
// get all indexes of rows with given transaction
var rows_to_clean = all_transactions.map((t, row) => t === transaction ? row : '')
.filter(String).slice(1);
// clean the rows
for (let r of rows_to_clean) {
cols_to_clean.forEach(c => data[r][headers.indexOf(c)] = '');
}
}
range.setValues([headers, ...data]);
}
I didn't remove my first update, I think this can be useful for educational purposes.

If cells of Column A are merge, exact cells to be merged in Column E

My sheet consists of details of working hours of crew in shifts. Column A is serial no. Column E is total duty hours. One day duty consists of smaller shifts and some details like S.No, Name, crew id gets repeated.
Initial data
I want to merge column with same cell values (Column A & Column E). I have been able to merge Column A of S.No (thanks to #Tanaike from this Forum) and want to do same thing for Column E.
Achieved so far
What i want
Condition - If Column A is merged, exactly no of cells should merge in Column E. So, if A11, A12 are merged = E11, E12 should merge; A13 not merged = E13 not merged; A14, A15, A16, A17 are merged = E14, E15, E16, E17 should merge.
Thanks.
Relevant Code so far -
// merge columns vertically for same cell value for Column A
var start = 10; //data starts from row 10
var c = {};
var k = "";
var offset = 0;
// Retrieve values of column A
var data = destSheet.getRange(start, 1, lastRow-2, 1).getValues().filter(String);
// Retrieve the number of duplication values.
data.forEach(function(e){c[e[0]] = c[e[0]] ? c[e[0]] + 1 : 1;});
// Merge cells.
data.forEach(function(e){
if (k != e[0]) {
destSheet.getRange(start + offset, 1, c[e[0]], 1).merge();
offset += c[e[0]];
}
k = e[0];
});
Two approaches to solve your issue
Apps Script offers methods like isPartOfMerge() and mergeVertically() which would allow you to transfer the merge formatting from column A to column E.
You can do it by looping through all merged ranges in column A, retreiving their start and end row, and merge the respective ranges in column E:
var range = destSheet.getRange(1,1, destSheet.getLastRow(), 1);
var mergedRanges = range.getMergedRanges();
for (var i = 0; i < mergedRanges.length; i++) {
Logger.log(mergedRanges[i].getA1Notation());
var start = mergedRanges[i].getRow();
var end = mergedRanges[i].getLastRow();
var destinationRange = destSheet.getRange(start, 5, end - start + 1, 1);
destinationRange.mergeVertically();
}
You can copy the formatting from the entire column A to column E - this will copy the merging
To do so, you can use the method copyTo(destination, copyPasteType, transposed) specifying CopyPasteType as PASTE_FORMAT:
var range = destSheet.getRange(1,1, destSheet.getLastRow(), 1);
var destinationRange = destSheet.getRange("E1");
range.copyTo(destinationRange, SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);

Find matches for two columns on two sheets google script

Im am trying to match 2 columns (A:B) in sheet1 with 2 columns in sheet2 (A:B) and if there is a match, copy contents of column C matching row in sheet1 to matching row in sheet2.
I've tried to adapt several scripts without success. The code below comes closest to my requirements, but with my limited knowledge of script I haven't been able to adapt it to my exact needs.
Sheet1
A B C
Week Rotation Working
Week1 11 In
Week1 5 In
Week1 4 In
Week1 3 In
Week1 3 Off
Week1 7 Off
Sheet2
A B C
Week Rotation Working
Week1 6
Week1 5
Week1 4
Week1 3
Week1 3
Week1 11 (In should be copied to here)
My code:
function MatchColumns(){
// gets spreadsheet A and the range of data
var sheetA
=SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Testa");
var dataA = sheetA.getRange(2, 1, sheetA.getLastRow(),
2).getValues();
// gets spreadsheet B and the range of data
var sheetB =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Test2");
var dataB = sheetB.getRange(2, 1, sheetB.getLastRow(),
1).getValues();
// Added
var res = [];
for (var b in dataB) {
for (var a in dataA) {
if (dataA[a][0] == dataB[b][0]) res.push([dataA[a][3]]);
}
if (b != res.length - 1) res.push([""]);
}
sheetB.getRange(2, 2, res.length, res[0].length).setValues(res);
Note that JavaScript is one of the many languages that use 0-base indexing. So res.push([dataA[a][3]]) is placing the 4th value from the row into the result array, i.e. Column D.
Your dataA and dataB variables don't actually include the column C data, as you initialized them with only 2 columns of data. So dataA[a][2] and dataA[a][3] are both undefined.
You probably don't want to collect these new values into an array via push, as this will lose the correlation between which row you matched in A & B, and which row you write into. To avoid losing existing information in column C, you need to read it from sheet 2 and assign to the specific index:
var destC = sheet2.getRange(2, 3, sheet2.getLastRow() - 1, 1).getValues();
/** Find matched rows */
...
destC[b][0] = dataA[a][2];
...
// Lastly, write values
sheet2.getRange(2, 3, destC.length, 1).setValues(destC);
Try using a nested for to iterate through the Values in Sheet1 and Sheet2 and compare them with
function MatchColumns(){
// gets spreadsheet A and the range of data
var sheetA = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var dataA = sheetA.getRange(2, 1, sheetA.getLastRow() - 1, 2).getValues();
// gets spreadsheet B and the range of data
var sheetB = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2");
var dataB = sheetB.getRange(2, 1, sheetB.getLastRow() - 1, 2).getValues();
for (var x = 0; x < sheetA.getLastRow() - 1; x++){
for (var y = 0; y < sheetB.getLastRow() - 1; y++){
if (dataA[x][0] == dataB[y][0]){
if (dataA[x][1] == dataB[y][1]){
sheetB.getRange(y + 2, 3).setValue(sheetA.getRange(x + 2, 3).getValue());
}
}
}
}
}
This copies the value of column C in Sheet1 to column C in Sheet2 if the corresponding cells in columns and B match.

Range selection and copying fixed value (from a cell) in that selection

Background
I have some code which is supposed to copy certain rows from Sheet B into Sheet A based on integer values in cells E1,J1 and I1. E1 has date format. After rows are copied from Sheet B to A, I need to fill column 12 (Column L) with the date from E1 to newly added rows.
https://docs.google.com/spreadsheets/d/15pTVfcoxM2wQTMC-3iLzXVXIEEaZFYXaOf97amy4yRg/edit?usp=sharing
Problem
The last three rows of code is not working well. Even though I am trying to select range for same column 12 (column L), it seems to select multiple columns and an additional 2 rows than what I had expected.
function test() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("B");
var aa = sheet.getRange("E1");
var Date = aa.getValue();
var aa = sheet.getRange("J1");
var lastrow = aa.getValue();
var aa = sheet.getRange("I1");
var lastrowV = aa.getValue();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("A");
var range = sheet.getRange(2, 1, lastrowV, 11);
var data = range.getValues();
sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("B");
sheet.getRange(lastrow, 1, data.length, 11).setValues(data); /* cell J1 gets updated after this*/
var aa = sheet.getRange("J1");
var lastrowN = aa.getValue() - 1;
range = sheet.getRange(lastrow, 12, lastrowN, 12);
range.activate();
sheet.getRange(lastrow, 12, lastrowN, 12).setValues(Date);
}
Background
The OP is attempting to insert a given date in the cell at the end of a row. However, the OP's definition of the range is faulty because it is selecting multiple columns (when only one column is required) and the number of rows is greater (by 2 (two)) than the number required. In addition, regardless of the range height, the OP is attempting to set a single value (rather than an array) into the range.
Problems
1) The definition of the datecolumn (Column L) included a value for the number of columns (probably a carry over from having defined the data range earlier).
Old range: getRange(lastrow,12, lastrowN, 12);. Delete the last parameter (number of columns) and the code behaves.
2) The code used this method setValues(Date) to populate the date column (8 rows in the OP's example data). the problem here is that the value assigned is the single value Date. not an array. This was addressed by creating and populating a temporary array datearray, and using this to update values in the date column.
3) In addition to the problems noted, the OP code is problematic in that a number of variables names were re-used with entirely different contexts (including "sheet" and "aa"), and some variables were declared multiple times. This made the code hard to read and debug. I took the opportunity to resolve as many of these as possible.
function so5473808801() {
// setup spreadsheet and sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetB = ss.getSheetByName("B");
var sheetA = ss.getSheetByName("A");
// define key variables
// date
var daterange = sheetB.getRange("E1");
var datevalue = daterange.getValue();
// rows on SheetA
var Arows = sheetB.getRange("I1"); // = 9
var Alastrow = Arows.getValue();
// rows on sheet B
var Brows = sheetB.getRange("J1"); // = 3
var Blastrow = Brows.getValue();
// define the data range on Sheet A
var Adatarange = sheetA.getRange(2, 1, Alastrow, 11);
// Logger.log("DEBUG: The defined range on Sheet A is "+Adatarange.getA1Notation());//DEBUG
var Adatavals = Adatarange.getValues();
// define a target range on Sheet B and set values from A
var targetrange = sheetB.getRange(Blastrow, 1, Adatavals.length, 11);
// Logger.log("DEBUG: The target on sheetB = "+targetrange.getA1Notation()); // DEBUG
targetrange.setValues(Adatavals);
// set a range to update date on Sheet B
var daterows = (Alastrow - 1); // doesn't take 2 row header on B intoi account
var Bdaterange = sheetB.getRange(Blastrow, 12, daterows);
// Logger.log("DEBUG: The date range on sheet B = "+Bdaterange.getA1Notation());
// create an array to store multiple copies of datevalue
var datearray = [];
//populate the array
for (var i = 0; i < daterows; i++) {
datearray.push([datevalue]);
}
// set the date into Column L
Bdaterange.setValues(datearray);
}