1

How to make Google sheets automatically add the ordinal number of the current row based on the following criteria 'new entry on this particular row?

How to make it work even when the data is not entered on a row contiguous basis (for example 1st entry on row 1 (say cell B1), 2nd entry on row 2 (in B2), 3rd entry on row 3 (B3), but then 4th entry on row 9 (B9), 5th on row 11 (B11), 6th on row (B7))?

And not adding ordinals to intermediary empty rows (for example when B5/row5, B6/row6, B8/row8, B10/row10 etc. are blanks, don't add ordinals to A5/row5, A6/row6, A8/row8, A10/row10, etc.)?

Here's the expected result:

Ordinals to non-contiguous rows based on data entry timestamps

The Sheet: Ordinals to non-contiguous rows based on data entry timestamps

So far I've come up with this pull down formula (to be pre-set in A2 and dragged down to A12):

=IF(B2<>"",MAX($A$2:$A)+1,"")  [in A2]
=IF(B3<>"",MAX($A$2:$A)+1,"")  [in A3]
=IF(B4<>"",MAX($A$2:$A)+1,"")  [in A4]
=IF(B5<>"",MAX($A$2:$A)+1,"")  [in A5]
=IF(B6<>"",MAX($A$2:$A)+1,"")  [in A6]
=IF(B7<>"",MAX($A$2:$A)+1,"")  [in A7]
=IF(B8<>"",MAX($A$2:$A)+1,"")  [in A8]
=IF(B9<>"",MAX($A$2:$A)+1,"")  [in A9]
=IF(B10<>"",MAX($A$2:$A)+1,"")  [in A10]
=IF(B11<>"",MAX($A$2:$A)+1,"")  [in A11]
=IF(B12<>"",MAX($A$2:$A)+1,"")  [in A12]

But the result I get when I enter then data succesively one by one in B2, B3, B4, B7, B9, and B12, is that it updates all previous cells with the new max value so that the succesion isn't achieved.

Here's a gif that shows the live result:

https://i.imgur.com/1I1Dk8f.gifv

How to lock the previous results so that the ordinal count can proceed to the next entry when it occurs consecutively?

I've consulted those post that are close to what I'm looking for:

How do you replace a formula with its result?

using this script:

function freezeOutput(){
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SummarySheet");
  var range = sheet.getRange("A1:A10");     
  range.copyTo(range, {contentsOnly:true});
}

Stop Excel from updating formula after a criteria is matched

using this formula:

=IF(NOW() < C1,2*A1,A2)

Alternatively this VBA code:

Function EvaluateIf(expression As String, condition As Boolean) As Variant
    Application.Volatile
    Dim myText As String
    Dim myVal As Variant
    If condition Then
        myVal = Application.Evaluate(expression)
    Else
        myText = Application.Caller.Text
        If IsNumeric(myText) Then
            myVal = Val(myText)
        Else
            myVal = myText
        End If
    End If
    EvaluateIf = myVal
End Function


Function FreezeAfter(expression As String, deadline As Date) As Variant
    Application.Volatile
    Dim myText As String
    Dim myVal As Variant
    If Now > deadline Then
        myText = Application.Caller.Text
        If IsNumeric(myText) Then
            myVal = Val(myText)
        Else
            myVal = myText
        End If
    Else
        myVal = Application.Evaluate(expression)
    End If
    FreezeAfter = myVal
End Function

How do I copy cell values programatically?

using this script:

function getRangeValues() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var range = sheet.getRange("A2:B4");
  var values = range.getValues();
  return values;
};

With Sheet here: Copy cell values programmatically (72539)

Lastly:

Add the Current Date to a Sheet When Data Is Added So That The Date Does Not Change(Static) – Google Sheets

using this script:

/**
* Creates a Date Stamp if a column is edited.
* https://yagisanatode.com/2018/02/21/add-the-current-date-to-a-sheet-when-data-is-added-so-that-the-date-does-not-changestatic-google-sheets/
*/

//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 6;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,-5];
// Sheet you are working on
var SHEETNAME = 'Sheet3'

function onEdit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  //checks that we're on the correct sheet.
  if( sheet.getSheetName() == SHEETNAME ) { 
    var selectedCell = ss.getActiveCell();
    //checks the column to ensure it is on the one we want to cause the date to appear.
    if( selectedCell.getColumn() == COLUMNTOCHECK) { 
      var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[8]);
      dateTimeCell.setValue(new Date());
      }
  }
}

But I don't see how to make it work.

The expected result shoud be simply add ordinal number to corresponding cell in column A upon entering data on corresponding cell in column B.

How do we do that?

Lod
  • 657
  • 1
  • 9
  • 30

1 Answers1

1

Flow:

  • Use edit trigger to capture events in Col B
  • Get all of Col A on edit of Col B
  • Calculate Max of Col A and add 1
  • SetValue the max to Col A

Snippet:

function onEdit(e) {
  var rg = e.range,
    row = rg.rowStart,
    col = rg.columnStart,
    sht = rg.getSheet();

  //exit code
  if (col !== 2 || sht.getName() !== 'Sheet1' || row === 1) return;
  
  //Calculate max value and add 1
  rg.offset(0, -1, 1, 1).setValue(//setvalue in colA
    rg
      .offset(2 - row, -1, sht.getLastRow() - 1, 1) //get all of colA
      .getValues()
      .reduce(function(acc, curr) {//get max of colA
        return Math.max(acc, Number(curr[0]));
      }, 0) + 1
  );
}

To Read and Practice:

Community
  • 1
  • 1
TheMaster
  • 45,448
  • 6
  • 62
  • 85
  • Hi @TheMaster! Thanks a lot for the ideas and references. I tried for 2 days to get it working to no avail! Tested and working flawlessly here: https://i.imgur.com/s8pXukQ.gif https://i.imgur.com/EDWkVDE.gif I'll consult the references today and see how I can make it make sense. By the way do you know of any good online course I could take to learn better? Thanks a lot again, you rock! All the best and have a great we! – Lod Jun 01 '19 at 06:24
  • 1
    @Lod If the second gif was meant to convey that you want col A to be deleted, if colB is deleted, then [this](https://stackoverflow.com/a/51548690) might be useful. Regarding online courses, there are plenty available online. But, Practice is the most important thing. Learn to read directly from the official documentation and practice regularly. – TheMaster Jun 01 '19 at 06:51
  • Thanks for the reading advice. I'll go for that. Thanks also for the new reference, I just tried to decipher Tanaike's modified script but a lot of new terms to understand. I'll pause for an hour or so and try to reproduce the Calendar issue on a new Sheet to see how it works. I'll then have a try at deleting Col A cells from new understanding. Take care! – Lod Jun 01 '19 at 07:57
  • Hi again! I've tested tweaking Tanaike's code to delete cell in ColA and here's my results so far: https://i.imgur.com/iLzZu27.gif It freezes ColA nums but doesn't delete it. Also when copying and pasting, the code doesn't work any more: https://i.imgur.com/g74ZvTI.gif I've carefully read Tanaike's answers but cannot see the workaround. Also do you know how to access your comments on Tanaike's answer? They're not there anymore. Or are there on another post? – Lod Jun 02 '19 at 12:00
  • Thanks a lot for the references in your answer, I've learned new terms and uses of .reduce and .offset and accumulator (acc) and currentValue (curr). – Lod Jun 02 '19 at 12:01
  • if ((e.value == null) && (e.oldValue == null)) { // When the value of cell with a value is removed, this becomes true. // If we delete cell var delvalinA = sht.getRange(rg).getValue(); for (i in delvalinA){ delvalinA[i].clearContent(); } } – Lod Jun 02 '19 at 12:03
  • It's better if you ask a new question. I deleted my comments there. 1. You should use the code below "Added" at the very end there.. 2. Think. Think about type. What's the type of `rg`? What type of argument does sht.getRange(argument) accept? Ask yourself what's the type of each variable and if you don't know, read the documentation and find out... what type does a method accept and what does it return and what type is it? String type? Number type? Range object type? Spreadsheet object type? – TheMaster Jun 02 '19 at 13:03
  • Ok cool, thanks for pointing me to what questions are needed and the reasoning process! I didn't consider those... only reasoning from the code... I was out for some hours but I will research answers to your questions and come back with what I find tomorrow. I'll submit a new post with what I find as well. Have a great evening! Talk soon. – Lod Jun 02 '19 at 16:31
  • Hi again! in the mean time I have commented your code to reflect my understanding of it with the help of some referenced documentation in line here: https://pastebin.com/v8sQx3xE . I'll go on and post the new question later today. Thanks again! – Lod Jun 03 '19 at 08:06
  • @Lod Not bad. But you still didn't reference type. What's the type of each variable? What's the type of `e`? From where does this `e` come from? What's the type of `rg`? type of `rg` is `object`, specifically, object of class range. Another example: `getValues()` returns a array, specifically, a 2D array. `A2: 1 row above column A's last row).` No. No matter where you edit, it'll always be A2:last row of ColA(not 1 row above it). Can you figure out why? `e.range` I'm not setting range to e. I'm getting range from e. Similarly, rg.offset.setValue-> I'm not setting value `rg` to this range.. – TheMaster Jun 03 '19 at 08:51
  • thanks for your new clues! I tried to provide answers here of how to explain the code with further references: https://pastebin.com/fQZ96Kyv I will attempt another solution for the new question tomorrow. Thanks a lot again and have a great evening! – Lod Jun 03 '19 at 16:49
  • @Lod Ok Too many questions. Let's just start with `e`. According to the documentation, what does `e` contain? `e` is a object. There are multiple key:value pairs in any object. Can you list all the keys in object `e` in this context? – TheMaster Jun 03 '19 at 18:52
  • Hi @TheMaster! According to the documentation, `e` "The event object contains information about the context that caused the trigger to fire." Here the `e` keys list I see: `rg` [Key1] = e.range [Value1], `row` [Key2] = rg.rowStart [Value2], `col` [Key3] = rg.columnStart [Value3], `sht` [Key4] = rg.getSheet() [Value4]; In ref. to this post: [link](https://stackoverflow.com/questions/25955749/what-is-a-key-value-pair) – Lod Jun 04 '19 at 05:08
  • @Lod `The event object contains information about the context that caused the trigger to fire."` correct. But, forget my script. What information is sent? How will you access this information? What are the key:values present in this object according to the documentation? First Review object basics: https://www.w3schools.com/js/js_objects.asp (do the exercises) and then review event object `e` from the documentation – TheMaster Jun 04 '19 at 05:12
  • What information is sent? `the editing of a cell from column B` How will you access this information? `currently by .setValues(), then .getValues(), then .reduce() methods to print the ordinals`. But to erase the ordinals: will need upon specific trigger (edit) of clearing adjacent cell in column B to also clear adjacent cells in column A. So perhaps create a 2nd trigger to: 1st get value in col B, 2nd trigger set upon erasing the value in Col B, 3rd create an offset to get adjacent value in Col A, 4th erase adjacent value in Col A. – Lod Jun 04 '19 at 05:38
  • The key:values in `e` object according to the documentation? [link](https://developers.google.com/apps-script/guides/triggers/events) – Lod Jun 04 '19 at 05:38
  • `oldValue`, (Cell value prior to the edit, if any. Only available if the edited range is a single cell. Will be undefined if the cell had no previous content.) `range` ( A Range object, representing the cell or range of cells that were edited.), `source` (A Spreadsheet object, representing the Google Sheets file to which the script is bound.), `value` (New cell value after the edit. Only available if the edited range is a single cell.)[link](https://developers.google.com/apps-script/guides/triggers/events) – Lod Jun 04 '19 at 05:38
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/194409/discussion-between-themaster-and-lod). – TheMaster Jun 04 '19 at 06:01