// Код скрипта "Крипто Балансы" для Google Таблиц
// Версия 1.1 | Автор: Громов А. А. | Сайт автора gaagaa.ru
function getBalancesFromAPI() {
const sheet = SpreadsheetApp.getActiveSheet();
// Проверяем, создана ли уже таблица (проверяем по заголовку в A2)
if (sheet.getRange('A2').getValue() === '💰 ОБЩИЕ СУММЫ') {
// Если таблица уже создана, просто обновляем балансы
getAllBalances();
return;
}
// Очищаем и создаем структуру (только если таблица еще не создана)
createTableStructure();
}
function createTableStructure() {
const sheet = SpreadsheetApp.getActiveSheet();
sheet.clear();
// Добавляем строку с информацией об авторе
sheet.getRange('A1:E1').setValues([[
'Версия 1.1 | Автор: Громов А. А. | Сайт автора gaagaa.ru', '', '', '', ''
]]);
// Создаем заголовки с итогами вверху
sheet.getRange('A2:E3').setValues([
['💰 ОБЩИЕ СУММЫ', '₿ Bitcoin', '⟠ Ethereum', '💵 Стоимость USD', '% Соотношение'],
['🌐 Адрес', '₿ Bitcoin', '⟠ Ethereum', '💵 Стоимость USD', '']
]);
// Вставляем пустые адреса с текстом "Добавьте адрес"
sheet.getRange('A4:A11').setValues([
['Добавьте адрес'],
['Добавьте адрес'],
['Добавьте адрес'],
['Добавьте адрес'],
['Добавьте адрес'],
['Добавьте адрес'],
['Добавьте адрес'],
['Добавьте адрес']
]);
// Применяем базовые стили
applyBaseStyles(sheet);
// Показываем подсказку при создании таблицы
SpreadsheetApp.getUi().alert(
'✅ Таблица создана!\n\n📝 Инструкция:\n1. Обновите страницу (F5) для появления меню\n2. Добавьте BTC/ETH адреса в столбец A\n3. Нажмите "💰 Крипто Балансы" → "🚀 Получить балансы"'
);
}
function isBTCAddress(address) {
return address.startsWith('1') || address.startsWith('3') || address.startsWith('bc1');
}
function isETHAddress(address) {
return address.startsWith('0x') && address.length === 42;
}
function applyBaseStyles(sheet) {
// Устанавливаем размеры колонок
sheet.setColumnWidth(1, 420);
sheet.setColumnWidth(2, 140);
sheet.setColumnWidth(3, 140);
sheet.setColumnWidth(4, 200);
sheet.setColumnWidth(5, 200);
// Стили для строки с информацией об авторе
const authorRange = sheet.getRange('A1:E1');
authorRange.merge()
.setBackground('#1a237e')
.setFontColor('white')
.setFontWeight('bold')
.setFontSize(12)
.setHorizontalAlignment('center')
.setVerticalAlignment('middle');
// Стили для строки итогов
const totalsRange = sheet.getRange('A2:E2');
totalsRange.setBackground('#4caf50')
.setFontColor('white')
.setFontWeight('bold')
.setFontSize(13)
.setHorizontalAlignment('center')
.setVerticalAlignment('middle');
// Стили для заголовков таблицы
const headerRange = sheet.getRange('A3:E3');
headerRange.setBackground('#ff9800')
.setFontColor('white')
.setFontWeight('bold')
.setFontSize(14)
.setHorizontalAlignment('center')
.setVerticalAlignment('middle');
// Базовые настройки
sheet.setFrozenRows(3);
sheet.setRowHeight(1, 35);
sheet.setRowHeight(2, 40);
sheet.setRowHeight(3, 45);
// Устанавливаем высоту строк для адресов
for (let i = 4; i <= 11; i++) {
sheet.setRowHeight(i, 45);
}
// Стили для текста "Добавьте адрес"
const addressRange = sheet.getRange('A4:A11');
addressRange.setFontColor('#a0aec0')
.setFontStyle('italic')
.setHorizontalAlignment('center')
.setFontSize(13)
.setVerticalAlignment('middle');
// Форматирование чисел для строки итогов
sheet.getRange('B2').setNumberFormat('0.00000000');
sheet.getRange('C2').setNumberFormat('0.00000000');
sheet.getRange('D2').setNumberFormat('$#,##0.00');
// Форматирование чисел для данных
sheet.getRange('B4:B100').setNumberFormat('0.00000000');
sheet.getRange('C4:C100').setNumberFormat('0.00000000');
sheet.getRange('D4:D100').setNumberFormat('$#,##0.00');
// Добавляем границы для строки итогов
sheet.getRange('A2:E2')
.setBorder(true, true, true, true, true, true, '#2e7d32', SpreadsheetApp.BorderStyle.SOLID_THICK);
}
function getPriceBTC() {
try {
const response = UrlFetchApp.fetch('https://blockchain.info/ticker');
const data = JSON.parse(response);
return data.USD.last;
} catch (e) {
console.log('Ошибка получения цены BTC');
return 0;
}
}
function getPriceETH() {
try {
const response = UrlFetchApp.fetch('https://api.ethplorer.io/getTokenInfo/0x0000000000000000000000000000000000000000?apiKey=freekey');
const data = JSON.parse(response);
return data.price.rate;
} catch (e) {
console.log('Ошибка получения цены ETH');
return 0;
}
}
function getAllBalances() {
const sheet = SpreadsheetApp.getActiveSheet();
const lastRow = sheet.getLastRow();
// Получаем все адреса
const addresses = sheet.getRange('A4:A' + lastRow).getValues().flat();
let totalBTC = 0;
let totalETH = 0;
// Получаем текущие цены
const btcPrice = getPriceBTC();
const ethPrice = getPriceETH();
// Для каждого адреса получаем баланс
for (let i = 0; i < addresses.length; i++) {
const address = addresses[i];
if (!address || address === 'Добавьте адрес') continue;
if (isBTCAddress(address)) {
const balance = getBTCBalance(address);
totalBTC += balance;
sheet.getRange('B' + (i + 4)).setValue(balance);
sheet.getRange('C' + (i + 4)).setValue('-');
} else if (isETHAddress(address)) {
const balance = getETHBalance(address);
totalETH += balance;
sheet.getRange('C' + (i + 4)).setValue(balance);
sheet.getRange('B' + (i + 4)).setValue('-');
}
// Расчет стоимости в USD для каждого адреса
const btcVal = sheet.getRange('B' + (i + 4)).getValue();
const ethVal = sheet.getRange('C' + (i + 4)).getValue();
let usdValue = 0;
if (btcVal !== '-' && btcVal > 0) usdValue = btcVal * btcPrice;
if (ethVal !== '-' && ethVal > 0) usdValue += ethVal * ethPrice;
sheet.getRange('D' + (i + 4)).setValue(usdValue);
}
// Обновляем итоговые значения
sheet.getRange('B2').setValue(totalBTC);
sheet.getRange('C2').setValue(totalETH);
const totalUSD = (totalBTC * btcPrice) + (totalETH * ethPrice);
sheet.getRange('D2').setValue(totalUSD);
// Обновляем процентное соотношение
if (totalUSD > 0) {
for (let i = 0; i < addresses.length; i++) {
const address = addresses[i];
if (!address || address === 'Добавьте адрес') continue;
const usdValue = sheet.getRange('D' + (i + 4)).getValue();
const percent = (usdValue / totalUSD) * 100;
sheet.getRange('E' + (i + 4)).setValue(percent.toFixed(2) + '%');
}
}
SpreadsheetApp.getUi().alert('✅ Балансы успешно обновлены!');
}
function getBTCBalance(address) {
try {
const response = UrlFetchApp.fetch('https://blockchain.info/q/addressbalance/' + address);
return parseFloat(response) / 100000000;
} catch (e) {
console.log('Ошибка получения баланса BTC');
return 0;
}
}
function getETHBalance(address) {
try {
const response = UrlFetchApp.fetch('https://api.ethplorer.io/getAddressInfo/' + address + '?apiKey=freekey');
const data = JSON.parse(response);
return parseFloat(data.ETH.balance);
} catch (e) {
console.log('Ошибка получения баланса ETH');
return 0;
}
}
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('💰 Крипто Балансы')
.addItem('🚀 Получить балансы', 'getBalancesFromAPI')
.addSeparator()
.addItem('➕ Добавить пустые строки', 'addEmptyRows')
.addItem('🗑️ Очистить всё', 'clearAllData')
.addSeparator()
.addItem('🧪 Тест API', 'testAPI')
.addToUi();
}
function addEmptyRows() {
const sheet = SpreadsheetApp.getActiveSheet();
const lastRow = sheet.getLastRow();
const newRow = lastRow + 1;
sheet.getRange('A' + newRow).setValue('Добавьте адрес');
sheet.getRange('A' + newRow).setFontColor('#a0aec0').setFontStyle('italic');
sheet.setRowHeight(newRow, 45);
SpreadsheetApp.getUi().alert('✅ Добавлена новая пустая строка для адреса');
}
function clearAllData() {
const sheet = SpreadsheetApp.getActiveSheet();
const lastRow = sheet.getLastRow();
if (lastRow > 3) {
sheet.getRange('A4:E' + lastRow).clearContent();
sheet.getRange('A4:A' + lastRow).setValue('Добавьте адрес').setFontColor('#a0aec0').setFontStyle('italic');
}
// Очищаем итоговые значения
sheet.getRange('B2:D2').clearContent();
sheet.getRange('B2').setNumberFormat('0.00000000');
sheet.getRange('C2').setNumberFormat('0.00000000');
sheet.getRange('D2').setNumberFormat('$#,##0.00');
SpreadsheetApp.getUi().alert('✅ Все данные очищены');
}
function testAPI() {
const ui = SpreadsheetApp.getUi();
try {
// Тест BTC API
const btcResponse = UrlFetchApp.fetch('https://blockchain.info/ticker');
const btcData = JSON.parse(btcResponse);
const btcPrice = btcData.USD.last;
// Тест ETH API
const ethResponse = UrlFetchApp.fetch('https://api.ethplorer.io/getTokenInfo/0x0000000000000000000000000000000000000000?apiKey=freekey');
const ethData = JSON.parse(ethResponse);
const ethPrice = ethData.price.rate;
ui.alert(
'✅ API тест пройден успешно!\n\n' +
'BTC Price: $' + btcPrice + '\n' +
'ETH Price: $' + ethPrice
);
} catch (e) {
ui.alert('❌ Ошибка подключения к API');
}
}