advanced help
per page, with , order by , clip by
Results of 1 - 1 of about 37686 for IF (0.008 sec.)
[[20111101135213]]
#score: 1591
@digest: 124c64bc2ec901f7ce6680e0eda1f73c
@id: 56506
@mdate: 2011-11-10T05:59:39Z
@size: 100764
@type: text/plain
#keywords: 荷コ (478626), 荷指 (363055), 出荷 (180223), 賞味 (156077), comabbr (132785), 品id (118588), 荷依 (108972), 味期 (103592), dicm (101224), 示書 (77771), 引当 (73361), 指示 (71806), トno (61215), 在庫 (59189), 品一 (43920), 商品 (43037), a001 (39145), 期限 (37992), 荷日 (36332), 入荷 (31958), 列: (26813), 荷数 (22391), 依頼 (15978), 履歴 (15156), 2012 (13267), 数量 (11908), offset (10949), ubound (10759), 品名 (10002), コー (9430), ロッ (8911), function (7658)
『Excelの先入先出の方法』(らんきち)
Windows 7,Excel2007,です。 VBAはほとんど扱ったことがないんですが仕事で商品の先入先出法での在庫管理表を作成するように言われて本やWebで勉強しながらやっています。 Sheet1(商品Aの現在の在庫) ※A〜E列、1〜4行目はそれぞれ比較表など別データが入っています ※商品IDは1つのシートでは全て同じです F G H I 5 商品ID 賞味期限 数量 ロットNo 6 A001 2012/2/1 500 AA 7 A001 2012/2/20 600 BB 8 A001 2012/3/5 1000 CC 9 A001 2012/3/15 700 DD Sheet2(出荷データ) A B C D 1 出荷コード 商品ID 数量 出荷日 2 P10 A001 550 2011/11/1 3 Q10 A001 700 2011/11/1 4 R10 A001 200 2011/11/2 上記のデータから、Sheet3に以下のようなデータを出力したいのです。 (賞味期限の古い方から出荷する) Sheet3 A B C D E F 1 出荷コード 商品ID 賞味期限 出荷数 ロットNo 出荷日 2 P10 A001 2012/2/1 500 AA 2011/11/1 3 P10 A001 2012/2/20 50 BB 2011/11/1 4 Q10 A001 2012/2/20 550 BB 2011/11/1 5 Q10 A001 2012/3/5 150 CC 2011/11/1 6 R10 A001 2012/3/5 200 CC 2011/11/2 過去の質問 http://www.excel.studio-kazu.jp/kw/20090528093123.html を参照して↑この内容に似たテストファイルを作って出荷数を出すまではできたのですが、実際に使うファイルに当てはめてコードをいじってみてもどうしてもうまくいきません。 どなたかご助力ください… よろしくお願いいたします ---- Sheet1は賞味期限の昇順に並んでいると考えていい? (ぶらっと) ---- >ぶらっと様 すみません、その通りです。 昇順に並んでます (らんきち) ---- 簡単なテストしかしてないのでバグあれば指摘して。 Option Explicit Sub Sample() Dim listIV As Range, listDL As Range Dim cIV As Range, cDL As Range Dim qIV As Long, qDL As Long Dim dic As Object With Sheets("Sheet1") Set listIV = .Range("F6", .Range("F" & .Rows.Count).End(xlUp)).Resize(, 4) End With With Sheets("Sheet2") Set listDL = .Range("A2", .Range("A" & .Rows.Count).End(xlUp)).Resize(, 4) End With If WorksheetFunction.Sum(listIV.Columns(3)) < WorksheetFunction.Sum(listDL.Columns(3)) Then MsgBox "在庫数量が出荷数量より少ないので処理できません" Else Set dic = CreateObject("Scripting.Dictionary") Set cIV = listIV(1) Set cDL = listDL(1) qIV = cIV.Offset(, 2).Value qDL = cDL.Offset(, 2).Value Do If qIV > qDL Then Allocation dic, qDL, cIV, cDL qIV = qIV - qDL Set cDL = cDL.Offset(1) qDL = cDL.Offset(, 2).Value ElseIf qIV < qDL Then Allocation dic, qIV, cIV, cDL qDL = qDL - qIV Set cIV = cIV.Offset(1) qIV = cIV.Offset(, 2).Value Else Allocation dic, qDL, cIV, cDL Set cDL = cDL.Offset(1) qDL = cDL.Offset(, 2).Value Set cIV = cIV.Offset(1) qIV = cIV.Offset(, 2).Value End If If Intersect(cDL, listDL) Is Nothing Then Exit Do Loop End If With Sheets("Sheet3") .Cells.ClearContents .Range("A1:F1").Value = _ Array("出荷コード", "商品ID", "賞味期限", "出荷数", "ロットNo", "出荷日") .Range("A2").Resize(dic.Count, 6).Value = _ WorksheetFunction.Transpose(WorksheetFunction.Transpose(dic.items)) End With Set dic = Nothing Set listIV = Nothing Set listDL = Nothing MsgBox "処理が終了しました" End Sub Private Sub Allocation(dic As Object, q As Long, cIV As Range, cDL As Range) dic(dic.Count + 1) = _ Array(cDL.Value, cDL.Offset(, 1).Value, cIV.Offset(, 1).Value, q, cIV.Offset(, 3).Value, cDL.Offset(, 3).Value) End Sub (ぶらっと) ---- >ぶらっと様 早速のご回答ありがとうございました! テストしてみたところうまく動きました。 本当に助かりました。ありがとうございます! (らんきち) ---- 動いたということでもう目にとまらないかもしれないけど、アップしたものを、つらつら眺めると不備がいろいろ。 極めつけ(?)は、Sheet2側の出荷数はゼロの場合、永久ループ。 質問文でリファーしていた前スレのコードのように、引き当て不足の時も、そこまでは作表したほうがいいかもしれないし。 このコードをみて参考にする人もおられるかもしれないので、後日、チューニングバージョンをアップ予定。 (ぶらっと) 落ち着いてコードを眺めてみたら「永久ループ」にはならず、若干、表現が美しくない(0の出荷等)ということなので このままでもいいかなぁとも思ったけど、一応、在庫不足表示も含めて以下。 Sub Sample2() Dim listIV As Range, listDL As Range Dim cIV As Range, cDL As Range Dim qIV As Long, qDL As Long Dim dic As Object Dim lackQ As Long Dim w(1 To 6) As Variant With Sheets("Sheet1") Set listIV = .Range("F6", .Range("F" & .Rows.Count).End(xlUp)).Resize(, 4) End With With Sheets("Sheet2") Set listDL = .Range("A2", .Range("A" & .Rows.Count).End(xlUp)).Resize(, 4) End With lackQ = WorksheetFunction.Sum(listDL.Columns(3)) - WorksheetFunction.Sum(listIV.Columns(3)) Set dic = CreateObject("Scripting.Dictionary") Set cIV = listIV(1).Offset(-1) Set cDL = listDL(1).Offset(-1) Set cIV = GetNext(cIV, listIV, w, False) Set cDL = GetNext(cDL, listDL, w, True) If cIV Is Nothing Or cDL Is Nothing Then MsgBox "処理すべきデータがありません" Exit Sub End If qIV = cIV.Offset(, 2).Value qDL = cDL.Offset(, 2).Value Do If qIV > qDL Then w(4) = qDL dic(dic.Count + 1) = w qIV = qIV - qDL Set cDL = GetNext(cDL, listDL, w, True) If Not cDL Is Nothing Then qDL = cDL.Offset(, 2).Value ElseIf qIV < qDL Then w(4) = qIV dic(dic.Count + 1) = w qDL = qDL - qIV Set cIV = GetNext(cIV, listIV, w, False) If Not cIV Is Nothing Then qIV = cIV.Offset(, 2).Value Else w(4) = qDL dic(dic.Count + 1) = w Set cDL = GetNext(cDL, listDL, w, True) If Not cDL Is Nothing Then qDL = cDL.Offset(, 2).Value Set cIV = GetNext(cIV, listIV, w, False) If Not cIV Is Nothing Then qIV = cIV.Offset(, 2).Value End If If cDL Is Nothing Then Exit Do If cIV Is Nothing Then Erase w w(1) = "在庫不足!!" w(4) = lackQ dic(dic.Count + 1) = w Exit Do End If Loop With Sheets("Sheet3") .Cells.ClearContents .Range("A1:F1").Value = _ Array("出荷コード", "商品ID", "賞味期限", "出荷数", "ロットNo", "出荷日") .Range("A2").Resize(dic.Count, 6).Value = _ WorksheetFunction.Transpose(WorksheetFunction.Transpose(dic.items)) End With Set dic = Nothing Set listIV = Nothing Set listDL = Nothing MsgBox "処理が終了しました" End Sub Private Function GetNext(c As Range, r As Range, w As Variant, dl As Boolean) As Range Do Set c = c.Offset(1) If Intersect(c, r) Is Nothing Then Set GetNext = Nothing Exit Do Else If c.Offset(, 2).Value <> 0 Then Set GetNext = c If dl Then w(1) = c.Value w(2) = c.Offset(, 1).Value w(6) = c.Offset(, 3).Value Else w(3) = c.Offset(, 1).Value w(5) = c.Offset(, 3).Value End If Exit Do End If End If Loop End Function (ぶらっと) ---- >ぶらっと様 ありがとうございます ※すみません、以下の内容を書いている間にぶらっと様が再度コードを書いてくださったので重複してしまうかもしれません;; 実はこの後Sheet3に商品IDに対応する商品名を入れるようにと言われて、別シートの商品ID商品名対応表から VLOOKUP関数でSheet3のG列に追加したところ、Sheet2の出荷入力をしてマクロを実行するたびにG列の関数が消えてしまいました。 最終的にはSheet3を A B C D E F G 1 出荷コード 商品ID 賞味期限 出荷数 ロットNo 出荷日 商品名 2 P10 A001 2012/2/1 500 AA 2011/11/1 ○○○ 3 P10 A001 2012/2/20 50 BB 2011/11/1 ○○○ 4 Q10 A001 2012/2/20 550 BB 2011/11/1 ○○○ 5 Q10 A001 2012/3/5 150 CC 2011/11/1 ○○○ 6 R10 A001 2012/3/5 200 CC 2011/11/2 ○○○ となるようにしたいです。 ちなみに商品ID対応表は 商品一覧(シート名) A B 1 商品ID 商品名 2 A001 ○○○ 3 B001 ××× 4 C001 △△△ ※A列は商品IDの昇順に並んでます となっています。 追加になってしまって申し訳ございませんが、マクロを実行してもSheet3の商品名が消えない方法、またはVBAで自動入力する方法をお教えください… (らんきち) ---- >NB様 ありがとうございます それは3行目にも関数を入力するのでしょうか? 理解悪くてすみません… ---- >ぶらっと様 何度もすみません(;ω;) Set cIV = listIV(1).Offset(-1) ここで 「実行時エラー '1004' アプリケーション定義またはオブジェクト定義のエラーです」 というメッセージが出ます… (らんきち) ---- たびたび本当にすみません… Sheet3のG列を消さない方法は With Sheets("Sheet3") .Cells.ClearContents を With Sheets("Sheet3") .Range("A2:F100").ClearContents にすることで解決しました… (らんきち) ---- A列、E列は1つ上のデータと比較する計算をしていますが、最初のデータ(A2、E2)はシート1、シート2の最初のデータを入れます。2つ目(A3、E3)以降は提示した計算式になります。 その他の列は始めから計算式を入れています。 A列、E列ははA3,E3を下へコピー、その他の列はC2、・・を下へコピー (NB) ---- >NB様 すみません、A2とF2以外全て#N/Aエラーになります Sheet1のA〜DはF〜Iに置き換えて入力しました (らんきち) >NB様 やはりA2とF2以外全て#N/Aエラーです… E2はなぜか0が入ります (らんきち) ---- > E2はなぜか0が入ります。 E2は最初のロット番号です。「提示した式」を入れるのではなく、自分でE2セルに"="の後"シート1のi6"をクリックで 「=Sheet1!I6」となります。 数式は最初に提示されたシート名、セル位置 シート1は F5から、シート2,シート3はA1から で作っています。 変更はありませんか。 (NB) ---- まず、「実行時エラー '1004' アプリケーション定義またはオブジェクト定義のエラーです」 実行した時のSheet1のF5には、"商品ID" といったタイトルが記載されているという前提だけど、F1〜F5まで空白だったということはない? (というか、F列が空白列) 次に、.Range("A2:F100").ClearContents じゃぁ、データが100行目の後にもあったらどうする? なので、ここを .Range("A2:F1000").ClearContents じゃぁ、1000行目の後にもあったらどうする? ということに(理屈としては)なるので、VBAコードとしては、このような記述をせず、最終行を動的に取得してクリアする。 これを行うコードをアップしてもいいんだけど、なぜ、これをやったかというとG列にVLOOKUP関数をいれたからだよね。 そうすると、Sheet3を作るために、ある部分はVBAで、ある部分はシート関数でと、これは、あまり好ましくないね。 NBさんから関数処理案がでているので、そちらで運用するなら、シート関数のVLOOKUPで。 そうじゃなく、VBAで処理するならG列の商品名もVBA内でセットすべきだね。 VBAでセットするバージョンをアップしてもいいけど、一応、上で質問したF1〜F5の状態の回答をもらってからにするね。 (ぶらっと) ---- 回答をもらってないけど見切り発車で。 (前のコードでもOKだと思うけど、シート状況に依存させず、cDL と CIV は直接セルアドレスを指定してセット) Sub Sample3() Dim listIV As Range, listDL As Range Dim cIV As Range, cDL As Range Dim qIV As Long, qDL As Long Dim dic As Object Dim lackQ As Long Dim w(1 To 7) As Variant Dim comName As String With Sheets("Sheet1") Set listIV = .Range("F6", .Range("F" & .Rows.Count).End(xlUp)).Resize(, 4) Set cIV = .Range("F5") End With With Sheets("Sheet2") Set listDL = .Range("A2", .Range("A" & .Rows.Count).End(xlUp)).Resize(, 4) Set cDL = .Range("A1") comName = "登録なし" On Error Resume Next comName = WorksheetFunction.VLookup(.Range("B2").Value, Sheets("商品一覧").Range("A:B"), 2) On Error GoTo 0 End With lackQ = WorksheetFunction.Sum(listDL.Columns(3)) - WorksheetFunction.Sum(listIV.Columns(3)) Set dic = CreateObject("Scripting.Dictionary") Set cIV = GetNext(cIV, listIV, w, False) Set cDL = GetNext(cDL, listDL, w, True) If cIV Is Nothing Or cDL Is Nothing Then MsgBox "処理すべきデータがありません" Exit Sub End If qIV = cIV.Offset(, 2).Value qDL = cDL.Offset(, 2).Value Do If qIV > qDL Then w(4) = qDL: w(7) = comName dic(dic.Count + 1) = w qIV = qIV - qDL Set cDL = GetNext(cDL, listDL, w, True) If Not cDL Is Nothing Then qDL = cDL.Offset(, 2).Value ElseIf qIV < qDL Then w(4) = qIV: w(7) = comName dic(dic.Count + 1) = w qDL = qDL - qIV Set cIV = GetNext(cIV, listIV, w, False) If Not cIV Is Nothing Then qIV = cIV.Offset(, 2).Value Else w(4) = qDL: w(7) = comName dic(dic.Count + 1) = w Set cDL = GetNext(cDL, listDL, w, True) If Not cDL Is Nothing Then qDL = cDL.Offset(, 2).Value Set cIV = GetNext(cIV, listIV, w, False) If Not cIV Is Nothing Then qIV = cIV.Offset(, 2).Value End If If cDL Is Nothing Then Exit Do If cIV Is Nothing Then Erase w w(1) = "在庫不足!!" w(4) = lackQ dic(dic.Count + 1) = w Exit Do End If Loop With Sheets("Sheet3") .Cells.ClearContents .Range("A1:G1").Value = _ Array("出荷コード", "商品ID", "賞味期限", "出荷数", "ロットNo", "出荷日", "商品名") .Range("A2").Resize(dic.Count, 7).Value = _ WorksheetFunction.Transpose(WorksheetFunction.Transpose(dic.items)) End With Set dic = Nothing Set listIV = Nothing Set listDL = Nothing MsgBox "処理が終了しました" End Sub Private Function GetNext(c As Range, r As Range, w As Variant, dl As Boolean) As Range Do Set c = c.Offset(1) If Intersect(c, r) Is Nothing Then Set GetNext = Nothing Exit Do Else If c.Offset(, 2).Value <> 0 Then Set GetNext = c If dl Then w(1) = c.Value w(2) = c.Offset(, 1).Value w(6) = c.Offset(, 3).Value Else w(3) = c.Offset(, 1).Value w(5) = c.Offset(, 3).Value End If Exit Do End If End If Loop End Function ---- >NB様 ありがとうございます。自分で入力したらE2には番号が入りました。 その他の変更はありません。 >ぶらっと様 Sheet1の1〜4はところどころに比較表などのデータが入っていて、F行はF1〜F4までは空白でした F5より下はデータが入っています。 表をクリアする件はおっしゃるとおりです… 上司からできればVBAでと言われているので何とかVBAでできないかと考えています。 もう一つお聞きしたいのですが、別の商品の在庫が入っているシート(フォーマットはSheet1と同じで商品IDと商品名が違います)があります。 教えていただいたコードをコピーして「Sheet1」の部分を別商品の在庫のシート(仮にSheet1_Bとします)に変えてSheet2に入力すればそちらも Sheet3に反映されるものと勝手に思っていたのですが違うのでしょうか。 つまり、最初に教えていただいたコードであれば With Sheets("Sheet1_B") Set listIV = .Range("F6", .Range("F" & .Rows.Count).End(xlUp)).Resize(, 4) End With と書き換えれば Sheet2(出荷データ) A B C D 1 出荷コード 商品ID 数量 出荷日 2 P10 A001 550 2011/11/1 3 Q10 A001 700 2011/11/1 4 R10 A001 200 2011/11/2 5 S10 B001 300 2011/11/1 ↑この5行目を入力したらSheet3にも5行目の内容が追加されるものと思っていたのですが… 次々に本当にすみません… (らんきち) ---- すみません!リロードしていませんでした… もう一度試してみます! (らんきち) ---- Sheet2(出荷データ) A B C D 1 出荷コード 商品ID 数量 出荷日 2 P10 A001 550 2011/11/1 3 Q10 A001 700 2011/11/1 4 R10 A001 200 2011/11/2 5 S10 B001 300 2011/11/1 この形ならこの形で、もちろん処理はできるけど、アップしたコードでは無理。 前提として、※商品IDは1つのシートでは全て同じです となっているので。 むしろ、在庫シートも出荷シートも商品IDが混在していて、それを「このように編集する」とか そのようなシートから商品IDを特定して処理するとか、業務要件に合わせて、整理してみたら? で、整理できれば、それを教えてもらえばいかようにでも。 (ぶらっと) ---- >ぶらっと様 本当に何度も申し訳ありません 最初から整理して業務の流れを書きますと、 @商品入荷 ・商品名 ・入荷日 ・賞味期限 ・数量 ・ロットNo を商品別の在庫表に記入 A商品別在庫表には ・商品ID ・商品名 ・入荷日 ・賞味期限 ・ロットNo ・在庫数量 があり、出荷の履歴として ・出荷コード ・出荷数 を横に追加していっています。 さらに a.前日の在庫数 b.当日の在庫数(当日最初の段階で倉庫にある在庫) c.入出荷指示後の在庫数(入出荷予定分を当日在庫から差し引いた在庫数) に分かれています。 出荷する際はc.入出荷指示後の在庫数から出荷分を割り当てます B商品の出荷依頼 ・出荷日 ・出荷コード ・商品名(一枚の指示表で複数の商品を出荷) ・出荷数 C倉庫への出荷指示 ・出荷コード ・商品コード ・商品名 ・賞味期限 ・ロットNo ・数量 現状入荷の入力は直接Aの在庫表に手入力しています。 今回やろうとしていることは、Bの出荷依頼が来た時に Aの在庫表から賞味期限の古い順に出荷を引き当て Aの在庫表に出荷履歴を残し、出荷した分の数量を差し引いた在庫を入力(←ややこしくなりそうなので上記の質問では省略していました) Cの出荷指示表を出力(出荷コードごと) 商品は10数種類で今後も増える予定、在庫は商品別(シート別)に管理したいとの指示でした。 不足な情報などは追加します。 一度の処理で不可能な部分は分けたりしようと思っています。 わかりにくくて申し訳ございません。 (らんきち) ---- 再説明してもらった内容に関しては違和感なし。 在庫シートのメンテナンスも含めて、処理案を考えてみるので、少し時間ください。 ところで、倉庫への出荷指示(Seet3)は複数商品混在?それとも商品ごと?いずれでも対応可能。 いずれにしても、出荷指示表が出荷コードごとということは、データが、仮に全て同じ商品コードであったとしても 複数シートにわかれる可能性があるということだよね。 また、対象の商品が複数あるとすれば、商品ごとの在庫シートも複数あるわけで、何か工夫が必要かな? 在庫表のシート名を商品コードと紐つけられるようなもの(在庫A001とか)にしておく等。 追記)出荷コード毎というのは、何も、それ毎に違うシートということではなく、 同じシートに出荷コードごとに、表示するという、アップ済みのものと同じということでいいのかも? ね? とすれば、後は、商品毎に出荷指示表をわけるのか、同じシートに記載するのか、それを教えて。 そうではなく、出荷データには複数商品があるけど、今回は、この商品、今回はこの商品と 分けて処理するのかな? いずれにしても、いかようにも。 (ぶらっと) ---- 目下、処理構成の想定中。以下がわかれば、もう少しクリアになるので教えて。 A商品別在庫表には ・商品ID ・商品名 ・入荷日 ・賞味期限 ・ロットNo ・在庫数量 があり、出荷の履歴として ・出荷コード ・出荷数 を横に追加していっています。 ●この具体的なレイアウトを教えて。商品IDから在庫数量までの項目は、最初にアップされたものとちょっと差異があるので。 加えて、横に追加していっている履歴のレイアウトも。(どの列からとか、履歴項目は2つだけか、もっとあるのか とか) さらに a.前日の在庫数 b.当日の在庫数(当日最初の段階で倉庫にある在庫) c.入出荷指示後の在庫数(入出荷予定分を当日在庫から差し引いた在庫数) に分かれています。 ●この具体的なイメージ(レイアウト)教えて 追記) ●出荷日が賞味期限を過ぎていた場合、そのロットは出荷停止?それとも、無視して出荷しちゃう? (ぶらっと) ---- >ぶらっと様 本当にお世話になります。 >倉庫への出荷指示(Seet3)は複数商品混在?それとも商品ごと? 複数商品混在で、商品ごとに並んでいます。 >出荷指示表が出荷コードごとということは、データが、仮に全て同じ商品コードであったとしても 複数シートにわかれる可能性があるということだよね。 出荷指示表を全て残すとなると1日で20以上になってしまいますので、出荷指示表に出荷コードを入力して一つの出荷指示を出して印刷 →別の出荷コードを入れて次の出荷指示 ※ただし一度印刷したものを再出力できるように という感じで、出荷コードごとに一枚のシートで管理というのが理想的です。 >商品毎に出荷指示表をわけるのか、同じシートに記載するのか できれば出荷コードごとに、同じシートに複数商品を載せたいです >具体的なレイアウト A2 の商品名は今は手入力ですが「商品一覧」シートから引っ張ってくることも可能 A B C D E F G H I 〜 R S 1 2 商品名 3 4 前日在庫 指示後在庫 11/1 11/1 5 入荷日 賞味期限 数量 ロットNo 商品ID 賞味期限 数量 ロットNo 〜 P10 Q10 6 2011/10/1 2012/2/1 800 AA A001 2012/2/1 600 AA 〜 500 7 2011/10/2 2012/2/20 900 BB A001 2012/2/1 700 BB 〜 50 550 8 2011/10/3 2012/3/5 1200 CC A001 2012/2/1 1000 CC 〜 150 前日在庫と指示後在庫、出荷履歴は上記のようなレイアウトです。 当日在庫はK以降で、指示後在庫と同じようなレイアウトですが、キャンセルという項目があります(下記) ※E列・J列・P列は空白、Q列はメモ欄 K L M N O 5 商品ID 賞味期限 数量 ロットNo キャンセル 6 A001 2012/2/1 500 AA 7 A001 2012/2/20 600 BB 8 A001 2012/3/5 1000 CC 9 A001 2012/3/15 700 DD > ●出荷日が賞味期限を過ぎていた場合、そのロットは出荷停止?それとも、無視して出荷しちゃう? 出荷停止になります。 このような内容でよろしいでしょうか。 不足情報はまた補足します。 たびたび申し訳ございませんがよろしくお願いいたしますm(__)m (らんきち) ---- 追加情報通読。 この説明を読む前に、こちらの勝手な仕様でコードを書いてアップしようとしていた矢先だった。 ひやぁ〜、ハードルがぐ〜〜〜んとアップした。でも、おもしろそう。 とりあえず以下確認。 1.出荷コードごとの複数商品混在の出荷指示書というのは了解。この出力順だけど、出荷依頼データの登場順じゃなく 商品順でいい? たとえば出荷依頼データにA商品、B商品、A商品、B商品と交互に記載があっても、出荷指示書は A商品、A商品、その下にB商品、B商品。 2.出荷依頼データに記載されている、全ての情報から複数の出荷指示書を作るということでいい? この出荷コードだけとか、この商品だけとかじゃなく。 3.言葉の問題だけど、アップ済みのコードでは在庫データとしてF列以降のものを使っている。 つまり、この処理を行う時点で出荷可能な在庫はF列以降にある数量。 ところが、今回の説明ではここが「指示後在庫」となっている。指示後在庫という意味は、今から出荷指図をしようとしているものを さっぴいた後の在庫(つまり今から行う処理が終わったとしたときの、出荷後の在庫)という意味ではないよね? あえていうと「指示前在庫」あるいは「指示した時点の在庫」なんじゃない? (ぶらっと) ---- ぶらっと様 >出荷コードごとの複数商品混在の出荷指示書というのは了解。この出力順だけど、出荷依頼データの登場順じゃなく 商品順でいい? はい。商品順でお願いします。 ただ、同じ商品の中では賞味期限が古い順に並ぶようにしたいです。 >出荷依頼データに記載されている、全ての情報から複数の出荷指示書を作るということでいい ええと、一つの出荷依頼書に一つの出荷コードが割り振られていますので、一つの出荷コードごとに一つの指示書が必要になります。 >あえていうと「指示前在庫」あるいは「指示した時点の在庫」なんじゃない? 言葉が足りなくてすみません… 出荷指示が来た時に、「指示後在庫」に在庫が残っている分から在庫を引き当てます。 現状では、R列以降に出荷数を入力したら「指示後在庫」からその数量が減っていきます。 つまり「指示後在庫」=「出荷依頼が来た時に引き当てられる在庫」になります。 あと >b.当日の在庫数(当日最初の段階で倉庫にある在庫) ※K〜N列 すみません、この説明間違っていました… 正しくは「翌日以降出荷予定分を含めた在庫(出荷指示は出ているけどまだ出荷されずに倉庫にある在庫)」になります。 このような説明で大丈夫でしょうか? (らんきち) ---- とりあえず、こちらが理解した要件で書いてみる。そちらのイメージと違っていれば、また、その時に。 すぐに時間がとれるかどうか、あやしいので、ちょっと待ってて。 追記)あっ、やっぱり1点だけ確認。 最初にアップされたサンプルでは、できあがりの出荷指示書(Sheet3)に複数の出荷コードが混在していたけど あれは間違いで、出荷コードごとに、シートがわかれるということでいいんだよね? (ぶらっと) ---- >最初にアップされたサンプルでは、できあがりの出荷指示書(Sheet3)に複数の出荷コードが混在していたけど あれは間違いで、出荷コードごとに、シートがわかれるということでいいんだよね? はい。最初はそこからさらに別表に出荷コードごとの指示書を作ろうと思っていたのですが、本来はコード毎の指示書が必要になります。 一度の処理でできればありがたいです。 (らんきち) ---- かなり、こちらの「勝手な仕様」を盛り込んで書いた。 コードをアップする前に、その「勝手な仕様」の説明を。 なを、処理後の在庫引き落としは、今回の処理にはいれていない。 出荷指示書を作成しても、「何らかの理由」で、その出荷を行わない可能性もありうるし、 そうなったら引き落とし済みの在庫を元に戻さなきゃいけない。 なので、出荷確定後に、あらためて引き落とし(履歴作成)処理を行うべきだし、そのコードは きわめてシンプルなのでそちらで、がんばって作るか、必要ならまたお手伝いする。 「勝手な仕様」 ・基本的には出荷コード1つに対して1枚の出荷指示書を作成する。 ・これを、出荷依頼データ(Sheet2)にあるものすべてについて作成する処理と、特定の出荷コードについて 作成する処理を可能にするため、「共通サブプロシジャ」として位置づけ。 ・各シートについて 「商品一覧」 提示通り 「Sheet2」 基本的には提示通り。同じ出荷コードのものは連続して記載されているとみなす。 また、「すべて作成」の場合、上から順に引き当てていく。(上の行が引き当て優先) 「Sheet3」 従来は出荷指示書だったけど、今回は、「出荷指示書の雛形・テンプレート」 一行目だけにタイトル行を入力しておき、列の幅や表示書式を設定しておく。 在庫シート 従来は「Sheet1」。これをやめて、商品毎にシートを準備。シート名は 商品コードのあたまに"在庫"(在庫A001等) なお、商品コードはシート名から抽出。F列は無視している。 出荷指示書 必要な指示書がSheet3をテンプレートにして自動生成される。シート名は 出荷コードの頭に"出荷指示"(出荷指示P10等) で、コード。標準モジュールに以下。 ちょっとややこしめの処理を、なるべく「コード的」にすっきりさせるため、同じ処理にまとめられるところを複数でやっているとか 一度チェックした情報を、もう一度頭からチェックしているとか、そういうところはあるけど、気になるなら、最終的に、そちらで チューニングしてね。 以下の、TestOne は出荷コード指定での作表サンプル。コートとしては出荷コードを固定で与えるものにしてあるけど これを、操作者が指定するようにもできるね。(その方法はいろいろある) TestAllは出荷依頼データ(Sheet2)にあるものをすべて作成。 簡単な稼働確認しかしてないのでバグあれば指摘お願い。 Option Explicit Enum func fnOpen fnGet fnPut fnClose End Enum Sub TestOne() Call io商品(fnOpen) Call 出荷指示by出荷コード("P10") Call 出荷指示by出荷コード("R10") Call io商品(fnClose) End Sub Sub TestAll() Dim c As Range Call io商品(fnOpen) With Sheets("Sheet2") For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp)) If c.Value <> c.Offset(1).Value Then Call 出荷指示by出荷コード(c.Value) Next End With Call io商品(fnClose) End Sub Private Sub 出荷指示by出荷コード(cd As Variant) Dim i As Long Dim buf As Variant Dim c As Range If make出荷指示書(fnOpen, cd) = False Then Exit Sub With Sheets("Sheet2") For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp)) If c.Value = cd Then buf = io商品(fnGet, cd, c.Offset(, 1).Value, c.Offset(, 2).Value, c.Offset(, 3).Value) If IsArray(buf) Then Call make出荷指示書(fnPut, buf) End If Next End With Call make出荷指示書(fnClose) End Sub Private Function io商品(fc As func, Optional cd As Variant, Optional comid As String, Optional qty As Long, Optional dldate As Date) As Variant Static dicM As Object Static comName As String Dim first As Boolean Dim c As Range Dim sh As Worksheet Dim cName As String Dim dKey As Variant Dim reqQty As Long Dim dDate As Date Dim dQty As Long Dim dLot As String Dim v() As Variant Dim setQty As Long Dim wk As Variant Select Case fc Case fnOpen Set dicM = CreateObject("Scripting.Dictionary") For Each sh In Worksheets If Left(sh.Name, 2) = "在庫" Then Set dicM(Mid(sh.Name, 3)) = CreateObject("Scripting.Dictionary") For Each c In sh.Range("G6", sh.Range("G" & sh.Rows.Count).End(xlUp)) dicM(Mid(sh.Name, 3))(dicM(Mid(sh.Name, 3)).Count + 1) = Array(c.Value, c.Offset(, 1).Value, c.Offset(, 2).Value) Next End If Next Case fnGet If Not dicM.exists(comid) Then Exit Function first = True reqQty = qty comName = "登録なし" On Error Resume Next comName = WorksheetFunction.VLookup(comid, Sheets("商品一覧").Range("A:B"), 2, False) On Error GoTo 0 For Each dKey In dicM(comid) dDate = dicM(comid)(dKey)(0) dQty = dicM(comid)(dKey)(1) dLot = dicM(comid)(dKey)(2) wk = dicM(comid)(dKey) If dldate <= dDate And dQty > 0 Then If dQty >= reqQty Then setQty = reqQty wk(1) = wk(1) - setQty Else setQty = dQty wk(1) = 0 End If reqQty = reqQty - setQty dicM(comid)(dKey) = wk If first Then ReDim v(1 To 7, 1 To 1) first = False Else ReDim Preserve v(1 To UBound(v, 1), 1 To UBound(v, 2) + 1) wk(1) = 0 End If v(1, UBound(v, 2)) = cd v(2, UBound(v, 2)) = comid v(3, UBound(v, 2)) = dDate v(4, UBound(v, 2)) = setQty v(5, UBound(v, 2)) = dLot v(6, UBound(v, 2)) = dldate v(7, UBound(v, 2)) = comName End If If dicM(comid)(dKey)(1) = 0 Then dicM(comid).Remove dKey If reqQty = 0 Then Exit For Next If Not first Then io商品 = WorksheetFunction.Transpose(v) End If Case fnClose dicM.RemoveAll Set dicM = Nothing End Select End Function Private Function make出荷指示書(fc As func, Optional v As Variant) As Boolean Static shn As String Select Case fc Case fnOpen shn = "出荷指示" & v If IsObject(Evaluate(shn & "!A1")) Then If MsgBox(shn & "がすでに存在します。削除して置き換えていいですか?", vbYesNo) = vbNo Then Exit Function Application.DisplayAlerts = False Sheets(shn).Delete Application.DisplayAlerts = True End If Sheets("Sheet3").Copy After:=Sheets(Sheets.Count) ActiveSheet.Name = shn Case fnPut With Sheets(shn) If getDimension(v) = 1 Then .Range("A" & .Rows.Count).End(xlUp).Offset(1).Resize(, UBound(v)).Value = v Else .Range("A" & .Rows.Count).End(xlUp).Offset(1).Resize(UBound(v, 1), UBound(v, 2)).Value = v End If End With Case fnClose 'So Far NOP End Select make出荷指示書 = True End Function Private Function getDimension(v) As Long Dim i As Long Dim wk As Long On Error Resume Next Do i = i + 1 wk = UBound(v, i) Loop While Err.Number = 0 On Error GoTo 0 getDimension = i - 1 End Function (ぶらっと) ---- 今回の「引き当て」処理については、上記、アップしたものを試してもらいたいけど 今後、「在庫メンテ」処理を考えていく上で、参考メモを。 入荷、在庫、出荷という流れをカバーするWMS(倉庫管理システム)で、最もハードルが高い部分は「引き当て」 ここは、要件が様々で、その要件次第で大変なことになる可能性もある部分。 ただし、それ以外はわりあいと平易な部分が多く、「自作」で対応するのも1つの方法だけど、 「VBAはほとんど扱ったことがないんですが」ということであれば、ちょっと心配。 本格的な倉庫業者は自社のWMS導入に○億円の投資もしているけど、ちょっとしたものなら、世の中に 10〜20万円程度のパッケージがたくさん存在するので、それらを検討したほうがいいかも。 予算的に・・ということなら、ベクターあたりでフリーソフトも数多く紹介されている。 まぁ、それはともあれ。 1.入荷->引当->出荷->在庫引落 という、前にまっすぐ行われていく業務を考えると @ 入荷(商品、ロットがキー、当該在庫シートに手作業で記入) A 出荷指示 アップ済みのコード(ただし、引当はしていない) B 引当履歴 現在のR列以降かな? ここにステータス「未出荷」で登録。 ★「出荷履歴」ではなく「引当履歴」 C 引当可能在庫 現在のF列以降だよね。@ - B(ステータス全て) ここまでが、通常の入出庫業務のための情報と処理。そのほかに、 D 出荷時、Bの引当履歴リスト(ステータス未出荷)から、出荷済分を選択してステータス「出荷済み」に。 E @ - B(ステータス 出荷済み)が 「現在の在庫」 F 夜、一日の出荷業務が終わった時点のEが「前日末在庫」 この中で、Fは、あまり利用価値がない情報かも。Eは、「棚卸」業務には使えそう。 2.「まっすぐ前に進む」ものでも上記のような処理を準備することが必要。 でも、通常は、「まっすぐには進まない」 業務の都合であったり、あるいはVBA処理の二重処理 等々がある。 そのため、「訂正」「取消」といった機能が必要になる。もちろん、この機能を動かした時 関連の在庫情報も正しく「元に戻る」ような仕掛けというか、データのキーが必要になる。 といったことを考えると、もう、「しっちゃか、めっちゃか」になりがち。 (ぶらっと) ---- >ぶらっと様 こんなに丁寧に作成していただいて、本当にお礼の言葉もありません… 早速実行してみたのですが、 >Private Function io商品(fc As func, Optional cd As Variant, Optional comid As String, Optional qty As Long, Optional dldate As Date) As Variant ここで「ユーザー定義型は定義されていません」のエラーが出ます… 「Microsoft Scripting Runtime」にはチェックを入れています。 あとシート名なんですが、実は商品IDというのは今回の作業を依頼された時に私が便宜上勝手に作ったものでして、他の人がファイルを 使用する際にシート名が商品名でないと混乱を招くかもしれないんです。 商品名の入力ミスで指示書が作成されないのを避けるためにとりあえず作ったものなんですが… 元のファイルのフォーマットはあまり変えないでほしいとのことでして(特に在庫表は社員全員が見るので)何とか在庫表の見出しか商品一覧から引っ張ってくることはできませんでしょうか? 勝手を申し上げて本当にすみません… (らんきち) ---- >ぶらっと様 参考メモ読ませていただきました。 本当にありがとうございます。 職場の人たちがほとんど全員「まったくのPC初心者」でして、Excelで何ができて何ができないというのをあまり理解していないんです。 そのために、多少PCを扱えるものとして私が雇われまして… できないならできないことを立証しないといけないんです。 最初は関数で何とかできないかと散々試行錯誤したんですがどうしてもうまくいかなくて… とりあえずの問題は、出荷指示表を現在手書きしておりまして、その際に ・賞味期限の記入ミスが多く、また記入に手間がかかるから自動で作成できるようにしてほしい ・賞味期限の古い順から引き当てるのに引き当てミスが多いので自動的に古い順から出せるようにしてほしい ということでした。 (らんきち) ---- >ここで「ユーザー定義型は定義されていません」のエラーが出ます… モジュールの先頭に、以下もコピペしてくれてる? Enum func fnOpen fnGet fnPut fnClose End Enum >「Microsoft Scripting Runtime」にはチェックを入れています。 はい。もっとも、アップしたコードは参照設定なしでも動くようにCreateObjectを使ってるけど 参照設定+CreaateObjectが、最も強力な組合せという人もいるので、いいことだと思う。 >他の人がファイルを使用する際にシート名が商品名でないと混乱を招くかもしれないんです。 これは、いかようにでも。 やたら長い商品名だとあまり感心しないし、シート名に使うことができない文字ってのが 記憶では31文字ほどあって、それが使われていなければいいよ。 ただし、ロジックは商品IDベースのほうが何かといいとは思う。 商品一覧、現在は商品ID、商品名なので、そこから、なんとか紐つけてみよう。 ↑訂正 シート名桁数が31文字で、つかっちゃいけない文字は7種類ほど。 http://support.microsoft.com/kb/436482/ja >元のファイルのフォーマットはあまり変えないでほしいとのことでして(特に在庫表は社員全員が見るので) >何とか在庫表の見出しか商品一覧から引っ張ってくることはできませんでしょうか? これは、こちらで在庫表のシート名を 在庫+商品ID にしてるけど、それを 在庫+商品名 でいいかな? 在庫シートかどうかをロジックでチェックしているところがあって、アップしたコードでは 頭が"在庫"ではじまっているかどうかの判定になっているので。 参考メモについては、後日、必要になったら、おいおいに議論していこう。 (ぶらっと) ---- ぶらっと様 ありがとうございます。 エラー解消されました! >在庫+商品名 でいいかな? はい、それで大丈夫です。 シート名は最大8文字程度、たまに【】や@などの記号が使われていますが、それほど長くはありません。 出荷コード別の指示書はコードをその都度指定してできるように… >操作者が指定するようにもできるね この方法でお願いしたいです… あと、さきほど上から訂正が入りまして、出荷指示書の「商品ID」と「商品名」の位置を入れ替えたいのですが、 v(1, UBound(v, 2)) = cd v(2, UBound(v, 2)) = comName v(3, UBound(v, 2)) = dDate v(4, UBound(v, 2)) = setQty v(5, UBound(v, 2)) = dLot v(6, UBound(v, 2)) = dldate v(7, UBound(v, 2)) = comid このように書き換えただけで大丈夫でしょうか? (一応これで位置は入れ替わりましたが他に影響が出ないかと思って…) 何度もすみません… (らんきち) ---- エラーがなくなってよかったね。 「商品ID」と「商品名」の列の入れ替えは、それでOKだよ。 操作者が指定する方法、たとえば、ユーザーフォームでコンボボックスを使う方法がある。 もし、(らんきち)さんがユーザーフォームは、ほとんどわからないとしても、ユーザーフォームを挿入して こちらの指定のコントロールを、そこに配置することができれば、それが(将来の引当履歴作成時にも)便利かも。 操作者にとっても、わかりやすいと思う。 あるいは、同じようなイメージだけど、もう1つ、たとえば"Menu"という名前のシートを用意して そこに、ボタン(全て処理とか、個別処理とか)を配置、個別処理の時には、やはり、Menuシートの上に配置した コンボボックスから処理必要なものを選ばせるということでもいいかも。 あるいは、出荷依頼データ(Sheet2)の当該行をマウスで選択させて実行させることもできるけど。 どんな方法がいいか、他の皆さんと相談してみて。 それを聞いてから、商品ID<->商品名 の紐つけバージョンを書くので、よろしく。 追加質問)SHeet2のB列は従来どおり商品IDでいい? それとも、ここも商品名? (ぶらっと) ---- >ぶらっと様 今日は職場の担当者が不在で出荷指示書のレイアウトなどの最終確認ができないのですが、現時点でわかっている点をお伝えします。 ★変更がありました 「在庫表」の「ロットNo」列と「数量」列を入れ替えることになりました A B C D E F G H I 〜 R S 1 2 商品名 3 4 前日在庫 指示後在庫 11/1 11/1 5 入荷日 賞味期限 ロットNo 数量 商品ID 賞味期限 ロットNo 数量 〜 P10 Q10 6 2011/10/1 2012/2/1 AA 800 A001 2012/2/1 AA 600 〜 500 7 2011/10/2 2012/2/20 BB 900 A001 2012/2/1 BB 700 〜 50 550 8 2011/10/3 2012/3/5 CC 1200 A001 2012/2/1 CC 1000 〜 150 それで、 dQty = dicM(comid)(dKey)(1) dLot = dicM(comid)(dKey)(2) ここのコードを入れ替えて dLot = dicM(comid)(dKey)(1) dQty = dicM(comid)(dKey)(2) としてみましたが、それだけではダメなんですね… また、出荷指示入力時のイメージとしては、おっしゃるようにユーザーフォームを作ることを想定していました。 処理の際にいくつもの画面を開くのではなく、一つの画面でできるだけ処理したいとのことなので、「MENU」シートに出荷入力できるフォーム(出荷コードごと)、コンボボックスを使った個別出荷指示ボタン、全出荷指示ボタンを配置できれば理想的です。 出荷指示入力の際に必要な項目は前述の B商品の出荷依頼 ・出荷日 ・出荷コード ・商品名(一枚の指示表で複数の商品を出荷) ・出荷数 の通りです。 >SHeet2のB列は従来どおり商品IDでいい? それとも、ここも商品名? 商品名の入力ミスを防ぐために商品IDにしていましたが、本来は商品名の方がよいです。 (らんきち) ---- ぶらっと様 担当者に確認をとりました。 出荷指示書のレイアウトは今のままでいいとのことです ただ、出荷指示した際に現状 A B C D E F G 1 出荷コード 商品名 賞味期限 出荷数 ロットNo 出荷日 商品ID 2 P10 ○○○ 2012/2/1 500 AA 2011/11/1 A001 3 P10 ○○○ 2012/2/20 50 BB 2011/11/1 A001 4 P10 ××× 2012/2/10 70 YY 2011/11/1 B001 5 P10 ××× 2012/2/15 80 ZZ 2011/11/1 B001 となっていて、「商品ごとの小計を出したい」(上の表で言えば商品○○○が550個、B001が150個、というように)とのことなので、おかしいとは思いましたがI列に(H列を空白)にSUMIF関数で小計欄を加えました。 A B C D E F G I H 1 出荷コード 商品名 賞味期限 出荷数 ロットNo 出荷日 商品ID 小計 2 P10 ○○○ 2012/2/1 500 AA 2011/11/1 A001 ○○○ 3 P10 ○○○ 2012/2/20 50 BB 2011/11/1 A001 550 4 P10 ××× 2012/2/10 70 YY 2011/11/1 B001 ××× 5 P10 ××× 2012/2/15 80 ZZ 2011/11/1 B001 150 本当はA001(○○○)の最後の行の横か下に小計を出せたらいいのですが、賞味期限ごとの在庫で何行になるかわからないので… また、たまにイレギュラーで古い賞味期限でも出さない場合があるということですが、そこまではここで判断するのは難しいと説明して、そのような場合は手入力で書き換えるようになりました。 (それもあるので強制的に在庫表から直接在庫を差し引くのは今の段階では怖い?とのこと) 入力はユーザーフォームでコンボボックスで商品を選択するなど、できるだけ入力作業を簡素化したいそうです。 このような内容でよろしいでしょうか? 本当にわがままを言って申し訳ございません;; (らんきち) ---- ↑で追加されたことも含めて新しいレイアウトをチェックして、また疑問点あれば質問するけど とりあえず以下、コメント。 1.もう一度、商品別在庫シートのフィールドの意味を教えて 1)A列から 前日末在庫? 2)F列から 指示後在庫。(今後の引当可能在庫) 3)K列から これは何だったっけ? 2.商品別在庫シートのその他の質問・確認 1)F列やK列に商品IDがあるね。(実務的には商品IDは使わないんだろうけど) 1つのシートは単一商品なので、各行に記入する意味はないのでは? もし、商品IDを記入するとしても、A1あたりに1ヶ所でいいんじゃない? レイアウト変更になるけど、F列、K列の削除も検討してみたらいかが? 2)現在、このシートにはF列,K列の商品ID、A2の商品名、シート名としての商品名がある。 人間が入力するわけで、この三者が食い違うこともありうる。コードとしてはこの中で シート名の中の商品名しか使わないので、後の二者が間違った値でも処理としては問題ないけど 実際に、A1が abcd、シート名が在庫xyz となっていると見る人にとって紛らわしいね。 A1を入力するのではなく、長ったらしくなるけど、以下の数式にしておけばシート名から 商品名を抽出して表示する。 =MID(CELL("filename",A1),FIND("]",CELL("filename",A1))+3,LEN(CELL("filename",A1))-FIND("]",CELL("filename",A1))-2) 3)今後の履歴セット、在庫引落の要件としても重要になるんだけど、R列以降の履歴について。 日付と出荷コード単位だね。ということは、同じ日に、同じ出荷コードの出荷が2回発生することはないということ? 逆に言えば、同じ日に既に出荷履歴があれば、出荷指示書作成処理で「エラー」にすべきなのでは? 4)追加。入荷時、在庫シートに入荷情報を記入するんだよね。具体的には、どこに何を記入している? (ぶらっと) ---- 1)A列から 前日末在庫? 2)F列から 指示後在庫。(今後の引当可能在庫) 3)K列から これは何だったっけ? A列・F列はその通りです。 K列は、出荷の予定はあるけど(出荷指示はしているけど)まだ出荷せずに倉庫にあるものも含めた在庫です。 1)F列やK列に商品IDがあるね 1つのシートは単一商品なので、各行に記入する意味はないのでは? もし、商品IDを記入するとしても、A1あたりに1ヶ所でいいんじゃない? レイアウト変更になるけど、F列、K列の削除も検討してみたらいかが? はい、私が関数で何とかできないかと色々いじっていた時の名残なのでA列のみにしてF列・K列は削除した方がいいです。 2) =MID(CELL("filename",A1),FIND("]",CELL("filename",A1))+3,LEN(CELL("filename",A1))-FIND("]",CELL("filename",A1))-2) これはA2に商品名を数式で自動表示するということでしょうか? 説明漏れですが、A2の商品名は商品の正式名称(長いものがある)、シート名は略称が入っていることがありますので、逆にシート名を長くする必要があり、 シートのタブが見づらくなる可能性があるかもしれません 3)同じ日に、同じ出荷コードの出荷が2回発生することはないということ それが、翌日以降出荷分は「PM」「PM2」という出荷コードが決まっています。 例えば「11/10出荷の“PM”」「11/11出荷の“PM”」のように出荷日が違って同じ出荷コードのものが履歴にあります。 その日に出す「PM」「PM2」の指示書は1回だけですが、出荷予定のものとしての「PM」「PM2」が複数存在することになります。 4)入荷時、在庫シートに入荷情報を記入するんだよね。具体的には、どこに何を記入している? A列に入荷日または入荷予定日、B列に賞味期限、C列にロットNo、D列に数量を、最後の行に追加していっています。 (A列に商品IDを入れるので列を一つずらすことになりますが) しかし賞味期限が前後することがあるので(入荷日は遅いのに賞味期限は古い)、それはソートするしかないかな、と思っています。 入荷予定日のみ決まっていて実際に入荷していないものは賞味期限以降は空白です。 ややこしくてすみません… (らんきち) ---- >K列は、出荷の予定はあるけど(出荷指示はしているけど)まだ出荷せずに倉庫にあるものも含めた在庫です。 つまり、現時点での「実在庫」ということで了解。 >これはA2に商品名を数式で自動表示するということでしょうか? はい。 >シート名は略称が入っていることがありますので 理解はできるけど、そうすると、出荷依頼データをもとに在庫シートを見ようとした時にシート名では紐つかないということだね。 で、出荷依頼データ(Sheet2)のB列は、商品IDではなく商品名にすることになったんだと思うけど、ここは 正式名称?略称?略称だとすると、シート名の略称と一致?それとは異なることもありうる? これによって、在庫チェックのロジックが大きくかわる。(いかようにでも対応するけど) >それが、翌日以降出荷分は「PM」「PM2」という出荷コードが決まっています。 う〜ん・・・よくわからない。出荷コードというのはユニークだと思っていたんだけど、PM という出荷が 今日も、明日も、明後日もありうるということ? で、もう1つの質問としては、せめて、というか最低というか、同じ日には、出荷コードはユニークなんだよね? >A列に入荷日または入荷予定日、B列に賞味期限、C列にロットNo、D列に数量を、最後の行に追加していっています。 ということは、A列以降にある情報は、最初は「入荷情報」、出荷された後は、「前日在庫」になっているということ? ★あとあとのためにも、入荷情報は上書きせず、どこかに保持しておいたほうがいいよ。 >(A列に商品IDを入れるので列を一つずらすことになりますが) 逆にF列、K列は廃止したら?という提案をしたけど、やはりそれらも残すということだね? で、A列に商品IDをいれるということは、それ以降のレイアウトもすべて右に1つ、ずれると考えておいていいの? >しかし賞味期限が前後することがあるので(入荷日は遅いのに賞味期限は古い)、それはソートするしかないかな これをマクロで実行させることはできるよ。 (ぶらっと) ---- >出荷依頼データ(Sheet2)のB列は、商品IDではなく商品名にすることになったんだと思うけど、ここは >正式名称?略称?略称だとすると、シート名の略称と一致? 略称でシート名と一致です。 >出荷コードというのはユニークだと思っていたんだけど すみません、私も今朝改めて説明を受けてそういう事例があるのを知りました… >もう1つの質問としては、せめて、というか最低というか、同じ日には、出荷コードはユニークなんだよね? はい、そうです。 >ということは、A列以降にある情報は、最初は「入荷情報」、出荷された後は、「前日在庫」になっているということ? そうなります… >★あとあとのためにも、入荷情報は上書きせず、どこかに保持しておいたほうがいいよ。 日々の入荷は別ファイルに月単位で別途作成しているようです。(つまり入荷した時に在庫表と入荷情報ファイルと2つのファイルに入力しています) >F列、K列は廃止したら?という提案をしたけど、やはりそれらも残すということだね すみません、書き方が悪かったです。A列に商品IDを入れて、現在のF・K列は削除です。 それ以外の情報はそのままずらします。 >マクロで実行 R列以降がかなり長くなることがありますがそのまま全部ソートされるということですよね? それでしたらお願いします。 (らんきち) ---- だいぶクリアになったので、とにかく目下のテーマ、出荷指示書作成のコードを、これから書いてみる。 少し時間ください。 ★ところで、在庫シートに関して 1.キャンセル列って、何に使っているのかな? 2.今、履歴は4行目に日付、5行目に出荷コードだけども、だまされたと思って、「出荷確定」を追加しておいて。 現行のレイアウトをあまりいじりたくなければ、3行目を、それにあててもいい。 (ぶらっと) ---- >1.キャンセル列って、何に使っているのかな? キャンセルで戻ってきて、まだ返品処理が終わっていないので引き当てられる在庫に入れられないもの (キャンセル処理中)を記入しています。 なので、K列の「未出荷分含めた在庫」の中に入ります。 ※K列の在庫は「倉庫にあって入出荷処理中のもの」と考えた方がいいかもしれません >2.今、履歴は4行目に日付、5行目に出荷コードだけども、だまされたと思って、「出荷確定」を追加しておいて。 了解いたしました。複数のファイルのレイアウトを変えやすいように3行目に追加します。 本当にお手数おかけします (らんきち) ---- 一度に聞ければいいんだけど、小出しになって恐縮。 在庫シートのレイアウトで、あくまで各行のキーはA列から始まる商品ID,賞味期限、ロットだよね。 (アップ済みのコードは、このロットを引当時のキーにしていなかったので、そこはなおすけど) なので、その後の列の(2ヶ所の在庫情報の)賞味期限、ロットはいらないんじゃない? というか、A列からはじまるキー情報と同じはずだよね。 なので、 A列:商品ID B列:入荷日 C列:賞味期限 D列:ロットNo E列:入荷数量 F列:前日在庫 G列:引当可能在庫 H列:今のK列からの中の数量(まだ用途がわからない) で、I列あるいは1列あけるのであればJ列から履歴 こんなレイアウトしたらいかが?皆さんと相談してみて。 (ぶらっと) ---- >その後の列の(2ヶ所の在庫情報の)賞味期限、ロットはいらないんじゃない? 確認とりました。 入力時に見やすければ後の列の2か所の賞味期限・ロットNoは省いて構わないとのことです。 レイアウトですが、 A列:商品ID B列:入荷日 C列:賞味期限 D列:ロットNo E列:入荷数量 F列:前日在庫 G列:引当可能在庫 H列:今のK列からの中の数量(倉庫にある未処理分含めた在庫) I列:キャンセル J列を空白でK列から履歴 これでお願いできますでしょうか。 よろしくお願いします。 (らんきち) ---- すみません、今頃になって追加です。 在庫表で、引当可能在庫に数量があっても、特別な指示がないと出せないケースがあるんです。 なので、引当基準になる賞味期限の列に退避列を作って、出せないものはそちらに賞味期限を入れて 自動引き当てになるのを防ごうかと思います。 (数量の列だと在庫数を計算する数式に影響が出るので) なので、C列に「備考欄」というものを挿入して、出荷できないものは賞味期限をそちらに入れて、本来の 賞味期限欄を空白にしておこうかと思うのですが大丈夫でしょうか? A列:商品ID B列:入荷日 C列:備考 D列:賞味期限 E列:ロットNo F列:入荷数量 G列:前日在庫 H列:引当可能在庫 I列:今のK列からの中の数量(倉庫にある未処理分含めた在庫) J列:キャンセル K列を空白でL列から履歴 こんな感じになります。 本当に次から次へと申し訳ございません… (らんきち) ---- 直前のレスの前までの状態でメモしたので、アップする。 直前のレスについては、このアップしたものをベースに、追加修正の形で連絡するので、 まずは、以下のコメントを読んで、コードやシートを準備しておいて。 =========================================================== とりあえず書いた。バグや仕様の勘違いも多々あると思うけど、動かしてみて。 なお、ちょっと説明と補足とお願い。 1.基本的に商品は、「商品名略称」をキーにしてロジックがくまれている。 2.で、お願い。商品略称をキーにして出荷指図書を作成するに当たり、商品IDが必要。 この紐つけのため、商品一覧に「略称名」列を追加。 3.追加の略称列も含めて、商品一覧の列をコードの最初で Public Const で規定。 実際のレイアウトにあわせて、ここを規定してほしい。 4.シートの状況、念のため以下。 「Menu」 シート名任意。ここにフォームツールのボタンを配置して処理を選択させる。 「商品一覧」 商品略称を追加。シート名は コードの先頭のPublic Const で規定。実態に合わせて変更OK。 前述の列規定による列に商品ID,商品名(フル)、商品名略称が登録されている。 「出荷依頼」 ここもシート名については同上。アップするコードでは"Sheet2”と規定。 B列は商品名略称。 「出荷指示書雛形」 シート名は同上。アップするコードでは"Sheet3"と規定。 なお、この雛形シートは運用上目障りであれば非表示にしておいてもかまわない。 「できあがりの出荷指示書」 雛形をコピーして作成。アップするコードでは 出荷コードの頭に"出荷指示" ただ、ここは、出荷日がかわれば同じ出荷コードありうるとのことなので、最終的には yyyymmdd_出荷指示●●● といったものにする必要があると思っている。 「在庫シート」シート名は 商品略称の頭に"在庫"。このシートにも商品IDあるいは商品名(フル)があるけど コードとしてはこれらを、一切参照せず、あくまでシート名から商品略称を抽出している。 なお、最終的には、賞味期限順の自動並び替えを行うけど、まだ実装はしていない。 5.なお、この処理は「出荷指示書」作成のみ。これをやったからといって引当可能在庫が実際に更新されるわけではない。 ただし、後述の仕掛けでユーザーフォームを表示させて処理するが、ユーザーフォーム表示中は、メモリー内で 引当可能在庫は減少させている。したがって 出荷コードAを処理し、ユーザーフォームを閉じないで出荷コードBを 処理した場合、このA,Bに同じ商品があった場合は、Aで引き落とされた結果の在庫に対してBの引当を行う。 もし、フォームが閉じられれば、また引当可能在庫は復活してしまうので要注意。 6.処理は、 1)Menuシートのボタンを押す 2)出荷指示用のユーザーフォームが表示される。 3)リストボックスから処理すべき出荷コードを選択 Ctrlキーをおして複数選択可能、1つ選択+Shiftキーで別のものを選択しても複数選択可能。 このあたりは、VBEヘルプでMultiSelectプロパティの説明をよく読んでおいてほしい。 また、「おまけ」で、「すべて選択」「すべて選択解除」も用意。 7.ユーザーフォーム 配置して欲しいコントロールは、ListBox1 CommandButton1,CommandButton2,CommandButton3 8.Menuシートに「フォームツール」ボタンを配置して、以下の "出荷指示"プロシジャをマクロ登録。 9.コードは以下。標準モジュールのコードは全て同じモジュールにおいてもいいけど、今後のメンテ等を考え 以下のようにわけてある。 1)Module1 ・Menuから選ばれて実行されるプロシジャ群(目下、出荷指示のみ) ・各モジュールで共通に使われるパブリックの変数、定数、定義体。 2)Module2 ・各モジュールで共通に使われる共通プロシジャ 3)Modulle3 以降(目下、Moduke3のみ) ・Menuから選ばれる機能ごとの実行処理部分。 ★なお、関連の機能(引当在庫の更新 等々)もあるけど、まずは、この出荷指示処理の完成に注力しよう。 関連の機能については、このレスとはわけて、後ほど、参考メモをアップする。 (標準モジュール Module1) Option Explicit Enum func fnOpen fnGet fnPut fnOrdered fnShipped fnSort fnClose End Enum Type DLOrder flag As Boolean vntDL As Variant End Type 'シート名規定 Public Const shn商品一覧 As String = "商品一覧" Public Const shn出荷依頼 As String = "Sheet2" Public Const tpl出荷指示 As String = "Sheet3" '商品一覧列規定 Public Const IDCol As String = "A" '商品ID列 Public Const NameCol As String = "B" '商品名列 Public Const ABBRCol As String = "C" '商品略称列 Sub 出荷指示() UserForm1.Show vbModeless End Sub Sub 入荷処理() 'Due To Release in Future End Sub Sub 引当更新() 'Due To Release in Future End Sub Sub 出荷確定() 'Due To Release in Future End Sub (標準モジュール Module2) Option Explicit Function io商品(fc As func, Optional cd As String, Optional comABBR As String, Optional qty As Long, Optional dldate As Date) As Variant Static dicM As Object Static dicH As Object Static comName Dim first As Boolean Dim c As Range Dim sh As Worksheet Dim comid As String Dim dKey As Variant Dim reqQty As Long Dim dDate As Date Dim dQty As Long Dim dLot As String Dim v() As Variant Dim setQty As Long Dim wk As Variant Select Case fc Case fnOpen Set dicM = CreateObject("Scripting.Dictionary") Set dicH = CreateObject("Scripting.DIctionary") For Each sh In Worksheets If Left(sh.Name, 2) = "在庫" Then comABBR = Mid(sh.Name, 3) Set dicM(comABBR) = CreateObject("Scripting.Dictionary") For Each c In sh.Range("A6", sh.Range("A" & sh.Rows.Count).End(xlUp)) ' 賞味期限 LotNo 引当可能数量 dicM(comABBR)(dicM(comABBR).Count + 1) = Array(c.Offset(, 2).Value, c.Offset(, 3).Value, c.Offset(, 4).Value) Next '引当履歴 Set dicH(comABBR) = CreateObject("Scripting.Dictionary") For Each c In sh.Range(sh.Cells(4, "K"), sh.Cells(4, sh.Columns.Count).End(xlToLeft)) ' 出荷日 出荷コード 出荷確定フラッグ dicH(comABBR)(c.Value2 & vbTab & c.Offset(1).Value) = c.Offset(-1).Value Next End If Next Case fnGet If Not dicM.exists(comABBR) Then Exit Function first = True reqQty = qty comName = "登録なし" comid = "登録なし" wk = Application.Match(comABBR, Sheets(shn商品一覧).Columns(ABBRCol), 0) If IsNumeric(wk) Then comName = Sheets(shn商品一覧).Cells(wk, NameCol).Value comid = Sheets(shn商品一覧).Cells(wk, IDCol).Value End If For Each dKey In dicM(comABBR) dDate = dicM(comABBR)(dKey)(0) dLot = dicM(comABBR)(dKey)(1) dQty = dicM(comABBR)(dKey)(2) wk = dicM(comABBR)(dKey) If dldate <= dDate And dQty > 0 Then If dQty >= reqQty Then setQty = reqQty wk(2) = wk(2) - setQty Else setQty = dQty wk(2) = 0 End If reqQty = reqQty - setQty dicM(comABBR)(dKey) = wk If first Then ReDim v(1 To 7, 1 To 1) first = False Else ReDim Preserve v(1 To UBound(v, 1), 1 To UBound(v, 2) + 1) wk(1) = 0 End If v(1, UBound(v, 2)) = cd v(2, UBound(v, 2)) = comABBR v(3, UBound(v, 2)) = dDate v(4, UBound(v, 2)) = setQty v(5, UBound(v, 2)) = dLot v(6, UBound(v, 2)) = dldate v(7, UBound(v, 2)) = comid End If If dicM(comABBR)(dKey)(1) = 0 Then dicM(comABBR).Remove dKey If reqQty = 0 Then Exit For Next If Not first Then io商品 = WorksheetFunction.Transpose(v) End If Case fnOrdered io商品 = dicH(comABBR).exists(CDbl(dldate) & cd) Case fnSort For Each sh In Worksheets If Left(sh.Name, 2) = "在庫" Then End If Next Case fnClose dicM.RemoveAll Set dicM = Nothing dicH.RemoveAll Set dicH = Nothing End Select End Function (標準モジュール Module3) Option Explicit Sub 出荷指示書作成(cds As Variant) Dim i As Long Dim buf As Variant Dim c As Range Dim wk As Variant Dim cd As String Dim myDL As DLOrder For Each wk In cds cd = wk If make出荷指示書(fnOpen, cd) Then With Sheets(shn出荷依頼) '出荷依頼データ For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp)) If c.Value = cd Then ' 出荷コード 商品ABBR 出荷日(シリアル値) If io商品(fnOrdered, cd, c.Offset(, 1).Value, dldate:=c.Offset(, 3).Value2) Then MsgBox "この出荷コード:" & cd & "は出荷指示済みです" Else ' 出荷コード 商品ABBR 数量 出荷日 buf = io商品(fnGet, cd, c.Offset(, 1).Value, c.Offset(, 2).Value, c.Offset(, 3).Value) If IsArray(buf) Then Call make出荷指示書(fnPut, buf) End If End If Next End With End If Call make出荷指示書(fnClose) Next End Sub Private Function make出荷指示書(fc As func, Optional v As Variant) As Boolean Static shn As String Select Case fc Case fnOpen shn = "出荷指示" & v If IsObject(Evaluate(shn & "!A1")) Then If MsgBox(shn & "がすでに存在します。削除して置き換えていいですか?", vbYesNo) = vbNo Then Exit Function Application.DisplayAlerts = False Sheets(shn).Delete Application.DisplayAlerts = True End If Sheets(tpl出荷指示).Copy After:=Sheets(Sheets.Count) ActiveSheet.Name = shn Case fnPut With Sheets(shn) If getDimension(v) = 1 Then .Range("A" & .Rows.Count).End(xlUp).Offset(1).Resize(, UBound(v)).Value = v Else .Range("A" & .Rows.Count).End(xlUp).Offset(1).Resize(UBound(v, 1), UBound(v, 2)).Value = v End If End With Case fnClose 'So Far NOP End Select make出荷指示書 = True End Function Private Function getDimension(v) As Long Dim i As Long Dim wk As Long On Error Resume Next Do i = i + 1 wk = UBound(v, i) Loop While Err.Number = 0 On Error GoTo 0 getDimension = i - 1 End Function (ユーザーフォームモジュール UserForm1) Option Explicit Private Sub UserForm_Initialize() Dim k As Long Dim sh As Worksheet Dim dic As Object Dim c As Range Call io商品(fnOpen) Set dic = CreateObject("Scripting.Dictionary") With Sheets(shn出荷依頼) '出荷依頼データ For Each c In .Range("A2", .Range("A" & .Rows.Count).End(xlUp)) dic(c.Value) = True Next End With ListBox1.List = dic.keys Set dic = Nothing '以下はユーザーフォームのプロパティで設定すればコードは不要 ListBox1.MultiSelect = fmMultiSelectExtended Me.Caption = "出荷指示書作成" CommandButton1.Caption = "実行" CommandButton2.Caption = "全て選択" CommandButton3.Caption = "全て解除" End Sub Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) Call io商品(fnClose) End Sub Private Sub CommandButton1_Click() Dim v() As Variant Dim i As Long Dim k As Long With ListBox1 ReDim v(1 To .ListCount) If .ListIndex < 0 Then Exit Sub End If For i = 0 To .ListCount - 1 If .Selected(i) Then k = k + 1 v(k) = .List(i) End If Next If k = 0 Then MsgBox "出荷コードが選択されていません" Exit Sub Else ReDim Preserve v(1 To k) Call 出荷指示書作成(v) End If End With MsgBox "出荷指示書作成処理が終了しました" End Sub Private Sub CommandButton2_Click() SelectAll True End Sub Private Sub CommandButton3_Click() SelectAll False End Sub Private Sub SelectAll(flag As Boolean) Dim i As Long With ListBox1 For i = 0 To .ListCount - 1 .Selected(i) = flag Next End With End Sub ---- 先ほど、こちらからのレスに書き忘れたことがあった。そちらからの追加要望も含めて以下。 1.まず、出荷指示書の商品小計、アップしたものには入っていないけど最終的には についてはVBA側でいれることを考えている。(雛形から作成する仕掛けなので、計算式をどこにセットするかわからないでしょ?) 2.で、そちらの追加要望。この形でもOKだけど、自分なら、C列を「出荷保留」列にして、通常は空白、出荷を止めたい場合は、 ここに 出荷保留マーク(空白じゃなかったらなんでもいい。たとえば X とか * とか) 出荷再開OKになったら、ここを空白にしておく。そのほうがコピペしなくてすむ。 3.「在庫計算の数式」も、ここが空白じゃなかったらというIF関数をかませればいいと思うけど、そもそも、その関数って どこに、どんな式で入っているの?今回のコードにも関係するかもしれないので、内容をおしえて。 2.の確認と3.の情報、よろしく。 (ぶらっと) ---- 先にふれた、「関連の機能」について、今後の(らんきち)さんの参考に。 まず、「まっすぐ前に進む処理」だけを考えると @商品マスタ登録 A入荷登録 B出荷依頼データ作成 C出荷指示(今回のコード) D出荷引当 Cの指示が実行されると確定した時に引当可能在庫を更新、引当履歴(ステータス、未出荷)の作成。 E出荷確定 確定出荷数量が出荷指示数量と異なれば修正したうえで、出荷済ステータスに。 この時、実在庫も更新。 F日時繰越 一日の業務の最終に、実在庫を前日在庫欄に転記。 これぐらいあるね。これらを人が手作業でやるのか、マクロにやらせるのか、まず、そこをしっかりと決める。 で、いずれの場合でも、その条件を明確に。このような場合には処理できないとか、この処理の結果、どういう情報が そのように更新されて、どういう情報がどのような形で新規生成されるか 等々をしっかりと決める。 で、これだけなら、まだいいけど、最も大変なのは、@〜Fの「訂正」「取消」。 これについては、人がやるのか、マクロにやらせるのかを、しっかり決める。 かつ、条件についても、「まっすぐ進む処理」のケースの数倍のきめ細かさで考えておく必要がある。 訂正・取消の結果、既に出来上がっているデータは、どこをどう変更するのか、あるいはデータそのものを削除するのか。 これをマクロにやらせようとすると(もちろん)その処理を行う情報(キーなんか)が、必ずどこかにあるということが 必要になるので、そのことも考えて、データのレイアウトや持ち方を決定する。(これは、しんどいよ〜) これらをマクロでやるとしても、コードは二の次。ます運用手順とルールと仕様を、まちがいのないものにする。 いきあたりばったりで、コードを準備すると、最後には、しっちゃかめっちゃかになるので要注意。 で、この後、上記で「マクロで実行」ときめたものについて、その優先順位を決めた上で「1つずつ」完成させていく。 現場の皆さんの圧力に負けて、あれも、これも、いっぺんに・・とすると、もう収拾がつかなくなるので。 とりあえずは、目下の出荷指示を完成させよう。 で、おそらくは、次の出荷引当が優先度高いかな? なんとなく、ぼんやりと、こうやったらいいなというイメージは 持っているので、また、必要なら、お手伝いはする。 いずれにしても、出荷指示をしあげよう。 (ぶらっと) ---- コード訂正。レイアウトがかわるので、所詮修正するんだけど、旧レイアウトを踏まえて上でアップしたコードの io商品 プロシジャのなかの dicM(comABBR)(dicM(comABBR).Count + 1) = Array(c.Offset(, 2).Value, c.Offset(, 3).Value, c.Offset(, 4).Value) この最後の c.Offset(, 4).Value は c.Offset(, 6).Value だった! (ぶらっと) ---- とりあえず、要望のあったレイアウト変更に対応。(備考と賞味期限の関係も提示どおりにしてある) 1点、小計挿入のみいれていない。 全ていれかえて、テストしてみて。 なお、ユーザーフォームのリストボックスの幅は、少し長めにデザインしておいてね。 (上で質問している数式の件、回答よろしく) 'ユーザーフォームモジュール Option Explicit Private Sub UserForm_Initialize() Dim k As Long Dim sh As Worksheet Dim dic As Object Dim c As Range Dim v As Variant Dim i As Long If Not make出荷指示書(fnOpen) Then Unload Me Else Call io商品(fnOpen) Call make出荷指示書(fnGetList, v) ListBox1.List = v '以下はユーザーフォームのプロパティで設定すればコードは不要 ListBox1.MultiSelect = fmMultiSelectExtended Me.Caption = "出荷指示書作成" CommandButton1.Caption = "実行" CommandButton2.Caption = "全て選択" CommandButton3.Caption = "全て解除" ListBox1.ColumnCount = 3 End If End Sub Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) Call io商品(fnClose) Call make出荷指示書(fnClose) End Sub Private Sub CommandButton1_Click() Dim v() As Variant Dim i As Long Dim k As Long With ListBox1 ReDim v(1 To .ListCount) If .ListIndex < 0 Then Exit Sub End If For i = 0 To .ListCount - 1 If .Selected(i) Then k = k + 1 v(k) = .List(i) End If Next If k = 0 Then MsgBox "出荷コードが選択されていません" Exit Sub Else ReDim Preserve v(1 To k) Call 出荷指示書作成(v) End If End With MsgBox "出荷指示書作成処理が終了しました" End Sub Private Sub CommandButton2_Click() SelectAll True End Sub Private Sub CommandButton3_Click() SelectAll False End Sub Private Sub SelectAll(flag As Boolean) Dim i As Long With ListBox1 For i = 0 To .ListCount - 1 .Selected(i) = flag Next End With End Sub '標準モジュール Module1 Option Explicit Enum func fnOpen fnInitial fnGet fnGetList fnPut fnOrdered fnShipped fnSort fnClose End Enum Type DLOrder flag As Boolean vntDL As Variant End Type 'シート名規定 Public Const shn商品一覧 As String = "商品一覧" Public Const shn出荷依頼 As String = "Sheet2" Public Const tpl出荷指示 As String = "Sheet3" '商品一覧列規定 Public Const IDCol As String = "A" '商品ID列 Public Const NameCol As String = "B" '商品名列 Public Const ABBRCol As String = "C" '商品略称列 Sub 出荷指示() UserForm1.Show vbModeless End Sub Sub 入荷処理() 'Due To Release in Future End Sub Sub 引当更新() 'Due To Release in Future End Sub Sub 出荷確定() 'Due To Release in Future End Sub '標準モジュール Module2 Option Explicit Function io商品(fc As func, Optional cd As String, Optional comABBR As String, Optional qty As Long, Optional dldate As Date) As Variant Static dicM As Object Static dicH As Object Static comName Dim first As Boolean Dim c As Range Dim sh As Worksheet Dim comid As String Dim dKey As Variant Dim reqQty As Long Dim dDate As Date Dim dQty As Long Dim dLot As String Dim v() As Variant Dim setQty As Long Dim wk As Variant Select Case fc Case fnOpen Set dicM = CreateObject("Scripting.Dictionary") Set dicH = CreateObject("Scripting.DIctionary") For Each sh In Worksheets If Left(sh.Name, 2) = "在庫" Then comABBR = Mid(sh.Name, 3) Set dicM(comABBR) = CreateObject("Scripting.Dictionary") For Each c In sh.Range("A6", sh.Range("A" & sh.Rows.Count).End(xlUp)) If Len(c.Offset(, 3).Text) > 0 Then '賞味期限あり ' 賞味期限 LotNo 引当可能数量 dicM(comABBR)(dicM(comABBR).Count + 1) = _ Array(c.Offset(, 3).Value, c.Offset(, 4).Value, c.Offset(, 7).Value) End If Next '引当履歴 Set dicH(comABBR) = CreateObject("Scripting.Dictionary") For Each c In sh.Range(sh.Cells(4, "L"), sh.Cells(4, sh.Columns.Count).End(xlToLeft)) ' 出荷日 出荷コード 出荷確定フラッグ If Len(c.Text) > 0 Then dicH(comABBR)(c.Value2 & vbTab & c.Offset(1).Value) = c.Offset(-1).Value End If Next End If Next Case fnGet If Not dicM.exists(comABBR) Then Exit Function first = True reqQty = qty comName = "登録なし" comid = "登録なし" wk = Application.Match(comABBR, Sheets(shn商品一覧).Columns(ABBRCol), 0) If IsNumeric(wk) Then comName = Sheets(shn商品一覧).Cells(wk, NameCol).Value comid = Sheets(shn商品一覧).Cells(wk, IDCol).Value End If For Each dKey In dicM(comABBR) dDate = dicM(comABBR)(dKey)(0) dLot = dicM(comABBR)(dKey)(1) dQty = dicM(comABBR)(dKey)(2) wk = dicM(comABBR)(dKey) If dldate <= dDate And dQty > 0 Then If dQty >= reqQty Then setQty = reqQty wk(2) = wk(2) - setQty Else setQty = dQty wk(2) = 0 End If reqQty = reqQty - setQty dicM(comABBR)(dKey) = wk If first Then ReDim v(1 To 7, 1 To 1) first = False Else ReDim Preserve v(1 To UBound(v, 1), 1 To UBound(v, 2) + 1) wk(1) = 0 End If v(1, UBound(v, 2)) = cd v(2, UBound(v, 2)) = comABBR v(3, UBound(v, 2)) = dDate v(4, UBound(v, 2)) = setQty v(5, UBound(v, 2)) = dLot v(6, UBound(v, 2)) = dldate v(7, UBound(v, 2)) = comid End If If dicM(comABBR)(dKey)(1) = 0 Then dicM(comABBR).Remove dKey If reqQty = 0 Then Exit For Next If Not first Then io商品 = WorksheetFunction.Transpose(v) End If Case fnOrdered io商品 = dicH(comABBR).exists(CDbl(dldate) & cd) Case fnSort For Each sh In Worksheets If Left(sh.Name, 2) = "在庫" Then With sh.Range("A6", sh.Range("A" & sh.Rows.Count).End(xlUp)).EntireRow .Sort Key1:=.Columns("A"), Order1:=xlAscending, _ Key2:=.Columns("D"), Order2:=xlAscending, Header:=xlNo End With End If Next Case fnClose If Not dicM Is Nothing Then dicM.RemoveAll Set dicM = Nothing End If If Not dicH Is Nothing Then dicH.RemoveAll Set dicH = Nothing End If End Select End Function Function make出荷指示書(fc As func, Optional v As Variant) As Boolean Static shn As String Static dicO As Object Dim cd As String Dim s As String Dim w As Variant Dim i As Long Dim c As Range Select Case fc Case fnOpen Set dicO = CreateObject("Scripting.Dictionary") With Sheets(shn出荷依頼) '出荷依頼データ For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp)) cd = c.Value s = c.Offset(, 1).Value & "(" & Format(c.Offset(, 2).Value, "#,##0") & ")" If dicO.exists(cd) Then If dicO(cd)(1) <> c.Offset(, 3).Value2 Then MsgBox "出荷コード:" & cd & "の出荷日は全て同じにしてください" Exit Function End If w = dicO(cd) w(2) = w(2) & " " & s dicO(cd) = w Else dicO(cd) = Array(cd, c.Offset(, 3).Value2, s) End If Next End With Case fnGetList v = dicO.items v = Application.Transpose(Application.Transpose(v)) For i = LBound(v, 1) To UBound(v, 1) v(i, 2) = CDate(v(i, 2)) Next Case fnInitial shn = "出荷指示_" & v & "_" & Format(CDate(dicO(v)(1)), "yy-mm-dd") If IsObject(Evaluate(shn & "!A1")) Then If MsgBox(shn & "がすでに存在します。削除して置き換えていいですか?", vbYesNo) = vbNo Then Exit Function Application.DisplayAlerts = False Sheets(shn).Delete Application.DisplayAlerts = True End If Sheets(tpl出荷指示).Copy After:=Sheets(Sheets.Count) ActiveSheet.Name = shn Case fnPut With Sheets(shn) If getDimension(v) = 1 Then .Range("A" & .Rows.Count).End(xlUp).Offset(1).Resize(, UBound(v)).Value = v Else .Range("A" & .Rows.Count).End(xlUp).Offset(1).Resize(UBound(v, 1), UBound(v, 2)).Value = v End If End With Case fnClose Set dicO = Nothing End Select make出荷指示書 = True End Function Private Function getDimension(v) As Long Dim i As Long Dim wk As Long On Error Resume Next Do i = i + 1 wk = UBound(v, i) Loop While Err.Number = 0 On Error GoTo 0 getDimension = i - 1 End Function '標準モジュール Module3 Option Explicit Sub 出荷指示書作成(cds As Variant) Dim i As Long Dim buf As Variant Dim c As Range Dim wk As Variant Dim cd As String Dim myDL As DLOrder For Each wk In cds cd = wk If make出荷指示書(fnInitial, cd) Then With Sheets(shn出荷依頼) '出荷依頼データ For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp)) If c.Value = cd Then ' 出荷コード 商品ABBR 出荷日(シリアル値) If io商品(fnOrdered, cd, c.Offset(, 1).Value, dldate:=c.Offset(, 3).Value2) Then MsgBox "この出荷コード:" & cd & "は出荷指示済みです" Else ' 出荷コード 商品ABBR 数量 出荷日 buf = io商品(fnGet, cd, c.Offset(, 1).Value, c.Offset(, 2).Value, c.Offset(, 3).Value) If IsArray(buf) Then Call make出荷指示書(fnPut, buf) End If End If Next End With End If Next End Sub (ぶらっと) ---- 小計挿入追加 make出荷指示書 プロシジャのみいれかえ。 勝手に、商品が1行の場合は、次の商品との間に空白行を挿入するけど、小計表示はスキップ。 複数行の場合にのみ小計を表示。 Function make出荷指示書(fc As func, Optional v As Variant) As Boolean Static shn As String Static dicO As Object Dim cd As String Dim s As String Dim w As Variant Dim i As Long Dim c As Range Select Case fc Case fnOpen Set dicO = CreateObject("Scripting.Dictionary") With Sheets(shn出荷依頼) '出荷依頼データ For Each c In .Range("A2", .Range("A" & Rows.Count).End(xlUp)) cd = c.Value s = c.Offset(, 1).Value & "(" & Format(c.Offset(, 2).Value, "#,##0") & ")" If dicO.exists(cd) Then If dicO(cd)(1) <> c.Offset(, 3).Value2 Then MsgBox "出荷コード:" & cd & "の出荷日は全て同じにしてください" Exit Function End If w = dicO(cd) w(2) = w(2) & " " & s dicO(cd) = w Else dicO(cd) = Array(cd, c.Offset(, 3).Value2, s) End If Next End With Case fnGetList v = dicO.items v = Application.Transpose(Application.Transpose(v)) For i = LBound(v, 1) To UBound(v, 1) v(i, 2) = CDate(v(i, 2)) Next Case fnInitial shn = "出荷指示_" & v & "_" & Format(CDate(dicO(v)(1)), "yy-mm-dd") If IsObject(Evaluate(shn & "!A1")) Then If MsgBox(shn & "がすでに存在します。削除して置き換えていいですか?", vbYesNo) = vbNo Then Exit Function Application.DisplayAlerts = False Sheets(shn).Delete Application.DisplayAlerts = True End If Sheets(tpl出荷指示).Copy After:=Sheets(Sheets.Count) ActiveSheet.Name = shn Case fnPut With Sheets(shn) With .Range("A" & .Rows.Count).End(xlUp).Offset(1) If getDimension(v) = 1 Then .Resize(, UBound(v)).Value = v .Offset(1).Value = " " 'スペース 商品ブレーク ただし1行ゆえ小計なし Else .Resize(UBound(v, 1), UBound(v, 2)).Value = v With .Offset(UBound(v, 1)) .Value = " " 'スペース 小計行 .Offset(, 2).Value = "小計" .Offset(, 3).Value = WorksheetFunction.Sum(WorksheetFunction.Index(v, 0, 4)) End With End If End With End With Case fnClose Set dicO = Nothing End Select make出荷指示書 = True End Function (ぶらっと) ---- >ぶらっと様 いつもありがとうございます。 すみません、2点エラーが出ました。 まず「io商品」プロシジャで dDate = dicM(comABBR)(dKey)(0) ここで「型が一致しません」のエラーが出ます。 また、その後再度「実行」をすると「make出荷指示書プロシージャ」の ActiveSheet.Name = shn で “実行時エラー1004 シートの名前をほかのシート、Visual Basic で参照されるオブジェクトライブラリまたはワークシートと同じ名前に変更することはできません” というエラーが出ます。 >C列を「出荷保留」列にして、通常は空白、出荷を止めたい場合は、ここに 出荷保留マーク おっしゃるようにその方がやりやすそうです。 >3.「在庫計算の数式」 元に入っていた数式がものすごくごちゃごちゃしていたので先ほど整理してみたところ、まず ・L列は出荷とは別に他の倉庫に移動させる数量が入っている(出荷指示はしないが引き当てられる在庫からは差し引く) 今はL列は手入力。項目名は「移動」 ・M〜R列が翌日以降出荷予定分で、引き当て済みだが倉庫に残っているもの (上で書いた「11/10出荷の“PM”」「11/11出荷の“PM”」の数量が入っている) というのが前提で、 F列:入荷数量→現状は空欄です。将来的には引当可能在庫に繰り入れる予定 G列:前日在庫→手入力(これが元のデータになる) H列:引当可能在庫→“前日在庫” - “L列移行の合計(移動・引当がかかっているものの合計)” I列:倉庫にある未処理分含めた在庫→“当日在庫” + “キャンセル分(J列)” + “M〜R列の合計” という感じになります。 あと、出荷引当もできるだけ早い段階で(一応の指示は今週中…)完成させてほしいと言われて少し泣きそうです;; 上で書きましたようにイレギュラーな出荷(在庫はあるのに指示がないと引当できない)パターンがあるので、 出荷指示と同時に処理でなく ・指示書作成 ↓ ・間違い無ければ出荷引当 のような感じでとのことです。 出荷引き当てはユーザーフォームのボタンで実行とかできますか? とりあえず出荷指示書・引当はマクロでできるようにしたいです。 それ以外の部分はもう一度確認します;; (らんきち) ---- 検証ありがとう。 実行環境を自宅には作ってないので、明日、報告のポイントをチェックしてみる。 平行して、そちらでは、シートのレイアウトを確認しておいて。 こちらでも、旧レイアウトのまま実行して、さんざん、型が違いますとかインデックスエラーを体験。 シート名が重複するエラーは、未だでていない。そこは、ちょっと自信があるんだけど、それも明日 こちらでも再確認する。 勝手にこちらで設定した列もあるので(コメントで連絡はしているけど) 出荷保留マークについては、いずれ、そのようにしよう。 出荷引き当てについては、平行してこちらで準備するので、まずは、出荷指示をしあげよう。 (ぶらっと) ---- まず、このレス含め、今後のやり取りは、 ・コードとしては、このレスの4つ前のフルセットのコードに、その後のmake出荷指示書プロシジャのいれかえを 反映したものをベースにする。 ・レイアウトとしては、 A列:商品ID B列:入荷日 C列:備考 D列:賞味期限 E列:ロットNo F列:入荷数量 G列:前日在庫 H列:引当可能在庫 I列:今のK列からの中の数量(倉庫にある未処理分含めた在庫 J列:キャンセル K列を空白でL列から履歴 これをベースにする。 で、最初のコード修正連絡は、このレスの最後に、C列:備考 -> C列:出荷保留 にするための訂正の件になるけど まず、↑で報告もらった障害について。 dDate = dicM(comABBR)(dKey)(0) これは dDate という日付型の変数に、在庫シートのD列(賞味期限)をいれようとしているところ。 (「現時点」でのロジック前提だから、ここが「空白」のものは対象外だけど) そこで型が違うというエラーになるということは、賞味期限が「日付型」のデータではないということなんだけど? ちなみにVBAコードとしては「スペース」は「空白」とはみなされない。 ここはどうだろうか? “実行時エラー1004 これは、既に作成した出荷指示書があるのに同名のシートを作成しようとしてエラーになるケース。 ただし、コードとしては事前にチェックして、同名のものがあるなら置き換えるのか、その指示書さくせいを やめるのかのメッセージをだしている「つもり」なんだけど、そのメッセージはでていないということだね。 こちらでは、そのケース、ちゃんとメッセージがでて、障害にはならないんだけど、実は、この「学校」の 別のQA(複数QA)で、その方式をアップしたところ、質問者さんの環境では、シートが存在するのに 存在していないと判断されてエラーになるケースが(最近)続けて発生していて、原因がわからないので 「もっと確実に」シート有無をチェックできる方式に変更している。 本件、これで悩んで時間を使うのはもったいないので、このレスの次になるけど、そこのコード訂正を 連絡するので、試してみて。 ★と、いったんアップしてから、こちらで実行したら今、「幸か不幸か」障害になった。 調べてバグつぶして、また連絡するね。おさわがせ。 で、C列:備考 -> C列:出荷保留 今、make出荷指示書の最初のほうに If Len(c.Offset(, 3).Text) > 0 Then '賞味期限あり こんなところがあるけど、それを If Len(c.Offset(, 2).Text) = 0 Then '保留マーク空白 これにかえてください。 (ぶらっと) ---- 1004の件、わかった。 現在のシート存在チェックは make出荷指示書 の Case fnInitial のちょっと下の If IsObject(Evaluate(shn & "!A1")) Then でおこなっている。 これは「k窓」というサイトで紹介された手法で、こちらでは長い間不都合なく使ってきてるけど、 最近、どこかのサイトで(どこか思い出せないけど)、この手法は、チェックする文字列によっては 万能ではないという記事を読んだ記憶がある。で、今、こちらで様々やってみると、少なくとも 最新にアップしたコードで、このシート名に日付を持たせる改訂の際に、"_"や"-"を使って、 (これ自体はいいんだけど)その場合、この手法だと、正しいチェックがなされないということがわかった。 なので、「確実にチェックできる方式」に変更する。 この If IsObject(Evaluate(shn & "!A1")) Then を If IsObject(Evaluate(shn & "!A1")) Then に変更。 かつ、Module2 に以下を追加して。 Function IsSheet(shn As String) As Boolean Dim wk As String On Error Resume Next wk = Sheets(shn).Name On Error GoTo 0 If Len(wk) > 0 Then IsSheet = True End Function ついでに念のため(レスが続いて、ついつい見過ごすかもしれないので)前レスで連絡した訂正も以下に。 ================================== で、C列:備考 -> C列:出荷保留 今、make出荷指示書の最初のほうに If Len(c.Offset(, 3).Text) > 0 Then '賞味期限あり こんなところがあるけど、それを If Len(c.Offset(, 2).Text) = 0 Then '保留マーク空白 これにかえてください。 ================================== 「型が違う」の件は、前レスに書いた質問の回答よろしくね。 (ぶらっと) ---- IsObject(Evaluate("'" & shn & "'!A1")) でもよさそうだけど。 追記 上のように書こうとして修正忘れちゃったのかな? (春日野馨) ---- 春日野馨さん ご教示、深謝。いえいえ、全く思いつかなかったんですよ。なぁるほど。 ところで、たとえば - や _ なんかがない場合は ' で囲まなくてもOK。 Evaluate以外でも ' をつける必要があったりするものがありますけど、 「こんな場合は付けること」というルールって、教えていただけないでしょうか? (らんきち) さん 春日野馨さんからのレスキューがはいったので、↑で連絡した IsSheetに変えるところ (Function IsSheet の追加も含めて)忘れてください。 で、If IsObject(Evaluate(shn & "!A1")) Then これを If IsObject(Evaluate("'" & shn & "'!A1")) に変更して下さいな。 おさわがせ。 (ぶらっと) ---- ぶらっとさんへ。 基本は下のリンク先のパターンだと思う。 http://support.microsoft.com/kb/410985/ja あとはセル番地と同じ物、これはA1形式、R1C1形式のどっちもなんでR、Cってシート名も'が必要になるよ。 また、AAA10ってシート名だと2003以前だと'は必要ないけど2007以降だと必要になって来るよ。 ただ、INDIRECTなんかは先頭が数値の場合とか一部については'が無くても対応してくれるみたい。 とりあえずシート名を扱うときは'を付けといたほうが安心みたい。 (春日野馨) ---- 春日野馨さん ありがとうございます。 こちらでも、ネット検索して、今、見つけたところでした。 不勉強を反省!です。 >とりあえずシート名を扱うときは'を付けといたほうが安心みたい。 ですね。誰かk窓にも連絡したらいいかもですね。(私ごときでは、恐れ多いので) (ぶらっと) ---- >ぶらっと様、春日野馨様ありがとうございます 「型が違う」の件ですが、賞味期限欄が空白(というか最後の行から先が空欄)になっているものや、 「2012.12.1※入荷日未定」のように日付の後に文字列が入っているものがありましたので、 そこに全て数字の「0」を入れてみましたがやはり「型が違う」のエラーが出ます。 また、ワークシートのエラーの件ですが、 If IsObject(Evaluate("'" & shn & "'!A1")) Then に置き換えると解消されました。 「備考」→「出荷保留」は既に見出しを「出荷保留」に変更しています。 (らんきち) ---- 型が違うの件、こちらでわかりました! 元のデータの日付の入力パターンが統一されておらず、 2012.12.1 という表示形式のシートがあり、これを2012/12/1に変えたら解消されました。 ただ、「2012/12/2※サンプル用」のように日付の後にコメントが入っているものがあります。 コメント自体は必要なんですが、別に列を挿入するなとした方がいいでしょうか? (らんきち) ---- たびたびすみません、不具合追加です。 > 「出荷指示書雛形」 シート名は同上。アップするコードでは"Sheet3"と規定。 > なお、この雛形シートは運用上目障りであれば非表示にしておいてもかまわない。 ということでしたが、雛形を非表示にすると最後にあるシートのシート名が「出荷指示_DM_11-11-01」と変更され、 元の在庫データの最後尾以降に出荷指示データが追加されてしまいます。 とりあえず雛形を表示にしておけば問題はないですが… (らんきち) ---- さらに追加とお詫び;; 作成した出荷指示書の空白と小計がおかしくなることがあります。 出荷指示入力の際に、梱包の都合上同じ出荷コードで同じ商品を2行に分けて入力する場合があります。 例) Sheet2(出荷データ) A B C D 1 出荷コード 商品ID 数量 出荷日 2 P10 A001 500 2011/11/1 3 P10 A001 700 2011/11/1 4 P10 B001 200 2011/11/1 この場合、2行目に入力したデータと3行目に入力したデータの間に一行空白行ができてしまい、 小計欄には3行目の「700」しか表示されません。 これも説明不足でした…すみません あと、前述の在庫表のロットNoと数量を入れ替えることになった際に作成される出荷指示書のレイアウトも 変更になったのをすっかり忘れてました;; A B C D E F G 1 出荷コード 商品名 賞味期限 ロットNo 出荷数 出荷日 商品ID 2 P10 ○○○ 2012/2/1 AA 500 2011/11/1 A001 3 P10 ○○○ 2012/2/1 AA 700 2011/11/1 A001 4 P10 ○○○ 2012/2/20 BB 50 2011/11/1 A001 5 小計 1250 6 P10 ××× 2012/2/10 YY 70 2011/11/1 B001 7 P10 ××× 2012/2/15 ZZ 80 2011/11/1 B001 何とか自力でコードを入れ替えられないかと思って別画面でいじってますがもしかして今後お伺いする時に邪魔になるかもと思い… 本当にすみません… (らんきち ---- 指示書のレイアウト変更ですが、下記の内容で一応できたのですが大丈夫でしょうか? io商品プロシージャ End If v(1, UBound(v, 2)) = cd v(2, UBound(v, 2)) = comABBR v(3, UBound(v, 2)) = dDate v(4, UBound(v, 2)) = dLot v(5, UBound(v, 2)) = setQty v(6, UBound(v, 2)) = dldate v(7, UBound(v, 2)) = comid make出荷指示書プロシージャ Case fnPut With Sheets(shn) With .Range("A" & .Rows.Count).End(xlUp).Offset(1) If getDimension(v) = 1 Then .Resize(, UBound(v)).Value = v .Offset(1).Value = " " 'スペース 商品ブレーク ただし1行ゆえ小計なし Else .Resize(UBound(v, 1), UBound(v, 2)).Value = v With .Offset(UBound(v, 1)) .Value = " " 'スペース 小計行 .Offset(, 3).Value = "小計" .Offset(, 4).Value = WorksheetFunction.Sum(WorksheetFunction.Index(v, 0, 5)) End With End If End With End With Case fnClose (らんきち) ---- >ただ、「2012/12/2※サンプル用」のように日付の後にコメントが入っているものがあります。 >コメント自体は必要なんですが、別に列を挿入するなとした方がいいでしょうか? 日付列は日付列として持っておくほうが、後々、様々な利用をしようとしたときに絶対に有利なので 別の列でコメント列(それこそ、本当の備考列)をつくって運用したほうがいいよ。 たとえば、プログラムとしては、そこが「日付型じゃなかったら対象外」というロジックにすることも できなくはないけどね。 あぁ、ついでに。次のテーマの引当で重要になってくるんだけど L列からの履歴の日付欄が 11/1 といった表記になっているけど、もちろん、ここも「日付型」なんだよね。 そうじゃなかったら、アップ済みの出荷指示書のロジックにも影響してくるので。 これは絶対条件だね。 >ということでしたが、雛形を非表示にすると最後にあるシートのシート名が「出荷指示_DM_11-11-01」と変更され、 >元の在庫データの最後尾以降に出荷指示データが追加されてしまいます。 ごめん。雛形を非表示にすると、できあがる出荷指示書も非表示になっちゃうね。 make出荷指示書の中の Case fnInitial のブロックに ActiveSheet.Name = shn があるので、その下に ActiveSheet.Visible = True をいれておいて。 「最後にあるシートのシート名が「出荷指示_DM_11-11-01」と変更され」はわからないなぁ。 最後にあるシートって、元は何だった?いずれにしても、こちらでは、作ったものが非表示なっているというのは 再現してるけど、既存のシートに悪さをするところはないんだけど? >出荷指示入力の際に、梱包の都合上同じ出荷コードで同じ商品を2行に分けて入力する場合があります。 実務としては理解するけど、ロジックはそうなってないのでね。 もしかしたら、根本的な改造が必要かも。なにせ、ここは「データのキー」なので。 ちょっと、悩んでみる。 >あと、前述の在庫表のロットNoと数量を入れ替えることになった際に作成される出荷指示書のレイアウトも >変更になったのをすっかり忘れてました;; はい、わかりましたよ。これは、割合と早く連絡できそう。 >もしかして今後お伺いする時に邪魔になるかもと思い… そうなんだよね、これがつらいところ。 でも、絶対に自信があれば、そちらで直して、逆に、こちらに連絡してくれれば、こちらも直すってことでも いいんだよ。 とりあえず、↑で連絡してくれたレイアウト変更のコード改訂は、今からチェックしてOKかどうか返事する。 ● で、今チェック完了。これでいいです。こちらも直しておきます。 (ぶらっと) ---- ★1つ提案。 このトピも、随分と長くなって、編集なんかすると、もう大変なので、いったん締めて、 No.2として別トピをたててくれない? で、以降(きっと、出荷引当ができるまでぐらいかな)は、その別トピで進めようよ。 (ぶらっと) ---- 了解いたしました。 次のトピを立てましたのでよろしくお願いします http://www.excel.studio-kazu.jp/cgi-bin/kazuwiki2.cgi (らんきち) ...
https://www.excel.studio-kazu.jp/wiki/kazuwiki/201111/20111101135213.txt - [detail] - similar
PREV NEXT
Powered by Hyper Estraier 1.4.13, with 97045 documents and 608224 words.

訪問者:カウンタValid HTML 4.01 Transitional