function differencesSummary(inCol)
{
var dummyUi = SpreadsheetApp.getUi(); // for debugging, just a dummy UI for Alert usage
// // SSF = Call to Server-side Apps Script Function (read-write to Google Server)
var ssa = SpreadsheetApp.getActiveSpreadsheet(); // SSF, gets Active Spreadsheet (returns Spreadsheet object)
var sheet = ssa.getActiveSheet(); // SSF, gets Active Sheet (returns Sheet object)
var sheetLastRow = sheet.getLastRow(); // SSF, get last row of data in sheet (of longest column) (returns Integer)
var maxRow = sheet.getMaxRows(); // SSF, get last available row in sheet (returns integer)
var wholeColumn = sheet.getRange(1, inCol, sheetLastRow); // SSF, referencing whole column range to worked from (returns Range object),14=skip hdr
var data = wholeColumn.getValues(); // SSF, reads in all values in range (returns 2D array)
var term = 'Script Range1'; // search term for finding start of analysis area
// array used, return val 1 less on spreadsheet
var endOptRow = data.findIndex( parm1 => { // Prototype function
return parm1[0] == term }); // array(data) finds 1st element, parm1 is parm which is element of array as temp array
if (endOptRow == -1) { // if no text was found
dummyUi.alert("Must put 'Script Range1' at start of Option Diffs"); // alert dialog with error message
return; // exit?
}
var inpOptRange = sheet.getRange(1,inCol,endOptRow); // SSF, referencing options range to worked from (returns Range object)
var inpOptValues = inpOptRange.getValues(); // SSF, get text of options in range of cells (returns 2D array)
var inpOptFontColorsObj = inpOptRange.getFontColorObjects(); // SSF, get Font Color of options in range of cells (returns Color[][] object)
var inpOptBckgnds = inpOptRange.getBackgrounds(); // SSF, get Background color of opts in range of cells (returns 2D array)
var inpOptFontWeights = inpOptRange.getFontWeights(); // SSF, get Font bold of opts in range of cells (returns 2D array)
var ndx = -1; // set index to "not used yet", used for first time usage in certain circumstances
var regex = /^\[.+\]$/; // used for searching of the [xxxx] labels
var isLabel = false; // set as not a label
var lastCopiedLabel = "Bogus_label"; // set last written label (bogus txt needed for 1st compare, especially if no label & colored)
var currentLabelName = ""; // will hold current label's name (will be used to write if any opt changes)
var currentLabelFontColor = ""; // will hold current label's Font Color so it will overlay output line if label used
var currentLabelBckgnd = ""; // will hold current label's Background so it will overlay output line if label used
var currentLabelFontWeight = ""; // will hold current label's Font Weight so it will overlay output line if label used
var outOptValuesArray = []; // empty array for values to be written (to be 2D array)
var outOptFontColorsArray = []; // empty array for Font Color values to be written (to be 2D array)
var outOptBckgndsArray = []; // empty array for Background Color values to be written (to be 2D array)
var outOptFontWeightsArray = []; // empty array for Font Weight values to be written (to be 2D array)
var inpOptFontColors = []; // empty array for input of Font Colors (due to Color objs needing conversion to string RGB vals)
for (var i in inpOptFontColorsObj) { // loop through all elements of Color[][] object array, to convert from obj to 2D array
inpOptFontColors.push([inpOptFontColorsObj[i][0]
.asRgbColor()
.asHexString()]); // append, put RGB string for Font Color into new inp array (as an array iteself)
}
const arrLen = inpOptFontColors.length; // set to length of Font Color array elements so not re-issueing length in loop
for (var i=14; i<arrLen; i++) { // go thru each element (eg. column cells in SS), starts after heading info in SS (line 14)
if (regex.test(inpOptValues[i][0])) { // if is [xxx] label
currentLabelName = inpOptValues[i][0]; // save the label name as the current label
currentLabelFontColor = inpOptFontColors[i][0]; // save label's Font Color as the current label Font Color
currentLabelBckgnd = inpOptBckgnds[i][0]; // save label's Background as the current label Background
currentLabelFontWeight = inpOptFontWeights[i][0]; // save label's Font Weight as the current label Font Weight
isLabel = true; // element reviewed IS a label
} else { // element not [xxx] label
isLabel = false; // element reviewed is not a label
}
// If font not black & not lite blue (manually changed options color) & not empty or not white background.
// See Programming/Formula Information Help tab for extra info on "#ff000000" vs "000000"
if (inpOptFontColors[i][0] !== "#ff000000" &&
inpOptFontColors[i][0] !== "#6d9eeb" &&
inpOptValues[i][0] != "" ||
inpOptBckgnds[i][0] !== "#ffffff") { // Value & Type compare (strict equality)
ndx++; // increment for later use to know number of times thru areas
if (currentLabelName == lastCopiedLabel) { // if element to be copied is under same label as last copied label
outOptValuesArray.push([inpOptValues[i][0]]); // append text value to output values array
outOptFontColorsArray.push([inpOptFontColors[i][0]]); // append Font Color of text to output Font Colors array
outOptBckgndsArray.push([inpOptBckgnds[i][0]]); // append Background of text to output Backgrounds array
outOptFontWeightsArray.push([inpOptFontWeights[i][0]]); // append Font Weight of text to output Font Weights array
} else { // else -labels are different
if (isLabel) { // if is a new label, which font is non-black
if (ndx > 0) { // if not 1st time thru
outOptValuesArray.push([""]); // append empty value to output values array
outOptFontColorsArray.push(["#ff000000"]); // append black Font Color to output Font Colors array
outOptBckgndsArray.push(["#ffffff"]); // append white Background to output Backgrounds array
outOptFontWeightsArray.push(["normal"]); // append non-bold Font Weight to output Font Weights array
//ndx++; // increment for next output arrays element index (after blank line)
}
outOptValuesArray.push([currentLabelName]); // append text value to output values array
outOptFontColorsArray.push([inpOptFontColors[i][0]]); // append Font Color of text to output Font Colors array
outOptBckgndsArray.push([inpOptBckgnds[i][0]]); // append Background of text to output Backgrounds array
outOptFontWeightsArray.push([inpOptFontWeights[i][0]]); // append Font Weight of text to output Font Weights array
} else { // isn't label but is 1st "new" item for diff label
if ((ndx > 0) ||
(ndx == 0 && currentLabelName != "")) { // if not 1st time thru or if 1st time here & actually has a label name prev
if (ndx > 0) { // if not 1st time thru
outOptValuesArray.push([""]); // append empty value to output values array
outOptFontColorsArray.push(["#ff000000"]); // append black Font Color to output Font Colors array
outOptBckgndsArray.push(["#ffffff"]); // append white Background to output Backgrounds array
outOptFontWeightsArray.push(["normal"]); // append non-bold Font Weight to output Font Weights array
//ndx++; // increment for next output arrays element index (after blank line)
}
outOptValuesArray.push([currentLabelName]); // append text label (colored item element belongs to) into out val arr
outOptFontColorsArray.push([currentLabelFontColor]); // append label's Font Color to output Font Colors array
outOptBckgndsArray.push([currentLabelBckgnd]); // append label's Background to output Backgrounds array
outOptFontWeightsArray.push([currentLabelFontWeight]); // append label's Font Weight to output Font Weights array
} else { // 1st time through AND no label so set own "bogus" label info
currentLabelName = "[No Label]"; // set bogus label as current since no label first, for use if more non-label cells
outOptValuesArray.push(["[No Label]"]); // use bogus text label since no label first, copy into out val arr
outOptFontColorsArray.push(["#999999"]); // use gray Font Color and copy into output Font Colors array
outOptBckgndsArray.push(["#fce5cd"]); // use lite orange Background and copy into output Backgrounds array
outOptFontWeightsArray.push(["bold"]); // use Bold Font Weight and copy into output Font Weights array
}
ndx++; // increment for next output arrays element index
outOptValuesArray.push([inpOptValues[i][0]]); // append text value (of colored element) to output values array
outOptFontColorsArray.push([inpOptFontColors[i][0]]); // append Font Color to output Font Colors array
outOptBckgndsArray.push([inpOptBckgnds[i][0]]); // append Background to output Backgrounds array
outOptFontWeightsArray.push([inpOptFontWeights[i][0]]); // append Font Weight to output Font Weights array
}
lastCopiedLabel = currentLabelName; // set as new last copied label
}
}
}
term = 'Script Range2'; // search term for finding start of Changes analysis area
// array used, return val 1 less on spreadsheet // syntax - array.findIndex(function(currentValue, index))
var startWriteRow = data.findIndex( parm1 => { // Prototype function, array(data) finds 1st element, parm1 is parameter
return parm1[0] == term },
endOptRow); // parm1 is element of array as temp array, start from Range1 index instead of start of array
if (startWriteRow == -1) { // if no text was found
dummyUi.alert("Must put 'Script Range2' at start of New Changes"); // alert dialog with error message
return; // exit?
}
startWriteRow = startWriteRow + 7; // need +7 to get out of output header area, for output
var startWrtNumRows = outOptValuesArray.length; // set len same as size of output values array, setValues+ req same size as out 2d array
var outOptRange = sheet.getRange(startWriteRow,
inCol,
startWrtNumRows); // SSF, output writeable area to put all data from arrays (returns Range object)
outOptRange.setValues(outOptValuesArray); // SSF, put ALL values in output values array into empty section in range
outOptRange.setFontColors(outOptFontColorsArray); // SSF, put ALL Font Colors assoc with values above into empty section in range
outOptRange.setBackgrounds(outOptBckgndsArray); // SSF, put ALL Background Colors assoc with values above into empty section in range
outOptRange.setFontWeights(outOptFontWeightsArray); // SSF, put ALL Font Weights assoc with values above into empty section in range
}