ST_FUNC開発日記

建築構造設計Excelアドイン開発の記録

配列を返す関数のテスト2

前に宣言した通り、断面性能関数をスピル対応にしようとしたら詰まってしまった。

ということで、配列の扱いをもう少し検証してみる。

前回は単に配列を返すだけだったので、今回は配列を受け取って配列を返すテスト。

/**
 * 配列を受け取り、配列を返すテスト
 * @customfunction
 */
export function testArrayFunction(propertyType: string[][]): number[][] {
  let result: number[][] = [];
  for (let i = 0; i < propertyType.length; i++) {
    let line: number[] = [];
    for (let j = 0; j < propertyType.length; j++) {
      line.push(i + j);
    }
    result.push(line);
  }
  return result;
}

この関数を受け取って範囲選択を引数に与えたら無事に結果が配列で出力された。

一方で、今回は通常の文字列を指定した場合は単純な数値を返し、配列を受け取ったときは配列を返したい。

ということはオーバーロード的なものが必要になる。

オーバーロードについては下記サイト等を参考にする。

qiita.com

オーバーロードさせるときはユニオン型というのを使うらしい。なかなか面白い仕組み。

そこで、まず下記のようなユニオン型をつかった関数を作成してみた。

/**
 * 配列を受け取り、配列を返すテスト2
 * @customfunction
 */
export function testArrayFunction2(propertyType: string | string[][]): number | number[][] {
  if (Array.isArray(propertyType)) {
    let result: number[][] = [];
    for (let i = 0; i < propertyType.length; i++) {
      let line: number[] = [];
      for (let j = 0; j < propertyType.length; j++) {
        line.push(i + j);
      }
      result.push(line);
    }
    return result;
  } else {
    return 100;
  }
}

引数を一つにするとうまくいったが、引数を配列にすると

持ち上げができない配列
個々の配列メンバーに対して関数を呼び出すために配列を持ち上げる (lift) ことができません

というエラーになってしまった。

これはオーバーロードで、ちゃんと配列を受け取ったら配列を返すという定義をしなければいけないのかな? ということで、関数の定義をしてみる。

**
 * 配列を受け取り、配列を返すテスト2
 * @customfunction
 */
export function testArrayFunction2(propertyType: string): number;
/**
 * 配列を受け取り、配列を返すテスト2
 * @customfunction
 */
export function testArrayFunction2(propertyType: string[][]): number[][];
/**
 * 配列を受け取り、配列を返すテスト2
 * @customfunction
 */
export function testArrayFunction2(propertyType: string | string[][]): number | number[][] {
  if (Array.isArray(propertyType)) {
    let result: number[][] = [];
    for (let i = 0; i < propertyType.length; i++) {
      let line: number[] = [];
      for (let j = 0; j < propertyType.length; j++) {
        line.push(i + j);
      }
      result.push(line);
    }
    return result;
  } else {
    return 100;
  }
}

これでどうかと思ったら今度はビルドが通らなかった。

- Error: C:\---\st_func_addin\src\functions\functions.ts @customfunction tag specifies a duplicate name: TESTARRAYFUNCTION2 (32,66)

というエラーメッセージを見ると、どうやらcustumfunctionしてだとオーバーロードは不可能っぽい?

だったらいっそのこと何でもありのanyにしたれ!

/**
 * 配列を受け取り、配列を返すテスト3
 * @customfunction
 */
export function testArrayFunction3(propertyType: any): any {
  if (Array.isArray(propertyType)) {
    let result: number[][] = [];
    for (let i = 0; i < propertyType.length; i++) {
      let line: number[] = [];
      for (let j = 0; j < propertyType.length; j++) {
        line.push(i + j);
      }
      result.push(line);
    }
    return result;
  } else {
    return 100;
  }
}

とおもってやってみたけれど、やっぱり

持ち上げができない配列
個々の配列メンバーに対して関数を呼び出すために配列を持ち上げる (lift) ことができません

のエラーが出てしまう・・・。

どうやら、数値を返すのと配列を返すのを切り替えることはできないということ?

でもExcelの普通の関数って両方対応してるよね?ABSとか。

いろいろやってるうちに、最初に作ったtestArrayFunctionに引数を一つ入れたら普通に値が返った。

ようするに、ワークシート上で普通に使うときは1x1の配列を受け取って、1x1の配列を返すということなのかしら?

そうすると、断面性能関数をシンプルに配列を対応させた関数にすればいいことになる。

なんか一般計算がすべて配列処理になるのちょっとやな気がする・・・けど、まあしょうがないか。