web-dev-qa-db-ja.com

配列数式のテキスト結果を使用可能な形式に変換する

配列数式の結果が数値の場合、配列を1つの結果にまとめる適切な方法を見つけるのは一般的に簡単です。ただし、配列数式の結果がテキストの場合、単一の望ましい結果が得られるように数式を操作するのは難しいと思います。要するに、私が見落としたテキスト結果の配列を操作する方法はありますか?最終的に必要な式については、この質問の下部を参照してください。動作せず、解決策を要求します。

*編集-これをもう一度読んだ後、質問を次のように要約することもできます:個別に選択せずに「数式配列の結果」から複数のテキスト要素にアクセスする方法はありますか(例:with INDEX)?

配列数式が機能する例、結果配列は数値

(1)例1:列Aの行1〜500がxyz123形式の製品IDのリストであり、列Bの行1〜500がその製品の総売上高を示しています。 IDの下3桁が400を超える、売上が最も高い製品の売上を検索する場合は、次のような配列数式を使用できます(EnterだけでなくCTRL + SHIFT + ENTERで確認)。

=MAX(IF(VALUE(RIGHT(A1:A500,3))>400,B1:B500,""))

(2)例2ここで、列BにSalesではなく製品名が含まれていると仮定します。ここで、製品IDの最後の3桁が400を超えるという基準に一致する名を単純に返したいと思います。これは次のように実行できます。

=INDEX(B1:B500,MIN(IF(VALUE(RIGHT(A1:A500,3))>400,ROW(A1:A500),"")))

ここでは、少し操作を行ったので、式[IF(RIGHT(A1:A500,3 ...]]の実際の配列部分が値の結果[最後の3桁がであるcellsA1:A500の行400以上];したがって、MINを使用して、一致する最初のROW#のみを表示できます。次に、その折りたたまれた結果を通常のINDEX関数で使用できます。

(3)例3最後の例については、こちらの同様の質問に関する説明を参照してください[以下の要約例よりも詳細に説明します。この質問に直接関係のない方法]: https://stackoverflow.com/a/31325935/5090027

ここで、すべての製品名のリストが必要であると想定します。ここで、製品IDの最後の3桁は> 400です。私の知る限り、これは実際には単一のセルで実行することはできません。個々の結果を後続のセルに配置することによって実行する必要があります。たとえば、次の数式をC1に配置し、10行下にドラッグすると、最初の10個の製品名が表示され、製品IDの最後の3桁が400を超えます。

=INDEX($B$1:$B$500,SMALL(IF(VALUE(RIGHT($A$1:$A$500,3))>400,ROW($A$1:$A$500),""),ROW()))

配列数式が機能しない例、結果の配列はテキスト値です

ここで、例3の結果を取得し、それらに対してテキスト操作を実行するとします。たとえば、それらすべてを1つのテキスト文字列に連結したいとします。 concatenateはこのような結果の配列を受け入れ可能な引数として受け取らないため、以下は機能しません。

=CONCATENATE((IF(VALUE(RIGHT($A$1:$A$500,3))>400,ROW($B$1:$B$500),"")))

質問は:この最後の式を機能させる方法を知っている人はいますか?または、テキスト結果の配列を受け取り、それを「使用可能な範囲」に変換する(上記の連結にプラグインできるようにする)か、テキスト引数ですぐに操作できる(midなど)数式を機能させる方法、検索、置換など]?今のところ、私が見ることができる唯一の方法は、上記の例3を使用し、さらに進んで、たとえばConcatenate(C1、C2、C3 ... C10)と言うことです。

12

前に述べたように、単一のセルで必要なことを実行できるネイティブ関数はありません。 VBAを絶対に使用できない場合は、ヘルパー列を使用して(必要に応じて列を非表示にすることができます)、結果が必要なセルにヘルパー列の最後のセルを表示することができます。

例:

Produce Name   Type
Apple          Fruit
Broccoli       Vegetable
Carrot         Vegetable
Orange         Fruit

1つのセルにすべてのFruitの結果を表示したいとします。別の列を使用して、この式をホストできます。後で列を非表示にするので、列Zのように、邪魔にならない場所を使用します。また、探しているものを簡単に変更できるようにしたいので、条件をセルD2に入れます。セルZ2でコピーして、次の数式を使用します。

=IF(B2=$D$2,IF(Z1="",A2,Z1&", "&A2),IF(Z1="","",Z1))

その結果、次のようになります。

Produce Name   Type              Search For   (other columns until you get to Z)      
Apple          Fruit             Fruit                                             Apple
Broccoli       Vegetable                                                           Apple
Carrot         Vegetable                                                           Apple
Orange         Fruit                                                               Apple, Orange

次に、結果セルが必要な場所で、D3と言います。この数式を使用して、ヘルパー列から最後の結果を取得し、ヘルパー列を非表示にします。

=Z5

その結果、次のようになります。

Produce Name   Type              Search For
Apple          Fruit             Fruit
Broccoli       Vegetable         Apple, Orange
Carrot         Vegetable
Orange         Fruit

単に=Z5の代わりに動的な名前付き範囲を使用して、ヘルパー列の最後のセルを常に取得し、データを拡大または縮小しても正しい結果が得られるようにすることができます。ただし、セルD2の内容をFruitからVegetableに変更すると、結果のセルにBroccoli, Carrotが表示されます。うまくいけば、このようなものがあなたのニーズに適応することができます。

4
tigeravatar

他の応答を繰り返すために、配列で連結関数を使用する方法が見つかりませんでした。ただし、1つの配列関数のみを使用し、いわゆる「ヘルパー列」を使用せずに「製品名」を連結する方法を見つけました。かなり長くて退屈ですが、これが議論に加わるかもしれないと思います。 1つは、このような数式を実際に何らかの有効な目的で使用する場合、または特定の障壁を克服する場合は、数式をコピーして貼り付けることで簡単に使用できます(つまり、実際には比較的適応性があります)。一方、あなたの興味がより好奇心であるならば、私の答えはあなたが望むかもしれないより平凡かもしれません。

問題のシミュレーションでは、2つの列もありましたが、行数を40に減らしました。左端の列( "C")には3つの文字と3つの数字のシーケンスが含まれ、右の列( "D")にはランダムなシーケンスが含まれます。あなたの「製品名」をシミュレートする文字と数字の。

ネストされた置換関数と連結関数を組み合わせて使用​​しました。以下の関数は、集約された関数の「基本単位」に焦点を当てるために切り刻まれています。

ベースユニット

REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2)))=TRUE,””,

上記の式は、基本的に、番号シーケンス> 400の対応する製品IDを持つ最初の製品名を調べ、同じ製品ID基準を満たす別の製品が存在する場合、それを連結に置き換えます。これは、最も内側の括弧から始まる「蓄積」連結と考えることができます。式のこの「基本単位」は、任意の範囲で繰り返すことができます。つまり、設定した製品ID基準を満たす200から280の製品がリストにあると思われる場合は、この基本コードを280回繰り返すことができます。ご覧のとおり、数式が存在しない製品名を連結しようとすると(280の数式基本単位があり、基準を満たす製品は275しかありません)、数式はある意味で自己終了します。実際には、すべての基本ユニットが制定されるまで、何も何度も連結し始めます。その結果、必要なすべての製品名が1つのセルに連結され、各セルがピリオドで区切られます。

基数ブロックから基数ブロックに変わるのは1つの数値だけで、それがSMALL配列のk番目の要素です。これらの変数は、明らかに各基本単位で1つずつ増加します。テストでは、14ベースユニットを使用しました。

14基本単位の完全な式

=REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),3)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),3)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),3))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),3)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),4)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),4)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),4))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),4)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),5)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),5)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),5))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),5)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),6)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),6)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),6))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),6)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),7)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),7)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),7))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),7)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),8)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),8)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),8))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),8)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),9)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),9)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),9))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),9)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),10)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),10)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),10))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),10)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),11)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),11)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),11))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),11)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),12)))=TRUE,””,**REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),12)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),12))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),12)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),13)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),13)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),13))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),13)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),14)))=TRUE,””,INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),14)))))))))))))))))))))))))))))))))))))))))

明らかに、数式全体を見ると、かなり判読できません。しかし、基本単位で見ると、簡単に構築してコピーして貼り付けることができることがわかります(最初の基本単位を書き込んだ後、すべてをまとめるのに約2分かかりました)。

2
bidout

これは、Excel 2016のGet&Transformまたは以前のバージョンのPowerQueryアドインを使用したVBAフリーのソリューションです。

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    ExtractLast3Digits = Table.AddColumn(Source, "Value", each Text.End([ProductID],3)),
    ChangeToNumber = Table.TransformColumnTypes(ExtractLast3Digits,{{"Value", type number}}),
    FilterAbove400 = Table.SelectRows(ChangeToNumber, each [Value] > 400),
    Concatenate = Text.Combine(FilterAbove400[ProductName])
in
    Concatenate

「配列出力」(ステップ「FilterAbove400」)であらゆる種類のテキスト操作を実行できます。この例では、リクエストを理解したので、区切り文字なしで連結しました。

最初のステップ(ソース)で、テーブル形式で「Table1」という名前の入力データを取得します。

ソリューションを含むファイルへのリンク: https://www.dropbox.com/s/utsraj0bec5ewqk/SE_ConvertArrayFormulasTextResult.xlsx?dl=

2
ImkeF

数式配列の結果を処理する独自の集計関数を作成できます。それは少しのVBAを必要とします...しかしそれは難しくありません。これにより、値の配列に対してあらゆる種類の文字列操作または数値解析を実行できます。

連結機能を実行するには、VBAコードウィンドウを開き、プロジェクト->挿入->新しいモジュールを右クリックして新しいモジュールを作成します。新しいモジュールをダブルクリックし、このコードを挿入して、配列を1つの大きな文字列に連結する関数を作成します。

Function ConcatenateArray(ParamArray Nums() As Variant) As Variant
Dim BigString As String
Dim N As Long
Dim A() As Variant
Let A = Nums(0)

BigString = ""
For N = LBound(A) To UBound(A)
    BigString = BigString & A(N, 1)
Next
ConcatenateArray = BigString

End Function

次に、セル内の配列数式を次のように変更します。

=ConcatenateArray(IF(VALUE(RIGHT($A$1:$A$500,3))>400,$A$1:$A$500,""))

もちろん、セルを配列数式として確認するには、EnterキーだけでなくCTRL + SHIFT + ENTERを押す必要があります。

1
Brian Pressler

私はこの投稿で提起されたいくつかの質問に対処しようとします:

テキスト結果の配列を取得し、それを「使用可能な範囲」に変換する数式を機能させる方法[上記の連結にプラグインできるようにする]、

この質問の最初の部分が実行可能であっても、最後の部分(つまり、 "[上記の連結にプラグインできる]"は不可能です。 CONCATENATE関数は、引数として範囲を取りません。

または、テキスト引数ですぐに操作できますか[mid、search、substituteなど]?今のところ、私が見ることができる唯一の方法は、上記の例3を使用し、さらに進んで、たとえばConcatenate(C1、C2、C3 ... C10)と言うことです。

これは確かに1つの方法ですが、これを試してみてください。

これから始めましょう:

ここで、例3の結果を取得し、それらに対してテキスト操作を実行するとします。たとえば、それらすべてを1つのテキスト文字列に連結したいとします。

ただし、最初に次のことを想定しましょう。

-。データ範囲は_D10:F510_にあり、次のフィールドが含まれます:ProductProductSales、およびProduct Name (Selection) *

*例3の式の結果を一覧表示するために使用

.-データには、例1で定義された基準に準拠する23のレコードが含まれています(図1を参照)

.-値_400_をセル_E4_に入力して、数式のハードコードの代わりに基準の変更を容易にします(図3を参照)

Fig. 1 図1

ここで、連結された結果を含む配列を生成し、それを使用可能な範囲に投稿するために、例3の式に小さな変更を適用しましょう。このFormulaArrayを_G11_に入力し、最後のレコードまでコピーします(10行だけではありません)

_=TRIM(CONCATENATE(
IF(ROW(G11)-ROW(G$11)+1=1,"",G10)," ",
IFERROR(INDEX($E$11:$E$510,
SMALL(IF(VALUE(RIGHT($D$11:$D$510,3))>$E$4,ROW($D$11:$D$510)-ROW($D$11)+1,""),
ROW(G11)-ROW(G$11)+1)),"")))
_

enter image description here 図2

_D4:E8_にあるSummaryセクションには、例1と2の結果とがあります。選択した製品のリストと連結した結果(図3を参照)。この数式を_E8_に入力します(行の高さを最大409に増やし、テキストをtrueにラップすることをお勧めします)

_=INDEX($M$11:$M$510,1+MAX(ROW($M$11:$M$510))-ROW($D$11))
_

enter image description here

図3

この質問に関して:

個別に選択せずに(例:INDEXを使用)、「数式配列の結果」から複数のテキスト要素にアクセスする方法はありますか?

この特定のケース(つまり、配列要素の連結)では、別のパースペクティブを適用し、連結された結果で配列を生成してから、必要な要素を選択します。 INDEXの使用が必要な場合。

最後に、これらの式について簡単に説明します。

例2:

_=INDEX(B1:B500,MIN(IF(VALUE(RIGHT(A1:A500,3))>400,ROW(A1:A500),"")))
_

データ範囲が_Row 1_で始まらない場合は、代わりに次の式を使用してください。

_=INDEX($E$11:$E$510,MIN(IF(VALUE(RIGHT($D$11:$D$510,3))>400,
1+ROW($D$11:$D$510)-ROW($D$11),"")))
_

例3:

_=INDEX($B$1:$B$500,SMALL(IF(VALUE(RIGHT($A$1:$A$500,3))>400,ROW($A$1:$A$500),""),ROW()))
_

データ範囲が_Row 1_で始まらない場合は、代わりに次の式を使用してください。

_=IFERROR(INDEX($E$11:$E$510,
SMALL(IF(VALUE(RIGHT($D$11:$D$510,3))>$E$4,
1+ROW($D$11:$D$510)-ROW($D$11),""),
1+ROW()-ROW($K$11))),"")
_
0
EEM