update 1904130940
This commit is contained in:
504
projects/google/liveSS/js/descriptions_builders.js
Normal file
504
projects/google/liveSS/js/descriptions_builders.js
Normal file
@@ -0,0 +1,504 @@
|
||||
/**
|
||||
* Updated: 2019-04-12
|
||||
*/
|
||||
|
||||
|
||||
/** Descriptions **/
|
||||
|
||||
function RangeDescription(value, row, column, desc) {
|
||||
/*
|
||||
* arguments: [value[, row[, column[, desc]]]]
|
||||
*
|
||||
* value -> any type
|
||||
* row -> integer (>0)
|
||||
* column -> integer (>0)
|
||||
* desc -> object containing full range description to override default settings
|
||||
*
|
||||
*/
|
||||
|
||||
var tag = 'range',
|
||||
sheetName = '',
|
||||
row = (row && typeof row == 'number') ? row : 1,
|
||||
column = (column && typeof column == 'number') ? column : 1,
|
||||
height = 1, width = 1,
|
||||
mustMerge = true, // options: true, false, 'vertically', 'across'
|
||||
wrapStrategy = SpreadsheetApp.WrapStrategy.CLIP,
|
||||
numberFormat = '@',
|
||||
background = '#efefef',
|
||||
validation = null,
|
||||
value = (value) ? value : '',
|
||||
protection = false, // options: true, false, 'warning'
|
||||
unprotected = false;
|
||||
|
||||
if (desc) {
|
||||
if (isPropDefined(desc, 'tag')) tag = desc.tag;
|
||||
if (desc.hasOwnProperty('sheetName') && typeof desc.sheetName == 'string') sheetName = desc.sheetName;
|
||||
if (desc.hasOwnProperty('row') && typeof desc.row == 'number') row = desc.row;
|
||||
if (desc.hasOwnProperty('column') && typeof desc.column == 'number') column = desc.column;
|
||||
if (desc.hasOwnProperty('height') && typeof desc.height == 'number') height = desc.height;
|
||||
if (desc.hasOwnProperty('width') && typeof desc.width == 'number') width = desc.width;
|
||||
if (isPropDefined(desc, 'mustMerge')) mustMerge = desc.mustMerge;
|
||||
if (isPropDefined(desc, 'wrapStrategy')) wrapStrategy = desc.wrapStrategy;
|
||||
if (isPropDefined(desc, 'numberFormat')) numberFormat = desc.numberFormat;
|
||||
if (isPropDefined(desc, 'background')) background = desc.background;
|
||||
if (isPropDefined(desc, 'validation')) validation = desc.validation;
|
||||
if (isPropDefined(desc, 'value')) value = desc.value;
|
||||
|
||||
if (isPropDefined(desc, 'protection')) protection = desc.protection;
|
||||
if (isPropDefined(desc, 'unprotected')) unprotected = desc.unprotected;
|
||||
}
|
||||
|
||||
function Border() {
|
||||
|
||||
var top = null, left = null, bottom = null, right = null,
|
||||
vertical = null, horizontal = null,
|
||||
color = null, style = null;
|
||||
|
||||
if (desc && isPropDefined(desc, 'border')) {
|
||||
var border = desc.border;
|
||||
if (isPropDefined(border, 'top')) top = border.top;
|
||||
if (isPropDefined(border, 'left')) left = border.left;
|
||||
if (isPropDefined(border, 'bottom')) bottom = border.bottom;
|
||||
if (isPropDefined(border, 'right')) right = border.right;
|
||||
if (isPropDefined(border, 'vertical')) vertical = border.vertical;
|
||||
if (isPropDefined(border, 'horizontal')) horizontal = border.horizontal;
|
||||
if (isPropDefined(border, 'color')) color = border.color;
|
||||
if (isPropDefined(border, 'style')) style = border.style;
|
||||
}
|
||||
|
||||
this.top = top;
|
||||
this.left = left;
|
||||
this.bottom = bottom;
|
||||
this.right = right;
|
||||
this.vertical = vertical;
|
||||
this.horizontal = horizontal;
|
||||
this.color = color;
|
||||
this.style = style;
|
||||
|
||||
}
|
||||
|
||||
function Alignment() {
|
||||
|
||||
var vertical = 'middle', horizontal = 'center';
|
||||
|
||||
if (desc && isPropDefined(desc, 'alignment')) {
|
||||
var alignment = desc.alignment;
|
||||
if (isPropDefined(alignment, 'vertical')) vertical = alignment.vertical;
|
||||
if (isPropDefined(alignment, 'horizontal')) horizontal = alignment.horizontal;
|
||||
}
|
||||
|
||||
this.vertical = vertical;
|
||||
this.horizontal = horizontal;
|
||||
|
||||
}
|
||||
|
||||
function Font() {
|
||||
|
||||
var family = 'Inconsolata',
|
||||
color = null,
|
||||
size = 10,
|
||||
weight = 'normal',
|
||||
style = 'normal',
|
||||
line = 'none';
|
||||
|
||||
if (desc && isPropDefined(desc, 'font')) {
|
||||
var font = desc.font;
|
||||
if (isPropDefined(font, 'family')) family = font.family;
|
||||
if (isPropDefined(font, 'color')) color = font.color;
|
||||
if (isPropDefined(font, 'size')) size = font.size;
|
||||
if (isPropDefined(font, 'weight')) weight = font.weight;
|
||||
if (isPropDefined(font, 'style')) style = font.style;
|
||||
if (isPropDefined(font, 'line')) line = font.line;
|
||||
}
|
||||
|
||||
this.family = family;
|
||||
this.color = color;
|
||||
this.size = size;
|
||||
this.weight = weight;
|
||||
this.style = style;
|
||||
this.line = line;
|
||||
|
||||
}
|
||||
|
||||
function Indent() {
|
||||
|
||||
var left = 0, right = 0;
|
||||
|
||||
if (desc && isPropDefined(desc, 'indent')) {
|
||||
var indent = desc.indent;
|
||||
if (isPropDefined(indent, 'left')) left = indent.left;
|
||||
if (isPropDefined(indent, 'right')) right = indent.right;
|
||||
}
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
}
|
||||
|
||||
// Meta
|
||||
this.tag = tag;
|
||||
|
||||
// Range
|
||||
this.sheetName = sheetName;
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.mustMerge = mustMerge;
|
||||
|
||||
// Appearance
|
||||
this.wrapStrategy = wrapStrategy;
|
||||
this.numberFormat = numberFormat;
|
||||
this.background = background;
|
||||
this.border = new Border;
|
||||
this.alignment = new Alignment;
|
||||
this.font = new Font;
|
||||
this.indent = new Indent;
|
||||
|
||||
// Data
|
||||
this.validation = validation;
|
||||
this.value = value;
|
||||
|
||||
// Protection
|
||||
this.protection = protection;
|
||||
this.unprotected = unprotected;
|
||||
|
||||
}
|
||||
|
||||
function SheetDescription(height, width, sheetName) {
|
||||
/*
|
||||
* arguments: [height[, width[, sheetName]]]
|
||||
*
|
||||
* height -> integer (>0) || array of integers(>0) representing different row heights
|
||||
* width -> integer (>0) || array of integers(>0) representing different column widths
|
||||
* sheetName -> string
|
||||
*
|
||||
*/
|
||||
|
||||
if (!height) height = 1;
|
||||
if (!width) width = 1;
|
||||
|
||||
var rowHeight = 21, columnWidth = 100;
|
||||
|
||||
if (Array.isArray(height)) {
|
||||
if (height.every(function(n) { return typeof n == 'number'; })) {
|
||||
rowHeight = height;
|
||||
height = height.length;
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(width)) {
|
||||
if (width.every(function(n) { return typeof n == 'number'; })) {
|
||||
columnWidth = width;
|
||||
width = width.length;
|
||||
}
|
||||
}
|
||||
|
||||
this.sheetName = (sheetName && typeof sheetName == 'string') ? sheetName : '';
|
||||
|
||||
// Dimensions
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.rowHeight = rowHeight;
|
||||
this.columnWidth = columnWidth;
|
||||
this.frozenRows = 0;
|
||||
this.frozenColumns = 0;
|
||||
|
||||
// Body
|
||||
this.range = new RangeDescription(undefined, undefined, undefined, sheetName);
|
||||
this.range.height = height;
|
||||
this.range.width = width;
|
||||
this.range.mustMerge = false;
|
||||
this.hasGridlines = false;
|
||||
|
||||
// Protection
|
||||
this.protection = false;
|
||||
/* must be either false or object (may be ommitted or deleted)
|
||||
* object: {
|
||||
* warning = boolean
|
||||
* unprotected = array of unprotected ranges
|
||||
* }
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Builders **/
|
||||
|
||||
function buildRange(desc) {
|
||||
/*
|
||||
* arguments: desc
|
||||
*
|
||||
* desc -> object containing full range description
|
||||
*
|
||||
*/
|
||||
|
||||
var ss = SpreadsheetApp.getActive(),
|
||||
sheet = (desc.sheetName) ? ss.getSheetByName(desc.sheetName) : ss.getActiveSheet(),
|
||||
range = sheet.getRange(desc.row, desc.column, desc.height, desc.width),
|
||||
cell = sheet.getRange(desc.row, desc.column);
|
||||
|
||||
var value = desc.value;
|
||||
if (value && typeof value == 'string') {
|
||||
var left = desc.indent.left,
|
||||
right = desc.indent.right;
|
||||
if (left || right) {
|
||||
polyfills__String_repeat();
|
||||
var lI = (left) ? ' '.repeat(left) : '',
|
||||
rI = (right) ? ' '.repeat(right) : '';
|
||||
value = lI + value + rI;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc.mustMerge) {
|
||||
switch (desc.mustMerge) {
|
||||
case 'vertically': range.mergeVertically(); break;
|
||||
case 'across': range.mergeAcross(); break;
|
||||
default: range.merge();
|
||||
}
|
||||
} else range.breakApart();
|
||||
|
||||
range
|
||||
.setBorder(
|
||||
desc.border.top, desc.border.left,
|
||||
desc.border.bottom, desc.border.right,
|
||||
desc.border.vertical, desc.border.horizontal,
|
||||
desc.border.color, desc.border.style
|
||||
)
|
||||
.setWrapStrategy(desc.wrapStrategy)
|
||||
.setNumberFormat(desc.numberFormat)
|
||||
.setHorizontalAlignment(desc.alignment.horizontal)
|
||||
.setVerticalAlignment(desc.alignment.vertical)
|
||||
.setBackground(desc.background)
|
||||
.setFontColor(desc.font.color)
|
||||
.setFontFamily(desc.font.family)
|
||||
.setFontSize(desc.font.size)
|
||||
.setFontLine(desc.font.line)
|
||||
.setFontWeight(desc.font.weight)
|
||||
.setFontStyle(desc.font.style)
|
||||
.setDataValidation(desc.validation);
|
||||
|
||||
cell.setValue(value);
|
||||
|
||||
}
|
||||
|
||||
function buildRanges(descArr) {
|
||||
/*
|
||||
* arguments: descArr
|
||||
*
|
||||
* descArr -> array of objects containing full range descriptions
|
||||
*
|
||||
*/
|
||||
|
||||
if (Array.isArray(descArr)) {
|
||||
for (var i = 0; i < descArr.length; i++) buildRange(descArr[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function buildSheet(desc, rangeArr, isNew) {
|
||||
/*
|
||||
* arguments: desc[, rangeArr[, isNew]]
|
||||
*
|
||||
* desc -> object containing full sheet description
|
||||
* rangeArr -> function to run after
|
||||
* isNew -> boolean (false by default)
|
||||
*/
|
||||
|
||||
if (!isNew) isNew = false;
|
||||
|
||||
var ss = SpreadsheetApp.getActive();
|
||||
var sheet, index, unprotected1 = [], unprotected2 = [];
|
||||
|
||||
var sheetName = (desc.sheetName) ? desc.sheetName : undefined,
|
||||
height = desc.height,
|
||||
width = desc.width,
|
||||
rowHeight = desc.rowHeight,
|
||||
columnWidth = desc.columnWidth,
|
||||
frozenRows = desc.frozenRows,
|
||||
frozenColumns = desc.frozenColumns;
|
||||
|
||||
if (isNew) {
|
||||
(sheetName) ? ss.insertSheet(sheetName) : ss.insertSheet();
|
||||
sheet = ss.getActiveSheet();
|
||||
} else {
|
||||
sheet = (sheetName) ? ss.getSheetByName(sheetName) : ss.getActiveSheet();
|
||||
}
|
||||
|
||||
index = sheet.getIndex() - 1;
|
||||
|
||||
shrinkSheet(sheet);
|
||||
|
||||
sheet.setHiddenGridlines(!desc.hasGridlines);
|
||||
|
||||
if (height > 1) sheet.insertRowsAfter(1, height - 1);
|
||||
if (width > 1) sheet.insertColumnsAfter(1, width - 1);
|
||||
|
||||
if (Array.isArray(rowHeight)) {
|
||||
for (var r = 0; r < rowHeight.length; r++) {
|
||||
sheet.setRowHeight(r + 1, rowHeight[r]);
|
||||
}
|
||||
} else {
|
||||
sheet.setRowHeights(1, height, rowHeight);
|
||||
}
|
||||
|
||||
if (Array.isArray(columnWidth)) {
|
||||
for (var c = 0; c < columnWidth.length; c++) {
|
||||
sheet.setColumnWidth(c + 1, columnWidth[c]);
|
||||
}
|
||||
} else {
|
||||
sheet.setColumnWidths(1, width, columnWidth);
|
||||
}
|
||||
|
||||
if (frozenRows && frozenRows < height) sheet.setFrozenRows(frozenRows);
|
||||
if (frozenColumns && frozenColumns < width) sheet.setFrozenColumns(frozenColumns);
|
||||
|
||||
if (rangeArr && Array.isArray(rangeArr)) {
|
||||
|
||||
for (var r = 0; r < rangeArr.length; r++) {
|
||||
var rng = rangeArr[r];
|
||||
if (sheetName) rng.sheetName = sheetName;
|
||||
if (rng.unprotected) {
|
||||
unprotected1.push(sheet.getRange(rng.row, rng.column, rng.height, rng.width));
|
||||
if (unprotected1.length == 1) sheet.setCurrentCell(sheet.getRange(rng.row, rng.column));
|
||||
}
|
||||
}
|
||||
|
||||
buildRanges(rangeArr);
|
||||
|
||||
}
|
||||
|
||||
var protection = ss.getProtections(SpreadsheetApp.ProtectionType.SHEET)[index];
|
||||
if (protection) protection.remove();
|
||||
|
||||
if (desc.hasOwnProperty('protection') && desc.protection) {
|
||||
|
||||
protection = sheet.protect();
|
||||
|
||||
if (desc.protection.hasOwnProperty('warning') && desc.protection.warning) {
|
||||
protection.setWarningOnly(true);
|
||||
} else {
|
||||
var owner = ss.getOwner();
|
||||
protection.addEditor(owner);
|
||||
protection.removeEditors(protection.getEditors());
|
||||
}
|
||||
|
||||
var hasUnprotected = isPropDefined(desc.protection, 'unprotected');
|
||||
|
||||
if (hasUnprotected || unprotected1.length) {
|
||||
|
||||
if (hasUnprotected && desc.protection.unprotected.length) {
|
||||
unprotected2 = desc.protection.unprotected;
|
||||
}
|
||||
|
||||
var unprotected = unprotected1.concat(unprotected2);
|
||||
|
||||
if (unprotected.length) protection.setUnprotectedRanges(unprotected);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function buildValidation(desc, showArrow, allowInvalid) {
|
||||
/*
|
||||
* arguments: desc[, showArrow[, allowInvalid]]
|
||||
*
|
||||
* desc -> array of description entities, where index 0 is purpose and others are arguments
|
||||
* showArrow -> boolean, if true dropdown arrow will appear in dropdown type of validation
|
||||
* allowInvalid -> boolean, if true will allow validation override
|
||||
*
|
||||
*/
|
||||
|
||||
if (desc) {
|
||||
|
||||
var validation = SpreadsheetApp.newDataValidation(),
|
||||
purpose = desc[0];
|
||||
(showArrow == undefined || showArrow == null) ? showArrow = true : showArrow = showArrow;
|
||||
(allowInvalid == undefined) ? allowInvalid = false : allowInvalid = allowInvalid;
|
||||
|
||||
switch (purpose) {
|
||||
|
||||
// Dates
|
||||
case 'date': validation.requireDate(); break;
|
||||
case 'date =': validation = validation.requireDateEqualTo(date(desc[1])); break;
|
||||
case 'date >': validation = validation.requireDateAfter(date(desc[1])); break;
|
||||
case 'date >=': validation = validation.requireDateOnOrAfter(date(desc[1])); break;
|
||||
case 'date <': validation = validation.requireDateBefore(date(desc[1])); break;
|
||||
case 'date <=': validation = validation.requireDateOnOrBefore(date(desc[1])); break;
|
||||
case 'date <=>': validation = validation.requireDateBetween(date(desc[1]), date(desc[2])); break;
|
||||
case 'date <>': validation = validation.requireDateNotBetween(date(desc[1]), date(desc[2])); break;
|
||||
|
||||
// Numbers
|
||||
case 'number =': validation = validation.requireNumberEqualTo(desc[1]); break;
|
||||
case 'number !=': validation = validation.requireNumberNotEqualTo(desc[1]); break;
|
||||
case 'number >': validation = validation.requireNumberGreaterThan(desc[1]); break;
|
||||
case 'number >=': validation = validation.requireNumberGreaterThanOrEqualTo(desc[1]); break;
|
||||
case 'number <': validation = validation.requireNumberLessThan(desc[1]); break;
|
||||
case 'number <=': validation = validation.requireNumberLessThanOrEqualTo(desc[1]); break;
|
||||
case 'number <=>': validation = validation.requireNumberBetween(desc[1], desc[2]); break;
|
||||
case 'number <>': validation = validation.requireNumberNotBetween(desc[1], desc[2]); break;
|
||||
|
||||
// Text
|
||||
case 'text =': validation = requireTextEqualTo(desc[1]); break;
|
||||
case 'text +': validation = requireTextContallowInvalidns(desc[1]); break;
|
||||
case 'text -': validation = requireTextDoesNotContallowInvalidn(desc[1]); break;
|
||||
|
||||
// Misc
|
||||
case 'checkbox':
|
||||
if (desc[1]) {
|
||||
if (desc[2]) validation = validation.requireCheckbox(desc[1], desc[2]);
|
||||
else validation = validation.requireCheckbox(desc[1]);
|
||||
} else validation = validation.requireCheckbox();
|
||||
break;
|
||||
case 'formula': validation = validation.requireFormulaSatisfied(desc[1]); break;
|
||||
case 'emallowInvalidl': validation = validation.requireTextIsEmallowInvalidl(); break;
|
||||
case 'url': validation = validation.requireTextIsUrl(); break;
|
||||
case 'list': validation = validation.requireValueInList(desc[1], showArrow); break;
|
||||
case 'range': validation = validation.requireValueInRange(desc[1], showArrow); break;
|
||||
|
||||
}
|
||||
|
||||
validation = validation.setAllowInvalid(allowInvalid).build();
|
||||
|
||||
return validation;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Misc **/
|
||||
|
||||
function shrinkSheet(sheet) {
|
||||
/*
|
||||
* arguments: sheet
|
||||
*
|
||||
* sheet -> sheet object
|
||||
*
|
||||
*/
|
||||
|
||||
var u;
|
||||
|
||||
var maxRows = sheet.getMaxRows(),
|
||||
maxColumns = sheet.getMaxColumns(),
|
||||
frozenRows = sheet.getFrozenRows(),
|
||||
frozenColumns = sheet.getFrozenColumns();
|
||||
|
||||
if (frozenRows) sheet.setFrozenRows(0);
|
||||
if (frozenColumns) sheet.setFrozenColumns(0);
|
||||
if (maxRows > 1) sheet.deleteRows(2, maxRows - 1);
|
||||
if (maxColumns > 1) sheet.deleteColumns(2, maxColumns - 1);
|
||||
|
||||
desc = new SheetDescription;
|
||||
sheet.setRowHeight(1, desc.rowHeight);
|
||||
sheet.setColumnWidth(1, desc.columnWidth);
|
||||
sheet.setHiddenGridlines(false);
|
||||
|
||||
buildRange(new RangeDescription(u, u, u, {
|
||||
sheetName: sheet.getName(),
|
||||
font: { color: new RangeDescription().background }
|
||||
}));
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user