0
votes

I am trying to create a number of rows in a Sheet after the last row having the specified date (F5 cell value) and based on user inputs in H5, I5, J5, K5 cells (some of them may be blank). User inputs are taken in the Dashboard Sheet, which is attached herewith this post. And the sheet where the data will be stored is specified in F5 having following format:

Date              Student ID      Umail                             Latitude  Longitude Subject
2020-08-20 (G5)   1902011 (H5)    1902011@icte.bdu.ac.bd (H5 + K3)    -         -       ICTE4115 (F5)
2020-08-20 (G5)   1902015 (I5)    1902015@icte.bdu.ac.bd (I5 + K3)    -         -       ICTE4115 (F5)
2020-08-20 (G5)   1902024 (J5)    1902024@icte.bdu.ac.bd (J5 + K3)    -         -       ICTE4115 (F5)
2020-08-20 (G5)   1902036 (K5)    1902036@icte.bdu.ac.bd (K5 + K3)    -         -       ICTE4115 (F5)

My codes are: When values in K6 cell selected, the function onePeriod() will be called.

function onePeriod(){
  // For a single Period Class
  var spreadsheet = SpreadsheetApp.getActive();
  var dashboard = spreadsheet.getSheetByName("Dashboard");
  var sheetName = dashboard.getRange("F5").getValue();
  var sheet = spreadsheet.getSheetByName(sheetName);
  
  var umailPattern = dashboard.getRange("K3").getValue();
  
  //Locate the lastrow of the specified date  
  var mDate = dashboard.getRange("G5").getDisplayValue();  
  var startRow = 2;
  var dateColumn = sheet.getRange(startRow,1,sheet.getLastRow(), 1);
  var dates = dateColumn.getDisplayValues().flat();
  var lastRow = dates.lastIndexOf(mDate)+startRow;
    
  //Dashboard is the place for user input where in H5, I5, J5, K5 cell student IDs are entered.  
  var sheet1 = spreadsheet.getSheetByName('Dashboard');
  
  //Need to bring all student IDss from those cells of Dashboard to students array. 
  var data = sheet1.getLastColumn();
  var students = [];
  var students = sheet1.getRange(5, 8, 1, data).getValues();  
  
  var ssId = SpreadsheetApp.getActiveSpreadsheet().getId();
  var ss = SpreadsheetApp.openById(ssId);
  for (var i=1; i<=students.length; i++){ // you are looping columwise through cells H5, I5, J5, K5 in row 5.
    if (students[i+7][0] !== ''){
      sheet.insertRowAfter(lastRow);
      range1 = sheet.getRange(lastRow+1, 1, 1, 6);
      
      range1.getCell(lastRow+1,1).setValue(dates);
      range1.getCell(lastRow+1,2).setValue(students[i+7][0].toString());
      range1.getCell(lastRow+1,3).setValue(students[i+7][0].toString() + umailPattern);
      range1.getCell(lastRow+1,4).setValue('');
      range1.getCell(lastRow+1,5).setValue('');
      range1.getCell(lastRow+1,6).setValue(sheetName);     
    }
  }  
}

Input values with Cell info at the Dashboard sheet

1
I have to apologize for my poor English skill. Unfortunately, from your question, I cannot understand about your input and output you expect. Especially, I cannot understand about (G5), (H5), (H5 + K3). So in order to correctly understand about your question, can I ask you about the detail of input and output you expect? And also, can I ask you about the detail of current issue of your script?Tanaike
Please add the textual error message and simplied version of your code (minimal reproducible example).Rubén
@Tanaike my inputs are in the attached image. for example, I will select from subject ICTE4215 (F5), Date 2020-08-20 (G5), Student ID 01 is 1902011 (H5), Student ID 02 is 1902015 (I5), Student ID 02 is 1902024 (J5), Student ID 04 is 1902036 (K5). based on the input in K6, the function onePeriod() will be called. The output sheet will be like the sheet given after the first 5 lines of the post having column (i) Date, (ii) Student ID, (iii) Umail, (iv) Latitude, (v) Longitude, (vi) subject. The issues is, the code does not insert the inputs in the output sheet, can't find where is the error.Aktaruzzaman Liton
Thank you for replying. From your replying. I understood the code does not insert the inputs in the output sheet, can't find where is the error.. But, unfortunately, I cannot still understand about your goal. This is due to my poor skill. I deeply apologize for this. In order to correctly understand about your goal, can you provide the sample input and output you expect? Unfortunately, I cannot understand about your goal from your question. I apologize for this, again.Tanaike
@Tanaike please check now. The input values with cell information from the Dashboard sheet are given at the attached image. And the output sheet name will be ICTE4115 (values in cell F5). The output pattern is given just above my codes in the post.Aktaruzzaman Liton

1 Answers

1
votes

I believe your situation and goal as follows.

  • When the cell "K6" is edited, your script of onePeriod() is run. (Do you use OnEdit event trigger?)
  • You want to retrieve the values from the cells "K3, F5, G5, H5, I5, J5, K5" from the source sheet ("Dashboard").
  • You want to put the converted values to the destination sheet. In this case, the sheet name is the cell "F5". And the sample output situation can be seen at the top of image in your question.
  • You want to put the converted values to the next row of last row of the same date in the column "A" on the destination sheet.

In your script, the values are retrieved each cell using getValue, getDisplayValue() and getValues(). And the values are put using setValue in the loop. By this, the process cost will be high. So in this modification, I would like to propose the following flow.

  1. Retrieve values from the source sheet.
    • In this case, getDisplayValues() is used for retrieving the values. And when the values are converted, "Student ID" is converted to the number type.
  2. Convert the values for putting to the destination sheet.
  3. Put the converted values to the destination sheet.

When above flow is reflected to the script, it becomes as follows.

Modified script:

function onePeriod() {
  const srcSheetName = "Dashboard";
  
  // 1. Retrieve values from the source sheet.
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const srcSheet = ss.getSheetByName(srcSheetName);
  const [[,,,,,k3],,[f5,g5,...h5i5j5k5]] = srcSheet.getRange("F3:K5").getDisplayValues();
  
  // 2. Convert the values for putting to the destination sheet.
  const dstValues = h5i5j5k5.reduce((ar, e) => {
    if (e != "") ar.push([g5, Number(e), e + k3, , , f5]);
    return ar;
  }, []);
  
  // 3. Put the converted values to the destination sheet.
  const dstSheet = ss.getSheetByName(f5);
  const dstCurrentValues = dstSheet.getRange(`A2:A${dstSheet.getLastRow()}`).getDisplayValues().flat();
  const index = dstCurrentValues.lastIndexOf(dstValues[0][0]) + 2;
  dstSheet.insertRowsAfter(index, dstValues.length);
  dstSheet.getRange(index + 1, 1, dstValues.length, dstValues[0].length).setValues(dstValues);
}
  • When this script is run, the values are put to the next row of the last row of destination sheet.

Note:

  • This sample script is for your sample input and output values in your question. So when your actual situation is different from this sample, the script might not work. So please be careful this.

  • When I could saw your shared Spreadsheet, I noticed the following 2 important points. Please be careful them.

    1. When I saw it, I noticed that the same function names (2 functions onePeriod()) are used in macros.gs and manualentry.gs.
    2. The last lines of the function onePeriod() in manualentry.gs which uses my script has the scripts which uses dashboard which is not declared.

Reference: