Низкая производительность надстройки Excel, если не подключен отладчик - PullRequest
0 голосов
/ 15 марта 2019

Я разрабатываю надстройку панели задач Excel, которая записывает и считывает данные из диапазонов по сообщению WebSockets (используя socket.io). Эти операции занимают 4-5 секунд, если я не присоединяю отладчик (будь то DevTools или Visual Studio), который заметно повышает производительность (примерно до 100 мс). Отладчику даже не нужно оставаться подключенным, улучшение производительности сохраняется до перезапуска надстройки.

Некоторые детали:

  • Диапазоны обычно не больше 10 ячеек.
  • Я пытался использовать как отладочную, так и неотладочную версии Office.js
  • Проблема возникает при операциях чтения и записи
  • Я на 99% уверен, что задержка происходит в функциях Excel.run (и не имеет ничего общего с socket.io или другой библиотекой)
  • Моя версия Excel - 1902 (сборка 11328.20146).
  • Я использую TypeScript и Webpack для связывания надстройки.
  • Я пробовал полифилл Promise для Bluebird и ES6-Promise

Единственная ссылка, которую я нашел до сих пор об этой проблеме, это этот вопрос , на который так и не получил ответа. Кажется, он испытал ту же проблему, что и я.

Пример операции чтения:

public async ReadObjectAsync(row) 
{
    var thisReader = this;

    return new Promise(async (resolve, reject) => 
    {
        try
        {
            await Excel.run(async (context) =>
            {
                var object = {}
                var boundingRectangle : Excel.Range = null;

                var mappedControllers = QuoteAttributeArray.map(function(attribute) // Creamos un objeto con pares de atributo y controlador
                {
                    return arrayFind(thisReader.AppContext.AttributeControllers, function(controller)
                    {
                        return controller.TargetAttribute == attribute;
                    })
                });

                for(var i = 0; i < QuoteAttributeArray.length; i++)
                {
                    var attribute = QuoteAttributeArray[i];
                    var controller = (mappedControllers[i] as ExcelAttributeController);

                    if(controller.ColumnSelector.SelectedColumnLetter == null)
                    {
                        object[attribute] = null;
                        continue;
                    }

                    var ws = context.workbook.worksheets.getActiveWorksheet();

                    var targetRange = ws.getRange(controller.ColumnSelector.SelectedColumnLetter + row);

                    if(boundingRectangle == null)
                    {
                        boundingRectangle = targetRange;
                    }
                    else
                    {
                        boundingRectangle = boundingRectangle.getBoundingRect(targetRange); // Construimos el bounding rectangle atributo por atributo
                    }

                    if(controller.AttributeInput instanceof PlazoAttributeInput)
                    {
                        targetRange.load('text');
                    }
                    else
                    {
                        targetRange.load('values');
                    }

                    boundingRectangle.load('address');

                    await context.sync();

                    if(controller.AttributeInput instanceof PlazoAttributeInput)
                    {
                        object[attribute] = targetRange.text[0];    
                    }
                    else
                    {
                        object[attribute] = targetRange.values[0];
                    }

                }

                var result = {
                    'boundingRectangleAddress' : boundingRectangle.address,
                    'object' : object
                };

                resolve(result);
            });
        }
        catch(error)
        {
            reject(error);
        }
    })
}

Для некоторого контекста: эта функция возвращает объект, представляющий книгу, как в

{
 isbn: '9788798',
 title : 'Blahblah'
 author : 'Blahblah'
}

, который читается из одной строки в Excel. Элементы в "QuoteAttributeArray" - это различные атрибуты книги (максимум 15), которые ранее были "сопоставлены" со столбцами.

Эта же функция выполняется 4 секунды при запросе из сообщения сокета, 1 секунда при выполнении запроса внутри надстройки и 100 мс (из сокета и внутри надстройки) после подключения отладчика.

Решения пробовали

Я реорганизовал функцию, чтобы сделать только один вызов context.sync (). Он значительно улучшается (до ~ 300 мс при первом выполнении и ~ 30 мс после, без отладчика), но есть разница, когда я присоединяю отладчик (~ 20 мс или меньше с первого раза). Я предполагаю, что это означает, что множественные вызовы context.sync () только увеличивают задержку, но она все еще там. Вот моя переработанная версия:

   public async ReadObjectAsync(row) 
{
    var thisReader = this;

    return new Promise(async (resolve, reject) => 
    {
        try
        {
            return await Excel.run(async (context) =>
            {


                var object = {}
                var boundingRectangle : Excel.Range = null;

                var mappedControllers = QuoteAttributeArray.map(function(attribute) // Creamos un objeto con pares de atributo y controlador
                {
                    return arrayFind(thisReader.AppContext.AttributeControllers, function(controller)
                    {
                        return controller.TargetAttribute == attribute;
                    })
                });

                let attributeRanges = {};

                for(let i = 0; i< QuoteAttributeArray.length; i++)
                {
                    var attribute = QuoteAttributeArray[i];
                    var controller = (mappedControllers[i] as ExcelAttributeController);

                    if(controller.ColumnSelector.SelectedColumnLetter == null)
                    {
                        object[attribute] = null;
                        continue;
                    }

                    var ws = context.workbook.worksheets.getActiveWorksheet();

                    var targetRange = ws.getRange(controller.ColumnSelector.SelectedColumnLetter + row);

                    if(boundingRectangle == null)
                    {
                        boundingRectangle = targetRange;
                    }
                    else
                    {
                        boundingRectangle = boundingRectangle.getBoundingRect(targetRange); // Construimos el bounding rectangle atributo por atributo
                    }

                    if(controller.AttributeInput instanceof PlazoAttributeInput)
                    {
                        console.log('attribute :' + attribute)
                        targetRange.load('text');
                    }
                    else
                    {
                        console.log('nonPlazo :' + attribute)
                        targetRange.load('values');
                    }

                    attributeRanges[attribute] = targetRange;
                }

                boundingRectangle.load('address');

                return context.sync().then(() =>
                {
                    for(var attribute in attributeRanges)
                    {
                        if(attribute == 'plazo')
                        {
                            object[attribute] = attributeRanges[attribute].text[0];    
                        }
                        else
                        {
                            object[attribute] = attributeRanges[attribute].values[0];
                        }

                    }

                    var result = {
                        'boundingRectangleAddress' : boundingRectangle.address,
                        'object' : object
                    };

                    return resolve(result);
                });
            });
        }
        catch(error)
        {
            return reject(error);
        }
    })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...