Excel JS API: запись, вычисление и загрузка значений из ячеек с помощью пользовательских функций - PullRequest
0 голосов
/ 17 января 2019

Цель состоит в том, чтобы записать формулу (пользовательскую функцию) в ячейку, вычислить ее , загрузить значения и извлечь их в одной функции.

function myFunc() {
    Excel.run(function (ctx) {
        var fExcel = '=SUM(1,2)';
        var fCustom = '=custFunc()';

        var rng = ctx.workbook.worksheets.getActiveWorksheet().getRange('A1');

        //rng.formulas = [[fExcel]]; // works OK          
        rng.formulas = [[fCustom]]; // values are #GETTING_DATA

        // try different calc calls

        rng.load("values");

        return ctx.sync().then(function () {
            console.log(rng.values);
        });
    });
}

Для встроенных функций Excel все работает как положено, и console записывает значение 3 после ctx.sync(). Для пользовательских функций (которые отправляют запрос на внешний сервер для вычисления результата) значения равны '#GETTING_DATA'. Я пробовал все следующие вещи до rng.load("values");, чтобы вызвать вычисления, но пока ничего не получалось:

  • rng.calculate();

  • var s = ctx.workbook.worksheets.getActiveWorksheet(); s.calculate(true);

  • ctx.workbook.application.calculate('Full');

Есть ли способ запустить расчет пользовательских функций и убедиться, что значения доступны после ctx.sync()?

1 Ответ

0 голосов
/ 12 февраля 2019

Интересный сценарий!

Сегодня это может быть выполнимым, используя событие onCalculate, но предостережение состоит в том, что он будет срабатывать 2 раза, когда ваша пользовательская функция вычисляет.

  • Это потому, что ваша пользовательская функция сначала покажет #GETTING_DATA, а она вычисляет в фоновом режиме.
    • Это дает пользователю возможность контроля, пока ваши функции все еще оцениваются, что позволяет приложению быть более отзывчивым. Это поведение отличается от пользовательских функций VBA или XLL, которые могут зависать в Excel.
  • Когда Excel завершит вычисление, он снова запустит событие вычисления. Это когда результаты возвращаются с выполнением обещания.

Этот Сценарий лабораторной работы должен дать вам представление о том, как это работает:

/*This gist works in combination with any registered Excel JS Custom function*/

$("#set-formulas").click(() => tryCatch(setFormulas));

var rangeToCheck;

async function setFormulas() {
  await Excel.run(async (context) => {
    //register for event
    context.workbook.worksheets.getActiveWorksheet().onCalculated.add(handleCalculate);

    //write to grid
    const sheet = context.workbook.worksheets.getItem("Sheet1");

    rangeToCheck = "A1";
    const range = sheet.getRange(rangeToCheck);
    range.formulas = [['=CONTOSO.CONTAINS(A1, Days)']];
    range.format.autofitColumns();

    await context.sync();
  });
}

async function handleCalculate(event) {
  //read cell
  console.log("calc ended - begin");

  console.log("Change type of event: " + event.changeType);
  console.log("Address of event: " + event.address);
  console.log("Source of event: " + event.source);

  //Read A1 and log it back to the console
  await Excel.run(async (context) => {
    //write to grid
    const sheet = context.workbook.worksheets.getItem("Sheet1");

    const range = sheet.getRange(rangeToCheck);
    range.load("values");

    await context.sync();

    if (range.values.toString() != "GETTING_DATA") {
      console.log("Success: " + range.values);
    }
  });
}

/** Default helper for invoking an action and handling errors. */
async function tryCatch(callback) {
  try {
    await callback();
  } catch (error) {
    OfficeHelpers.UI.notify(error);
    OfficeHelpers.Utilities.log(error);
  }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...