web-dev-qa-db-ja.com

Excelで、複数の動的/スピルアレイを単一のダイナミック/スピルアレイに「スプライス」できますか?

手短に

4つの(たとえば)列のデータがあり、それぞれが動的/スピル配列です。それらを別の列に「スタック」して、4つのオリジナルの「スプライス」を含む単一の動的/スピル配列を生成したいと思います。

VBAを使用せずに実行したいので、4つの初期配列のいずれかのサイズが変更された場合、最小限の変更が必要であり、理想的には、スプライシングに使用される式などを変更する必要はありません。

TL; DRの詳細

「ヘルパー」列の作成を含む方法はすでにありますが、理想的ではありません。これは次のように機能します(例 ここ ):

  1. まず、元の配列の最大「次元」を選択します。つまり、4つのうち最大のものが必要になる最大サイズです。
  2. 次に、ヘルパー列として、4つの元の配列の「手動」スタッキングを作成します。しかし、私は、それぞれが元のサイズではなく、私が選択した最大寸法を占めるようにしています。 (したがって、少なくとも4つのオリジナルのサイズが大きく異なることが多い私の典型的なユースケースでは、ヘルパー列に多くのギャップがあります。)
  3. 最後に、FILTER()を使用してギャップを取り除きます。これにより、ギャップが解消されるだけでなく、申し訳ない混乱全体が、動的/流出配列の形式で、ニースの連続した範囲に変換されます。それが私が欲しいものです。

それは機能しますが、(少なくとも)2つの明らかな制限があります。

  1. そのハードコードされた最大寸法の必要性。初期配列サイズが変更された場合に数式を変更する必要がないという私の要件に失敗します。はい、最大寸法を使用すると、サイズが全体の最大値の範囲内にとどまる場合に限り、そのようなサイズ変更による変更に対する耐性が得られます。もちろん、制限自体を増やすことで、その制限内にとどまる可能性を高めることはできますが、サイズと速度にコストがかかります。次のポイントを参照してください。
  2. A)4つの初期配列のサイズが大きく異なる可能性があり、b)特定のユースケースでは、データセット全体の小さなスライスのみを確認したい場合があります。この方法は非常にスペースを浪費します。最終的にはその小さなスライスだけを見たいという事実にもかかわらず、ヘルパー列は非常に大きくなる可能性があります。それは不器用で、もっと重要なのは遅いです。

私がlikeしたいのは、それぞれC8、D8、E8、およびF8をルートとする4つの初期配列が与えられた場合(添付の例による)、このようなものを突き出すことができるようにすることです単一のセルに:

=(C8#、D8#、E8#、F8#)

そしてそれをすべて持っているJust Work

何か案は?

P.S. DropBoxのExcelファイルへのリンクを使用して例を示しました。しかし、人々が私のようであるならば、彼らはインターネット上のランダムな男からのランダムなリンクをクリックすることに熱心ではないでしょう。私はそうしないことを知っています! (とはいえ、これはマルウェアをすべてにドロップしようとする非常に長い方法であるため、私が推測することは常にあります。:-))したがって、添付する、またはそうでない場合は、そのようなものを提供するより良い方法がある場合ファイル、聞いていただければ幸いです。

2
tkp

[〜#〜] vba [〜#〜]を避けたいとのことですが。ただし、再検討する場合:

VBAユーザー定義関数を使用する場合は、標準の配列数式をスタックするのと同じ方法で動的配列をスタックできます。

[〜#〜] a [〜#〜]および[〜#〜のデータから開始するとします。 ] b [〜#〜]そして列[〜#〜] b [〜#〜][〜#〜] a [〜#〜]の一意のアイテムのすぐ下:

enter image description here

まず、このUDFを標準モジュールに入力します。

Public Function stack(arr1 As Variant, arr2 As Variant)
    Dim i As Long, a

    ReDim temp2(1 To UBound(arr1) + UBound(arr2))
    i = 1
    For Each a In arr1
        temp2(i) = a
        i = i + 1
    Next a

    For Each a In arr2
        temp2(i) = a
        i = i + 1
    Next a
    stack = Application.Transpose(temp2)

End Function

次に、C1に次のように入力します。

=stack(UNIQUE(A1:A7),UNIQUE(B1:B8))

enter image description here

注:

  1. C1数式は自動的にスピルダウンするため、配列を入力する必要はありません。
  2. 複数列のスピルダウンの場合、詳細ははるかに複雑になりますが、アプローチは同じです。
2
Gary's Student

試してみてください:

B1: =FILTERXML("<t><s>" & SUBSTITUTE(TEXTJOIN(",",TRUE,TRANSPOSE($C$8:$F$17)),",","</s><s>")&"</s></t>","//s")
  • TEXTJOINは、範囲内の空白以外のエントリのコンマ区切りリストを作成します。
  • 最初に範囲をTRANSPOSEして、順序が行ではなく列であるようにします(これは、このタイプの範囲参照の通常のケースです。
  • ノードがコンマで区切られているXMLを作成します。
  • 次に、FILTERXMLは、各ノードを個別の配列要素に分割します。これにより、動的配列機能を使用して、列をSPILL下に移動します。

enter image description here

注:式では、ハードコードされた範囲を使用しました参照。ただし、私が持っていない情報によっては、ダイナミックレンジ参照を使用することもできます。しかし、それは範囲がどのように変化するかによって異なります。

最も簡単な方法は、これをテーブルにすることです。その場合、行/列を追加/削除/挿入すると、参照は自動的に展開/縮小されます

テーブルは、こぼれた配列ではうまく機能しません。

  • そこで、サンプルテーブルの最初のセルの数式を次のように変更しました。
    C12: =IFERROR(INDEX(SEQUENCE(C$6,1,IF(COLUMNS($A:A)=1,1,COLUMNS($A:A)*6),1),ROWS($1:1)),"")

また、上記と同じ式で範囲参照としてTable1を使用しました。

そしてもちろん、数式は自動的にFill Downします。

サンプルシート:

enter image description here

動的にこぼれた配列(テーブルの使用を排除する)を本当に使用したい場合は、サンプルワークシートで、次のような配列を動的に定義できます。

=$C$11:INDEX($A:$XFD,MAX($6:$6)+10,COUNT($6:$6)+2)

式は次のようになります。

=FILTERXML("<t><s>" & SUBSTITUTE(TEXTJOIN(",",TRUE,TRANSPOSE($C$11:INDEX($1:$1048576,MAX($6:$6)+10,COUNT($6:$6)+2))),",","</s><s>")&"</s></t>","//s")

ExcelがA:XFD1:1048576に変更したことに注意しますが、それらは同じ領域(シート全体)を参照しています。

2
Ron Rosenfeld