I am bit stuck here and trying to figure out the following:
I do have a check to skip if the code and time are blank, it appears that it does not work for row#5. I only want to post the new code when there is a value in column B.
How this code works (adopted from this) is to check if there is an existing code in column A. If yes, assign a new code by incrementing the last digit to 1.
TIA!
Here is the snippet of the code I am using:
function createCode() {
var s = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('FormResp');
var LR = sheet.getLastRow();
var sheet_Range = sheet.getRange(2, 1, LR, sheet.getLastColumn());
var sheet_Values = sheet_Range.getValues();
for (var x = 0; x < sheet_Values.length - 1; x++) {
var code = sheet_Values[x][0];
var time = sheet_Values[x][1];
var status = sheet_Values[x][2];
if (code && time == "") { continue; }
if (((code == "" && time != "" && status == "") || (code && time != "" && status == ""))) {
var prevRowData = sheet.getRange(x + 2, 1).getValue();
if (prevRowData.length > 4) {
var codeId = parseInt(prevRowData.toString().substring(prevRowData.indexOf('-') + 1, prevRowData.length));
codeId++
var newCodeId = '0000' + codeId.toString();
var start = prevRowData.toString().substring(0, prevRowData.indexOf('-') + 1);
sheet.getRange((x + 2) + 1, 1).setValue(start + newCodeId);
}
}
}
s
, sheetResp
, and timestamp
are not declared.How increment the id (code) if it reaches Item-00010 or Item-00100..and so on? Is it better to start the value string to "Item-1000" rather than Item-00000? I don't know if it makes any difference.
, if you want to use the same length of the number value, how about using the zero padding?How to stop the code when it reaches the last row (with values) but somehow the value is still getting posted in an empty row (see screenshot an example)
, I think that the reason for this issue might be due to var sheet_Range = sheet.getRange(2, 1, LR, sheet.getLastColumn());
. In the case of var sheet_Range = sheet.getRange(2, 1, LR, sheet.getLastColumn());
, the values are retrieved from the 2nd row to the next row of the last row.When these points are reflected in your showing script, how about the following modification?
In this modification, your showing script was modified.
function createCode() {
var ss = SpreadsheetApp.getActive(); // Modified
var sheet = ss.getSheetByName('FormResp');
var LR = sheet.getLastRow(); // Modified
var sheet_Range = sheet.getRange(2, 1, LR - 1, sheet.getLastColumn()); // Modified
var sheet_Values = sheet_Range.getValues();
for (var x = 0; x < sheet_Values.length - 1; x++) {
var code = sheet_Values[x][0];
var time = sheet_Values[x][1];
var status = sheet_Values[x][2];
if (code && time == "") { continue; }
if (((code == "" && time != "" && status == "") || (code && time != "" && status == ""))) {
var prevRowData = sheet.getRange(x + 2, 1).getValue();
if (prevRowData.length > 4) {
var codeId = parseInt(prevRowData.toString().substring(prevRowData.indexOf('-') + 1, prevRowData.length));
codeId++
var newCodeId = String(codeId).padStart(5, "0"); // Modiifed
var start = prevRowData.toString().substring(0, prevRowData.indexOf('-') + 1);
sheet.getRange((x + 2) + 1, 1).setValue(start + newCodeId);
}
}
}
}
As another approach, when getValue
and setValue
are used in a loop, the process cost becomes high. Ref When this point is reflected, how about the following modification?
function createCode2() {
var sheet = SpreadsheetApp.getActive().getSheetByName('FormResp');
var range = sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getLastColumn());
var sheet_Values = range.getValues();
sheet_Values.forEach((r, i, a) => {
const [code, time, status] = r;
if (code && time == "") return;
if ((code == "" && time != "" && status == "") || (code && time != "" && status == "")) {
if (i == 0) {
a[i] = ["item-00001", time, status];
} else {
let [prefix, suffix] = a[i - 1][0].split("-");
const newSuffix = String(Number(suffix) + 1).padStart(5, "0");
a[i] = [`${prefix}-${newSuffix}`, time, status];
}
}
});
range.setValues(sheet_Values);
As another approach, in your situation, how about using the number format? When the number format is used, the actual value can be managed as a number value while the display value is like item-#####
. When this point is reflected, how about the following modification?
I'm not sure whether this approach is included in your expected result. If this was not included in your goal, please ignore this.
function createCode3() {
var sheet = SpreadsheetApp.getActive().getSheetByName('FormResp');
var lastRow = sheet.getLastRow();
sheet.getRange("A2:A" + lastRow).setNumberFormat('"item"-00000');
var range = sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getLastColumn());
var sheet_Values = range.getValues();
sheet_Values.forEach((r, i, a) => {
const [code, time, status] = r;
if (code && time == "") return;
if ((code == "" && time != "" && status == "") || (code && time != "" && status == "")) {
a[i] = [i == 0 ? 1 : i + 1, time, status];
}
});
range.setValues(sheet_Values);
}
When the above scripts are used, the following result is obtained.