/** Main function to add a new movement entry from the 'Schedule' tab
* to the appropriate table on the 'Movements' tab.
* Assign this function to your "Save" button.
*/
function
addMovementEntry ()
{
var
ss =
SpreadsheetApp
.
getActiveSpreadsheet ();
var
scheduleSheet =
ss .
getSheetByName (
"Schedule"
);
// Assuming the entry line is on Row 2.
// A2 is the dropdown, B2:J2 are the 9 data points.
var
entryRange =
scheduleSheet .
getRange (
"A2:J2"
);
var
entryValues =
entryRange .
getValues ()[
0
];
var
targetRangeName =
entryValues [
0
];
// The named range from the dropdown
var
dataToLog =
entryValues .
slice (
1
);
// The 9 data points
// Validation: Check if a movement is selected
if
(!
targetRangeName ||
targetRangeName ===
""
)
{
SpreadsheetApp
.
getUi ().
alert (
"Please select a Movement from the dropdown in column A."
);
return
;
}
// Validation: Check if at least a date is entered
if
(
dataToLog [
0
]
===
""
)
{
SpreadsheetApp
.
getUi ().
alert (
"Please enter at least a Date for the entry."
);
return
;
}
// Get the target named range
var
targetRange =
ss .
getRangeByName (
targetRangeName );
if
(!
targetRange )
{
SpreadsheetApp
.
getUi ().
alert (
"Could not find the table named '"
+
targetRangeName +
"'. Check your named ranges."
);
return
;
}
// Find the next empty row within this specific named range
var
rangeValues =
targetRange .
getValues ();
var
nextEmptyRowIndex =
-
1
;
// We start the loop at index 2 (which is the 3rd row of the named range)
// because index 0 is the Title, and index 1 is the Column Headers.
for
(
var
i =
2
;
i <
rangeValues .
length ;
i ++)
{
if
(
rangeValues [
i ][
0
]
===
""
)
{
// Checking the "Date" column to see if it's empty
nextEmptyRowIndex =
i ;
break
;
}
}
if
(
nextEmptyRowIndex ===
-
1
)
{
SpreadsheetApp
.
getUi ().
alert (
"The table for "
+
targetRangeName +
" is full! Please expand the named range."
);
return
;
}
// Write the data to the correct row and columns
// targetRange.getRow() gets the absolute starting row (e.g., Row 2)
var
writeRow =
targetRange .
getRow ()
+
nextEmptyRowIndex ;
var
writeCol =
targetRange .
getColumn ();
var
writeSheet =
targetRange .
getSheet ();
writeSheet .
getRange (
writeRow ,
writeCol ,
1
,
9
).
setValues ([
dataToLog ]);
// Clear the input fields on the Schedule sheet (B2:J2), leaving the dropdown intact
scheduleSheet .
getRange (
"B2:J2"
).
clearContent ();
// Show a success message
ss .
toast (
"Entry added successfully to "
+
targetRangeName +
"!"
,
"Success"
,
3
);
}
/** Bonus function: Recalls the most recent entry from the selected table
* and populates it back into the 'Schedule' tab.
* Assign this function to a "Recall Last" button.
*/
function
recallLastEntry ()
{
var
ss =
SpreadsheetApp
.
getActiveSpreadsheet ();
var
scheduleSheet =
ss .
getSheetByName (
"Schedule"
);
// Get the selected movement from the dropdown in A2
var
targetRangeName =
scheduleSheet .
getRange (
"A2"
).
getValue ();
if
(!
targetRangeName ||
targetRangeName ===
""
)
{
SpreadsheetApp
.
getUi ().
alert (
"Please select a Movement in column A to recall."
);
return
;
}
var
targetRange =
ss .
getRangeByName (
targetRangeName );
if
(!
targetRange )
{
SpreadsheetApp
.
getUi ().
alert (
"Could not find the table named '"
+
targetRangeName +
"'."
);
return
;
}
var
rangeValues =
targetRange .
getValues ();
var
lastUsedRowIndex =
-
1
;
// Find the last row that HAS data
for
(
var
i =
2
;
i <
rangeValues .
length ;
i ++)
{
if
(
rangeValues [
i ][
0
]
===
""
)
{
lastUsedRowIndex =
i -
1
;
// The row right before the empty one
break
;
}
}
// If lastUsedRowIndex is 1, it means only the headers exist
if
(
lastUsedRowIndex <=
1
)
{
SpreadsheetApp
.
getUi ().
alert (
"There are no entries logged for "
+
targetRangeName +
" yet."
);
return
;
}
// Extract the data from the last used row
var
lastData =
rangeValues [
lastUsedRowIndex ];
// Write the data back to the Schedule entry line (B2:J2)
scheduleSheet .
getRange (
"B2:J2"
).
setValues ([
lastData ]);
ss .
toast (
"Last entry for "
+
targetRangeName +
" has been recalled."
,
"Success"
,
3
);
}