セルの内容を n 個の等しい値に繰り返し分割し、連続するセルに再分配します。

セルの内容を n 個の等しい値に繰り返し分割し、連続するセルに再分配します。

私が持っているもの:

n = 5
0, 0, 0, 0, 1000, 0, 0, 0, 0

私が欲しいもの:

0, 0, 0, 0, 200, 200, 200, 200, 200, 0, 0...

つまり、上の行に値(1000)が表示された場合、下の行には均等にその価値を分割するすべての分割の合計が元の値と等しくなるまで繰り返します。

可能であれば、VB の使用は避けたいと思います。


編集1:

遭遇するあらゆる値が n で割り切れるという保証はありますか?

いいえ。ただし、合計値と元の値の差が 1 未満になったら、続行します。

n 回の分割に十分なセルがあることが保証されていますか?

いいえ。

ゼロ以外の値が 1 つだけあることが保証されていますか?

いいえ、複数の値があります。上の行に別の値が表示され、下の行の分割が完了していない場合、下の行では古い分割と新しい分割が合計されます。

ゼロ以外の値は常に同じ位置にありますか?

いいえ。最初の位置以外の任意の位置に出現できます。


編集2:

透明性を保つために、私は大きな費用を均等に分散させようとしています年。

おそらく、これはより良い例でしょう: 予想される入力と予想される出力のタイムライン

ご了承ください:

  • 入力値を分割するプロセスは、それぞれの分割の合計が入力値と等しくなるまで実行する必要があります。

  • 前の入力値の分割がまだ完了していないときに別の入力値が見つかった場合、出力行は、すべての入力値の最初のポイントの条件が満たされるまで、それぞれの分割を合計して続行されます。

答え1

編集:以前の不必要に複雑な式(この改訂) は依然として役に立ちますが、たとえば、入力にスライディング スケーリング係数を適用する必要がある場合は、この回答では、よりシンプルで理解しやすい新しいバージョンに置き換えました。


ヘルパー行/列や追加のテーブルを必要としない非 VBA ソリューションを次に示します。

ワークシートのスクリーンショット

配列に次の数式を入力しB3、右方向に入力します。

{=SUM(IFERROR(INDEX($2:$2,N(IF(1,COLUMN()-(COLUMN(INDEX(3:3,1):INDEX(3:3,$A$5))-1))))/$A$5,0))}

説明:

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

{=
SUM(
  IFERROR(
    INDEX(
      ($2:$2),
      N(IF(1,COLUMN()-(COLUMN(INDEX(3:3,1):INDEX(3:3,$A$5))-1)))
    )/$A$5,
    0
  )
)}

INDEX()n = 5 の場合、最初の引数の 2 番目の引数が実質的に次の引数と同等であることを考慮すると、式ははるかに理解しやすくなります。

COLUMN()-{0,1,2,3,4}


これは基本的に、可変長 (A5私の例では格納されている n に基づく) のオフセット配列を生成して、前の n-1 と現在の入力値にアクセスすることによって機能します。

数式を順に実行すると、I3上記の内容がより明確になります。

  • (COLUMN(INDEX(3:3,1):INDEX(3:3,$A$5))-1){1,2,3,4,5}-1{0,1,2,3,4}
  • COLUMN()-{0,1,2,3,4}{9}-{0,1,2,3,4}{9,8,7,6,5}
  • N(IF(1,{9,8,7,6,5}))N({9,8,7,6,5}){9,8,7,6,5}
  • (INDEX($2:$2,{9,8,7,6,5})/$A$5{100000,0,0,0,7}/5{20000,0,0,0,1.4}
  • SUM(IFERROR({20000,0,0,0,1.4},0))20001.40

INDEX($2:$2,N(IF(1,expression)))は、Excelに配列を返させるために必要なハックです。2expression番目の引数はINDEX()デフォルトで単一の値に評価されるためです。INDEX($2:$2,expression)I3

INDEX($2:$2,COLUMN()-(COLUMN(INDEX(3:3,1):INDEX(3:3,$A$5))-1))INDEX($2:$2,9-(COLUMN($A$3:$E$3)-1))→ → →INDEX($2:$2,9-(1-1))INDEX($2:$2,9)100000

単一の値を返す式内では、範囲の最初のセルの列が返されます。COLUMN(multi-cell-range)

このIFERROR()関数は、数式がシートの左側に近いセルに存在する場合に必要となり、その結果、行ヘッダーにアクセスするか、列の左側のセルにアクセスしようとすることになりますA

ノート:

  • 整形された数式は、入力すると実際に機能します。
  • 整形されたバージョンでは、 を独自の行に残すために括弧($2:$2)が必要です。$2:$2

*なぜハックが機能するのかという正確な説明は、まず私自身が理解するまで待たなければなりません ;-)

答え2

コード:

Sub Divide(n As Integer)
Dim temp(), i As Integer, j As Integer, cnt As Integer, tmp

' Copy values from row to array
temp = Rows(Selection.Row).Value

' Search for the last cell. Use SpecialCells instead is the better variant.
For i = UBound(temp, 2) To LBound(temp, 2) Step -1
    If Not IsEmpty(temp(1, i)) Then
        cnt = i
        Exit For
    End If
Next i

' Perform main operation
For i = cnt To 1 Step -1
    If Rows(Selection.Row).Cells(1, i).Value <> 0 Then
        tmp = Rows(Selection.Row).Cells(1, i).Value
        Rows(Selection.Row).Cells(1, i).Delete Shift:=xlShiftToLeft
        For j = 1 To n
            Rows(Selection.Row).Cells(1, i).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
            Rows(Selection.Row).Cells(1, i).Value = tmp / n
        Next
    End If
Next

End Sub
  • Sub はn値をパラメータとして受け入れます。

  • サブは、選択範囲(左上隅)の行を処理します。

  • Sub は、セル内の値が比較および0除算のために数値に変換されるかnどうかをチェックしません。

  • 他のエラーもチェックされません。

  • 列制限を超えて移動した場合、シフトされた値は失われます。

  • そして最適化は全く行われていません。

このコードをアイデアとして使用します。

答え3

ここでは、VBA を使用する必要のない実用的なソリューションを示します。

唯一の違いは、各コストを個別に入力するためにどこかにテーブルを追加する必要があることです。

これを実行することを強くお勧めします。計算が大幅に簡素化され、財務面での明確さも大幅に向上します。コスト参照、説明、サーバーの種類などの列を簡単に追加できます。また、複数のアイテムがある場合は、数量と基本価格の列を追加することもできます。これを拡張して興味深いレポートを作成できます。私の意見では、VBA を書くよりもはるかに簡単です。


黄色のセルは入力を表します。

ここに画像の説明を入力してください


  1. C2では、他の場所から_N簡単に変数にアクセスできるようにセルに名前を付けます。5 years
  2. 費用(範囲)については、参照しやすいようにA5:D10名前を付けられる表を挿入します。Costs

使用する数式は次のとおりです。必要に応じて、右にドラッグ/コピーします (スクリーンショットでは青色で示されています)。

=IFERROR([@[Real Cost]]/_N;0)

=IF([@From]>0,[@From]+_N-1,"")

=SUMPRODUCT((B$13=Costs[From])*(Costs[Real Cost]))

=SUMPRODUCT((B$13>=Costs[From])*(B$13<=Costs[Until])*(Costs[Yearly Cost]))

関連情報