hyperformula icon indicating copy to clipboard operation
hyperformula copied to clipboard

export ArraySize from hyperformula

Open MartinDawson opened this issue 3 years ago • 6 comments

ArraySize is needed in customFunctions I think.

Here's my custom funciton below. You can see it accepts either 1, 2, 3 or 4 arguments.

If the first parameter is financialStatements then I need to tell hyperformula to return an ArraySize so that it can overflow into subsequent cells.

  // Pre-fixed with TT due to there already being a FinancialPlugin
  // in hyperformula
  class TTFinancialPlugin extends FunctionPlugin {
    financial({ args }) {
      if (!args.length) {
        return new InvalidArgumentsError(1);
      }
      if (!hasFinancialsLoaded) {
        return "Loading...";
      }
      const attribute = args[0].value;
      // TODO: Add proper error checking here later
      if (args.length === 1) {
        if (attribute === "currencyCode") {
          const currencyCode = ttmData[attribute];
          return convertSubCurrencyToCurrency(currencyCode);
        }
        if (attribute === "financialStatements") {
          return SimpleRangeValue.onlyValues(statements);
        }
        return ttmData[attribute] ?? "";
      }
      const startDate = args[1].value;
      const statementType = getTypeOfStatementToUse(attribute);
      if (args.length === 2) {
        if (attribute === "description") {
          return ttmData[attribute];
        }
        return (
          historicalDataArrays[statementType].yearly[startDate][attribute] ?? ""
        );
      }
      const endDate = args[2].value;
      if (args.length === 3) {
        return SimpleRangeValue.onlyValues([
          getYearlyValues(attribute, statementType, startDate, endDate),
        ]);
      }
    }
    financialSize({ args }) {
      if (!hasFinancialsLoaded) {
        return ArraySize.scalar();
      }

      const attribute = args[0].value;
      const statementType = getTypeOfStatementToUse(attribute);
      const startDate = args[1] ? args[1].value : null;
      const endDate = args[2] ? args[2].value : null;

      if (attribute === "financialStatements") {
        return ArraySize.fromArray(statements);
      }

      if (args.length === 3) {
        const yearlyValues = getYearlyValues(
          attribute,
          statementType,
          startDate,
          endDate,
        );

        return ArraySize.fromArray([yearlyValues]);
      }

      return ArraySize.scalar();
    }
  }

  TTFinancialPlugin.implementedFunctions = {
    FINANCIAL: {
      method: "financial",
      arraySizeMethod: "financialSize",
    },
  };

  TTFinancialPlugin.aliases = {
    FIN: "FINANCIAL",
  };

The above works well but I believe ArraySize needs to be exported from hyperformula because currently I have to import it like so:

import { ArraySize } from "hyperformula/es/ArraySize";

MartinDawson avatar Oct 16 '21 10:10 MartinDawson

Should be doable @izulin? Can you confirm that ArraySize is useful for creating array functions?

wojciechczerniak avatar Oct 19 '21 07:10 wojciechczerniak

Should be doable @izulin? Can you confirm that ArraySize is useful for creating array functions?

yes, this should definitely be exported

izulin avatar Oct 20 '21 09:10 izulin

Could anyone suggest a workaround for the browser to export ArraySize until this is included properly?

mlconnor avatar Jul 10 '22 16:07 mlconnor

@mlconnor Please share a demo of your code. We need to know your use-case to find a workaround for it. Use codesandbox.io or jsfiddle.net if possible.

sequba avatar Jul 11 '22 12:07 sequba

Issue resolved. Here is a sandbox in case anyone is interested. Take a peek at hyperformulaConfig.js file. It's broken because the ArraySize class isn't exported. This class is required to implement custom array functions because the sizing method requires the method to return an ArraySize object.

https://codesandbox.io/s/hyperformula-custom-fn-arraysize-issue-ywryj1

  ARRAYFNSIZE(ast, state) {
    return this.runFunction(
      ast.args,
      state,
      this.metadata("ARRAYFN"),
      (objectsRange, headers) => {
        var list = objectsRange.valuesFromTopLeftCorner();
        var value = list[0];
        var values = value.split(",");
        // in order to implement this function, we need access to the ArraySize class
        return { width: values.length, height: 1, isScalar: () => false };
      }
    );
  }

mlconnor avatar Jul 11 '22 15:07 mlconnor

@mlconnor Thanks for your feedback. This bug is a known issue and will be fixed in one of the upcoming releases. I'm glad that you could find a workaround.

sequba avatar Jul 12 '22 08:07 sequba

Will be done in scope of #779

sequba avatar Dec 15 '22 09:12 sequba

Hi @MartinDawson, @mlconnor!

I'm more than happy to announce that we just released HyperFormula 2.3.0 where this issue is fixed. Also, we have a new custom functions guide with an advanced example. We are closing this issue as solved. If there is anything that won't work for you after updating please leave a comment.

sequba avatar Dec 22 '22 15:12 sequba