Использование SliderDataSDK.

Приложения 1-11

Содержание.
Приложение 1. Полный текст кода макроса «Комплексный тест».
Приложение 2. Полный текст кода макроса «Тест гетерогенных подключений».
Приложение 3. Полный текст кода макроса «Тест ExternalXLSX (ExcelJS)».
Приложение 4. Полный текст кода макроса «Тест AlaSQL».
Приложение 5. Полный текст кода макроса «Тест UserGUIHelper».
Приложение 6. Полный список методов класса XLDBProxy.js.

1. Управление параметрами и конфигурацией. 1.1 defaultOptions.
1.2 newParams()
1.3 htgParams()
1.4 copyOnlyNeedParametrs(objToCopy)
1.5 loadParametrsFromLocalStorage()
1.6 loadParametrsFromFile(filePath)
1.7 loadParametrsFromServer()
2. Основные методы API
2.1 checkConnection(paramsName, options)
2.2 getTables(paramsName, options)
2.3 getViews(paramsName, options)
2.4 getFields(paramsName, options)
2.5 executeQuery(paramsName, options)
3. Гетерогенные запросы (HTG)
3.1 loadHTGConnectionsFromServer()
3.2 hasHTGRelations(nameHTGRelation)
3.3 loadHTGFields(nameHTGRelation)
3.4 registerHTGRelation(options)
3.5 unregisterHTGRelation(options)
3.6 executeAndUpdateHtgQuery(options)
4. Вспомогательные методы.
4.1 getColumns(response)
4.2 getData(response)
4.3 getColumnsAndData(response)
4.4 getError(response, stackLevel)
4.5 getCallerName(level)

Приложение 7. Полный список методов класса AlaSQLProxy.js.

1 Методы API
1.1 executeQuery(query, params)
1.2 createLocalStorageDatabase(dbName)
1.3 attachLocalStorageDatabase(dbName)
1.4 dropLocalStorageDatabase(dbName)
1.5 detachDatabase(dbName)
1.6 useDatabase(dbName)
1.7 createTable(tableName, columnsDefinition)
1.8 insertInto(tableName, values)
1.9 updateTable(tableName, values, whereClause)
1.10 readExcel(filePath, sheetName)
1.11 writeExcel(filePath, data, sheetName)
1.12 executeQueryOnExcel(filePath, coreQuery, params)
1.13 getExcelSheetNames(filePath)
1.14 selectFromArray(dataArray, query, params)
1.15 executeQueryOnExcelSheet(filePath, sheetName, coreQuery, params)

Приложение 8. Полный список методов класса UserGUIHelper

1. Методы API
1.1 initUI(commonUI)
1.2 getVersion()
1.3 errorWindow(message, onClose)
1.4 alertWindow(title, message, onClose)
1.5 confirmWindow(message, onClose)
1.6 infoWindow(message, onClose)
1.7 warningWindow(message, onClose)
1.8 withOneButtonWindow (titleWindow, messageForUser, ...)
1.9 userInputWindow(titleWindow, labelForInputField, ...)
1.10 userComboBoxWindow(titleWindow, labelForComboBoxField, ...)
1.11 cellRegionWindow(rangeBegin, onClose)
1.12 pathToFileWindow(ext, onClose)
1.13 tableDataWindow(tableData, titleWindow, messageForUser,...)

Приложение 9. Полный список методов класса ExternalXLSXProxy.

1. Методы API
1.1. getVersion()
1.2 getApi()
1.3 init()
1.4 initWithSheetJS()
1.5 initWithExcelJS()
1.6 loadWorkbook(fileID, fileData)
1.7 loadWorkbookFromUrl(fileID, url)
1.8 getSheetsList(fileID)
1.9 readSheet(fileID, sheetIdentifier)
1.10 readRange(fileID, sheetIdentifier, range)
1.11 readCell(fileID, sheetIdentifier, cellAddress)
1.12 writeData(fileID, sheetIdentifier, startCellAddress, dataArray)
1.13 saveWorkbook(fileID)
1.14 unloadWorkbook(fileID)
1.15 A1toR1C1(address)
1.16 R1C1toA1(address)
1.17 detectAddressType(address)
1.18 convertAddressToA1(address)
1.19 convertAddressToR1C1(address)

Приложение 10. Полный список методов класса OlapProxy.js.

1. Методы API
1.1 init()
1.2 initWithXmla()
1.3 loadConnection(connectionID, connectionParams)
1.4 executeQuery(connectionID, mdxQuery)
1.5 writeToActiveSheet(connectionID, mdxQuery, startCellAddress)
1.6 saveQueryResult(connectionID, queryID)
1.7 defaultOptions.
1.8 newParams()
1.9 copyOnlyNeedParametrs(objToCopy)
1.10 loadParametrsFromLocalStorage()
1.11 loadParametrsFromFile(filePath)
1.12 loadParametrsFromServer()
1.13 executeQuery(connection, query, error, success)
1.14 queryStaticData(connection, query, success)
1.15 getVersion()

Приложение 11. Типичные ошибки и их решения в SliderDataSDK.

1. Модуль 1. Основы SliderDataSDK.
Ошибка 1: SDK не инициализирован.
Ошибка 2: Системный плагин не установлен.
Ошибка 3: Подмодуль не загружен динамически.

Модуль 2. XLDBProxy.
Ошибка 1: Прокси-сервер недоступен.
Ошибка 2: Неправильные параметры подключения.
Ошибка 3: Неправильный формат SQL-запроса.
Ошибка 4: HTG-запросы не найдены..

Модуль 3. AlaSQLProxy.
Ошибка 1: AlaSQL не инициализирован.
Ошибка 2: Неправильный путь к Excel файлу.
Ошибка 3: Проблемы с localStorage базой данных.
Ошибка 4: Неправильная структура данных для запросов к массиву.

Модуль 4. UserGUIHelper
Ошибка 1: UI не инициализирован.
Ошибка 2: Callback-функции не работают.
Ошибка 3: Неправильные размеры окон.
Ошибка 4: Проблемы с валидацией ввода.

Модуль 5. ExternalXLSXProxy.
Ошибка 1: Библиотека не инициализирована.
Ошибка 2: Файл не найден или поврежден.
Ошибка 3: Неправильный адрес ячейки.
Ошибка 4: Утечка памяти при работе с большими файлами.

Модуль 6. OlapProxy.
Ошибка 1: XMLA сервер недоступен.
Ошибка 2: Неправильный MDX запрос.
Ошибка 3: Превышен лимит соединений.

Общие рекомендации по обработке ошибок.
1. Всегда используйте try-catch для асинхронных операций.
2. Проверяйте инициализацию модулей.
3.Общие рекомендации по обработке ошибок.
Приложение 1. Полный текст кода макроса «Комплексный тест»
/*
 Тесты для JavaScript библиотеки SliderDataSDK (для браузера) для простых SQL запросов к СУБД.
 */
 (function(){
    if(Common.R7ConsultLibs){
        if(Common.R7ConsultLibs.SliderDataSDK&&Common.R7ConsultLibs.SliderDataSDK.XLDBProxy){
            var XLDBProxy=Common.R7ConsultLibs.SliderDataSDK.XLDBProxy;
            XLDBProxy.defaultOptions= {
                protocol: "http://",//Протокол подключения
                host: "89.169.162.67", // Адрес прокси localhost
                port: "55080",     // Порт подключения к прокси
            };                      
            messageWindow("Внимание!",`SliderDataSDK ver.(${Common.R7ConsultLibs.SliderDataSDK.getVersion()})\n Результаты всех тестов можно посмотреть в консоли отладчика!`);
            runTests(XLDBProxy);          
        }
        else{
            messageWindow("Внимание!",`Библиотека SliderDataSDK не загружена!`);
        }
    }else{
        messageWindow("Внимание!",`R7ConsultLibs не загружен!`);
    }            
})();
 
//Функция комплексного SQL теста
async function runTests(XLDBProxy) {
    // Параметры подключения для тестов (замените на свои)
    const testParams = {
        engine: "postgres",//Имя технологии СУБД ("postgres","mssql","mysql","localfolder","htg" и т.д. согластно протоколу работы с прокси сервером XLDB SQL)
        database: "",//Имя БД
        user: "",//Логин входя в СУБД
        password: "",//Пароль входя в СУБД
        dbms_host: "",//Адрес ip или url точки подключения к СУБД
        dbms_port: "",//Порт tcp точки подключения к СУБД
        schema: "",//Схема БД (если требуется)
        relation_schema: "",//
        is_admin: "1",//Уровень привелегий пользователя user
        relation_type: "table"//Уровень работы: с таблицами "table", с просмотрами "view"
    };
   
    let testParamsName = "";//Идентификатор подключения


    console.log("Выполняется  тест библиотеки SliderDataSDK...");


    //Проверка загрузки параметров создаваемых плагином Слайдер Данные хранимых в localStorage
    await XLDBProxy.loadParametrsFromLocalStorage();
 
    const namesConnection=Object.keys(XLDBProxy.paramsCache);
    if(namesConnection.length && XLDBProxy.paramsCache["pg"])//Вместо "pg" вставить свое имя для соединения с postgresql
        testParamsName='pg';
    else{//Если нет записи с параметрами подключения в localStorage, параметры запроса берутся из заполненной структуры testParams
        testParamsName = "testConnection";
        // Load test parameters into the cache
        XLDBProxy.paramsCache[testParamsName] = testParams;
    }


    // checkConnection()  - тест функции подключения к СУБД
    try {
        const response = await XLDBProxy.checkConnection(testParamsName);
        assert(response !== undefined, "checkConnection() вернул результат");
        if(response)
        console.info("checkConnection() результат:", response);        
        //assert(response.traceback === "", "checkConnection() успешно установил соединение");
    } catch (error) {
        console.error("checkConnection() тест не пройден:", error);
    }


    // getTables()  тест. Получение списка таблиц в СУБД
    try {
        const response = await XLDBProxy.getTables(testParamsName);
        assert(response !== undefined, "getTables вернул результат");
        assert(Array.isArray(response.data), "getTables вернул массив данных");
        if(response.data)
        console.info("getTables() результат:", response.data);
    } catch (error) {
        console.error("getTables() тест не пройден:", error);
    }


    // getViews() тест. Получение списка просмотров в СУБД
    try {
        const response = await XLDBProxy.getViews(testParamsName);
        assert(response !== undefined, "getViews() вернул результат");
        assert(Array.isArray(response.data), "getViews() вернул массив данных");
        if(response)
        console.info("getViews() результат:", response);
    } catch (error) {
        console.error("getViews() тест не пройден:", error);
    }



    // getFields() тест. Получение списка полей в таблице "address"
    try {
        const response = await XLDBProxy.getFields(testParamsName, { relation_name: "address", relation_type: "table" });
        assert(response !== undefined, "getFields() вернул результат");
        assert(Array.isArray(response.data) && response.data.length, "getFields() вернул массив данных");
        if(response.data)
        console.info("getFields() результат:", response.data);
    } catch (error) {
        console.error("getFields() тест не пройден:", error);
    }


    // executeQuery()  тест. Получение данных  в СУБД через SQL запрос
    try {
               
        const response = await XLDBProxy.executeQuery(testParamsName, { query: `select * from "person"."address" limit 10` });
        assert(response !== undefined, "executeQuery() вернул результат");
       
        if(response){            
            let meta=XLDBProxy.getColumns(response);
            let result= XLDBProxy.getData(response);
            console.info("executeQuery() результат:",response);
            fillHeader(meta);
            fillData(result);
        }
         Api.asc_calculate(Asc.c_oAscCalculateType.ActiveSheet);
           
    } catch (error) {
        console.error("executeQuery() тест не пройден:", error);
    }



    console.log("SliderDataSDK тест пройден.");
}
 
//Заполнение заголовка таблицы
function fillHeader(headerData){      
    if(headerData){
        let worksheet=Api.GetActiveSheet();                                        
        let rowIdx=1;
        let colIdx=1;
        for(let row of headerData){                                
            worksheet.GetCells(rowIdx,colIdx).SetValue(row);
            colIdx++;            
        }
    }
}
 
//Вывод окна сообщения пользователю
function fillData(sheetData){    
    if(sheetData){
        let worksheet=Api.GetActiveSheet();                                        
        let rowIdx=2;
       
        for(let row of sheetData){                                
            let colIdx=1;
            for(let cell in row){
                worksheet.GetCells(rowIdx,colIdx).SetValue(row[cell]);
                colIdx++;
            }
            rowIdx++;
        }
    }
}
 
//Простой вариант проверки с логирование
function assert(condition, message) {
    if (!condition) {
        console.error("Тест провален: " + message);
    }
    else {
        console.log("Тест пройден: " + message);
    }
}
 
//Вывод окна сообщения пользователю
function messageWindow(title,textMessage){
    Common.UI.alert(
            {
                title: title,
                msg: textMessage,
                width: "auto",            
                closable: true            
            });
}

Приложение 2. Полный текст кода макроса «Тест гетерогенных подключений»
/*
 Тесты для JavaScript библиотеки SliderDataSDK (для браузера) с тестирование возможностей гетерогенных запросов.
 */
 (function(){
    if(Common.R7ConsultLibs){
        if(Common.R7ConsultLibs.SliderDataSDK.XLDBProxy){
            var SliderDataSDK=Common.R7ConsultLibs.SliderDataSDK.XLDBProxy;
            SliderDataSDK.defaultOptions= {
                protocol: "http://",//Протокол подключения
                host: "89.169.162.67", // Адрес прокси localhost
                port: "55080",     // Порт подключения к прокси
            };                      
            messageWindow("Внимание",`SliderDataSDK ver.(${Common.R7ConsultLibs.SliderDataSDK.getVersion()})\nРезультаты всех тестов можно посмотреть в консоли отладчика!`)
            runTests(SliderDataSDK);          
        }
        else{
            messageWindow("Внимание!",`Библиотека SliderDataSDK не загружена!`);
        }
    }else{
        messageWindow("Внимание!",`R7ConsultLibs не загружен!`);
    }                
})();


//Функция комплексного теста гетерогенных запросов
async function runTests(SliderDataSDK) {
    console.log("Выполняется  тест гетерогенных запросов библиотеки SliderDataSDK...");

     // loadHTGConnectionsFromServer() тест. Запроса зарегистрированных в  прокси htg запросов
    try {        
        await SliderDataSDK.loadHTGConnectionsFromServer();
        if(SliderDataSDK.htgCache.size){
            let keys=Array.from(SliderDataSDK.htgCache.keys());
            console.info("Зарегистрированы гетерогенные запросы:", keys);
        }
        else{
            console.info("На сервере нет зарегистрированых гетерогенных запросов!");
        }
     } catch (error) {
        console.error("loadHTGConnectionsFromServer() тест не пройден:", error);
    }
   
    let testHTGName="test";
    // hasHTGRelations()  тест. Имеется ли в прокси сервере зарегистрированный запрос с именем в переменно testHTGName
    try {      
        let hasHTG=await SliderDataSDK.hasHTGRelations(testHTGName);
        if(hasHTG){            
            console.info(`На сервере зарегистрирован гетерогенный запрос ${testHTGName}!`);
        }
        else{
            console.info(`На сервере не зарегистрирован гетерогенный запрос ${testHTGName}!`);
        }
     } catch (error) {
        console.error("hasHTGRelations() тест не пройден!:", error);
    }
   
    // loadHTGFields() тест. Имеется ли в прокси сервере зарегистрированный запрос с именем в переменной testHTGName
    try {      
        let hasHTGFields=await SliderDataSDK.loadHTGFields(testHTGName);
        if(hasHTGFields){
            let htg=SliderDataSDK.htgCache.get(testHTGName);
            if(htg.fields&&htg.fields.length){                            
                console.info(`Поля гетерогенный запроса ${testHTGName}!:`, htg.fields);
            }
            else{
                console.info(`В гетерогенном запросе  ${testHTGName} нет полей!:`);
            }
        }
        else{
            console.info(`На сервере не зарегистрирован гетерогенный запрос ${testHTGName}!`);
        }
     } catch (error) {
        console.error("loadHTGFields() тест не пройден!:", error);
    }
 
        // executeQuery тест. Получение списка просмотров в СУБД
    try {                
        const response = await SliderDataSDK.executeAndUpdateHtgQuery({ query: `select * from ${testHTGName} limit 10` });
        assert(response !== undefined, "executeAndUpdateHtgQuery() вернул результат");        
        if(response){            
            let meta=SliderDataSDK.getColumns(response);
            let result= SliderDataSDK.getData(response);
            console.info("executeAndUpdateHtgQuery() результат:",response);
            //Заполнение текущего листа документа данными полученными из запроса
            fillHeader(meta);
            fillData(result);
        }
         Api.asc_calculate(Asc.c_oAscCalculateType.ActiveSheet);
    } catch (error) {
        console.error("executeAndUpdateHtgQuery() тест не пройден:", error);
    }
    console.log("SliderDataSDK тест гетерогенных запросов пройден!");
}

//Заполнение заголовка таблицы
function fillHeader(headerData){      
    if(headerData){
        let worksheet=Api.GetActiveSheet();                                        
        let rowIdx=1;
        let colIdx=1;
        for(let row of headerData){                                
            worksheet.GetCells(rowIdx,colIdx).SetValue(row);
            colIdx++;            
        }
    }
}


//Заполнение данных таблицы
function fillData(sheetData){    
    if(sheetData){
        let worksheet=Api.GetActiveSheet();                                        
        let rowIdx=2;   
        for(let row of sheetData){                                
            let colIdx=1;
            for(let cell in row){
                worksheet.GetCells(rowIdx,colIdx).SetValue(row[cell]);
                colIdx++;
            }
            rowIdx++;
        }
    }
}
 
//Простой вариант проверки с логирование
function assert(condition, message) {
    if (!condition) {
        console.error("Тест провален: " + message);
    }
    else {
        console.log("Тест пройден: " + message);
    }
}


//Вывод окна сообщения пользователю
function messageWindow(title,textMessage){
    Common.UI.alert(
            {
                title: title,
                msg: textMessage,
                width: "auto",            
                closable: true            
            });
}
Приложение 3. Полный текст кода макроса «Тест ExternalXLSX (ExcelJS)»
// Убедитесь, что библиотеки ExcelJS и jQuery (или библиотека, предоставляющая $ajax) загружены.
(function(){
    if(Common.R7ConsultLibs)        
        if(Common.R7ConsultLibs.SliderDataSDK&&Common.R7ConsultLibs.SliderDataSDK.ExternalXLSXProxy){
            console.info("We have SliderDataSDK.ExternalXLSXProxy library!");            
            let extApi=Common.R7ConsultLibs.SliderDataSDK.ExternalXLSXProxy;            
            extApi.init();
            let idFile='test.xlsx';
            let url="file:\\\\C:\Projects\\test.xlsx";  

            /* download data into an ArrayBuffer object */
            loadAndProcessFile(extApi,idFile,url);          
        }            
})();

// Загрузка рабочей книги из URL (асинхронно)
async function loadAndProcessFile(extApi,idFile,pathToFile) {
  try {
    await extApi.loadWorkbookFromUrl(idFile, pathToFile);


    // Теперь вы можете работать с загруженной книгой
    const sheetData = extApi.readSheet(idFile, 'Лист1');
     if(sheetData){
        let worksheet=Api.GetActiveSheet();                                        
        let rowIdx=1;    
        for(let row of sheetData){                                
            for(let colIdx=1;colIdx<=row.length;colIdx++){
                worksheet.GetCells(rowIdx,colIdx).SetValue(row[colIdx-1]);
            }
            rowIdx++;
        }
        let cellA1=extApi.readCell(idFile, 'Лист1','R1C1');
        messageWindow("Тестирования считывания ячейки A1",cellA1);

        Api.asc_calculate(Asc.c_oAscCalculateType.ActiveSheet);
        }
    extApi.unloadWorkbook(idFile); // Выгрузить из кеша после использования
  } catch (error) {
    console.error("Ошибка при загрузке или обработке файла:", error);
  }
}

function messageWindow(title,textMessage){
    Common.UI.alert(
            {
                title: title,
                msg: textMessage,
                width: 600,            
                closable: true            
            });
}
Приложение 4. Полный текст кода макроса «Тест AlaSQL»
// Убедитесь, что библиотеки AlaSQL и jQuery (или библиотека, предоставляющая $ajax) загружены.
(function(){
    if(Common.R7ConsultLibs)                
        if(Common.R7ConsultLibs.SliderDataSDK&&Common.R7ConsultLibs.SliderDataSDK.AlaSQLProxy){            
            console.info("We have SliderDataSDK.AlaSQLProxy library!");
            let extApi=Common.R7ConsultLibs.SliderDataSDK.AlaSQLProxy;
            messageWindow("Внимание",`SliderDataSDK ver.(${Common.R7ConsultLibs.SliderDataSDK.getVersion()})\nРезультаты всех тестов можно посмотреть в консоли отладчика!`)             
            runAllTests(extApi);          
        }            
})();

// Простая функция для утверждений
function assert(condition, message) {
  if (condition) {
    console.log("Тест пройден: " + message);
  } else {
    console.error("Тест не пройден: " + message);
  }
}

// Функция для глубокого сравнения объектов/массивов
function deepEqual(a, b) {
    if (a === b) return true;
    if (a == null || typeof a != "object" ||
        b == null || typeof b != "object") return false;

    if (Array.isArray(a) !== Array.isArray(b)) return false;
    if (Array.isArray(a)) {
        if (a.length !== b.length) return false;
        for (let i = 0; i < a.length; i++) {
            if (!deepEqual(a[i], b[i])) return false;
        }
        return true;
    }
    const keysA = Object.keys(a);
    const keysB = Object.keys(b);

    if (keysA.length !== keysB.length) return false;
    for (const key of keysA) {
        if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
    }
    return true;
}

// Тесты для основных операций с базой данных
async function testBasicDatabaseOperations(AlaSQLProxy) {
  console.log("Запуск тестов для основных операций с базой данных...");

  // Тест: выполнение базового запроса
  console.log(" Тест: выполнение базового запроса");
  try {
    const result = await AlaSQLProxy.executeQuery('SELECT 1 + 1');
    assert(deepEqual(result, [{ '1 + 1': 2 }]), 'Должен выполнять базовый запрос "SELECT 1 + 1"');
  } catch (error) {
    console.error("Ошибка при выполнении базового запроса:", error);
    assert(false, 'Должен выполнять базовый запрос');
  }
  // Тест: создание и использование базы данных
  console.log(" Тест: создание и использование базы данных");
  try {
    await AlaSQLProxy.createLocalStorageDatabase('testdb');
    const result =await AlaSQLProxy.attachLocalStorageDatabase('testdb');    
    assert(result===1, 'Должен создавать и использовать базу данных');
  } catch (error) {
    console.error("Ошибка при создании и использовании базы данных:", error);
    assert(false, 'Должен создавать и использовать базу данных');
  } finally {
     // Очистка: удаление тестовой базы данных
    try {
       await AlaSQLProxy.dropLocalStorageDatabase('testdb');
    } catch (error) {
      console.error("Ошибка при очистке тестовой базы данных:", error);
    }
  }
  // Тест: создание таблицы
  console.log(" Тест: создание таблицы");
  try {
    await AlaSQLProxy.createLocalStorageDatabase('testdb');
    await AlaSQLProxy.attachLocalStorageDatabase('testdb');
    await AlaSQLProxy.useDatabase('testdb');
    await AlaSQLProxy.createTable('users', 'id INT, name STRING');
    // Проверка создания таблицы путем попытки вставки данных
    const insertResult = await AlaSQLProxy.insertInto('users',[{id:1,name:'Тестовый пользователь 1'}]);
    assert(insertResult === 1, 'Должен создавать таблицу');
    const selectResult = await AlaSQLProxy.executeQuery('SELECT * FROM users');
    console.log('Должен правильно выбирать вставленные данные',selectResult);
  } catch (error) {
    console.error("Ошибка при создании таблицы:", error);  
  } finally {
     // Очистка: удаление тестовой базы данных
    try {
       await AlaSQLProxy.dropLocalStorageDatabase('testdb');
    } catch (error) {
      console.error("Ошибка при очистке тестовой базы данных:", error);
    }
  }

  // Тест: вставка нескольких строк в таблицу
  console.log(" Тест: вставка нескольких строк в таблицу");
  try {
    await AlaSQLProxy.createLocalStorageDatabase('testdb');
    await AlaSQLProxy.attachLocalStorageDatabase('testdb');
    await AlaSQLProxy.useDatabase('testdb');
    await AlaSQLProxy.createTable('other', 'id INT, name STRING');

    const dataToInsert = [{id:3,name:'Пользователь 2'},{id:4,name:'Пользователь 3'}];    
    //debugger;
    const insertResult = await AlaSQLProxy.insertInto('other', dataToInsert);
    assert(insertResult === 2, 'Должен вставлять 2 строки в таблицу');
    const selectResult = await AlaSQLProxy.executeQuery('SELECT * FROM other');
    console.log('Должен правильно выбирать вставленные данные',selectResult);
  } catch (error) {
    console.error("Ошибка при вставке нескольких строк в таблицу:", error);    
  } finally {
     //  await AlaSQLProxy.detachDatabase('testdb');
     //Очистка: удаление тестовой базы данных
    try {      
      await AlaSQLProxy.dropLocalStorageDatabase('testdb');
    } catch (error) {
      console.error("Ошибка при очистке тестовой базы данных:", error);
    }
  }
  console.log("Тесты основных операций с базой данных завершены.");
}

// Тесты для операций с массивами и Excel
async function testArrayAndExcelOperations(AlaSQLProxy) {
  const filePath ="file:\\\\C:\Projects\\test.xlsx";
  const sheetName = 'Лист1';
  console.log("Запуск тестов для операций с массивами и Excel...");


  // Тест: выборка данных из двухмерного массива
  try {
    const data = [
      [1, 'Яблоко', 0.5],
      [2, 'Банан', 0.3],
      [3, 'Вишня', 0.8]
    ];
    const query = 'SELECT [0] AS id, [1] AS name FROM ? WHERE [2] > 0.4';
    const result = await AlaSQLProxy.selectFromArray(data, query);    
    console.log(`выборка данных из двухмерного массива`, result);
  } catch (error) {
    console.error("Ошибка при выборке данных из двухмерного массива:", error);    
  }

  // Тесты для функций Excel
  // Тест: должен формировать правильный запрос для чтения файла Excel
  try {      
    let received =await AlaSQLProxy.readExcel(filePath, sheetName);
    console.log(`должен формировать правильный запрос для чтения файла Excel`, received);    
  } catch (error) {
     console.error("Ошибка при тестировании формирования запроса для чтения файла Excel:", error);
     assert(false, 'Должен формировать правильный запрос для чтения файла Excel');
  }

   // Тест: должен формировать правильный запрос для чтения файла Excel без имени листа
  try {      
    let received =await AlaSQLProxy.readExcel(filePath);
    console.log(`должен формировать правильный запрос для чтения файла Excel без имени листа`, received);
  } catch (error) {
     console.error("Ошибка при тестировании формирования запроса для чтения файла Excel без имени листа:", error);
     assert(false, 'Должен формировать правильный запрос для чтения файла Excel без имени листа');
  }
  // Тест: должен формировать правильный запрос для записи в файл Excel
  try {
    const fileOutPath = 'output.xlsx';
    const sheetNameOut = 'Лист1';    
    const data = [['Заголовок1', 'Заголовок2'], [1, 'Данные1'], [2, 'Данные2']];
    const result =await AlaSQLProxy.writeExcel(fileOutPath, data, sheetNameOut);
    console.log(`должен формировать правильный запрос для записи в файл Excel`, result);   
  } catch (error) {
     console.error("Ошибка при тестировании формирования запроса для записи в файл Excel:", error);
     assert(false, 'Должен формировать правильный запрос для записи в файл Excel');
  }

//    // Тест: должен формировать правильный запрос для записи в файл Excel без имени листа
//   try {
//     const fileOutPath =  'output.xlsx';;
//     const data = [['Заголовок1', 'Заголовок2'], [1, 'Данные1'], [2, 'Данные2']];  
//     const result = await AlaSQLProxy.writeExcel(fileOutPath, data);
//     console.log(`должен формировать правильный запрос для записи в файл Excel без имени листа`, result);
//   } catch (error) {
//      console.error("Ошибка при тестировании формирования запроса для записи в файл Excel без имени листа:", error);
//      assert(false, 'Должен формировать правильный запрос для записи в файл Excel без имени листа');
//   }

  // Тест: должен формировать правильный запрос для получения имен листов Excel
  try {        
    const sheetNames = await AlaSQLProxy.getExcelSheetNames(filePath);
     console.log(`должен формировать правильный запрос для получения имен листов Excel`, sheetNames);
  } catch (error) {
     console.error("Ошибка при тестировании формирования запроса для получения имен листов Excel:", error);
     assert(false, 'Должен формировать правильный запрос для получения имен листов Excel');
  }

  // Тест: должен формировать правильный запрос для выполнения запроса к файлу Excel
  try {    
    const coreQuery = 'WHERE id = 1';
    const result =await AlaSQLProxy.executeQueryOnExcel(filePath, coreQuery);
    console.log(`должен формировать правильный запрос для выполнения запроса к файлу Excel`, result);
  } catch (error) {
     console.error("Ошибка при тестировании формирования запроса к файлу Excel:", error);
     assert(false, 'Должен формировать правильный запрос для выполнения запроса к файлу Excel');
  }  
  console.log("Тесты операций с массивами и Excel завершены.");
}

// Запуск всех тестов
async function runAllTests(AlaSQLProxy) {
  //await testBasicDatabaseOperations(AlaSQLProxy);
  await testArrayAndExcelOperations(AlaSQLProxy);
  console.log("Все тесты AlaSQLProxy завершены.");
}
function messageWindow(title,textMessage){
    Common.UI.alert(
            {
                title: title,
                msg: textMessage,
                width: 600,            
                closable: true            
            });
}
Приложение 5. Полный текст кода макроса «Тест UserGUIHelper»
/*
 Тесты для JavaScript библиотеки SliderDataSDK (для браузера) для простых SQL запросов к СУБД.
 */
 var userHelper=null;
 var currentMenu=null;
 (function(){
         if(Common.R7ConsultLibs){
         if(Common.R7ConsultLibs.SliderDataSDK&&Common.R7ConsultLibs.SliderDataSDK.UserGUIHelper){
             userHelper=Common.R7ConsultLibs.SliderDataSDK.UserGUIHelper;
             if(userHelper){
                 userHelper.ui=Common.UI;                
                 MainLevelMenu ();          
             }            

         }
         else{
             messageWindow("Внимание!",`Библиотека SliderDataSDK не загружена!`);
         }
     }else{
         messageWindow("Внимание!",`R7ConsultLibs не загружен!`);
     }  
 })();

 function MainLevelMenu()
 {
     if(!userHelper)
         return;
     if(currentMenu)
         currentMenu.close();
     currentMenu=Common.UI.alert(
     {
         title: "Главное меню:",
         msg: "Выберите набор тестов библиотеки SliderDataSDK.UserGUIHelper",
         resizable: true,
         width: 300,
         buttons: [
         {
             caption: "Простые окна",
             value: "SimpleWindows"
         },
         {
             caption: "Ввод данных",
             value: "InputData"
         },      
         ],
         primary: "no",
         closable: true,
         callback: MainLevelMenuFunc,
     });
 }

 function MainLevelMenuFunc(value)
 {  
     switch(value){
         case "SimpleWindows":
             SimpleWindows_LevelMenu();
             break;
         case "InputData":
             InputWindows_LevelMenu();
             break;      
     }        
 }

 function SimpleWindows_LevelMenu()
 {
     if(!userHelper)
         return;
     if(currentMenu)
         currentMenu.close();
     currentMenu=Common.UI.alert(
     {
         title: "Меню информационных окон:",
         msg: "Выберите из набор тестов для информирующих окон",
         resizable: true,
         width: "800",
         buttons: [
         {
             caption: "Назад",
             value: "mainLevelMenu"
         },
         {
             caption: "Простое окно",
             value: "allertWindow"
         },
         {
             caption: "Окно подтверждения",
             value: "confirmWindow"
         },
         {
             caption: "Окно предупреждения",
             value: "warningWindow"
         },        
         {
             caption: "Окно ошибки",
             value: "errorWindow"
         },
         {
             caption: "Окно информации",
             value: "infoWindow"
         },        
         {
             caption:"Кастомное",
             value: "customWindow"
         },
         ],
         primary: "no",
         closable: true,
         callback: SimpleWindows_MenuFunc,
     });
 }

 function SimpleWindows_MenuFunc(value)
 {    
     switch(value){
         case "mainLevelMenu":
             MainLevelMenu();
             break;
         case "confirmWindow":
             userHelper.confirmWindow("Подтверждение",onCloseSimpleWindow);
             break;
         case "warningWindow":
             userHelper.warningWindow("ВНИМАНИЕ!",onCloseSimpleWindow);
             break;
         case "allertWindow":
             userHelper.alertWindow("Моё окно","Мое сообщение!",onCloseSimpleWindow);
             break;
         case "errorWindow":
             userHelper.errorWindow("Моя ошибка!",onCloseSimpleWindow);
             break;
         case "infoWindow":
             userHelper.infoWindow("Моя информация!",onCloseSimpleWindow);
             break;
         case "customWindow":
             userHelper.withOneButtonWindow("Кастомное окно","Мое сообщение","Закрыть",200,200,onCloseSimpleWindow);
             break;
     }        
 }


 function onCloseSimpleWindow(){
    SimpleWindows_LevelMenu();    
 }

 function InputWindows_LevelMenu()
 {
     if(!userHelper)
         return;
     if(currentMenu)
         currentMenu.close();
     currentMenu=Common.UI.alert(
     {
         title: "Меню окон ввода:",
         msg: "Выберите из набора тестов для окон ввода",
         resizable: true,
         width: "300",
         buttons: [
         {
             caption: "Назад",
             value: "mainLevelMenu"
         },
         {
             caption: "Окно ввода",
             value: "inputTextWindow"
         },
         // {
         //     caption: "Окно предупреждения",
         //     value: "warningWindow"
         // },
         // {
         //     caption: "Окно опасности",
         //     value: "allertWindow"
         // },
         // {
         //     caption: "Окно ошибки",
         //     value: "errorWindow"
         // },
         // {
         //     caption: "Окно информации",
         //     value: "infoWindow"
         // },
          ],
         primary: "no",
         closable: true,
         callback: InputWindows_MenuFunc,
     });
 }

 function InputWindows_MenuFunc(value)
 {    
     switch(value){
         case "mainLevelMenu":
             MainLevelMenu();
             break;
         case "inputTextWindow":
             userHelper.userInputWindow("Введите данные","Ваше имя (результат в консоли):",200,100,(val)=>{console.log(val);},onCloseInputWindows);
             break;
         //case "warningWindow":
         //       userHelper.withOneButtonWindow("Введите данные","Ваше имя (результат в консоли):",200,100,(val)=>{console.log(val);},onCloseInputWindows);
         //     userHelper.warningWindow("ВНИМАНИЕ!",onCloseSimpleWindow);
         //     break;
         // case "allertWindow":
         //     userHelper.alertWindow("Мое предупреждение!",onCloseSimpleWindow);
         //     break;
         // case "errorWindow":
         //     userHelper.errorWindow("Моя ошибка!",onCloseSimpleWindow);
         //     break;
         // case "infoWindow":
         //     userHelper.infoWindow("Моя информация!",onCloseSimpleWindow);
         //     break;
     }        
 }

 function onCloseInputWindows(){
    InputWindows_LevelMenu();    
 }

 //Вывод окна сообщения пользователю
 function messageWindow(title,textMessage){
     Common.UI.alert(
             {
                 title: title,
                 msg: textMessage,
                 width: "auto",            
                 closable: true            
             });
 }
Приложение 6. Полный список методов класса XLDBProxy.js
1. Управление параметрами и конфигурацией

1.1 defaultOptions
Назначение: Объект с настройками подключения к прокси-серверу по умолчанию.
Структура:
  • protocol (string): Протокол подключения ("http://")
  • host` (string): IP-адрес или доменное имя сервера ("127.0.0.1")
  • port (string): Порт сервера ("55080")
1.2 newParams()
  • Назначение: Создаёт пустой объект-шаблон для параметров подключения к СУБД.
  • Описание: Возвращает стандартизированный объект, поля которого используются в качестве параметров в URL-запросах к прокси-серверу.
  • Параметры: Нет
  • Возвращаемое значение: object — объект с пустыми полями (engine, database, user, password и др.)

1.3 htgParams()
  • Назначение: Создаёт объект с параметрами по умолчанию для работы с гетерогенными запросами (HTG).
  • Описание: Возвращает предопределённый набор параметров для выполнения операций с HTG.
  • Параметры: Нет
  • Возвращаемое значение: object — объект с параметрами для HTG

1.4 copyOnlyNeedParametrs(objToCopy)
  • Назначение: Копирует и преобразует параметры из пользовательского объекта в стандартный формат.
  • Описание: Функция-адаптер, которая принимает объект с произвольными именами полей (например, из UI) и сопоставляет их со стандартными полями, используемыми в API (namedb → database, typedb → engine и т.д.).
Параметры:
Имя
Тип
Описания
Обязательный
objToCopy

object

Объект с пользовательскими параметрами подключения

Да
Возвращаемое значение: object - стандартизированный объект параметров
1.5 loadParametrsFromLocalStorage()
  • Назначение: Загружает и кеширует параметры подключений из localStorage.
  • Описание: Ищет в localStorage ключ xldbCommStateConnect, парсит его и сохраняет все найденные подключения во внутренний кеш paramsCache.
  • Параметры: Нет
  • Возвращаемое значение: void
1.6 loadParametrsFromFile(filePath)
  • Назначение: Загружает и кеширует параметры подключений из файла.
  • Описание: Асинхронно загружает JSON-файл (.con), содержащий список подключений, и добавляет их в кеш.
  • Параметры:
Имя
Тип
Описания
Обязательный
filePath

string

Путь к файлу конфигурации

Да
Возвращаемое значение: void
1.7 loadParametrsFromServer()

  • Назначение: Загружает и кеширует параметры подключений с прокси-сервера.
  • Параметры: Нет
  • Возвращаемое значение: Promise<void>.
2. Основные методы API

2.1 checkConnection(paramsName, options)
  • Назначение: Проверяет доступность и корректность подключения к базе данных. Использует кешированные параметры по paramsName.
  • Параметры:
Имя
Тип
Описания
Обязательный
options

object

Объект для переопределения или добавления параметров запроса

Нет
Возвращаемое значение: Promise<object> — промис, разрешающийся с JSON-ответом от сервера. В случае ошибки выбрасывает исключение.

Пример использования:
XLDBProxy.checkConnection("MyPostgresDB")
  .then(response => {
    console.log("Соединение успешно:", response);
  })
  .catch(error => {
    console.error("Ошибка соединения:", error);
  •   });
2.2 getTables(paramsName, options)

  • Назначение: Получает список таблиц из указанной схемы базы данных.
  • Параметры:
Имя
Тип
Описания
Обязательный
paramsName

string

Имя подключения из кеша

Да
options

object

Дополнительные параметры (например, { schema: 'public' })

Нет
Возвращаемое значение:Promise<object> — промис с ответом сервера, содержащим список таблиц в поле data.

Пример использования:
XLDBProxy.getTables("MyPostgresDB", { schema: 'public' })
  .then(response => {
    const tables = XLDBProxy.getData(response);
    console.log("Таблицы:", tables);
  });
2.3 getViews(paramsName, options)

  • Назначение: Получает список представлений (views) из указанной схемы.
  • Параметры:
Имя
Тип
Описания
Обязательный
paramsName

string

Имя подключения из кеша

Да
options

object

Дополнительные параметры (например, { schema: 'public' })

Нет
Возвращаемое значение: Promise<object> — промис с ответом сервера
2.4 getFields(paramsName, options)

  • Назначение: Получает список полей (столбцов) для указанной таблицы или представления.
  • Параметры:
Имя
Тип
Описания
Обязательный
paramsName

string

Имя подключения из кеша

Да
options

object

Обязательно должен содержать relation_name (имя таблицы) и relation_schema

Да
Возвращаемое значение: Promise<object> — промис с ответом сервера, содержащим список полей.

Пример использования:
XLDBProxy.getFields("MyPostgresDB", {
      relation_schema: 'public',
      relation_name: 'users'
    })
    .then(response => {
      const fields = XLDBProxy.getData(response);
      console.log("Поля таблицы 'users':", fields);
    });
2.5 executeQuery(paramsName, options)

  • Назначение: Выполняет произвольный SQL-запрос.
  • Описание: Основной метод для выполнения запросов к СУБД через прокси-сервер.
  • Параметры:
Имя
Тип
Описания
Обязательный
paramsName

string

Имя подключения из кеша

Да
options

object

Обязательно должен содержать поле query с текстом SQL-запроса

Да
Возвращаемое значение: Promise<object> — промис с результатом выполнения запроса

Пример использования:
const sql = "SELECT id, name FROM users WHERE age > 30";
XLDBProxy.executeQuery("MyPostgresDB", { query: sql })
  .then(response => {
    const { header, data } = XLDBProxy.getColumnsAndData(response);
    console.log("Заголовки:", header);
    console.log("Данные:", data);
  });
3. Гетерогенные запросы (HTG)
HTG - это специфическая функциональность прокси-сервера, позволяющая создавать, регистрировать и выполнять сложные именованные запросы, которые могут объединять данные из разных источников.

3.1 loadHTGConnectionsFromServer()
  • Назначение: Загружает с сервера и кеширует список всех зарегистрированных HTG-отношений.
  • Описание: Инициализирует кеш HTG-отношений для последующего использования в других методах.
  • Параметры: Нет
  • Возвращаемое значение: Promise<void>
3.2 hasHTGRelations(nameHTGRelation)

  • Назначение: Проверяет, зарегистрировано ли на сервере HTG-отношение с указанным именем.
  • Описание: При первом вызове может инициировать загрузку списка HTG с сервера.
  • Параметры:
Имя
Тип
Описания
Обязательный
nameHTGRelation

string

Имя HTG-отношения для проверки

Да
Возвращаемое значение: Promise<boolean> - true, если отношение существует
3.3 loadHTGFields(nameHTGRelation)

  • Назначение: Загружает и кеширует метаданные (поля) для указанного HTG-отношения.
  • Описание: Получает структуру полей HTG-отношения для использования в запросах.
  • Параметры:
Имя
Тип
Описания
Обязательный
nameHTGRelation

string

Имя HTG-отношения

Да
Возвращаемое значение:Promise<boolean> - true в случае успеха
3.4 registerHTGRelation(options)

  • Назначение: Регистрирует новое HTG-отношение на сервере.
  • Описание: Отправляет запрос на `/registerHTGRelation` для создания нового именованного запроса.
  • Параметры:
Имя
Тип
Описания
Обязательный
options

object

Объект с параметрами для регистрации, включая relation_name и query

Да
Возвращаемое значение: Promise<object> - ответ сервера
3.5 unregisterHTGRelation(options)

  • Назначение: Удаляет (отменяет регистрацию) HTG-отношение на сервере.
  • Описание: Отправляет запрос на `/unregisterHTGRelation` для удаления именованного запроса.
  • Параметры:
Имя
Тип
Описания
Обязательный
options

object

Должен содержать relation_name для удаления

Да
Возвращаемое значение: Promise<object> - ответ сервера
3.6 executeAndUpdateHtgQuery(options)

  • Назначение: Выполняет HTG-запрос и опционально обновляет его.
  • Описание: Отправляет запрос на `/executeAndUpdateHtgQuery` для выполнения или обновления HTG-запроса.
  • Параметры:
Имя
Тип
Описания
Обязательный
options

object

Должен содержать relation_name и, возможно, новый query для обновления

Да
Возвращаемое значение: Promise<object> - результат выполнения HTG-запроса
4. Вспомогательные методы
4.1 getColumns(response)

  • Назначение: Извлекает из ответа сервера массив с именами колонок.
  • Описание: Парсит структуру ответа и возвращает только имена колонок для удобства работы с результатами запросов.
  • Параметры:
Имя
Тип
Описания
Обязательный
response

object

Ответ сервера

Да
Возвращаемое значение: array - массив с именами колонок
4.2 getData(response)

  • Назначение: Извлекает из ответа сервера массив с данными.
  • Описание: Парсит структуру ответа и возвращает только данные без метаинформации.
  • Параметры:
Имя
Тип
Описания
Обязательный
response

object

Ответ сервера

Да
Возвращаемое значение: array - массив с данными
4.3 getColumnsAndData(response)

  • Назначение: Возвращает объект с двумя полями: header (колонки) и data (данные).
  • Описание: Комбинирует функциональность getColumns и getData для удобного получения полной информации о результате запроса.
  • Параметры:
Имя
Тип
Описания
Обязательный
response

object

Ответ сервера

Да
Возвращаемое значение: object - объект с двумя полями: header и data
4.4 getError(response, stackLevel)

  • Назначение: Проверяет наличие ошибки в ответе сервера и, если она есть, выбрасывает исключение с подробным описанием.
  • Описание: Анализирует ответ сервера на наличие ошибок и формирует детальное сообщение об ошибке для отладки.
  • Параметры:
Имя
Тип
Описания
Обязательный
response

object

Ответ сервера

Да
stackLevel

number

Уровень в стеке вызовов для получения имени функции

Нет
Возвращаемое значение: void
4.5 getCallerName(level)

  • Назначение: Вспомогательная функция для отладки, возвращает имя функции из стека вызовов.
  • Описание: Используется для получения контекстной информации при обработке ошибок и отладке.
  • Параметры:
Имя
Тип
Описания
Обязательный
level

number

Уровень в стеке вызовов для получения имени функции

Нет
Возвращаемое значение: string - имя функции из стека вызовов
Приложение 7. Полный список методов класса AlaSQLProxy.js
1 Методы API
1.1 executeQuery(query, params)

  • Назначение: Выполняет SQL-запрос с использованием AlaSQL.
  • Описание: Основная функция-обертка для выполнения любого SQL-запроса. Она принимает строку запроса и опциональные параметры, возвращая результат выполнения в виде промиса.
  • Параметры:
Имя
Тип
Описания
Обязательный
query

string

Строка SQL-запроса для выполнения

Да
params

Array<any>

Массив параметров для подстановки в SQL-запрос

Нет
Возвращаемое значение: Promise<any> - промис, который разрешается с результатом выполнения запроса. В случае ошибки промис будет отклонен

Пример использования:
AlaSQLProxy.executeQuery("SELECT * FROM MyTable WHERE id = ?", [1])
  .then(result => {
    console.log("Найдена запись:", result);
  })
  .catch(error => {
    console.error("Ошибка выполнения запроса:", error);
  });
1.2 createLocalStorageDatabase(dbName)

  • Создает новую или подключается к существующей базе данных в localStorage.
  • Описание: Использует синтаксис CREATE localStorage DATABASE для создания постоянной базы данных в хранилище браузера.
  • Параметры:
Имя
Тип
Описания
Обязательный
dbName

string

Имя создаваемой базы данных

Да
Возвращаемое значение: Promise<void> — промис, который разрешается после успешного создания базы данных.

Пример использования:
AlaSQLProxy.createLocalStorageDatabase("MyLocalDB")
  .then(() => {
    console.log("База данных 'MyLocalDB' успешно создана.");
  });
1.3 attachLocalStorageDatabase(dbName)

  • Описание: Присоединяет существующую базу данных из localStorage для выполнения запросов.. Делает базу данных доступной для последующих операций USE.
  • Параметры:
Имя
Тип
Описания
Обязательный
dbName

string

Имя присоединяемой базы данных

Да
Возвращаемое значение: Promise<void> — промис, который разрешается после успешного присоединения.

Пример использования:
AlaSQLProxy.attachLocalStorageDatabase("MyLocalDB")
  .then(() => {
    console.log("База данных 'MyLocalDB' присоединена.");
  });
1.4 dropLocalStorageDatabase(dbName)

  • Описание: Полностью удаляет указанную базу данных и все её таблицы из хранилища браузера.
  • Параметры:
Имя
Тип
Описания
Обязательный
dbName

string

Имя удаляемой базы данных

Да
Возвращаемое значение: Promise<void> — промис, который разрешается после успешного удаления.

Пример использования:
AlaSQLProxy.dropLocalStorageDatabase("MyLocalDB")
  .then(() => {
    console.log("База данных 'MyLocalDB' удалена.");
  });
1.5 detachDatabase(dbName)

  • Описание: Отсоединяет базу данных от текущего сеанса AlaSQL. Данные остаются в localStorage, но база данных становится недоступной для запросов до следующего ATTACH.
  • Параметры:
Имя
Тип
Описания
Обязательный
dbName

string

Имя отсоединяемой базы данных

Да
Возвращаемое значение: Promise<void> — промис, который разрешается после успешного отсоединения.

Пример использования:
AlaSQLProxy.detachDatabase("MyLocalDB")
  .then(() => {
    console.log("База данных 'MyLocalDB' отсоединена.");
  });
1.6 useDatabase(dbName)

  • Устанавливает указанную базу данных как текущую для выполнения последующих запросов.
  • Описание: Аналог USE database в стандартном SQL. Все последующие операции с таблицами будут выполняться в контексте этой базы данных.
  • Параметры:
Имя
Тип
Описания
Обязательный
dbName

string

Имя базы данных для использования

Да
Возвращаемое значение: Promise<void> — промис, который разрешается после успешной смены контекста.

Пример использования:
AlaSQLProxy.useDatabase("MyLocalDB")
  .then(() => {
    console.log("Теперь используется база данных 'MyLocalDB'.");
  •   });
1.7 createTable(tableName, columnsDefinition)

  • Создает новую таблицу в текущей базе данных.
  • Описание: Выполняет запрос CREATE TABLE IF NOT EXISTS. Если таблица с таким именем уже существует, операция не выполняется.
  • Параметры:
Имя
Тип
Описания
Обязательный
tableName

string

Имя создаваемой таблицы

Да
columnsDefinition

string

Определение столбцов в формате SQL (например, "id INT, name STRING").

Да
Возвращаемое значение: Promise<void> — промис, который разрешается после создания таблицы.

Пример использования:
AlaSQLProxy.createTable("Users", "id INT, name STRING, email STRING")
  .then(() => {
    console.log("Таблица 'Users' создана.");
  });
1.8 insertInto(tableName, values)

  • Вставляет данные в указанную таблицу.
  • Описание: Функция использует синтаксис INSERT INTO ... SELECT * FROM ? для вставки массива объектов или массива массивов.
  • Параметры:
Имя
Тип
Описания
Обязательный
tableName

string

Имя таблицы для вставки

Да
values

Array

Данные для вставки

Да
Возвращаемое значение: Promise<void> — промис, который разрешается после вставки данных.

Пример использования:
const newUsers = [
    { id: 1, name: "John Doe", email: "john@example.com" },
    { id: 2, name: "Jane Doe", email: "jane@example.com" }
  ];
  AlaSQLProxy.insertInto("Users", newUsers)
    .then(() => {
      console.log("Данные успешно вставлены в таблицу 'Users'.");
    });
1.9 updateTable(tableName, values, whereClause)

  • Обновляет существующие записи в таблице.
  • Описание: Формирует и выполняет запрос UPDATE. Позволяет обновлять одно или несколько полей для записей, удовлетворяющих условию WHERE.
  • Параметры:
Имя
Тип
Описания
Обязательный
tableName

string

Имя таблицы для обновления

Да
values

object

Объект с парами "ключ-значение", где ключ — имя столбца, а значение — новое значение

Да
whereClause

string

Условие для фильтрации обновляемых записей (например, "id = 1").

Нет
Возвращаемое значение: Promise<void> — промис, который разрешается после обновления данных.

Пример использования:
AlaSQLProxy.updateTable("Users", { email: "new.email@example.com" }, "id = 1")
  .then(() => {
    console.log("Email пользователя с id=1 обновлен.");
  });
1.10 readExcel(filePath, sheetName)

  • Читает данные изфайла Excel.
  • Описание: Использует функциональность AlaSQL для прямого чтения данных из .xlsx файла.
  • Параметры:
Имя
Тип
Описания
Обязательный
filePath

string

Путь к файлу Excel.

Да
sheetName

string

Имя листа для чтения. Если не указано, читается первый лист.

Нет
Возвращаемое значение: Promise<Array<Array<any>>> — промис, который разрешается с массивом данных из листа.

Пример использования:
AlaSQLProxy.readExcel("data.xlsx", "Sheet1")
  .then(data => {
    console.log("Данные из Excel:", data);
  });
1.11 writeExcel(filePath, data, sheetName)

  • Описание: Записывает данные в файл Excel. Использует синтаксис SELECT * INTO XLSX(...) для сохранения массива данных в .xlsx файл.
  • Параметры:
Имя
Тип
Описания
Обязательный
filePath

string

Путь к файлу для записи

Да
data

Array<Array<any>>

Двумерный массив данных для записи.

Да
sheetName

string

Имя листа, в который будут записаны данные.

Нет
Возвращаемое значение: Promise<void> — промис, который разрешается после успешной записи файла.

Пример использования:
const dataToWrite = [
    ["ID", "Name"],
    [1, "Product A"],
    [2, "Product B"]
  ];
  AlaSQLProxy.writeExcel("output.xlsx", dataToWrite, "Products")
    .then(() => {
      console.log("Данные успешно записаны в output.xlsx");
    });

1.12 executeQueryOnExcel(filePath, coreQuery, params)

  • Описание: Выполняет SQL-запрос непосредственно к данным в файле Excel. Позволяет выполнять сложные SQL-запросы (фильтрация, агрегация) к данным Excel-файла, не загружая их предварительно в базу данных.
  • Параметры:
Имя
Тип
Описания
Обязательный
filePath

string

Путь к файлу Excel

Да
coreQuery

string

Основная часть SQL-запроса (например, "WHERE Category = 'Books'").

Да
params

Array<any>

Параметры для запроса.

Нет
Возвращаемое значение: Promise<any> — промис, который разрешается с результатом запроса.

Пример использования:
AlaSQLProxy.executeQueryOnExcel("sales.xlsx", "WHERE Amount > ?", [1000])
  .then(results => {
    console.log("Продажи с суммой > 1000:", results);
  });
1.13 getExcelSheetNames(filePath)

  • Описание: Получает список имен всех листов в указанном файле Excel. Выполняет специальный запрос SELECT SHEETNAMES FROM XLSX(...) для извлечения метаданных файла.
  • Параметры:
Имя
Тип
Описания
Обязательный
filePath

string

Путь к файлу Excel

Да
Возвращаемое значение: Promise<string[]> — промис, который разрешается с массивом строк, содержащих имена листов.

Пример использования:
AlaSQLProxy.getExcelSheetNames("report.xlsx")
  .then(sheetNames => {
    console.log("Имена листов:", sheetNames); // ["Summary", "Details"]
  });
1.14 selectFromArray(dataArray, query, params)

  • Выполняет SQL-запрос к массиву данных в памяти.
  • Описание: Позволяет обрабатывать JavaScript-массивы с помощью SQL-синтаксиса, используя конструкцию FROM ?.
Параметры:
Имя
Тип
Описания
Обязательный
dataArray

Array<Array<any>>

Двумерный массив данных для запроса.

Да
query

string

SQL-запрос, использующий ? в качестве источника данных (например, "SELECT * FROM ? WHERE [0] > 1").

Да
params

Array<any>

Дополнительные параметры для запроса.

Нет
Возвращаемое значение: Promise<any> — промис, который разрешается с результатом запроса.

Пример использования:
const data = [
    [1, "Apple"],
    [2, "Banana"],
    [3, "Cherry"]
  ];
  AlaSQLProxy.selectFromArray(data, "SELECT * FROM ? WHERE [0] > 1")
    .then(result => {
      console.log("Отфильтрованные данные:", result);
    });
1.15 executeQueryOnExcelSheet(filePath, sheetName, coreQuery, params)

  • Описание: Выполняет SQL-запрос к данным на определенном листе файла Excel. Аналогично executeQueryOnExcel, но позволяет явно указать лист для выполнения запроса.
Параметры:
Имя
Тип
Описания
Обязательный
filePath

string

Путь к файлу Excel.

Да
sheetName

string

Имя листа в файле Excel.

Да
coreQuery

string

Основная часть SQL-запроса.

Да
params

Array<any>

Параметры для запроса.

Нет
Возвращаемое значение: Promise<any> — промис, который разрешается с результатом запроса.

Пример использования:
AlaSQLProxy.executeQueryOnExcelSheet("report.xlsx", "Q1_Sales", "WHERE Region = ?", ["North"])
  .then(results => {
    console.log("Продажи в северном регионе за 1 квартал:", results);
  });
Приложение 8. Полный список методов класса UserGUIHelper
1 Методы API
1.1 initUI(commonUI)

  • Описание: Инициализирует класс, сохраняя ссылку на объект UI. Этот метод обязателен к вызову перед использованием любых функций, создающих окна. Он позволяет модулю взаимодействовать с API пользовательского интерфейса редактора.
Параметры:
Имя
Тип
Описания
Обязательный
commonUI

object

Объект Common.UI из API редактора.

Да
Возвращаемое значение: void

Пример использования:
// Предполагается, что parent.Common.UI доступен
UserGUIHelper.initUI(parent.Common.UI);
1.2 getVersion()

  • Описание: Служит для идентификации версии модуля при отладке. Возвращает номер версии модуля.
  • Параметры: Нет.
  • Возвращаемое значение: string — строка с номером версии (например, "0.1.3").
Пример использования:
console.log("Версия userGUIHelper:", UserGUIHelper.getVersion());
1.3 errorWindow(message, onClose)

  • Описание: Создаёт стандартное окно ошибки с иконкой и одной кнопкой "ОК". Отображает модальное окно с сообщением об ошибке.
Параметры:
Имя
Тип
Описания
Обязательный
message

string

Текст ошибки для отображения.

Да
onClose

function

Callback-функция, вызываемая при закрытии окна.

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.

Пример использования:
UserGUIHelper.errorWindow("Не удалось загрузить данные.", () => {
    console.log("Окно ошибки закрыто.");
  });
1.4 alertWindow(title, message, onClose)

  • Описание: Показывает диалоговое окно с произвольным заголовком и сообщением. Отображает модальное окно с предупреждением и заголовком.
Параметры:
Имя
Тип
Описания
Обязательный
title

string

Заголовок окна.

Да
message

string

Текст сообщения.

Да
onClose

function

Callback-функция, вызываемая при закрытии окна.

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.

Пример использования:
UserGUIHelper.alertWindow("Внимание", "Операция может занять несколько минут.");
1.5 confirmWindow(message, onClose)

  • Описание: Создаёт стандартное окно подтверждения с кнопками "ОК" и "Отмена". Отображает модальное окно для получения подтверждения от пользователя.
Параметры:
Имя
Тип
Описания
Обязательный
message

string

Вопрос или сообщение, требующее подтверждения.

Да
onClose

function

Callback-функция, вызываемая при нажатии "ОК".

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.

Пример использования:
// В коде `onClose` сработает только на 'ok'
UserGUIHelper.confirmWindow("Вы уверены, что хотите удалить элемент?", () => {
    console.log("Пользователь подтвердил удаление.");
  });
1.6 infoWindow(message, onClose)

  • Описание: Стандартное окно для информирования пользователя о каком-либо событии. Отображает информационное модальное окно.
Параметры:
Имя
Тип
Описания
Обязательный
message

string

Информационное сообщение.

Да
onClose

function

Callback-функция при закрытии.

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.

Пример использования:
UserGUIHelper.infoWindow("Операция успешно завершена.");
1.7 warningWindow(message, onClose)

  • Описание: Отображает предупреждающее модальное окно.
Параметры:
Имя
Тип
Описания
Обязательный
message

string

Текст предупреждения.

Да
onClose

function

Callback-функция при закрытии.

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.

Пример использования:
UserGUIHelper.warningWindow("Некоторые данные могут быть потеряны.");
1.8 withOneButtonWindow (titleWindow, messageForUser, ...)

  • Создаёт кастомное модальное окно с сообщением и одной кнопкой.
  • Описание: Позволяет создать простое окно с настраиваемым заголовком, текстом и кнопкой.
Параметры:
Имя
Тип
Описания
Обязательный
titleWindow

string

Заголовок окна.

Да
messageForUser

string

Основной текст сообщения в окне.

Да
buttonCaption

string

Текст на кнопке. По умолчанию "Закрыть".

Нет
wWindow

number

Ширина окна в пикселях. По умолчанию 100.

Нет
hWindow

number

Высота окна в пикселях. По умолчанию 100

Нет
onClose

function

Callback-функция при закрытии окна.

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.

Пример использования:
UserGUIHelper.withOneButtonWindow(
    "Отчет",
    "Отчет успешно сформирован и сохранен.",
    "Отлично!",
    300,
    150);
1.9 userInputWindow(titleWindow, labelForInputField, ...)

  • Описание: Создаёт модальное окно с полем для ввода текста. Удобно для запроса у пользователя короткой текстовой информации, например, имени или значения.
Параметры:
Имя
Тип
Описания
Обязательный
titleWindow

string

Заголовок окна.

Да
labelForInputField

string

Текст метки над полем ввода

Да
wWindow

number

Ширина окна. По умолчанию 200.

Нет
hWindow

number

Высота окна. По умолчанию 130

Нет
onChange

function

Callback, вызываемый при нажатии "ОК". Принимает введенное значение.

Нет
onClose

function

Callback, вызываемый при закрытии окна (любым способом).

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.

Пример использования:
UserGUIHelper.userInputWindow("Новая категория", "Введите название:", 300, 150, (value) => {
    if (value) {
      console.log("Пользователь ввел:", value);
    }
  });
1.10 userComboBoxWindow(titleWindow, labelForComboBoxField, ...)

  • Описание: Создаёт модальное окно с выпадающим списком. Используется, когда нужно предоставить пользователю выбор из нескольких предопределенных вариантов.
Параметры:
Имя
Тип
Описания
Обязательный
titleWindow

string

Заголовок окна.

Да
labelForComboBoxField

string

Текст метки над списком.

Да
stringItems

string

Строка с элементами списка
Да
symbSplit

string

Символ-разделитель для stringItems.

Да
wWindow

number

Ширина окна. По умолчанию 200.

Нет
hWindow

number

Высота окна. По умолчанию 130.

Нет
onSelect

function

Callback при нажатии "ОК". Принимает выбранное значение.

Нет
onClose

function

Callback при закрытии окна.

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.

Пример использования:
UserGUIHelper.userComboBoxWindow(
    "Выбор города",
    "Укажите ваш город:",
    "Москва;Санкт-Петербург;Казань",
    ";",
    300,
    150,
    (selectedValue) => {
      console.log("Выбран город:", selectedValue);
    }
  );
1.11 cellRegionWindow(rangeBegin, onClose)

  • Описание: Вызывает системное немодальное окно Р7 для выбора диапазона ячеек. Интегрируется со стандартным диалогом редактора для выбора ячеек на листе.
Параметры:
Имя
Тип
Описания
Обязательный
rangeBegin

string

Начальный диапазон для отображения в окне (например, "Лист1!$A$1").

Нет
onClose

function

Callback, вызываемый после выбора диапазона и закрытия окна. Принимает выбранный диапазон в виде строки.

Нет
Возвращаемое значение: void.

Пример использования:
UserGUIHelper.cellRegionWindow("Лист1!$A$1:$B$5", (selectedRange) => {
    console.log("Пользователь выбрал диапазон:", selectedRange);
  });
1.12 pathToFileWindow(ext, onClose)

  • Описание: Вызывает системный диалог выбора полного пути к файлу. Используется, когда нужно предоставить пользователю выбор файла для последующих операций с ним
Параметры:
Имя
Тип
Описания
Обязательный
ext

string

Расширение для файла (по умолчанию "*.xlsx")

Нет
onClose

function

Callback, вызываемый после выбора диапазона и закрытия окна.

Нет
Пример использования:

UserGUIHelper.pathToFileWindow("*.xlsx",
    (val)=>{
      UserGUIHelper.infoWindow(`Выбран файл:${val}`,
      onCloseInputWindows)
      });
1.13 tableDataWindow(tableData, titleWindow, messageForUser,...)

  • Создаёт модальное окно для отображения данных в виде таблицы, с возможностью сравнения двух таблиц в стандартном режиме отображения, и режиме специальном разностном (diff) режиме.
  • Описание: Эта функция позволяет вывести двумерный массив данных в удобном табличном представлении внутри модального окна. Окно содержит заголовок, опциональное сообщение над таблицей и кнопку для закрытия. Для случая, когда используется сравнение и передается второй набор данных (и заголовков), автоматически появляются:
  • Кнопка для переключения между режимами сравнения
  • В режиме diff(разностного) сравнения имеется чекбокс, который позволяет показать все строки исходной таблицы, а не только изменные, что является режимом показа по умолчанию
Параметры:
Имя
Тип
Описания
Обязательный
tableData

object

Объект с данными для таблицы. Должен содержать поля headers (массив заголовков) и rows (массив массивов со строками).

Да
titleWindow

string

Заголовок окна.

Да
messageForUser

string

Сообщение, отображаемое над таблицей.

Да
buttonCaption

string

Текст на кнопке. По умолчанию "Закрыть".

Нет
wWindow

number

Ширина окна в пикселях. По умолчанию 400.

Нет
hWindow

number

Высота окна в пикселях. По умолчанию 300.

Нет
windowStartOption

number

Объект описатель дополнительных опций для работы с таблицами

Нет
onClose

function

Callback-функция, вызываемая при закрытии окна.

Нет
Возвращаемое значение: object | null — объект окна или null, если UI не инициализирован.
Описание опций windowStartOption Данный объект позволяет указать дополнительные опции полезные для конфигурирования начального режима работы окна в случае его использования для сравнения двух таблиц, и внешнего вида самой таблицы (параметры цветов для разных частей таблиц и состояния ячеек). Объект описатель опций состоит из 2 частей:
  • comparisonMode - режим показа типа таблицы сравнения (comparisonMode==true включает при первом показе diff режим таблицы сравнения)
  • colorOptions Описание различных цветовых значений для раскраски разных элементов таблицы, в формате CSS. Можно указаывать выборочные значения, а не все. Доступны следующие переменные:
·        colorBorder:"#ddd" //цвет линий границ ячеек
·        colorHeader:"#f2f2f2" //цвет шапки таблицы
·        colorRowRule:"#f9f9f9" //цвет линейки строк
·        colorColumnsRule:"#f9f9f9" //цвет линейки столбцов
·        colorOdd:"#f9f9f9" //цвет нечетных строк
·        colorEven:"#ffffff" //цвет чётных строк
·        colorCompareError:"rgba(250,0,0,0.5)" //цвет обозначения несовпадения при сравнении
·        colorAddedError:"rgb(55, 241, 217)" //цвет добавленных строк или столбцов в diff режиме
·        colorDeletedError:"rgb(176, 241, 55)" //цвет добавленных строк или столбцов в diff режиме

Пример использования метода:
const data = {
    headers: [{title: 'Имя'}, {title: 'Возраст'}],
    rows: [
      ['Иван', 30],
      ['Мария', 25]
    ]
  };
  UserGUIHelper.tableDataWindow(
    data,
    "Список пользователей",
    "Это список зарегистрированных пользователей.",
    "OK",
    {
      comparisonMode:false,
        colorOptions{
          colorBorder:"red"  
        }
    },
    500,
    350
  );
Приложение 9. Полный список методов класса ExternalXLSXProxy
1. Методы API

1.1 getVersion()

  • Описание: Возвращает текущую версию модуля. Полезно для отладки и проверки, какая версия модуля используется.
  • Параметры: Нет
  • Возвращаемое значение: string — строка с номером версии (например, '0.4.0').
Пример использования:
const version = ExternalXLSX.getVersion();
console.log("Версия ExternalXLSXProxy:", version);
1.2 getApi()

  • Описание: Возвращает сам объект API. Может использоваться для получения ссылки на объект модуля.
  • Параметры: Нет.
  • Возвращаемое значение: object — объект ExternalXLSX.
Пример использования:
const api = ExternalXLSX.getApi();
api.init(); // Инициализация

1.3 init()


  • Описание: Инициализирует API с использованием библиотеки по умолчанию (ExcelJS). Этот метод необходимо вызвать перед использованием любых других функций модуля. Он создаёт внутренний менеджер для работы с данными.
  • Параметры: Нет.
  • Возвращаемое значение: void.
Пример использования:
ExternalXLSX.init();

1.4 initWithSheetJS()

  • Описание: Инициализирует API с использованием библиотеки SheetJS. Явно указывает модулю использовать SheetJS для всех последующих операций.
  • Параметры: Нет.
  • Возвращаемое значение: void.
Пример использования:
ExternalXLSX.initWithSheetJS();
1.5 initWithExcelJS()

  • Описание: Инициализирует API с использованием библиотеки ExcelJS. Явно указывает модулю использовать ExcelJS для всех последующих операций.
  • Параметры: Нет.
  • Возвращаемое значение: void.
Пример использования:
ExternalXLSX.initWithExcelJS();
1.6 loadWorkbook(fileID, fileData)

  • Описание: Загружает рабочую книгу из данных файла и кеширует её. Если книга с указанным fileID уже была загружена, возвращает её из кеша. В противном случае, читает данные и сохраняет книгу в памяти.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Уникальный идентификатор для кеширования книги.

Да
fileData

ArrayBuffer | string

Данные файла. ArrayBuffer является предпочтительным форматом.

Да
Возвращаемое значение: Promise<any> | any — промис, который разрешается с объектом рабочей книги (для ExcelJS), или сам объект книги (для SheetJS).

Пример использования:
// fileData - это ArrayBuffer, полученный, например, из <input type="file">
const fileID = "myReport.xlsx";
ExternalXLSX.loadWorkbook(fileID, fileData)
  .then(workbook => {
    console.log("Книга успешно загружена:", workbook);
  });
1.7 loadWorkbookFromUrl(fileID, url)

  • Описание: Асинхронно загружает рабочую книгу по URL. Выполняет AJAX-запрос для получения файла, а затем использует loadWorkbook для его обработки и кеширования.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Уникальный идентификатор для кеширования книги.

Да
url

string

URL-адрес .xlsx файла.

Да
Возвращаемое значение: Promise<any> — промис, который разрешается с объектом рабочей книги после её загрузки.

Пример использования:
const fileUrl = "https://example.com/reports/data.xlsx";
ExternalXLSX.loadWorkbookFromUrl("reportFromServer", fileUrl)
  .then(workbook => {
    console.log("Книга с сервера загружена.");
  });
1.8 getSheetsList(fileID)

  • Описание: Получает список имён всех листов в загруженной рабочей книге. Удобный метод для получения перечня доступных листов перед чтением данных.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Идентификатор ранее загруженной книги.

Да
Возвращаемое значение: Promise<string[]> — промис, который разрешается с массивом имён листов.

Пример использования:
ExternalXLSX.getSheetsList("myReport.xlsx")
  .then(sheetNames => {
    console.log("Доступные листы:", sheetNames); // ["Итоги", "Данные"]
  });
 
1.9 readSheet(fileID, sheetIdentifier)

  • Описание: Читает все данные с указанного листа. Возвращает содержимое всего листа в виде двумерного массива.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Идентификатор ранее загруженной книги.

Да
sheetIdentifier

string | number

Имя листа или его индекс (для SheetJS индекс с 0, для ExcelJS — с 1).

Да
Возвращаемое значение: Array<Array<any>> — двумерный массив, представляющий данные листа.

Пример использования:
const sheetData = ExternalXLSX.readSheet("myReport.xlsx", "Итоги");
console.log(sheetData);
1.10 readRange(fileID, sheetIdentifier, range)

  • Описание: Читает данные из указанного диапазона ячеек. Позволяет получить срез данных, не читая весь лист.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Идентификатор ранее загруженной книги.

Да
sheetIdentifier

string | number

Имя или индекс листа.

Да
range

string

Диапазон в формате A1 (например, "A1:C5").

Да
Возвращаемое значение: Array<Array<any>> — двумерный массив данных из диапазона.

Пример использования:
const rangeData = ExternalXLSX.readRange("myReport.xlsx", "Данные", "B2:D10");
console.log(rangeData);
1.11 readCell(fileID, sheetIdentifier, cellAddress)

  • Описание: Читает значение одной ячейки. Эффективный способ получить значение конкретной ячейки. Адрес может быть в формате A1 или R1C1.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Идентификатор ранее загруженной книги.

Да
sheetIdentifier

string | number

Имя или индекс листа.

Да
cellAddress

string

Адрес ячейки (например, "A1" или "R1C1").

Да
Возвращаемое значение: any — значение ячейки.

Пример использования:
const cellValue = ExternalXLSX.readCell("myReport.xlsx", "Итоги", "B5");
console.log("Значение в B5:", cellValue);
1.12 writeData(fileID, sheetIdentifier, startCellAddress, dataArray)

  • :Записывает двумерный массив данных на лист, начиная с указанной ячейки. Этот метод изменяет только внутреннее представление книги в памяти. Для сохранения изменений в файл необходимо вызвать saveWorkbook.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Идентификатор ранее загруженной книги.

Да
sheetIdentifier

string | number

Имя или индекс листа. Если лист не существует, он будет создан.

Да
startCellAddress

string

Адрес левой верхней ячейки для начала записи (например, "A1").

Да
dataArray

Array<Array<any>>

Двумерный массив данных для записи.

Да
Возвращаемое значение: void
.
Пример использования:
const newData = [
    ["Заголовок 1", "Заголовок 2"],
    [100, 200],
    [150, 250]
  ];
  ExternalXLSX.writeData("myReport.xlsx", "Новый лист", "B2", newData);
1.13 saveWorkbook(fileID)

  • Сохраняет все изменения в рабочей книге и возвращает её данные.
  • Описание: Генерирует бинарные данные .xlsx файла из текущего состояния книги в памяти.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Идентификатор книги для сохранения.

Да
Возвращаемое значение: Promise<ArrayBuffer> | ArrayBuffer — промис, разрешающийся с ArrayBuffer (для ExcelJS), или сам ArrayBuffer (для SheetJS).

Пример использования:
// После вызова writeData
Promise.resolve(ExternalXLSX.saveWorkbook("myReport.xlsx"))
  .then(fileData => {
    // fileData - это ArrayBuffer, который можно сохранить в файл
    // (например, с помощью FileSaver.js)
    const blob = new Blob([fileData], { type: "application/octet-stream" });
    // saveAs(blob, "myReport_updated.xlsx");
    console.log("Книга готова к сохранению.");
  });
1.14 unloadWorkbook(fileID)

  • Описание: Удаляет рабочую книгу из кеша. Освобождает память, занимаемую кешированной книгой.
Параметры:
Имя
Тип
Описания
Обязательный
fileID

string

Идентификатор книги для удаления из кеша.

Да
Возвращаемое значение: void.

Пример использования:
ExternalXLSX.unloadWorkbook("myReport.xlsx");
1.15 A1toR1C1(address)

  • Описание: Конвертирует адрес ячейки из формата A1 в R1C1.
Параметры:
Имя
Тип
Описания
Обязательный
address

string

Адрес в формате A1 (например, "B5").

Да
Возвращаемое значение: string — адрес в формате R1C1 (например, "R5C2").

Пример использования:
const r1c1 = ExternalXLSX.A1toR1C1("B5"); // "R5C2"
1.16 R1C1toA1(address)

  • Описание: Конвертирует адрес ячейки из формата R1C1 в A1.
Параметры:
Имя
Тип
Описания
Обязательный
address

string

Адрес в формате R1C1 (например, "R5C2").

Да
Возвращаемое значение: string — адрес в формате A1 (например, "B5").

Пример использования:
const a1 = ExternalXLSX.R1C1toA1("R5C2"); // "B5"
1.17 detectAddressType(address)

  • Определяет формат адреса ячейки (A1 или R1C1).
Параметры:
Имя
Тип
Описания
Обязательный
address

string

Адрес ячейки для проверки.

Да
Возвращаемое значение: string — либо "A1", либо "R1C1".

Пример использования:
const type1 = ExternalXLSX.detectAddressType("AZ10"); // "A1"
const type2 = ExternalXLSX.detectAddressType("R10C50"); // "R1C1"
1.18 convertAddressToA1(address)

  • Конвертирует любой адрес в формат A1.
  • Описание: Удобная утилита, которая сначала определяет тип адреса, а затем конвертирует его в A1, если это необходимо.
Параметры:
Имя
Тип
Описания
Обязательный
address

string

Адрес ячейки в формате A1 или R1C1.

Да
Возвращаемое значение: string — адрес в формате A1.

Пример использования:
const a1_1 = ExternalXLSX.convertAddressToA1("D20");     // "D20"
const a1_2 = ExternalXLSX.convertAddressToA1("R20C4");   // "D20"
1.19 convertAddressToR1C1(address)

  • Конвертирует любой адрес в формат R1C1.
  • Описание: Удобная утилита, которая сначала определяет тип адреса, а затем конвертирует его в R1C1, если это необходимо.
Параметры:
Имя
Тип
Описания
Обязательный
address

string

Адрес ячейки в формате A1 или R1C1.

Да
Возвращаемое значение: string — адрес в формате R1C1.

Пример использования:
const r1c1_1 = ExternalXLSX.convertAddressToR1C1("D20");   // "R20C4"
const r1c1_2 = ExternalXLSX.convertAddressToR1C1("R20C4"); // "R20C4"
Приложение 10. Полный список методов класса OlapProxy.js
1. Методы API

1.1 init()

  • Описание: Инициализирует API с использованием библиотеки XMLA по умолчанию. Этот метод необходимо вызвать перед использованием любых других функций модуля. Он создаёт внутренний менеджер для работы с соединениями и устанавливает обработчики ошибок.
  • Параметры: Нет.
  • Возвращаемое значение: void.
Пример использования:
SliderDataSDK.OlapProxy.init();
1.2 initWithXmla()

  • Описание: Инициализирует API с использованием библиотеки XMLA. Явно указывает модулю использовать XMLA для всех последующих операций и устанавливает специфичные настройки.
  • Параметры: Нет.
  • Возвращаемое значение: void.
Пример использования:
SliderDataSDK.OlapProxy.initWithXmla();
1.3 loadConnection(connectionID, connectionParams)

  • Описание: Загружает соединение с OLAP-сервером и кеширует его. Если соединение с указанным connectionID уже было загружено, возвращает его из кеша. В противном случае, создает новое подключение и сохраняет его в памяти.
Параметры:
Имя
Тип
Описания
Обязательный
connectionID

string

Уникальный идентификатор для кеширования соединения

Да
connectionParams

object

Параметры подключения (url, catalog, source, user, password)

Да
Возвращаемое значение: Promise<Connection> — промис, который разрешается с объектом соединения.

const connectionParams = {
    name: "Adventure Works",
    url: "http://localhost:8080/xmla",
    catalog: "Adventure Works DW 2019",
    source: "Adventure Works DW 2019",
    user: "admin",
    password: "admin"
};
SliderDataSDK.OlapProxy.loadConnection("main", connectionParams)
    .then(connection => {
        console.log("Соединение успешно загружено:", connection);
    });
1.4 executeQuery(connectionID, mdxQuery)

  • Описание: Выполняет MDX-запрос к OLAP-серверу используя указанное соединение. Возвращает результат в структурированном виде с осями, ячейками и метаданными.
Параметры:
Имя
Тип
Описания
Обязательный
connectionID

string

Идентификатор ранее загруженного соединения

Да
mdxQuery

string

MDX-запрос для выполнения

Да
Возвращаемое значение: Promise<QueryResult> — промис с результатом запроса.

Пример использования:
const mdxQuery = `
    SELECT
        [Date].[Calendar Year].Members ON 0,
        [Product].[Category].Members ON 1
    FROM [Adventure Works]
    WHERE [Measures].[Sales Amount]
`;
SliderDataSDK.OlapProxy.executeQuery("main", mdxQuery)
    .then(result => {
        console.log("Результат запроса:", result);
        console.log("Данные в табличном виде:", result.flatData);
    });

1.5 writeToActiveSheet(connectionID, mdxQuery, startCellAddress)

  • Описание: Выполняет MDX-запрос и записывает результат прямо в активный лист документа, начиная с указанной ячейки. Этот метод автоматически преобразует многомерные данные OLAP в плоскую табличную структуру.
Параметры:
Имя
Тип
Описания
Обязательный
connectionID

string

Идентификатор ранее загруженного соединения

Да
mdxQuery

string

MDX-запрос для выполнения

Да
startCellAddress

string

Адрес левой верхней ячейки для начала записи (например, "A1")

Да
Возвращаемое значение: Promise<void>.

Пример использования:
const mdxQuery = `
    SELECT
        [Date].[Calendar Year].[Calendar Year].ALLMEMBERS ON 0,
        [Product].[Category].[Category].ALLMEMBERS ON 1
    FROM [Adventure Works]
    WHERE [Measures].[Sales Amount]
`;
SliderDataSDK.OlapProxy.writeToActiveSheet("main", mdxQuery, "B2")
    .then(() => {
        console.log("Данные успешно записаны в лист");
    });
1.6 saveQueryResult(connectionID, queryID)

  • Описание: Сохраняет результат выполненного запроса и возвращает его данные в различных форматах для экспорта или дальнейшей обработки.
Параметры:
Имя
Тип
Описания
Обязательный
connectionID

string

Идентификатор соединения

Да
queryID

string

Идентификатор запроса для сохранения

Да
Возвращаемое значение: Promise<QueryExport> — промис, разрешающийся с данными для экспорта.

Пример использования:
SliderDataSDK.OlapProxy.saveQueryResult("main", "query_001")
    .then(exportData => {
        console.log("Результат готов к сохранению:", exportData);
        // exportData содержит данные в различных форматах
    });
1.7 defaultOptions

  • Описание: Объект с настройками подключения к прокси-серверу по умолчанию. Содержит параметры для формирования URL при отправке запросов.
  • Параметры: Нет (это свойство-объект).
  • Возвращаемое значение: object — объект со структурой: protocol, host, port.
Пример использования:
console.log(SliderDataSDK.OlapProxy.defaultOptions);
// { protocol: "http://", host: "127.0.0.1", port: "55080" }
1.8 newParams()

  • Описание: Создаёт пустой объект-шаблон для параметров подключения к OLAP-источнику. Возвращает стандартизированную структуру для настройки соединения.
  • Параметры: Нет.
  • Возвращаемое значение: object — объект с полями: name, catalog, source, url, user, password.
Пример использования:
const params = SliderDataSDK.OlapProxy.newParams();
console.log("Шаблон параметров:", params);
1.9 copyOnlyNeedParametrs(objToCopy)

  • Описание: Копирует только необходимые параметры из произвольного объекта в стандартизированную структуру параметров подключения.
Параметры:
Имя
Тип
Описания
Обязательный
objToCopy

object

Объект, из которого копируются значения

Да
Возвращаемое значение: object — новый стандартизированный объект параметров.

Пример использования:
const sourceObj = { name: "Test", url: "http://test.com", extraField: "ignored" };
const cleanParams = SliderDataSDK.OlapProxy.copyOnlyNeedParametrs(sourceObj);
1.10 loadParametrsFromLocalStorage()

  • Описание: Загружает икеширует параметры подключений из localStorage браузера. Ищет ключ "xldb-xmla-connections2" и сохраняет найденные подключения во внутренний кеш.
  • Параметры: Нет.
  • Возвращаемое значение: void.
Пример использования:
SliderDataSDK.OlapProxy.loadParametrsFromLocalStorage();
console.log("Параметры загружены из localStorage");
1.11 loadParametrsFromFile(filePath)

  • Описание: Асинхронно загружает параметры подключений из JSON-файла конфигурации и добавляет их в внутренний кеш параметров.
Параметры:
Имя
Тип
Описания
Обязательный
filePath

string

Путь к файлу конфигурации (например, .con файл)

Да
Возвращаемое значение: void.

Пример использования:
SliderDataSDK.OlapProxy.loadParametrsFromFile("config/connections.con");
1.12 loadParametrsFromServer()
  • Описание: Загружает и кеширует параметры подключений с сервера через GET-запрос
  • Параметры: Нет.
  • Возвращаемое значение: Promise<void>.
Пример использования:
SliderDataSDK.OlapProxy.loadParametrsFromServer()
    .then(() => {
        console.log("Параметры успешно загружены с сервера");
    });
1.13 executeQuery(connection, query, error, success)

  • Описание: Низкоуровневый метод для выполнения MDX-запроса к OLAP-серверу с пользовательскими обработчиками успеха и ошибок.
Параметры:
Имя
Тип
Описания
Обязательный
connection

object

Объект с параметрами подключения

Да
query

object

Объект, содержащий MDX-запрос в поле query

Да
error

function

Функция обратного вызова при ошибке

Да
success

function

Функция обратного вызова при успехе

Да
Возвращаемое значение: void.

Пример использования:
const connection = { /* параметры подключения */ };
const query = { query: "SELECT [Date].[Calendar Year].Members ON 0 FROM [Adventure Works]" };
SliderDataSDK.OlapProxy.executeQuery(
    connection,
    query,
    (error) => console.error("Ошибка:", error),
    (result) => console.log("Успех:", result)
);
1.14 queryStaticData(connection, query, success)

  • Описание: Высокоуровневая обертка для выполнения MDX-запроса с автоматической обработкой результата через функцию successStaticData.
Параметры:
Имя
Тип
Описания
Обязательный
connection

object

Объект с параметрами подключения

Да
query

string

Текст MDX-запроса

Да
success

function

Пользовательская функция обработки (по умолчанию OlapProxy.successStaticData)

Нет
Возвращаемое значение: void.

Пример использования:
const connection = { /* параметры подключения */ };
const mdxQuery = "SELECT [Date].[Calendar Year].Members ON 0 FROM [Adventure Works]";
SliderDataSDK.OlapProxy.queryStaticData(connection, mdxQuery);
1.15 getVersion()

  • Описание: Возвращает текущую версию подмодуля OlapProxy для диагностики и совместимости.
  • Параметры: Нет.
  • Возвращаемое значение: string — строка с номером версии.
Пример использования:
const version = SliderDataSDK.OlapProxy.getVersion();
console.log("Версия OlapProxy:", version);
Приложение 11. Типичные ошибки и их решения в SliderDataSDK
1. Модуль 1. Основы SliderDataSDK

Ошибка 1: SDK не инициализирован
// Неправильно
if(Common.R7DataConsulting.SliderDataSDK.XLDBProxy){
    // код использования
}
Решение: Проверить наличие SDK перед использованием

// Правильно
if(Common.R7DataConsulting && Common.R7DataConsulting.SliderDataSDK){
    if(Common.R7DataConsulting.SliderDataSDK.XLDBProxy){
        // код использования
    }
} else {
    messageWindow("Ошибка", "SliderDataSDK не загружен");
}


Ошибка 2: Системный плагин не установлен
Проблема: R7ConsultLibs is not defined
Решение:
  1. Убедиться, что установлен плагин "Loader SliderDataSDK (v0.1.1).plugin"
  2. Перезапустить редактор после установки
  3. Проверить список установленных плагинов в настройках

Ошибка 3: Подмодуль не загружен динамически
Проблема: Обращение к модулю до его загрузки
Решение: Использовать инициализацию SDK с ожиданием загрузки

Common.R7DataConsulting.SliderDataSDK.initSDK(['XLDBProxy'])
    .then(() => {
        // Теперь можно использовать XLDBProxy
        const proxy = Common.R7DataConsulting.SliderDataSDK.XLDBProxy;
    });
Модуль 2. XLDBProxy

Ошибка 1: Прокси-сервер недоступен
Проблема: Connection refused или timeout при вызове методов
Решение:

Ошибка 2: Неправильные параметры подключения
Проблема: Authentication failed или Invalid database
Решение: Проверить параметры в localStorage или кеше

// Проверить подключение перед основными операциями
XLDBProxy.checkConnection("MyDB")
    .then(response => {
        console.log("Соединение OK");
        // продолжить работу
    })
    .catch(error => {
        console.error("Сервер недоступен:", error);
        // показать сообщение пользователю
    });

Ошибка 3: Неправильный формат SQL-запроса
Проблема: Синтаксические ошибки в SQL
Решение: Добавить валидацию и обработку ошибок
 const sql = "SELECT id, name FROM users WHERE age > ?";
XLDBProxy.executeQuery("MyDB", { query: sql }, [25])
    .then(response => {
        const data = XLDBProxy.getData(response);
        // обработка результата
    })
    .catch(error => {
        console.error("Ошибка SQL:", error);
        messageWindow("SQL Ошибка", error.message || "Неверный запрос");
    });

Ошибка 4: HTG-запросы не найдены
Проблема: HTG relation 'test' not found
Решение:

// Сначала загрузить и проверить доступные HTG
XLDBProxy.loadHTGConnectionsFromServer()
    .then(() => {
        if(XLDBProxy.hasHTGRelations("MSSQL_HTG")) {
            // выполнить HTG запрос
        } else {
            console.error("HTG запрос 'MSSQL_HTG' не найден");
        }
    });
Модуль 3. AlaSQLProxy

Ошибка 1: AlaSQL не инициализирован
Проблема: AlaSQLProxy.alasql is undefined
Решение:
 // Проверить инициализацию перед использованием
if(!AlaSQLProxy.alasql) {
    console.error("AlaSQL не инициализирован");
    return;
}

Ошибка 2: Неправильный путь к Excel файлу
Проблема: File not found при чтении Excel
Решение:

// Использовать try-catch для обработки ошибок файлов
AlaSQLProxy.readExcel("data.xlsx", "Sheet1")
    .then(data => {
        if(data && data.length > 0) {
            console.log("Файл прочитан:", data.length, "строк");
        } else {
            console.warn("Файл пустой или не найден");
        }
    })
    .catch(error => {
        console.error("Ошибка чтения файла:", error);
        messageWindow("Ошибка", "Не удалось прочитать файл: " + error.message);
    });
Ошибка 3: Проблемы с localStorage базой данных
Проблема: Database 'MyLocalDB' already exists
Решение:

// Проверить существование БД перед созданием
AlaSQLProxy.executeQuery("SHOW DATABASES")
    .then(databases => {
        const dbExists = databases.some(db => db.name === "MyLocalDB");
        if(!dbExists) {
            return AlaSQLProxy.createLocalStorageDatabase("MyLocalDB");
        }
    })
    .then(() => {
        // продолжить работу с БД
    });

Ошибка 4: Неправильная структура данных для запросов к массиву
Проблема: Cannot read property of undefined
Решение:

// Валидация данных перед использованием
const salesData = [
    [1, 'Телефоны', 'Январь', 15, 25000],
    // ...
];



if(!Array.isArray(salesData) || salesData.length === 0) {
    console.error("Данные должны быть непустым массивом");
    return;
}

// Проверка структуры первой строки
if(!Array.isArray(salesData[0]) || salesData[0].length < 5) {
    console.error("Неправильная структура данных");
    return;
}
AlaSQLProxy.selectFromArray(salesData, "WHERE [3] > 10")
    .then(result => {
        console.log("Отфильтровано записей:", result.length);
    });
Модуль 4. UserGUIHelper

Ошибка 1: UI не инициализирован
Проблема: UserGUIHelper.ui is null
Решение:

// Всегда инициализировать UI перед использованием
if(Common.UI) {
    UserGUIHelper.initUI(Common.UI);
    // теперь можно использовать методы окон
} else {
    console.error("Common.UI недоступен");
    return;
}

Ошибка 2: Callback-функции не работают
Проблема: Функции обратного вызова не выполняются
Решение:

// Правильное использование callback
UserGUIHelper.userInputWindow("Ввод", "Введите значение:", 300, 150,
    (value) => {
        // onChange callback
        if(value && value.trim()) {
            console.log("Введено:", value);
            // обработка значения
        } else {
            messageWindow("Предупреждение", "Значение не может быть пустым");
        }
    },
    () => {
        // onClose callback
        console.log("Окно закрыто");
    }
);

Ошибка 3: Неправильные размеры окон
Проблема: Окна отображаются некорректно
Решение:
 // Использовать разумные размеры окон
const minWidth = 250;
const minHeight = 120;
UserGUIHelper.userInputWindow("Заголовок", "Текст:",
    Math.max(minWidth, 300),
    Math.max(minHeight, 150),
    callback);

Ошибка 4: Проблемы с валидацией ввода
Проблема: Некорректные данные от пользователя
Решение:    

// Добавить валидацию в callback
UserGUIHelper.userInputWindow("Email", "Введите email:", 350, 150,
    (email) => {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if(emailRegex.test(email)) {
            console.log("Email корректен:", email);
        } else {
            UserGUIHelper.errorWindow("Ошибка", "Некорректный формат email");
            // можно повторно показать окно ввода
        }
    }
);

Модуль 5. ExternalXLSXProxy

Ошибка 1: Библиотека не инициализирована
Проблема: ExternalXLSXProxy not initialized
Решение:
 // Инициализировать перед использованием
try {
    ExternalXLSXProxy.initWithExcelJS(); // или init()
    console.log("ExternalXLSXProxy инициализирован");
} catch(error) {
    console.error("Ошибка инициализации:", error);
}

Ошибка 2: Файл не найден или поврежден
Проблема: Cannot read workbook при загрузке
Решение:

// Добавить проверку файла
ExternalXLSXProxy.loadWorkbook("report.xlsx", fileData)
    .then(workbook => {
        if(!workbook) {
            throw new Error("Не удалось загрузить книгу");
        }
        console.log("Книга загружена успешно");
    })
    .catch(error => {
        console.error("Ошибка загрузки файла:", error);
        messageWindow("Ошибка", "Файл поврежден или имеет неверный формат");
    });

Ошибка 3: Неправильный адрес ячейки
Проблема: Invalid cell address 'AA1'
Решение:
 // Валидация адреса ячейки
function isValidCellAddress(address) {
    const regex = /^[A-Z]+[1-9]\d*$/;
    return regex.test(address);
}



const cellAddress = "A1";
if(isValidCellAddress(cellAddress)) {
    ExternalXLSXProxy.writeData("file.xlsx", "Sheet1", cellAddress, data);
} else {
    console.error("Неправильный адрес ячейки:", cellAddress);
}

Ошибка 4: Утечка памяти при работе с большими файлами
Проблема: Браузер зависает или выдает ошибки памяти
Решение:

// Освобождать ресурсы после использования
function processLargeFile(fileID, fileData) {
    return ExternalXLSXProxy.loadWorkbook(fileID, fileData)
        .then(workbook => {
            // обработка данных
            const data = ExternalXLSXProxy.readSheet(fileID, 1);
            return data;
        })
        .finally(() => {
            // обязательно выгружать книгу
            ExternalXLSXProxy.unloadWorkbook(fileID);
            console.log("Ресурсы освобождены");
        });
}

Модуль 6. OlapProxy

Ошибка 1: XMLA сервер недоступен
Проблема: XMLA connection timeout
Решение:
 // Проверка подключения с timeout
const connectionParams = {
    url: "http://localhost:8080/xmla",
    catalog: "Adventure Works",
    // ...
};



// Установить разумный timeout
setTimeout(() => {
    console.error("Timeout: XMLA сервер не отвечает");
}, 10000);



OlapProxy.loadConnection("main", connectionParams)
    .then(connection => {
        console.log("OLAP подключение успешно");
    })
    .catch(error => {
        console.error("Ошибка OLAP подключения:", error);
        messageWindow("Ошибка", "OLAP сервер недоступен");
    });



Ошибка 2: Неправильный MDX запрос
Проблема: MDX syntax error
Решение:
// Валидация базовой структуры MDX
function validateMDX(mdxQuery) {
    const hasSelect = mdxQuery.toUpperCase().includes('SELECT');
    const hasFrom = mdxQuery.toUpperCase().includes('FROM');
    return hasSelect && hasFrom;
}



const mdxQuery = `
    SELECT
        [Date].[Calendar Year].Members ON 0
    FROM [Adventure Works]
`;



if(validateMDX(mdxQuery)) {
    OlapProxy.executeQuery("main", mdxQuery)
        .then(result => {
            console.log("MDX выполнен успешно");
        });
} else {
    console.error("Некорректный MDX запрос");
}

Ошибка 3: Превышен лимит соединений
Проблема: Too many connections
Решение:
 // Управление соединениями
const maxConnections = 5;
let activeConnections = 0;

function createManagedConnection(connectionID, params) {
    if(activeConnections >= maxConnections) {
        console.warn("Превышен лимит соединений, ожидание...");
        return Promise.reject(new Error("Слишком много активных соединений"));
    }

    activeConnections++;
    return OlapProxy.loadConnection(connectionID, params)
        .finally(() => {
            activeConnections--;
        });
}
Общие рекомендации по обработке ошибок

1. Всегда используйте try-catch для асинхронных операций
async function safeOperation() {
    try {
        const result = await SomeProxy.someMethod();
        return result;
    } catch (error) {
        console.error("Операция завершилась с ошибкой:", error);
        messageWindow("Ошибка", error.message || "Неизвестная ошибка");
        return null;
    }
}

2. Проверяйте инициализацию модулей 
function checkSDKReady() {
    const checks = [
        { name: 'SDK', obj: Common.R7DataConsulting?.SliderDataSDK },
        { name: 'XLDBProxy', obj: Common.R7DataConsulting?.SliderDataSDK?.XLDBProxy },
        // добавить другие модули
    ];

    for (const check of checks) {
        if (!check.obj) {
            console.error(`${check.name} не доступен`);
            return false;
        }
    }
    return true;
}
3. Логирование для отладки 
function debugLog(module, operation, data) {
    if (console && console.log) {
        console.log(`[${module}] ${operation}:`, data);
    }
}
// Использование
debugLog('XLDBProxy', 'executeQuery', { query: sql, params: params });