Эффективность заполнения диапазона массивом
Проверка эффективности использования заполнения диапазона ячеек целиком массивом в сравнении с заполнением ячеек диапазона через цикл по массиву.
Влияние типа данных на скорость вывода.
Для вывода данных на лист в макросах Р7-Офис можно использовать разные подходы. Можно поэлементно выводить значения массива в строки или столбцы, а можно целиком выводить массив в нужный диапазон. Такие же подходы используются в макросах VBA MS Office. Там эффект от использования второго подхода значителен.

Для первого варианта в цикле используется метод GetRangeByNumber(nRow, nCol).SetValue(элемент массива). Во втором варианте метод GetRangeByNumber(nRow, nCol) используется только для указания диапазона, который целиком заполняется данными из массива (выполняется метод SetValue(массив) к этому диапазону).

Важно знать, на сколько увеличивается скорость заполнения диапазона на листе во втором подходе по сравнению с первым – пошаговым.

Интересно также проверить влияние типа данных массива на эту скорость.

Для получения данных и расчета результатов напишем три макроса для тестирования скорости и сведем результаты в соответствующие таблицы.
Горизонтальный диапазон, числовой тип данных массива.
Программа (макрос) для проверки горизонтального диапазона.
test_arr_h(20);
function test_arr_h(l_buf4) {
    var buffer = new ArrayBuffer(l_buf4*4);
    var Uint32 = new Uint32Array(buffer);
    var arr_h = [];
    let ws=Api.GetActiveSheet();
    ws.GetRange("1:20").Clear();

    for(var i = 0; i < l_buf4; ++i) {
         Uint32[i] = ((Math.random() * 0x100) | 0)+1000*i;
         arr_h[i] = Uint32[i];
    }
    let l_uint=Uint32.length;
    let l_arr_h=arr_h.length;
    console.log("buffer:"+buffer.byteLength);
    console.log("Uint32:"+l_uint);
    console.log("Length arr_horiz:"+l_arr_h);
    
    let rng_h=ws.GetRange(ws.GetRangeByNumber(2,5),ws.GetRangeByNumber(2,5+l_arr_h-1));
    
    console.time('horiz_arr');
    rng_h.SetValue(arr_h);
    console.timeEnd('horiz_arr');  //10000 353ms
    
    console.time('horiz_arr_n');
    for (let i=0;i<l_uint;i++){ ws.GetRangeByNumber(0,i+5).SetValue(arr_h[i]);}
    console.timeEnd('horiz_arr_n');  //10000 470ms
}
Результат тестирования при разном количестве элементов в массиве:
Вызов test_arr_h(200000); приводит к ошибке переполнения стека в строке создания диапазона для массива. Строка:
let rng_h=ws.GetRange(ws.GetRangeByNumber(2,5),ws.GetRangeByNumber(2,5+l_arr_h-1));
Вывод: Скорость работы по сравнению с выводом в цикле возрастает от 1,7 до 1,9 раз. По моим ощущениям (не проверенным численно), это менее интересно по сравнению с VBA. Кроме того, ограничение Р7 по размеру выбранного диапазона сужает применимость такого подхода или затрудняет его использование.
Вертикальный диапазон, числовой тип данных массива.
Программа (макрос) для проверки вертикального диапазона.
test_arr_v(100);

function test_arr_v(l_buf4) {
   var buffer = new ArrayBuffer(l_buf4*4);
   var Uint32 = new Uint32Array(buffer);
   var arr_v = [];
   let ws=Api.GetActiveSheet();
   ws.GetRange("A:M").Clear();

   for(var i = 0; i < l_buf4; ++i) {
        Uint32[i] = ((Math.random() * 0x100) | 0)+1000*i;
        arr_v[i] = [Uint32[i]];
   }
    let l_uint=Uint32.length;
    let l_arr_v=arr_v.length;
    console.log("buffer:"+buffer.byteLength);
    console.log("Uint32:"+l_uint);
    console.log("arr_vert:"+l_arr_v);
    let rng_v=ws.GetRange(ws.GetRangeByNumber(1,1),ws.GetRangeByNumber(1+l_arr_v-1,1));
    
    console.time('vert_arr');
    rng_v.SetValue(arr_v);
    console.timeEnd('vert_arr');
    
    console.time('vert_arr_n');
    for (let i=0;i<l_uint;i++){ ws.GetRangeByNumber(i+1,3).SetValue(arr_v[i]);}
    console.timeEnd('vert_arr_n');
}
Результат тестирования при разном количестве элементов в массиве:
Вызов test_arr_v(200000); приводит к ошибке переполнения стека в строке создания диапазона для массива. Строка:
let rng_v=ws.GetRange(ws.GetRangeByNumber(2,5),ws.GetRangeByNumber(2,5+l_arr_v-1));
Вывод: Скорость работы по сравнению с выводом в цикле возрастает от 1,9 до 2.2 раза. По моим ощущениям (не проверенным численно), это менее интересно по сравнению с VBA. Кроме того, ограничение Р7 по размеру выбранного диапазона сужает применимость такого подхода или затрудняет его использование.
Как влияет тип данных массива на скорость вывода.
Проверим влияние типа данных на скорость вывода, добавив массив со строковыми данными.
Программа (макрос) для проверки вертикального диапазона.
test_arr_v(10000);

function test_arr_v(l_buf4) {
   var buffer = new ArrayBuffer(l_buf4*4);
   var Uint32 = new Uint32Array(buffer);
   var arr_v = [];
   var arr_vs = [];
   let ws=Api.GetActiveSheet();
   ws.GetRange("A:M").Clear();

   for(var i = 0; i < l_buf4; ++i) {
        Uint32[i] = ((Math.random() * 0x100) | 0)+1000*i;
        arr_v[i] = [Uint32[i]];
        arr_vs[i] = [String(Uint32[i])];
//        arr_vs[i] = ["!1234567890!"+String(Uint32[i])];
   }
    let l_uint=Uint32.length;
    let l_arr_v=arr_v.length;
    console.log("buffer:"+buffer.byteLength);
    console.log("Uint32:"+l_uint);
    console.log("arr_vert:"+l_arr_v);
//    console.log(arr_vs);
    
    let rng_v=ws.GetRange(ws.GetRangeByNumber(1,1),ws.GetRangeByNumber(1+l_buf4-1,1));
    
    let rng_vs=ws.GetRange(ws.GetRangeByNumber(1,2),ws.GetRangeByNumber(1+l_buf4-1,2));
    
    console.time('vert_arr');
    rng_v.SetValue(arr_v);
    console.timeEnd('vert_arr');

    console.time('vert_arrs');
    rng_vs.SetValue(arr_vs);
    console.timeEnd('vert_arrs');
    
    console.time('vert_arr_n');
    for (let i=0;i<l_buf4; i++){ ws.GetRangeByNumber(i+1,3).SetValue(arr_v[i]);}
    console.timeEnd('vert_arr_n');
    
    console.time('vert_arr_ns');
    for (let i=0;i<l_buf4;i++){ ws.GetRangeByNumber(i+1,4).SetValue(arr_vs[i]);}
    console.timeEnd('vert_arr_ns');
}
Результат тестирования при 10 000 элементов в массиве:
Результат тестирования при 100 000 элементах в массиве:
Вывод:
Скорость расчета и вывода данных массива в диапазон мало зависит от типа данных.
Поддержка слушателей курса
"Основы Java Script для Р7"