• ベストアンサー

エクセル:条件に合致するセルに遡って値を入れたい

Excel2013を使っています。 完了日を入力したら、それ以前の同じ顧客コードの空欄の完了日にも、完了日と同じ日付を入れたいです。 例の添付画像の、上の画像から下の画像のようにしたいのです。 D7に「5月31日」と入力すると、D6にも「5月31日」と入って欲しいです。(D3は既に値が入っているので、除外します。) D8に「6月1日」と入力すると、D2、D4、D5にも「6月1日」と入って欲しいです。 どのようにしたらよいでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.8

No.7お礼コメント拝見しました。 メッセージに報れた気がします。ありがとう! 思惑通りの仕様が実現できていない点が幾つかあったりで、 修正と念入り動作確認と概説コメントを追加しました。 差し換えてお試し下さい。 先々困ることがなるべくないよう 少しでもVBAの処理内容が解り易くなるよう シートレイアウト変更時の修正点が解るよう 今出来る事はしたつもりです。 大量コメントが却って煩いかも、ですが 解ったところから消す、ようにして貰えたなら寧ろ嬉しく思います。 正直 この解決策によって、貴方を困らせる事になったりしないかと少しまだ心配です。  前回分はVBAで今回分はVBA以外 という解決だけはとてもおかしいとは思うので  前回分と合わせた包括的解決策の提示 他の方からもあるかも知れませんから もう暫く待ってみて遠慮なく最善の選択をなさるように望んでおります。 ' ' // Private Sub Worksheet_Change(ByVal Target As Range) ' Target : 値が[変化(した)セル] Dim vID ' [顧客コード] 以下 Dim は変数の宣言 Dim vRet ' InputBoxの戻り値 [列2](=B列)では設定する[作業内容]の値 [列4](=D列)では[完了日]を設定するセル範囲 Dim vPrt ' [列2]では[作業内容]に設定する値候補 [列4]では[完了日]の日付値 Dim nTgtRow As Long ' [変化セル]の行番号  If Target.Count > 1 Then Exit Sub ' [変化セル]が複数セルの場合 [(この時点で処理を)抜ける]  If Target.Value = "" Then Exit Sub ' [変化セル]の値が消された場合 [抜ける]  nTgtRow = Target.Row ' [変化セル]の行番号を取得  If nTgtRow < 3 Then Exit Sub ' [変化セル]の行番号が3未満の場合 [抜ける]  Select Case Target.Column ' [変化セル]の列番号によって以降の処理を分岐  Case 2 ' [列2] [顧客コード]が[変化セル]だった場合の処理が以下。   If Cells(nTgtRow, 3) <> "" Then Exit Sub ' [変化セル]行にある[作業内容]が設定済の場合 [抜ける]   vID = Target.Value ' [顧客コード] 取得 Dim i As Long ' [作業内容]を上にループして直近の[作業内容]値を探す際の行番号   For i = nTgtRow - 1 To 2 Step -1 ' [作業内容]を[変化セル]行の直上から2行目まで上方向にループ    If Cells(i, 2) = vID Then Exit For ' [顧客コード]が一致する行を見つけたらループを抜ける   Next i   If i = 1 Then Exit Sub ' [顧客コード]が一致する行が見つからなかったらループ [抜ける]   vPrt = Cells(i, 3).Value ' [顧客コード]が一致した行から [作業内容]に設定する値候補 を取得   Application.EnableEvents = False ' ワークシートのイベント一時停止   On Error GoTo Exit_   Cells(nTgtRow, 3).Select ' [作業内容]の値を設定するセルを選択表示   ' InputBoxで[作業内容]に設定する値候補を表示し、ユーザーに確認・修正を求める   vRet = Application.InputBox("(コード [ " & vID & " ] が正しいか再確認お願いします)" _    & vbLf & vbLf & "[作業内容] [ C" & nTgtRow & " ]" _    & vbLf & vbTab & "  に" _    & vbLf & vbTab & "【" & vPrt & "】" _    & vbLf & "  を 設定しますか?" _    , vID & " [作業内容]", vPrt, , , , , 2)   ' InputBoxで[キャンセル]または[閉じるボタン]が選択された場合は[作業内容]値設定をしない   If VarType(vRet) <> vbBoolean Then Cells(nTgtRow, 3) = vRet ' [作業内容]値設定  Case 4 ' [列4] [完了日]が[変化セル]だった場合の処理が以下。 Dim rngEmp As Range ' [変化セル]直上の [空白(セル)範囲] Dim rTgt As Range ' [変化セル]直上の空白セルの内、[顧客コード]が[変化セル]と共通する [完了日値拡張(セル)範囲] Dim c As Range ' [空白(セル)範囲]総当たりループする際の セル   Application.EnableEvents = False ' (既述   On Error GoTo Exit_ '   ' [完了日][変化セル]直上の [空白(セル)範囲] を取得 見つからない場合は [抜ける]   Set rngEmp = Cells(2, 4).Resize(nTgtRow - 1).SpecialCells(xlCellTypeBlanks)   On Error GoTo 0   Application.EnableEvents = True ' ワークシートのイベント再開   vID = Cells(nTgtRow, 2).Value ' [顧客コード] 取得   Set rTgt = Target ' [完了日値拡張範囲] の最初に[変化セル]を設定   For Each c In rngEmp ' [変化セル]直上の [空白範囲]のセルを総当たりループ    ' [顧客コード]が一致する行を見つけたら    If Cells(c.Row, 2) = vID Then Set rTgt = Union(rTgt, c) ' [完了日値拡張範囲]を追加   Next   If rTgt.Count = 1 Then Exit Sub ' [完了日値拡張範囲]の追加がなければ [抜ける]   vPrt = Target.Value ' [完了日]日付値 所得   Application.EnableEvents = False ' (既述   On Error GoTo Exit_   Target.Select ' [変化セル]=[完了日]日付値セル を選択表示   ' InputBoxで[完了日値拡張範囲]候補を表示し、ユーザーに確認・修正を求める   vRet = VBA.Array(Application.InputBox("[完了日] " & """" & vPrt & """" _    & vbLf & vbTab & "  を" _    & vbLf & vbTab & "【" & rTgt.Address(0, 0) & "】" _    & vbLf & vbTab & "  に" _    & vbLf & vbTab & "範囲拡張して設定しますか?" _    , vID & " [完了日]", rTgt.Address(0, 0), , , , , 8)) '  Array関数追加   ' InputBoxで[キャンセル]または[閉じるボタン]が選択された場合は[完了日]値拡張設定をしない   If VarType(vRet(0)) <> vbBoolean Then vRet(0).Value = vPrt ' [完了日値拡張範囲]に[完了日]日付値設定  Case Else: Exit Sub ' [列2] [列4] 以外の列だった場合 [抜ける]  End Select ' [変化セル]の列番号による分岐を終了 Exit_:  Application.EnableEvents = True ' (既述  If Err <> 1004 And Err <> 0 Then MsgBox "エラー:" & Err & vbLf & Err.Description ' エラーメッセージ End Sub ' ' // ' ' ' 以下、シートレイアウト変更時の修正点 ' ' [顧客コード]が[列2]にあることを指す数字としての 2 ' Case 2 ' Cells(i, 2) Cells(nTgtRow, 2) Cells(c.Row, 2) ' ' [作業内容]が[列3]にあることを指す... 3 ' Cells(i, 3) Cells(nTgtRow, 3) ' ' [完了日]が[列4]にあることを指す... 4 ' Case 4 ' Cells(2, 4) ' ' タイトル行が[行1]にあることを指す... 1 ' If i = 1 Then Exit Sub ' ' タイトル行が[行1]にあり、これに 2 を加えた数字を指す 3 ' If nTgtRow < 3 Then ... ' ' タイトル行が[行1]にあり、これに 1 を加えた数字を指す 2 ' ... To 2 Step -1 ' Cells(2, 4) ' ' //

yoshi1401
質問者

お礼

前回既にすばらしいものを作っていただいたのに、さらに改良版を、ありがとうございます!もう、完璧です!! 質問すべきことがないか確認していたため、お礼が遅くなってしまい、申し訳ありません。 大量コメント、非常にありがたかったです。 シートレイアウト変更に、私でも対応できるようにしてくださり、ありがとうございます。 これも、本当に助かります。 実際に使ってみて変更したい箇所も出て来ると思いますが、ある程度は自分で変更できて、長く長く使わせていただくことになると思います。 VBAで作っていただいて、今回はよかったと思います。 値が固定することで、最下段の値と連動して上の方の値が変化してしまうこともありませんし、データの並べ替えをしたとしても大丈夫ですし。 VBAの元に戻せない特性を心に留め、こまめに保存をしながら使っていこうと思います。 realbeatin様に回答していただけて、本当によかったです。 どうもありがとうございました。 また機会がありましたら、助けていただけるとうれしいです。 この回答をベストアンサーとし、これにて締めさせていただきます。

その他の回答 (7)

回答No.7

こんにちは。 たぶん、もっと簡単に出来るものだと思っていた処が、 話が色々な方向に拡散していることに驚きつつ 何も手が進まない状況になっていることと推察します。 とりあえず、後段で、 前回Q9335940 と 今回9335990 両方の要件を満たす VBAコードを提示しますので。 でも、その前に、少し我慢してでも、 概要の説明を読んで貰えたら、と思います。 Q9335940 ではVBAでいう ワークシート・イベントのWorksheet_Change を使った形で解決をみています。 今回のご質問は、Q9335940 に対する追加、 という意図なのだと思われます。 ワークシート・イベントは、1シートにひとつずつ、しか 書けませんから、Q9335940 の要件と今回の要件とを、 どう組み合わせてひとつに纏めていくか、 ということがこれまでの流れに沿った解決への鍵となります。 しかし、それぞれを散発の質問としてあげる、ということは、 一般的な解釈として、「部分的なサンプル=パーツ」 さえ教えて貰えれば、後の応用は自身で熟せる、 という意味になってしまいます。 たぶん、今回は、これらの前提、特に、1シートにひとつずつ、 ということを知らないでの質問ということだと思います。 その点で、Excel数式を求める質問とは随分と勝手が違ってしまうのです。 知らないことがあったって全然OKなのですが、 解答する方も難しくなる、という点だけは理解して欲しいのと、 もしも次に、似たような処理を追加したい、と考える時は、 (或いはVBAに限らずシートデザインに関わる質問をする時は、) 全体を見渡した最終仕様を考えた上で、ご自身で設計し、仕様書を書く、 というような意識(無論、完璧に出来るものではありません) で、質問を構築するようになるべく努めてみて下さい。 それから、 VBAのワークシート・イベントを扱うことについては、 VBAを覚える課程の中でも初級に位置する内容なので、 Q9335940 での解決回答者様がお書きになったような内容であれば、 人によっては、学ぶことの多いものになっていると思っています。 VBAを始めとしたプロブラムというのは、この世に多々ある訳ですが、 手打ちでの入力作業を副次的にサポートする、 という目的で作るものは、 技術的な面以外の部分で難度の高い課題を抱えたもの、 つまり、中でも難しいプロブラムということになります。 No.1,4様のご指摘も正にこの点に関わることで、 手作業で編集者が確認しながら入力を確定していくのと、 編集者の確認を経ずに自動的に確定していくのとでは、 よほど注意深く、PCによる確認方法を確立しておかないと、 間違いがあった時に修正が難しくなります。 一回、一日で完結する処理内容ならともかく、 日付を遡って処理を加えるとなると、何を基準に修正するか、 人間にもPCにも判別が難しくなってしまうということです。 とまぁ、退屈であろう話をつらつら書いていますが、こいうのを読んで、 "面倒臭い"と感じる方の方が圧倒的大多数で、 私等のようにVBAを扱うことを苦にしない者の方が少数派なのです。 なので、無理に勧めるつもりはありません。 ご自身で関わり方を決めて、 もしもVBAを覚えようということでしたら、応援してくれる人は ここにも、たくさん居るということは、思い出して貰えたら嬉しいです。 んで、ワークシート・イベントは、1シートにひとつずつ ですので、恐縮ながらQ9335940 の解決解答コードは削除した上で 以下のものに替えることになります。 自動的に確定することには変わりありませんが、 ユーザーに[OK|キャンセル]確認を求めるダイアログ表示を挟んでいます。 黙って勝手に確定する場合からすれば、手順的に、Enterキー を一回余計に押すことになります。 手打ちでの入力作業を副次的にサポートする 場合によく見かける対話型の処理、ということになります。 こういう仕様を実現する為に、少し複雑な内容になっています。 コードの1行、1文字に、求める仕様を表現しています。 普段の私は、処理内容を概説するコメントを添えて掲げる ことが多いのですが、今回はコトバに纏めるのも 量的に大変なこともあって、こちらからは説明は書きません。 今後興味を持たれることがあればお尋ねください。 出来れば、一度、動作を確認してみてください。 恐らく採用されないだろうなとは想っていますし、 VBA以外の方法を検討するのがいいという判断もあると思います。 でも試してみれば、前段で説明した難点とか、 仕様とかシート設計というものが、 今より少しイメージし易くなるのでは、と思っています。 ' ' // Private Sub Worksheet_Change(ByVal Target As Range) Dim rngEmp As Range, rTgt As Range, c As Range Dim vID, vRet, vPrt, nTgtRow As Long, i As Long  If Target.Count > 1 Then Exit Sub  If Target.Value = "" Then Exit Sub  If Not Target.Column Like "[24]" Then Exit Sub  nTgtRow = Target.Row  If nTgtRow = 1 Then Exit Sub  Select Case Target.Column  Case 2   If Cells(nTgtRow, 3) <> "" Then Exit Sub   vID = Target.Value   For i = nTgtRow - 1 To 2 Step -1    If Cells(i, 2) = vID Then Exit For   Next i   If i = 1 Then Exit Sub   vPrt = Cells(i, 3).Value   Application.EnableEvents = False   On Error GoTo Exit_   Cells(nTgtRow, 3).Select   vRet = Application.InputBox("(コード [ " & vID & " ] が正しいか再確認お願いします)" _    & vbLf & vbLf & "[作業内容] [ C" & nTgtRow & " ]" _    & vbLf & vbTab & "  に" _    & vbLf & vbTab & "【" & vPrt & "】" _    & vbLf & "  を 設定しますか?" _    , vID & "    [作業内容]", vPrt, , , , , 2)   If VarType(vRet) <> vbBoolean Then Cells(nTgtRow, 3) = vPrt  Case 4   On Error GoTo Out_   Set rngEmp = Cells(2, 4).Resize(nTgtRow - 1).SpecialCells(xlCellTypeBlanks)   On Error GoTo 0   vID = Cells(nTgtRow, 2).Value   Set rTgt = Target   For Each c In rngEmp    If Cells(c.Row, 2) = vID Then Set rTgt = Union(rTgt, c)   Next   If rTgt.Count = 1 Then Exit Sub   vPrt = Target.Value   vRet = Application.InputBox("[完了日] " & """" & vPrt & """" _    & vbLf & vbTab & "  を" _    & vbLf & vbTab & "【" & rTgt.Address(0, 0) & "】" _    & vbLf & vbTab & "  に" _    & vbLf & vbTab & "範囲拡張して設定しますか?" _    , vID & "    [完了日]", rTgt.Address(0, 0), , , , , 8)   If VarType(vRet) <> vbBoolean Then    Application.EnableEvents = False    On Error GoTo Exit_    rTgt = vPrt   End If  Case Else: Exit Sub  End Select Exit_:  Application.EnableEvents = True  If Err Then MsgBox "エラー:" & Err & vbLf & Err.Description Out_: End Sub ' ' // Excelに備わっている  手打ちでの入力作業を副次的にサポートする 為の機能、  ●セルを選択した状態で Alt+↓キーで、入力候補を表示して選択入力  ●[データ]>[データの入力規則]>[リスト]で、入力候補を表示して選択入力 等の活用についても、考えてみても良さそうかな?と思います。 以上、ご参考まで。

yoshi1401
質問者

お礼

私の思いを汲んでくださっての丁寧な回答を、ありがとうございます。 まさにご推察通りの状況でした。 皆様の回答を拝見して、どうすればよいのかと途方に暮れていたところ、realbeatin様より、すべてが解決できる方法と今後私が質問する際に心掛けるべきことを教えていただけました。 今まで、試しに使ってみて、もっとこうしたいということに気づいて足すというやり方でエクセルを使ってきました。 これからはもっと、最初から全体を見渡して考えることを、心がけようと思います。 本当にありがとうございました。 作っていただいたワークシート・イベントは、すばらしいものでした。 相手の求める以上のものを汲み取ってこのようなものを作ることができるrealbeatin様を、尊敬します。 本当に本当に、ありがとうございました。 これで締め切りたいところですが、作っていただいたワークシート・イベントのことで質問したいことが出てくるかもしれないので、もう少しだけ締め切らずにいようと思います。

  • bunjii
  • ベストアンサー率43% (3589/8249)
回答No.6

>完了日を入力したら、それ以前の同じ顧客コードの空欄の完了日にも、完了日と同じ日付を入れたいです。 組み込み巻数を使った数式をD列へ入力して置き、完了日が確定した日付を1ヶ所キーボードから入力すると同一顧客コードに対するD列がすべて同一日付が代入されると言うことでしょうか? 他の解答者から循環参照になるとの意見もありますので好ましい考え方ではありません。 しかし、作業用の列を用意することで循環参照を回避することが可能になります。 但し、D列の数式はキーボードから入力したセルについて数式を日付で上書きされますのでキーボードから入力したセルは元の数式を破棄することになります。 F列を作業用に使うとして次の数式をF2セルへ設定します。 =MAX(MAX(INDEX((B3:B$11=B2)*NOT(ISBLANK(B3:B$11))*NOT(ISFORMULA(D3:D$11))*ROW(D3:D$11),0)),MAX(INDEX((B$1:B1=B2)*NOT(ISFORMULA(D$1:D1))*ROW(D$1:D1),0))) F2セルを下へ10行目までコピーします。 D2セルには次の数式を設定します。 =IF(F2,INDEX(D:D,F2),"") D2セルを下へ10行目までコピーします。 D2:D10がすべて数式のときF2:F10はすべて0が代入されます。 D3セルに5/6と入力すると先に設定された数式は2017/5/6と言う日付に置き換わり、D6とD7が同じ日付を表示します。 次にD7セルへ5/31と入力するとD7セルは2017/5/31に置き換わり、D6セルがD7セルと同じ日付に置き換わります。 最後にD8セルへ6/1と入力するとD2とD4とD5セルはD8セルと同じ日付に置き換わります。 最終結果の画像を添付します。 実際のデータでは行数が多くなると思いますので数式のB$11とD$11について行番号を実際のデータ行数に合わせて修正してください。

yoshi1401
質問者

お礼

ご回答くださり、ありがとうございます。 おおむね期待通りの動きをしてくれるのですが、同じ顧客コードで複数の日付を入力した場合、式の部分が全て一番新しい日付で置き換わってしまうのが難点でした。 (一度、完了日が入ったセルの値は、固定したかったので。質問の仕方がわかりにくかったですね。すみません。) でも、考えてくださってうれしかったです。 ありがとうございました。 今回は、No.7様の案を採用させていただくことにしました。 これで締め切りたいところですが、質問したいことが出てくるかもしれないので、もう少しだけ締め切らずにいさせて下さい。

  • imogasi
  • ベストアンサー率27% (4737/17069)
回答No.5

直前の質問もそうだが、質問の表現が甘いのでは。こんなことでは、回答できないように思う。 >D3は既に値が入っているので、除外します。 D3の行の顧客コードは4321で、D8の行の顧客コードは1234だね。 顧客コードが同じ行だけ6月1日の日付を入れるのではないのか。 そういうことを含めて、別に説明することがあるのでは。 ーー 関数での回答を望んでいるのか。質問内容からして、関数での処理には適してない。こういう仕事関連らしい課題を関数などでやろうというのは無理だと思う。 最低VBAは使えるのか。 VBAなりを(それも、初級ではなくて)勉強して考える問題。それにデータベース処理を使わないとやりにくいと思う。 ーー ちなみに、なぜ5月2日や5月3日に6月1日の日付を入れるのか? 5月2日や5月3日には入力途中で、6月1日に完了したのか。 すると入力は1連のものとなるが、他の種類の入力はあり得るのでは? そういう仕事内容を説明できない人に、こんな会社のようなパブリックのシステムを任せて大丈夫か? ーー Changeイベントを使う方法の回答が出ているが、私は直前の質問に対して、シートにボタンを1つ設け、そのクリックイベントで対象顧客コードや 完了日を取った方がよいのではと思った。 ーー 6月1日をとらえるタイミングにあいまいさを感じるので、人間が意識して 選択するようにすべきでしょう。未済が2つ以上の顧客(コード)が(最近の下部の行に)あったりしないのか?。

yoshi1401
質問者

お礼

わかりにくい質問をして不快にさせてしまい、申し訳ありません。 >>D3は既に値が入っているので、除外します。 >D3の行の顧客コードは4321で、D8の行の顧客コードは1234だね。 >顧客コードが同じ行だけ6月1日の日付を入れるのではないのか。 D3除外は、同じ顧客コードのD7に入力した際の記述でした。 >関数での回答を望んでいるのか。 どんな方法で実現できるのか、自分でもわからない状態での質問でした。 >ちなみに、なぜ5月2日や5月3日に6月1日の日付を入れるのか? >5月2日や5月3日には入力途中で、6月1日に完了したのか。 作業した日が5/2や5/3で、作業が完了したのが6/1ということです。 間に違う作業をすることがあるので、必ずしも作業日に完了はしないのです。 また、作業日ごとに、行を改める必要があったのです。 >そういう仕事内容を説明できない人に、こんな会社のようなパブリックのシステムを任せて大丈夫か? 返す言葉もございません。 >Changeイベントを使う方法の回答が出ているが、私は直前の質問に対して、シートにボタンを1つ設け、そのクリックイベントで対象顧客コードや完了日を取った方がよいのではと思った。 それもひとつの方法ですね。アドバイスをありがとうございます。 >6月1日をとらえるタイミングにあいまいさを感じるので、人間が意識して 選択するようにすべきでしょう。未済が2つ以上の顧客(コード)が(最近の下部の行に)あったりしないのか?。 未済が2つ以上の顧客コードは、あり得ます。 同顧客コードで未決のものは、すべて同じ完了日を入れたかったです。 今回は、No.7様の方法で、解決することができましたが、厳しいご意見に、自分の甘さを思い知りました。 ありがとうございました。

回答No.4

と言ってもピンと来ないかもしれませんので、老婆心ながら少しだけ。 例えば前の質問で、 A8・B8セルにそれぞれ、「5/1」「1234」と入力したとします。 すると、C8セルには最新データを参照し「入力」と自動入力されます。 あ、間違った!顧客コードは「2345」だわ!!最新は「返却」だわ!!! と気付き、顧客コードを打ち直してもC8は「入力」のままです。 元に戻す機能も使えません。 ってことは、自力で最新データを拾ってくるか、 保存せずに閉じて開きなおすか、という選択肢を迫られます。 ・・・大丈夫ですか? 例えば、今回の質問。これは杞憂かもしれませんが。 例示を拝見すると、顧客番号「4321」について、 5/6に完了(3行目)とあります。 対し、5/4の時点で完了日が入っていないレコード(6行目)も見られます。 これは 「5/4の時点で、同じ顧客コードの作業が2個発生する可能性がある」 ということでしょうか。 だとしたら、5/6の完了時点で「同じ顧客コードだから♪」と 6行目に「5/6」を入力されてしまったら・・・大丈夫ですか? 他にも幾つか(私が作るなら)思うところがあるんですが、 そんなこんなで、運用面で問題は出ませんか? という問いに行きつきました。 エクセルは表計算ソフトですから、 データベースとしての運用はあまり得意ではありません。  ※出来ないとは言いません。 踏まえ、もう少し運用を含めて構成を検討し直した方が良いかもしれません。 自動化しても使い勝手が悪かったら意味がありませんから。 3番さんのご回答にもあるように、 「入力用」と「表示用」は別に持つ方が良いと思いますよ。 そうすれば関数だけで(頑張れば)実現可能な案件ですよ。 何でもかんでもVBAというのもどうなのかと思いますし。 配列関数は不得意で分かりづらい式になってしまって申し訳ないのですが、 =IFERROR(IF(C8<>"","",INDEX(C$2:C7,MAX(IF((B$2:B7=B8),G$2:G7,"")))),"")   ※Ctrl+Shift+Enter で確定(配列数式) 例えばこんな式で作業列(図のG列)を使って、前の質問も対応できます。 図のD列がソレです。  ※コピペするなら、D8セルに貼ってください。

yoshi1401
質問者

お礼

No.1に続いて、詳しく問題点を教えてくださり、ありがとうございます。 また、VBA以外の選択肢も考えてくださり、ありがとうございます。 確かに失敗が少なそうですね。 ただ、列がかなり増えてしまうのですよね…。 今回は、No.7様の案を採用させていただきますが、tsubu-yuki様にもいろいろためになることを教えていただきました。 どうもありがとうございました。

  • mt2015
  • ベストアンサー率49% (258/524)
回答No.3

配列数式と書式設定でやる例です。 完了日の入力と表示で列を別けましょう。 添付の図では、D列を入力用、E列を表示用としました。 E2セルに↓の式を入れ、Shift+Ctrl+Enterで配列数式として確定します。 =MIN(IF((B2:B$100=B2)*(D2:D$100<>""),D2:D$100,"")) さらにセルの書式設定でユーザ定義を選択し、以下の様に書式設定してください m"月"d"日";;"" 後は、E2セルを下方向にコピーします。 #行の最後を100行目としています。ここは実際の表に合わせて変更してください。

yoshi1401
質問者

お礼

ご回答くださり、ありがとうございます。 おおむね期待通りの動きをしてくれるのですが、同じ顧客コードで複数の日付を入力した場合、式の部分が一番新しい日付で置き換わってしまうのが難点でした。 (一度、完了日が入ったセルの値は、固定したかったので。) でも、考えてくださってうれしかったです。 ありがとうございました。

  • Nouble
  • ベストアンサー率18% (330/1783)
回答No.2

先ず、質問です 以下の、やり方 では 反復計算が 必要に、なりますが 構いませんか? 反復計算を onに、します https://support.office.com/ja-jp/article/%25E6%2595%25B0%25E5%25BC%258F%25E3%2581%25AE%25E5%2586%258D%25E8%25A8%2588%25E7%25AE%2597%25E3%2580%2581%25E5%258F%258D%25E5%25BE%25A9%25E8%25A8%2588%25E7%25AE%2597%25E3%2580%2581%25E3%2581%25BE%25E3%2581%259F%25E3%2581%25AF%25E7%25B2%25BE%25E5%25BA%25A6%25E3%2582%2592%25E5%25A4%2589%25E6%259B%25B4%25E3%2581%2599%25E3%2582%258B-F38C7793-0367-41CE-B892-DFE54946BD76?ui=ja-JP&rs=ja-JP&ad=JP&fromAR=1 D2を、選択 ユーザー書式で m/d;"";"";@ に、設定 http://udemy.benesse.co.jp/office-enhance/excel-user-definition.html =MAX(INDEX((B2:B8=B2)*(D2:D8),,)) と、入力 D8まで、フィル 以上です 実際に、使用する 際は セル範囲の、変更が 求められます

yoshi1401
質問者

お礼

ご回答くださり、ありがとうございます。 おおむね期待通りの動きをしてくれるのですが、同じ顧客コードで複数の日付を入力した場合、式の部分が一番新しい日付で置き換わってしまうのが難点でした。 でも、考えてくださってうれしかったです。 ありがとうございました。

yoshi1401
質問者

補足

今回は、No.7様の案を採用させていただくことにしました。 これで締め切りたいところですが、質問したいことが出てくるかもしれないので、もう少しだけ締め切らずにいさせて下さい。

回答No.1

例えば。 Private Sub Worksheet_Change(ByVal Target As Range)   If Target.Column = 4 And Target.Value <> "" Then     For i = Target.Row - 1 To 2 Step -1       If Cells(i, 2) = Cells(Target.Row, 2) And Cells(i, 4) = "" Then         Cells(i, 4) = Target.Value       End If     Next   End If End Sub VBAを走らせると、基本的には「元に戻す」機能が初期化されます。 つまり、入力後に「あ、間違った!」が許されなくなるんです。 先ほどの質問でも思ったんですが、 VBAのメンテナンスはできますか?も含めて その運用で本当に大丈夫ですか? 少し心配です。

yoshi1401
質問者

お礼

ご回答くださり、ありがとうございます。 単体では、希望通りの動作をしてくれました。 また、VBAの弱点も教えてくださり、ありがとうございます。 確かに自分でも、運用が不安になってしまいました。 No.4のお礼に、続きます。

関連するQ&A