Класс для управления Properties
#snippet #GAS
#snippet #GAS
/**
* Класс для управления Properties
* DocumentProperties or ScriptProperties or UserProperties
*
* Creates an instance of Props.
* @param {string} prop
* @memberof Props
* @constructor
* https://developers.google.com/apps-script/reference/properties
* @example
* const testProps=()=>{
* const scrProp=new Props("ScriptProperties");
* scrProp.set("v","1")
* concole.log(scrProp.get("v"))
* }
* @return {} Class Properties
*/
class Props {
constructor(prop) {
this[prop] = PropertiesService['get'+prop]();
this.type=prop
return this;
}
get(name) {
return this[this.type].getProperty(name);
}
getProperties(name) {
return this[this.type].getProperties();
}
type(prop) {
return this.type;
}
set(name, value) {
return this[this.type].setProperty(name, value);
}
forget(name) {
return this[this.type].deleteProperty(name);
}
getKeys() {
return this[this.type].getKeys();
}
has(callback,name) {
return this[this.type].getKeys().some(callback,element);
}
deleteAllProperties(){
this[this.type].deleteAllProperties();
}
setProperties(properties){
this[this.type].setProperties(properties);
}
setProperties(properties, deleteAllOthers){
this[this.type].setProperties(properties, deleteAllOthers);
}
}Как получить имя запущенной функции в JavaScript?
#snippet
#snippet
const es6=()=>{console.log(getMyName())}
function getMyName() {
var e = new Error('dummy');
var stack = e.stack
.split('\n')[2]
// " at functionName ( ..." => "functionName"
.replace(/^\s+at\s+(.+?)\s.+/g, '$1' );
return stack
}ᅠ
Заполнить пустые ячейки данными из предыдущих непустых
#snippet
Заполнить пустые ячейки данными из предыдущих непустых
#snippet
/**
* Заполнить пустые ячейки данными из предыдущих непустых
* тут формулами https://contributor.pw/post/fill-blank-cells-with-data-from-above-cell/
* но для одного столбца
* @param {Object} obj {arr,columnIndexStart,columnIndexStart}
* @param {Array[[]]} obj.arr - Индекс столбца с которого начинается преобразование
* @param {Number} obj.columnIndexStart - Индекс столбца с которого начинается преобразование
* @param {Number} obj.columnIndexEnd - Индекс столбца перед которого закончится преобразование(В выборку не попадает)
* @returns {Array} Преобразованный массив
* @example
* input Array
* let arr=[
* [1,2,3],
* [,,5],
* [8,9,10],
* [,11,12]
* ]
* return Array
* [ [ 1, 2, 3 ],
* [ 1, 2, 5 ],
* [ 8, 9, 10 ],
* [ 8, 11, 12 ]
* ]
*
*
*
*/
const fillData_ = ({ arr, columnIndexStart = 0, columnIndexEnd }) => {
/*
// tmp.forEach((item,j)=>{ //!!!!!forEach НЕ ВИДИТ undefined элементы
*/
let arrReptValue = arr[0].slice(columnIndexStart, columnIndexEnd)
arr.forEach((row, i, data) => {
let tmp = row.slice(columnIndexStart, columnIndexEnd)
for (j = 0; j < tmp.length; j++) {
if (isEmpty(tmp[j])) {
arr[i][j] = arrReptValue[j]
} else {
arrReptValue[j] = arr[i][j]
}
}
})
return arr
}
const isEmpty = (value) => {
return value === undefined || value === null || value === "";
}Как удалить пустые столбцы в 2D Array в JS
#snippet #JS #GAS
#snippet #JS #GAS
var csvData = [["", "2", ""], ["", "3", ""], ["", "4", ""], ["1", "3", ""]],
columns = csvData.reduce(
(r, a) => (a.forEach((v, i) => r[i] = r[i] || v), r),
csvData[0].map(_ => false)
);
csvData = csvData.map(a => a.filter((_, i) => columns[i]));
console.log(csvData);Текущее время смайликами
=join("➗";{VLOOKUP((HOUR(NOW())-mod(HOUR(NOW());10))/10;{SEQUENCE(10;1;0)\{"0️⃣";"1️⃣";"2️⃣";"3️⃣";"4️⃣";"5️⃣";"6️⃣";"7️⃣";"8️⃣";"9️⃣"}};2)&VLOOKUP(mod(HOUR(NOW());10);{SEQUENCE(10;1;0)\{"0️⃣";"1️⃣";"2️⃣";"3️⃣";"4️⃣";"5️⃣";"6️⃣";"7️⃣";"8️⃣";"9️⃣"}};2)\VLOOKUP((MINUTE(NOW())-mod(MINUTE(NOW());10))/10;{SEQUENCE(10;1;0)\{"0️⃣";"1️⃣";"2️⃣";"3️⃣";"4️⃣";"5️⃣";"6️⃣";"7️⃣";"8️⃣";"9️⃣"}};2)&VLOOKUP(mod(MINUTE(NOW());10);{SEQUENCE(10;1;0)\{"0️⃣";"1️⃣";"2️⃣";"3️⃣";"4️⃣";"5️⃣";"6️⃣";"7️⃣";"8️⃣";"9️⃣"}};2)\VLOOKUP((SECOND(NOW())-mod(SECOND(NOW());10))/10;{SEQUENCE(10;1;0)\{"0️⃣";"1️⃣";"2️⃣";"3️⃣";"4️⃣";"5️⃣";"6️⃣";"7️⃣";"8️⃣";"9️⃣"}};2)&VLOOKUP(mod(SECOND(NOW());10);{SEQUENCE(10;1;0)\{"0️⃣";"1️⃣";"2️⃣";"3️⃣";"4️⃣";"5️⃣";"6️⃣";"7️⃣";"8️⃣";"9️⃣"}};2)})/
* @OnlyCurrentDoc
* EN: Restricts script access to the current sheet only.
* RU: Ограничивает доступ скрипта только к текущему листу.
*/
/* exported REGEXMATCHS */
/* globals sorosWrapper_ */
/
* 𝗘𝗡: Returns an array of matches.
*
* 𝗥𝗨: Возвращает массив совпадений.
*
* 𝗩𝗲𝗿𝘀𝗶𝗼𝗻: 1.0
*
* 𝗔𝘂𝘁𝗵𝗼𝗿: Stoyanov Maksim (stomaks)
* 𝗦𝗶𝘁𝗲: stomaks.me
* 𝗕𝗹𝗼𝗴: G-Apps-Script.COM
*
* @param {string} text
* 𝗘𝗡: The text to check.
*
* 𝗥𝗨: Текст, который необходимо проверить.
*
* @param {string} regexp
* 𝗘𝗡: The regular expression to find in the text.
*
* 𝗥𝗨: Регулярное выражение, которое нужно найти в тексте.
*
* @param {number} type
* 𝗘𝗡: Type of response (
* 0 - substring;
* 1 - index of the first character of the substring;
* 2 - substring length;
* 3 - index of the last character of the substring).
*
* 𝗥𝗨: Тип ответа (
* 0 - подстрока;
* 1 - индекс первого символа подстроки;
* 2 - длина подстроки;
* 3 - индекс последнего символа подстроки).
*
* @return {array}
* 𝗘𝗡: An array of matches.
*
* 𝗥𝗨: Массив совпадений.
*
* @customfunction
*/
function REGEXMATCHS ( text, regexp, type ) {
var response = [];
text = String(text);
var flags = "g";
if ( /^\(\?i\)/.test(regexp) ) {
regexp = regexp.replace(/^\(\?i\)/, "");
flags += "i";
}
var subs = text.match( new RegExp(regexp, flags) );
if ( !subs ) return null;
for ( var cursor = subs.index, l = subs.length, i = 0; i < l; i += 1 ) {
var index = cursor;
if ( i+1 !== l && subs[i] !== subs[i+1] ) {
nextIndex = text.indexOf(subs[i+1], cursor);
while ( true ) {
currentIndex = text.indexOf(subs[i], index);
if ( currentIndex !== -1 && currentIndex <= nextIndex ) {
index = currentIndex + 1;
} else break;
}
index -= 1;
} else {
index = text.indexOf(subs[i], cursor);
}
cursor = index + subs[i].length;
switch ( type ) {
case 1:
response.push( index );
break;
case 2:
response.push( subs[i].length );
break;
case 3:
response.push( index + subs[i].length );
break;
case 0:
default:
response.push( subs[i] );
break;
}
}
return response;
}/**
* Как разбить массив на заданные куски
* splitEvery(3, [1, 2, 3, 4, 5, 6, 7]); //=> [[1, 2, 3], [4, 5, 6], [7]]
* Number → [a] → [[a]]
* @param {*} n
* @param {*} row
* @returns
*/
function splitEvery(n, row) {
return (row) => {
var result = [];
var idx = 0;
while (idx < row.length) {
result.push(row.slice(idx, idx += n));
}
return result
}
}
#snippetВытягиваем код Вашего проекта в таблицу
/**
* Returns an array of function names and their code
* In the current project
* Arrow functions do not fall into this array
* ....................................................
* Возвращает массив имен функций и их кода
* В текущем проекте
* Функции-стрелки в этот массив не попадают
*
* @return {Array}
* @customfunction
*/
function getFunction(){
const nameFn=Object.keys(this)
return (nameFn.map(el=>[el,this[el]]))
}
#snippet #GASО сортировке замолвите слово
function compareNumbers(a, b) {
if (a === b) return 0;
if (a > b) return 1;
/* else */
return -1;
}
function compareNumbers1(a, b) {
if (+a === +b) return 0;
if (+a > +b) return 1;
/* else */
return -1;
}
let nums = ["7", "3", "1", "5", "8", "11", "6", "4", "2"];
nums.sort()
console.log(nums)
nums.sort(compareNumbers);
console.log(nums);
/* 〕[
'1', '11', '2',
'3', '4', '5',
'6', '7', '8'
]
*/
nums.sort(compareNumbers1);
console.log(nums);
/*
[
'1', '2', '3',
'4', '5', '6',
'7', '8', '11'
]
*/Собираем диапазоны в один,
по именам листов указанных в диапазоне
по именам листов указанных в диапазоне
/**
* Собираем диапазоны в один,
* по именам листов указанных в диапазоне
* @param {String} sheetNames NameSheet
* @returns {Array}
* @customfunction
*/
function UNION(sheetNames){
const getSheetDataRange=(name)=>{
const data=SpreadsheetApp.
getActiveSpreadsheet().
getSheetByName(name[0]).
getDataRange().
getValues();
data.shift();
return data
}
const data=sheetNames.map(getSheetDataRange).flat(1)
return data
}
#customformula/**
* https://t.me/google_spreadsheets_chat/112103
* Собираем несколько диапазонов в один,
* замена =INDIRECT() в массиве.
* Диапазоны могут быть разной размерности.
* @param {string} ranges NameSheet!A1Notation range
* @returns {Array}
* @customfunction
*/
function indirects(ranges){
var ss = SpreadsheetApp.getActiveSpreadsheet();
if(ranges.map){
return [].concat.apply([], ranges.map(function(i){
return ss.getRange(i).getValues()}));}
else {
return ss.getRange(ranges).getValues(); }
}
#customformula/**#customformula
* v8 работает только в ES6
* Собираем несколько диапазонов в один,
* замена =INDIRECT() в массиве.
* Диапазоны могут быть разной размерности.
* @param {String} ranges NameSheet!A1Notation range
* @returns {Array}
* @customfunction
* @example
*/
function UNIONRANGES(ranges){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var getValues=(A1Not)=>ss.getRange(ranges).getValues()
return ranges.map?ranges.map(getValues).flat(1):getValues(ranges)
}
Объединяем свойства объектов JS
‼️ А так правильно ‼️
const a={a:1,b:2}
const c={c:3}
const d={b:3,e:4}
// Создаст новый объект g
const g=Object.assign(a,d,c)
console.log(g)//{ a: 1, b: 3, e: 4, c: 3 }
console.log(a)//{ a: 1, b: 3, e: 4, c: 3 }
😱 "а" МУТИРОВАЛ (изменился)‼️ А так правильно ‼️
const g=Object.assign({},a,d,c)
const f={...a,...d,...c}
console.log(f) //{ a: 1, b: 3, e: 4, c: 3 }
console.log(a)
// :) { a: 1, b: 2 }
#JSForwarded from volond
Деструктуризация разделения строки по разделителю
// Деструктуризация разделения строки по разделителю
//вариант а
const key='a^b'
const ssID_src = key.split("^")[0];
const sheet_src = key.split("^")[1];
//вариант б
const [хssID_src,sheet_src]=key.split("^")
console.log(хssID_src)
console.log(sheet_src)
#GAS #JS/**
* Получаем лист с активной книги по имени листа
* Get a sheet from the active book by sheet name
* @param {*} {sheetName}
* @returns {SpreadsheetApp.sheet}
*/
const getSheetFromActiveBookBySheetName=({sheetName})=>{
const ss = SpreadsheetApp.getActive();
return ss.getSheetByName(sheetName);
}
#GAS #JS
* Получаем лист с активной книги по имени листа
* Get a sheet from the active book by sheet name
* @param {*} {sheetName}
* @returns {SpreadsheetApp.sheet}
*/
const getSheetFromActiveBookBySheetName=({sheetName})=>{
const ss = SpreadsheetApp.getActive();
return ss.getSheetByName(sheetName);
}
#GAS #JS