Volond Apps
221 subscribers
216 photos
28 videos
22 files
994 links
Программирование для души и от лени
Добро пожаловать! У нас есть отличное сообщество любителей Excel и VBA, Google Sheet и Google Apps Script, а также всех тех, кто готов работать с этим программным обеспечением. Присоединяйтесь к нам, чтобы задавать и от
Download Telegram
Учебник JavaScript для новичков от Трепачёва Дмитрия
Источник:
На данной странице размещается начало учебника JavaScript для новичков. Для его освоения вам необходимо иметь хотя бы минимальные знания HTML и CSS. Обратитесь к учебнику HTML и CSS для новичков для их получения (для изучения JavaScript вам нужно пройти хотя бы 3-4 урока минимум).

Язык JavaScript предназначен для выполнения в браузере наряду с HTML и CSS. Но, если эти языки предназначены для верстки структуры сайта, то JavaScript позволяет 'оживлять' web-страницы - делать их реагирующими на действия пользователя или демонстрировать некоторую динамичность (к примеру, смена картинок в блоке или красивые плавно выпадающие менюшки).

Итак, давайте без лишних слов приступим к изучению этого, бесспорно, полезного языка.
••••••••••
Обсудить:
Как проверить, является ли строка JSON или нет?
Источник:
Предупреждение:
для методов, использующих JSON.parse- массивы и строки, заключенные в кавычки, также пройдут (т. Е. console.log(JSON.parse('[3]'), JSON.parse('"\uD800"')))

Чтобы избежать использования всех примитивов JSON, не являющихся объектами (логические, нулевые, массив, число, строка), я предлагаю использовать следующее:

/* Validate a possible object ie. o = { "a": 2 } */
const isJSONObject = (o) =>
!!o && (typeof o === 'object') && !Array.isArray(o) &&
(() => { try { return Boolean(JSON.stringify(o)); } catch { return false } })()

/* Validate a possible JSON object represented as string ie. s = '{ "a": 3 }' */
function isJSONObjectString(s) {
try {
const o = JSON.parse(s);
return !!o && (typeof o === 'object') && !Array.isArray(o)
} catch {
return false
}
}

Код Пояснение
!! o - не ложь (исключая null, который регистрируется как typeof( 'object')
(typeof o === 'object') - исключает логическое, числовое и строковое
! Array.isArray (o) - Исключить массивы (которые регистрируются как typeof( 'объект')
попробуйте ... JSON.stringify / JSON.parse - запрашивает движок JavaScript, чтобы определить, действителен ли JSON

Почему бы не использовать ответ hasJsonStructure ()?
Полагаться на toString()- не лучшая идея. Это связано с тем, что разные механизмы JavaScript могут возвращать другое строковое представление. В общем, методы, которые полагаются на это, могут дать сбой в различных средах или могут потерпеть неудачу позже, если движок когда-либо изменит строковый результат.
Почему перехват исключения - это не взлом?
Было поднято, что перехват исключения для определения достоверности чего-либо - неправильный путь. В целом это хороший совет, но не всегда. В этом случае перехват исключений, вероятно, является лучшим способом, поскольку он основан на реализации механизма JavaScript для проверки данных JSON.
Использование движка JS дает следующие преимущества:
1. Более тщательный и постоянно обновляемый по мере изменения спецификации JSON
2. Скорее всего, будет работать быстрее (так как это код более низкого уровня)

‼️ Когда мне представится возможность опереться на движок JavaScript, я бы посоветовал это сделать. Особенно в этом случае. Хотя это может показаться хакерским перехватом исключения, на самом деле вы просто обрабатываете два возможных состояния возврата из внешнего метода.
#JS #JSON #cromeextension
Excel Formula Utilities for JavaScript
Источник:
Excel Formula Utilities for JavaScript is a library that can be used to pretty print excel formulas or convert excel formulas into JavaScript. The JavaScript generated by this library will not execute on it's own. You'll need to include something like formula.js to cover all the functions from Excel.

••••••••••
Обсудить:
Imgur API
Источник:
Начиная
API Imgur предоставляет всю инфраструктуру Imgur через стандартизованный программный интерфейс. Используя API Imgur, вы можете делать практически все, что можете делать на imgur.com, используя при этом язык программирования по вашему выбору. Imgur API - это RESTful API, основанный на HTTP-запросах и JSON-ответах.

Эта версия API, версия 3, использует OAuth 2.0. Это означает, что все запросы необходимо будет зашифровать и отправить через HTTPS. Это также означает, что вам необходимо зарегистрировать свое приложение, даже если вы не разрешаете пользователям входить в систему.

Самый простой способ начать использовать Imgur API - нажать кнопку « Выполнить в Postman» выше. Postman - это бесплатный инструмент, который помогает разработчикам запускать и отлаживать запросы API, и является источником достоверной информации для этой документации. Каждая задокументированная конечная точка, которую вы видите здесь, легко доступна при запуске нашей коллекции Postman.

An AutoIt UDF to help you upload images using Imgur API.
Источник:
#api #autoIt
Forwarded from STM Solution (Stanislav Maslakov)
Приложение разработанное нашими коллегами из дружественного чата @google_sheets

ДАШБОРДЕР. ПРИЛОЖЕНИЕ.
ЭВОТОР + GOOGLE ТАБЛИЦЫ

Привет, друзья!

Мы сделали приложение для интеграции касс Эвотор и Google таблиц, приложение официально выложено в Google, оно позволяет:

– выгружать ваши чеки по api-ключу в таблицу
– выгружать их регулярно после активации триггера
– чеки подставляются в отчеты, в которых можно выбрать магазин / даты и увидеть информацию по товару
– внутри приложения есть отправка диапазонов в телеграм

Сейчас набираем первую группу пользователей, с каждый создадим личный чат для поддержки / приема фидбека

GIF-пример
https://t.me/google_sheets/637

Условия - 5000 рублей / 4 месяца, подробнее программу на канале про Google Таблицы
https://t.me/google_sheets/638

Будут вопросы - пишите в личку @IT_sAdmin, на всё отвечу
Snippet Generator
Источник:
Snippet generator is a tiny React app to help you create Visual Studio Code, Sublime Text and Atom snippets.

I built it for fun. It is hosted on Netlify for free (thanks Netlify). The only thing that I pay money for is a domain name (
snippet-generator.app). If you enjoy using snippet generator, help me to renew this domain please.

Enjoy!
••••••••••
#tools
Google Workspace Developers
Источник:
••••••••••
Обсудить:
Forwarded from DidacticСardsBot
Svelte Front-end Fun с AppsScripts

Источник:



Мне нравятся инструменты для написания, поэтому я считаю себя скорее «бэкенд-программистом», если бы мне захотелось. На самом деле я действительно хочу подчеркнуть, что действительно важно то, что оба «конца» должны согласовываться и работать вместе, что, возможно, означает, что я программист «полного стека».

В любом случае я должен работать в области JavaScript, учитывая контекст, в котором я работаю и в котором я строю. И JavaScript известен своей привлекательностью внешнего интерфейса: если вы хотите работать над пользовательским интерфейсом в браузере, вы говорите о разработке интерфейса JavaScript, и вместе с этой банкой червей приходит серия библиотек, фреймворков, зависимостей, инструментов варианты ... Я вижу много упоминаний о «хрюканье» и «грант» и смутно знаю, что они собой представляют ... но я не уделяю слишком много внимания этим вещам.

Я много читал о React и заинтересовался Vue, но у меня никогда не получалось. Затем я прочитал приличный обзор этого. Потом посмотрел несколько уроков . А потом я нашел статью, в которой говорилось о том, как использовать Svelte в контексте AppsScripts , в котором я живу.

ПОЧЕМУ SVELTE ТАК ВАЖЕН


Наблюдение, которое привлекло меня к Svelte больше, чем к другим фреймворкам, заключалось в том, насколько он был упрощен и в то же время предоставлял такие мощные абстракции, основанные на его простоте. Большинство вещей, которые я делаю, связаны с относительно простым взаимодействием с пользователем, например, надстройка с боковой панелью или что-то вроде простого щелчка-щелчка. Раньше я использовал инструмент с низким кодом, такой как AppMaker, потому что мне не требовалась тяжелая работа. Платформа, которую я использовал, была довольно простой и сдержанной.

Хотя меня интересовала технология, перспектива использования React и Vue была похожа на бензопилу, чтобы разрезать сыр. Между тем, Svelte в основном был тем, чем, как я думал, должен был быть написан сам HTML / CSS / JavaScript, если бы мы попробовали еще раз:
••••••••••
Обсудить:
Идентификатор родительской папки электронной таблицы приложений Google
Источник:

var spreadsheetId =  SpreadsheetApp.getActiveSpreadsheet().getId();
var spreadsheetFile = DriveApp.getFileById(spreadsheetId);
var folderId = spreadsheetFile.getParents().next().getId();

Я еще немного потестил. Вам не обязательно быть владельцем электронной таблицы, но вам нужно иметь разрешение на просмотр или, что лучше, на папку, чтобы получить информацию о папке. Например, если кто-то предоставил вам доступ к электронной таблице, но не к папке, в которой она находится, вы, к сожалению, не сможете получить свойства папки.

Правильный Код который не подвержен ошибке
Достигнут
конец итератора
Exception: Cannot retrieve the next object: iterator has reached the end.

function getParentFolder(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var file = DriveApp.getFileById(ss.getId());
var folders = file.getParents();
while (folders.hasNext()){
Logger.log('folder name = '+folders.next().getName());
Logger.log('folder name = '+folders.next().getId());
}
}


••••••••••
Обсудить:
#DriveApp #SpreadsheetApp
Копейка рубль бережет!

var num=123457.12546544
// С округлением
console.log(Math.round((num-Math.trunc(num))*100))
// Без округления
console.log(Math.trunc(num % 1 * 100))

#snippet #GAS #JS #customformula
Как создать триггер для запуска программы в назначенное время?

Источник:



Чтобы не терять триггерное время, а оно очень лимитировано для обычных аккаунтов, лучше всего использовать самовоспроизводящийся триггер


/**
* это то, что вы должны запустить один раз при первом запуске вашего триггера.
* Другие настройки не требуются
*/
function runOnce() {
trigger_();
}

/**
 * это и триггер и конфигурация вашего триггера
*/
function trigger_() {
try {
triggerAction();
} catch (error) {
console.error(error.message, error);
} finally {
var hours = 10;
var minutes = 17;
var seconds = 56;
var now = new Date();
var nextTime = new Date();
nextTime.setHours(0, 0, 24 * 3600 + hours * 3600 + minutes * 60 + seconds);
var delta = nextTime.getTime() - now.getTime();
ScriptApp.newTrigger('trigger_')
.timeBased()
.after(delta)
.create();
}
}

/**
* это то, что выполняет ваш скрипт
*/
function triggerAction() {
console.log("I'm fine");
}

triggerAction - это то, что выполняет ваш скрипт
runOnce - это то, что вы должны запустить один раз при первом запуске вашего триггера. Другие настройки не требуются
trigger_ - это и триггер и конфигурация вашего триггера

Такой триггер выполняется с высокой степенью точности, погрешность часто составляет меньше половины секунды.
••••••••••
Обсудить:
#JS #GAS #triggers
Облегчение функции IMPORTRANGE v.2.0

Источник:
При связи двух и более таблиц с помошью формулы importrange - при переходе определенного порога нагрузки (зависит от количества импортируемых ячеек а так же от количества символов в ячейках) мы сталкиваемся с ошибкой импорта, когда данные просто не импортируются или импортируются не всегда. Работать с данными становится проблематично. Для решения этой проблемы можно использовать следующий метод облегчения функции IMPORTRANGE. Метод позволяет импортировать примерно в 2 раза больше данных.
Суть метода состоит в 2-х аспектах:
1. Мы с помощью формулы импортируем ровно столько строк, сколько необходимо для импорта, не более того
2. Мы многократно уменьшаем количество импортируемых ячеек при том же количестве информации - с помощью сжатия данных до одного столбца.

На примере двух вкладок "импортируемые данные" и "экспорт" продемонстируем метод, действия описаны ниже:
#formula
Change queue time of Google spreadsheet app script trigger

Источник:

Ask Question


Если точность имеет первостепенное значение, вы можете вообще отказаться от использования триггеров сценариев приложений и вместо этого использовать сторонний инструмент.

Я бы рекомендовал использовать
cron-job.org . Эта служба может создавать задания cron, которые отправляют запросы POST на указанную вами конечную точку URL, и вы можете планировать время с точностью до минуты. Чтобы использовать его с Apps Script, реализуйте a doPost()для обработки почтовых запросов и развертывания вашего скрипта как веб-приложения. Затем вы создаете задание cron с помощью службы и передаете ему URL-адрес веб-приложения в качестве конечной точки.

Задание cron запускается в запланированное время, и вы можете выполнять любые необходимые операции внутри doPost()в ответ на входящий запрос POST.

Спасибо случайным деталям и Dimu Designs за руководство. На основе экспериментов вот ответы на мои вопросы:

Возможно ли, кроме наблюдения за ежедневной обработкой, определить точное время выполнения триггера, которое было назначено? Ответ: Ни в коем случае, кроме как путем наблюдения случайного времени запуска, назначенного в пределах запрошенного часового окна.
При случайном назначении можно ли создавать и удалять триггеры сценария, пока не будет получено приемлемо точное время выполнения? Ответ: Да. Я скорректировал назначенное мне время выполнения сценария, наблюдая за временем выполнения триггера (через временную метку сообщения электронной почты), а также удаляя, воссоздавая и наблюдая за случайно назначенным временем выполнения триггера, пока не получу приемлемую минуту в пределах запрошенного часового окна.
••••••••••
смотрите также
Обсудить:
#triggers #webapp
Forwarded from DidacticСardsBot
XPath Tester using Web Apps Created by Google Apps Script

Источник:



В этом посте я хотел бы представить тестер xpath, использующий веб-приложения, созданные с помощью скрипта Google Apps.


Применение


1. Подготовьте таблицу Google.
Создайте новую таблицу Google на своем Google Диске.

2. Включите API Таблиц.
Откройте редактор сценариев в созданной новой электронной таблице и включите API таблиц в расширенных службах Google .

3. Подготовьте образец сценария.
Скопируйте и вставьте следующий скрипт в редактор скриптов в созданную новую электронную таблицу и сохраните его.

function doGet(e) {
const url = e.parameter.url;
const xpath = e.parameter.xpath;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheets()[0];
sheet.clear();
const range = sheet.getRange("A1");
range.setFormula(`=IMPORTXML("${url}";"${xpath}")`);
do {
SpreadsheetApp.flush();
Utilities.sleep(1000);
} while (range.getDisplayValue() == "Loading...");
const values = sheet.getDataRange().getDisplayValues();
const res = { url: url, xpath: xpath, values: values };
if (values[0][0] == "#N/A") {
const obj = Sheets.Spreadsheets.get(ss.getId(), {
ranges: [sheet.getSheetName()],
fields: "sheets",
});
const v = obj.sheets[0].data[0].rowData[0].values[0];
if (
v.hasOwnProperty("effectiveValue") &&
v.effectiveValue.hasOwnProperty("errorValue")
) {
res.error = v.effectiveValue.errorValue;
}
}
sheet.clear();
return ContentService.createTextOutput(JSON.stringify(res)).setMimeType(
ContentService.MimeType.JSON
);
}


4. Разверните веб-приложения


Выберите «Я» для «Выполнить как» .
Пожалуйста , выберите «Любой» для «Кто имеет доступ»

С помощью этого параметра любой может получить доступ к вашим веб-приложениям. В данном случае это для тестирования этого скрипта.
Конечно, вы можете использовать токен доступа в этой ситуации. Но в этом случае в качестве простой настройки я использую ключ доступа вместо токена доступа.

Скопируйте URL-адрес веб-приложения. Это как https://script.google.com/macros/s/###/exec.
После изменения скрипта Google Apps повторно разверните его как новую версию. Таким образом, измененный сценарий отражается в веб-приложениях. Пожалуйста, будьте осторожны.

5. Тестирование.


Например, когда xpath обнаруживает ошибку, возвращается следующий результат.


$ curl -L 'https://script.google.com/macros/s/###/exec?url=https://tanaikech.github.io/index.xml&xpath=//channel/sample'


{
"url": "https://tanaikech.github.io/index.xml",
"xpath": "//channel/sample",
"values": [["#N/A"]],
"error": { "type": "N_A", "message": "Imported content is empty." }
}
••••••••••
Обсудить:
Forwarded from volond
https://xfanatical.com/blog/print-google-sheet-as-pdf-using-apps-script/
Возможные улучшения:
Экспорт листов как отделных таблиц Google или xlsx
Оправка через Gmail/Телеграмм/Вайбер
Генерация имени по шаблонным правилам


#GAS #SheetAPI #export #PDF
Объединить несколько PDF-файлов в один PDF-файл

Источник:

Задать вопрос


У меня такая же проблема, и я временно использую RestFul API для слияния PDF-файлов:
https://www.convertapi.com/pdf-to-merge

function merge() {
var folder = DriveApp.getFolderById('<ID FOLDER>'); // folder with files pdf
var files = folder.getFiles(); // get all files pdf

var formData = {};
var index = 0;
while(files.hasNext()) {
var file = files.next();
formData['Files[' + index + ']'] = file.getBlob();
index++;
}

var options = {
'method' : 'post',
'payload' : formData,
'muteHttpExceptions': true
};

var response = UrlFetchApp.fetch('https://v2.convertapi.com/pdf/to/merge?Secret=<YOUR SECRET>', options);

if(response.getResponseCode() == 200) {
var contentText = JSON.parse(response.getContentText());
var blob = Utilities.base64Decode(contentText.Files[0].FileData);
folder.createFile(Utilities.newBlob(blob, 'application/pdf', 'merge.pdf'));
}
}

Так что это больше, чем просто объединение данных из каждого файла. Фактически используемые данные для каждого файла «упакованы» с пометками и другим кодом (аналогично HTML и другим форматам документов). Фактически вам нужно декодировать каждый PDF-файл, объединить необходимые части, а затем перекодировать с новой «упаковкой». Для этого требуется практическое знание спецификаций и структуры PDF-файла, который можно бесплатно получить в Adobe здесь .

Я использовал эту информацию, чтобы написать сценарий, достаточный для моих нужд. Однако он не учитывает все возможности, поэтому, в частности, слияние любых документов, требующих PDF-1.4 и выше, потребует довольно большой работы.
https://pastiebin.com/601c57a966040
••••••••••
Обсудить:
Forwarded from DidacticСardsBot
Номер телефона

Источник:



Регулярное выражение для валидации номера телефона:


^((8|\+7)[\- ]?)?(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}$

Ориентировано на российские мобильные + городские с кодом из 3 цифр (например, Москва).

Зеленый свет для:
+79261234567
89261234567
79261234567
+7 926 123 45 67
8(926)123-45-67
123-45-67
9261234567
79261234567
(495)1234567
(495) 123 45 67
89261234567
8-926-123-45-67
8 927 1234 234
8 927 12 12 888
8 927 12 555 12
8 927 123 8 123

••••••••••
Обсудить:
Forwarded from DidacticСardsBot
Отображение данных из GitHub API в Google Таблицах с помощью Apps Script и Oauth

Источник:



В этом посте показано, как подключить Google Sheet к API GitHub с помощью Oauth и Apps Script. Цель состоит в том, чтобы получить данные и информацию из GitHub и отобразить их в вашей таблице Google для дальнейшего анализа и визуализации.

Если вы управляете командой разработчиков или являетесь техническим менеджером проекта, то это может быть действительно полезным способом анализа и визуализации статистики кодирования вашей команды или проекта в сравнении с целями, такими как количество коммитов, языки, вовлеченные люди и т. Д. С течением времени. .
••••••••••
Обсудить:
function ins(){
var ss= SpreadsheetApp.getActive()
var sheet=ss.getActiveSheet()
var data=sheet.getDataRange().getValues()
for (i=data.length;i>1;i--){
console.log(i)
sheet.insertRowsAfter(i, 1);

}
}
function insAndCopy(){
var ss= SpreadsheetApp.getActive()
var sheet=ss.getActiveSheet()
var data=sheet.getDataRange().getValues()
for (i=data.length;i>1;i--){

var range = sheet.getRange(i,1,1,data[0].length);
sheet.insertRowsAfter(i, 1);
range.copyTo(sheet.getRange(i+1, 1, 1, data[0].length), {contentsOnly:false});
range.copyFormatToRange(sheet.getRange(i+1, 1, 1, data[0].length), {contentsOnly:false});

}
}
JavaScript-массивы: пересечение, разность и объединение в ES6

Источник:
Пересечение даст нам элементы, которые объединяют оба массива, в этом случае результат должен быть [1,5].

let intersection = arrA.filter(x => arrB.includes(x));


Разность будет выводить элементы из массива A, которых нет в массиве B. Результат будет [3,4].


let difference = arrA.filter(x => !arrB.includes(x));


В этом случае вы получите массив, содержащий все элементы arrA, которых нет в arrB, и наоборот, так что результат должен быть [2,3,4,6,7].


let difference = arrA.filter(x => !arrB.includes(x)).concat(arrB.filter(x => !arrA.includes(x)));


Объединение должно быть самым простым из них всех, в конце концов, результатом должны быть все элементы из A, все из B или оба, как это [1,2,3,4,5,6,7].

let union = [...arrA, ...arrB];


Но есть проблема в том, что мы получим дублированные элементы, так что теоретически это не объединение. Для этого мы можем использовать new Set():

let union = [...new Set([...arrA, ...arrB)];

••••••••••