• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:エクセル:最大値の取得と欠番の一覧表示)

エクセルで最大値の取得と欠番の一覧表示

このQ&Aのポイント
  • エクセルでA列に場所名、B列に棚の番号または名称、C・D列に数字が入ったデータを扱います。同じ並びのデータが複数存在し、E・F・G列にA・B・C列の並びで重複しないデータを表示したいです。さらにH列には対応するD列の最大値を表示させたいです。
  • このような場合、ピボットテーブルの機能を使うことで要求を満たすことができます。
  • さらに、I列に欠番の数とJ列より右に欠番の一覧を表示させたいです。また、J列以降には連続した数値を表示することができます。

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

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.10

こんばんは。Wendy02です。 >こちらとしては単純に優先順位ABCDの順に昇順で並び替えられればOKなのですが。 元のご質問の >倉庫 12  2  21 >書庫  5  3  1   ←こちらが下になって、12 と 5では、5が下になっていたからです。 一番目のSort のOrder1 をxlAscending, に換え、 .Sort _        Key1:=.Cells(1, 2), _        Order1:=xlAscending, 二番目のSort のOrder1 をxlAscending, に換えれば標準的な並べ替えになるはずです。 .Sort _        Key1:=.Cells(2, 2), _        Order1:=xlAscending, _ ただ、元の表が、どのような並び方が良いのかは、本当は分かっていませんので、たぶん、こんな風かなっていうところで、これは、あまり自信がないです。まあ、記録マクロでも可能なものですから、最初は、手作業で試して、記録マクロに写してもよいです。

その他の回答 (9)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.9

こんばんは。Wendy02です。 もしかしたら、「お礼」をつけてしまうと、後、入れられない恐れがあるかもしれない不安がありましたので、以下はダミーでもありませんが、当初、作っておいた並べ替えマクロをここにおいておきます。 Sub SortPrc() '並べ替えマクロ '基本的に、項目行としての1行目は必要です。 With Range("A1", Range("A65536").End(xlUp)).Resize(, 4) '4列に対して      .Sort _        Key1:=.Cells(1, 2), _        Order1:=xlDescending, _        Header:=xlGuess, _        OrderCustom:=1, _        MatchCase:=False, _        Orientation:=xlTopToBottom, _        SortMethod:=xlPinYin             .Sort _        Key1:=.Cells(2, 2), _        Order1:=xlDescending, _        Key2:=.Cells(2, 3), _        Order2:=xlAscending, _        Key3:=.Cells(2, 4), _        Order3:=xlAscending, _        Header:=xlGuess, _        OrderCustom:=1, _        MatchCase:=False, _        Orientation:=xlTopToBottom, _        SortMethod:=xlPinYin   End With End Sub

HGK
質問者

補足

丁寧にありがとうございます。この並び替えはどういうルールになっているのでしょうか?こちらとしては単純に優先順位ABCDの順に昇順で並び替えられればOKなのですが。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.8

こんばんは。 それは良かったでした。ただ、もうしばらく試してみて、こうしたほうがよい、ということがあったら、ここに加えてください。今、こちらから言うのは変ですが、なんとなく、システム的には足りないような気がしています。 その理由の一つとしては、並び替えは、ユーザーに依存しているのが原因だからです。少し、特殊な並べ替えをしているような気がしました。もしも、そちら側で出来ていらっしゃるのでしたら、これは、無視なさって結構です。 なお、今、このご質問は、こちらでマーキングしていますので、こちらに特別な事情がない限りは、しばらく返事が付かなくても、必ず、フィードバックします。

HGK
質問者

お礼

丁寧にありがとうございます。この質問はあえて締め切らずしばらくこのままにしておきます。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.7

こんばんは。Wendy02です。 >2つで1組とか3つで1組のものがあり同じ並びで重複する場合が少しはあるのです。 私は、それに関しては想定していませんでしたが、並びが昇順になっていなかったら、というのは、頭の片隅にはありました。 >実際の欠番は2と3のため「欠番個数」は2と表示したいです。 それはここだけを直せば、欠番個数は正しくでるはずです。 以下のところから、8行目の部分を直せばよいはずです。 Function BetweenCount(arg2() As Integer) As Integer :1行目 '数値間をカウントする 8行目: If arg2(i) > 0 Then      ↓     If arg2(i) > 0 And bufNum <> arg2(i) Then '加入 としてあげれば、直るはずです。 一応、うまくできなかったら、もう一度、こちらですべてをチェックしなおし、コードをすべて出します。

HGK
質問者

お礼

今日、会社で最終確認しました。私がやりたかった事が完全にできました。本当にありがとうございました。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

こんばんは。Wendy02です。 再度、間の数字の生成部分の出力方法を全面的に変更しました。 コードの真ん中の以下の部分をFunction ~ End Function までのひとまとまりの部分を上書きしてください。 分かりにくいようでしたら、Visual Basic Editor の 「(General)  |  ここの窓 の▼」 ←をクリックして、  StringOut という名称を選んでくだされば、その場所に飛びます。下のFunction BetweenCount は、残してくださいね。 「数値が文字列として保存」に関しては、そのままでも良いように、日付に変わらないように、罫線素片を利用しました。ですから、オプションのエラーチェックの変更は必要ありません。ただし、文字列と数値が混在になります。 '-------------------------------------------------------- Function StringOut(arg() As Integer) As Variant  '数字間を文字列出力  Dim c As Variant  Dim i As Long  Dim j As Long  Dim k As Long  Dim arBuf() As String  Dim arBuf2() As Variant  Dim buf As String  Dim buf2 As String  Dim strJoin As String  ReDim arBuf(UBound(arg()))  For i = LBound(arg()) To UBound(arg())   arBuf(i) = CStr(arg(i))  Next i  strJoin = "," & Join(arBuf, ",") & ","    j = 1  Do Until j = arg(UBound(arg())) + 1   If InStr(strJoin, "," & CStr(j) & ",") = 0 Then    If buf = "" Then     buf = j    End If   End If   If InStr(strJoin, "," & CStr(j) & ",") > 0 Then    If buf <> "" Then     buf2 = j - 1     ReDim Preserve arBuf2(k)     If buf <> buf2 Then      arBuf2(k) = buf & " ─ " & buf2 '罫線素片を使用     Else      arBuf2(k) = buf     End If     k = k + 1     buf = ""    End If   End If   j = j + 1  Loop  If k = 0 Then   'ダミー   ReDim arBuf2(0)  End If  StringOut = arBuf2() End Function '-------------------------------------------------------- なお、今は、画面の出方が遅いので、以下の部分を修正してください。 PickupMax のだいたい、29 行目あたりに、出力用タイトルとありますが、その下に、以下を加えてください。 '出力用タイトル  Application.ScreenUpdating = False '加入 また、同じマクロの最後の部分で、以下の二行を加えてください。  Set mRng = Nothing '加入  Application.ScreenUpdating = True '加入 End Sub なお、うまく行かないようでしたら、こちらで、もう一度、始めからコードを出します。

HGK
質問者

お礼

こんばんは。会社でいろいろ試してみました。ほとんど問題なく出来ましたが「欠番個数」が-2 になったものがありました。調べてみると忘れていたことがありました。それはA~D列の並びが完全に同じ行が複数ある点です。2つで1組とか3つで1組のものがあり同じ並びで重複する場合が少しはあるのです。欠番個数は最大値からD列の数を引いて出してますよね?重複があれば計算が合わなくなります。あらかじめA~D列の並びが完全に同じ行が複数行ある場合1行分だけ残して他の行は削除するのが簡単だと思いますが、行の削除をせずに「欠番個数」がきちんと計算される方法はないでしょうか? 例) 倉庫 12 1 1 1 倉庫 12 1 1 1 倉庫 12 1 1 1 倉庫 12 1 1 4 なら現状では「欠番個数」は0になりますが、実際の欠番は2と3のため「欠番個数」は2と表示したいです。

HGK
質問者

補足

何度もありがとうございます。今手元にある簡単な例ではエラーもなく完璧に動作しました。明日会社で実際に試してみて再度お礼させていただきます。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.5

こんばんは。Wend02です。 とりあえず、この件だけですが、 >緑の三角印がでます。他の数字では1つだけの欠番の場合4-4とか5-5とかの表示になります。 そのまま出力すると、日付のシリアル値に変わってしまいますので、それは、「'(アポストロフィ)」をつけて、文字列として出しています。 ツール-オプション-エラーチェックの  文字列として保存されている数値(N) ( 領域内の矛盾した数式(F))←たぶん必要はない 辺りをオフにしてくださいるとありがたいのですが。 書式で、文字列にしてしまうと、また、別の問題が発生することがあります。 それは、数式を用いたときに、Excelでは、そのセルを参照すると、そのセルの数式が不活性になってしまうという不具合があるのです。別に、文字列書式(@)にすることは、やぶさかではないのですが。 それから、 >4-4は単に4と表示されるのが理想です。 今は、1 の場合しか、想定されていませんでした。 今は、こちらで仮定したデータでしか、検査されていませんので、まだ、見えていない部分があります。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

こんばんは。Wendy02です。 丁寧に、調べたつもりです。ただ、様々な条件の下では、これがうまくいくか分かりません。なお、ここには、並べ替えプログラムはついていませんので、必ず、並べ替えした状態で行ってください。別途、並べ替えプログラムは、用意はしてあります。 ここを換えれば、位置を替えて書き出すことが可能です。 --------------------------------------------------  'ユーザー設定  Const RNG_NAME As String = "E2" '書き出す列の1列目  Const START_ROW As Integer = 2 'データの始まりの行数 -------------------------------------------------- '標準モジュールに設定してください。 '---------------------------------------------------------------- Private Const MAXCOL As Integer = 256 '現行の最大列は、256列 Sub PickupMax() '最大値の取得と欠番の一覧表示  Dim i As Long  Dim j As Long '出力行  Dim k As Integer  Dim ChkDat As String '1~3行目までを合わせた文字列  Dim ColumnChk As Integer '出力列数  Dim mRng As Range  Dim bufNum() As Integer  Dim Buf1 As Variant '--------------------------------------------------  'ユーザー設定  Const RNG_NAME As String = "E2" '書き出す列の1列目  Const START_ROW As Integer = 2 'データの始まりの行数 '---------------------------------------------------  'データ範囲  Set mRng = Range("A" & CStr(START_ROW), Range("A65536").End(xlUp)).Resize(, 4)    With mRng    '出力部分を一旦消去    With Range(RNG_NAME).CurrentRegion      .Offset(, Range(RNG_NAME).Column - 1).Resize(, .Columns.Count - Range(RNG_NAME).Column + 1).ClearContents    End With      '出力用タイトル  If Range(RNG_NAME).Row > 1 Then j = -1    Range(RNG_NAME).Offset(j, 0).Value = "場所"  'ユーザー設定値    Range(RNG_NAME).Offset(j, 1).Value = "大分類"    Range(RNG_NAME).Offset(j, 2).Value = "中分類"    Range(RNG_NAME).Offset(j, 3).Value = "最大値"    Range(RNG_NAME).Offset(j, 4).Value = "欠番個数"    Range(RNG_NAME).Offset(j, 5).Value = "欠番一覧"  j = j + 1   'チェック用の複数列の文字列データ    ChkDat = .Cells(1, 1).Value & .Cells(1, 2).Value & "," & .Cells(1, 3).Value     For i = 1 To .Rows.Count + 1    If ChkDat <> .Cells(i, 1).Value & .Cells(i, 2).Value & "," & .Cells(i, 3).Value Then     '最大値出力     .Cells(i - 1, 1).Resize(, 4).Copy Range(RNG_NAME).Offset(j)     '内訳出力(サブルーチン)     If k > 0 Then      Range(RNG_NAME).Offset(j, 4).Value = BetweenCount(bufNum())      Buf1 = StringOut(bufNum())            '出力列のチェック      If (UBound(Buf1) + 5 + Range(RNG_NAME).Column) > MAXCOL Then        ColumnChk = MAXCOL - (UBound(Buf1) + 5 + Range(RNG_NAME).Column)      Else        ColumnChk = UBound(Buf1) + 1      End If            Range(RNG_NAME).Offset(j, 5).Resize(, ColumnChk).Value = Buf1      Erase bufNum()      k = 0      ChkDat = ""     Else      '間がなく次に違うCheck行がある場合      ReDim bufNum(0)      bufNum(0) = .Cells(i - 1, 4).Value            Range(RNG_NAME).Offset(j, 4).Value = BetweenCount(bufNum())      Buf1 = StringOut(bufNum())      Range(RNG_NAME).Offset(j, 5).Value = Buf1      ChkDat = ""     End If     j = j + 1    Else     ReDim Preserve bufNum(k)     bufNum(k) = .Cells(i, 4).Value     k = k + 1    End If   If ChkDat = "" Then    ChkDat = .Cells(i, 1).Value & .Cells(i, 2).Value & "," & .Cells(i, 3).Value    k = 0    ReDim bufNum(k)    bufNum(k) = .Cells(i, 4).Value    k = k + 1   End If   Next i  End With End Sub Function StringOut(arg() As Integer) As Variant  '数字間を文字列出力  Dim c As Variant  Dim i As Long  Dim j As Long  Dim arBuf() As String  If UBound(arg()) > 0 Then   '番号2 より以上   If arg(0) > 2 Then    ReDim Preserve arBuf(j)     arBuf(j) = "'1 - " & CStr(arg(i - 1) - 1)     j = j + 1   ElseIf arg(0) = 2 Then    ReDim Preserve arBuf(j)     arBuf(j) = "'1 "     j = j + 1   End If   For i = 1 To UBound(arg())     If arg(i) - arg(i - 1) > 1 Then     ReDim Preserve arBuf(j)       arBuf(j) = "'" & CStr(arg(i - 1) + 1) & " - " & CStr(arg(i) - 1)       j = j + 1    End If   Next i  Else   ReDim arBuf(0)   If arg(0) > 2 Then    arBuf(0) = "'1 - " & CStr(arg(0) - 1)   ElseIf arg(0) = 2 Then     arBuf(0) = "'" & CStr(arg(0) - 1)   End If  End If  StringOut = arBuf() End Function Function BetweenCount(arg2() As Integer) As Integer '数値間をカウントする  Dim cnt As Integer  Dim bufNum As Integer  Dim i As Integer  If UBound(arg2()) > 0 Then   For i = LBound(arg2()) To UBound(arg2())    If arg2(i) > 0 Then     If arg2(i) <> 1 And bufNum = 0 Then      cnt = arg2(i) - 1     ElseIf bufNum > 0 Then      cnt = cnt + (arg2(i) - bufNum) - 1     End If     bufNum = arg2(i)    End If   Next i  Else   If arg2(i) > 0 Then    cnt = arg2(i) - 1   Else    cnt = 0   End If  End If  BetweenCount = cnt End Function '----------------------------------------------------------------

HGK
質問者

補足

熱心に考えて頂いてありがとうございます。 並び替えはあらかじめしています。 いくつかの例で試してみました。 うまくいかなかった例は次のような場合です。 質問の欄にあげた例で説明します。(1行目にはタイトルとしてA,B,C,Dが入っています) まず1行目は 場所 大分類 中分類 最大値 欠番個数 欠番一覧 ときちんと表示されます。 2行目にはA~D列の最初のカタマリの場所、大分類、中分類、最大値、欠番個数、欠番一覧も問題なく出来ます。 E2セルから順に 倉庫,12,1,15,13,2-14 のようにです。 3行目は 倉庫,12,2,21,19 までは表示されますが、J列より右の欠番一覧が出ません。 ここで止まり以下のエラーメッセージが表示されます。 実行時エラー'9' インデックスが有効範囲にありません と出ました。 デバックしてみると 真ん中より少し下 ’番号2より以上 という部分から3行下の arBuf(j) = "'1 - " & CStr(arg(i - 1) - 1) が黄色くなっています。 いろいろためしてみた結果、セルD4の数字が0,1,2の場合は成功します。3以上だとエラーが出ます。 他のD列でも同様みたいです。現実には1や2が欠番ということもあります。また0が入力されることはありません。 D列が2の場合欠番一覧の最初のセル(J列)には1と表示されますが、数値が文字列として保存されて場合に出る 緑の三角印がでます。他の数字では1つだけの欠番の場合4-4とか5-5とかの表示になります。 わがままついで言いますと4-4は単に4と表示されるのが理想です。 お忙しいと思いますがもう少しお付き合い願えれば幸いです。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.3

こんにちは。Wendy02です。 少し、てこずっています。少し、言い訳させていただきます。 コードを書いているうちに、実務的には、私が、最初考えていたよりも単純ではないような気がしました。やっている内に、私の昔やっていた仕事を思い出したからです。 単なる想像の範囲ならよいのですが……。1000個までとおっしゃいましたが、なんとなく、同じ雰囲気がしたからです。たぶん、ここに出したサンプルの表は、かなり単純化されているのではないでしょうか? (一応、並べ替えは済んでいるものとしています) A  B  C  D 倉庫 12  1  1 倉庫 12  1  15 倉庫 12  2  5 倉庫 12  2  21 書庫  5  3  1   このサンプルの表は、12,1, 1~12,1,15 で、ないものは、確かに、2-14 ですね。 最初は、その歯抜けの数字が、シリーズ(1ずつ増えて、最大値の一つ手前まで抜けはない)になっていると考えていたのですが、私の人生経験(^^;)から、そんなにうまくいかないだろうなって思い、出来上がったものをやり直すことにしました。 私のしていた仕事で、その番号が、お客さんとメーカーの橋渡しのために使われたりしたのです。例えば、国内で流通したものか、海外に輸出されたものか、など、サポート体制が違ってしまいます。 具体的には、以下のようなものを想定しなければ、ダメだなって思ったからです。 A  B  C  D 倉庫 12  1  1 倉庫 12  1  6 倉庫 12  1  10 倉庫 12  1  15 倉庫 12  2  5 倉庫 12  2  15 倉庫 12  2  21 書庫  5  3  1 すみませんが、もう少し、お時間をください。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんにちは。Wendy02です。 お話は分かりました。 >できれば一つのセルに 2-14 とか 1-4 とか6-20 のように表示できればうれしいです。 の方が、VBAでは楽だと思います。VBAで作ってみます。 ただし、ピボットで作った場所自体は、ちょっとデータの吐き出し場所としては、不適当な気がします。 しかし、最初から作ると、こちらでは予想外の問題が発生するような気がします。 コードが長くなると、こちらの思惑で進めることが出来ませんので、いちいち途中で確認してもらわないといけなくなります。 どちらがよいのか、こちらで、しばらく考えてみます。ただし、ピボット自体は、使いません。ピボットはテーブルを残していますので、それが「ある・なし」の判断条件でコードを変えなくてはならないから、面倒な気がします。 特に、この掲示にレスは必要ありません。次にコードを載せてからで良いです。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.1

こんばんは。 設問は読みましたが、以下のようになる、根拠がさっぱり見えてきません。 >1行目のE・F・G・H列は 倉庫 12  1  15 >2行目のE・F・G・H列は 倉庫 12  2  21 >3行目のE・F・G・H列は 書庫 5   3  1  > >となるようにしたい。 と最初の表示とは、一体、どんな結びつきがあるというのでしょうか? 重複を省くというのは、同じものを出さないということであって、同じものがあるもの、すべてを省くということではないと思います。 倉庫 12  1  1 倉庫 12  2  5 これらは、どんな条件で、これは省かれたのでしょうか?

HGK
質問者

補足

すみません、言葉が足りませんでした。 第一段階として、E・F・G列にA・B・C列の並びで重複するものは省いて表示させます。 1行目と2行目のA・B・C列は 倉庫 12 1 と同じなのでE・F・G列の1行目は 倉庫 12 1、同じく2行目は 倉庫 12 2 、3行目は書庫 5 3になります。 第二段階としてH列の表示です。1行目のE・F・G列は 倉庫 12 1 であり、 この「倉庫 12 1」の並びと同じものをA・B・C列からさがし、対応するD列の最大値をH列に表示させたいのです。1と15なら15が最大値なのでH1には15を表示させたいのです。H2は21、H3は1になります。 また質問の後半部分であるJ列より右の欠番部分の表示ですがエクセルの最大列数が256であることを忘れていました。できれば一つのセルに 2-14 とか 1-4 とか6-20 のように表示できればうれしいです。 

関連するQ&A