[[20111122110935]] 『Excel在庫管理で入荷処理』(らんきち) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『Excel在庫管理で入荷処理』(らんきち)

[[20111101135213]]
[[20111110145634]]
[[20111114163123]]

 に関連して、Excelでの入荷処理について質問です。

 一つのファイルに13種類ほどの商品別在庫シートがあります。
 このファイルは毎日その日の分として1日1ファイル作られます。
 出荷・在庫引当は前の質問でできたのですが、今度は入荷処理をできるようにしてくれと言われています。
 在庫シートの構成は下記の通りです。

    A   B   C    D    E   F    G    H      I      J     K    L   M 〜 
 1 商品ID 入荷日 出荷保留 賞味期限 備考 ロットNo 入荷数 前日在庫 引当可能在庫 倉庫在庫 キャンセル 空白 出荷履歴 〜

 出荷履歴はAR列まであり、AS・AT・AUには合計などの数式がそれぞれ入っています。
 また商品ごとに表の行数は違います(10行程度のものから35行ぐらいあるものもあります)
 G列以降の項目の最後の行にはSUM関数でそれぞれの合計が入っています。

 ※前日在庫:前の日が終わった時点の在庫
  引当可能在庫:出荷可能な在庫
  倉庫在庫:引当済みのものと引当てなしのものを含めた、倉庫にある在庫

 各商品シートは「在庫○○」(○○=商品名)というように「在庫」が頭につくようになっています。

 今回やりたいのは、

 @入荷データが来る
 A各商品シートに入荷日(B列)、賞味期限(D列)、ロットNo(F列)、入荷数(H列)にユーザーフォームからデータを入力

 ということですが、重要なのが“賞味期限の昇順に並べること”です。
 入荷時は必ずしも新しいものが入ってくるとは限らず、キャンセルで古いものが入ってくることもあります。
 なので、入力時または入力後に入力した全ての商品のデータを賞味期限の昇順に並べ替える必要があります。

 また入荷数は、G列に入力すれば自動的にI列の引当可能在庫に入るようにI列に数式が入っています。

 まとめると、
 ・Aのデータをユーザーフォームから入力
 ・商品IDまたは商品名から判断して各商品シートに入力(列が足りないようなら追加、または毎回追加でもOK)
 ・賞味期限の昇順に並べ替える

 ということです。

 Aのユーザーフォームで商品を選ぶ時は、入力ミスを防ぐため商品マスタからコンボボックスで商品ID、または商品名(商品略称)を選びたいと思っています。

 商品マスタシート(商品IDの昇順)

    A   B   C
 1 商品ID 商品名 商品略称
 2 01_AAA あああ  あ
 3 02_BBB いいい  い

 ※商品略称=在庫シート名の「在庫○○」の○○部分と同じ

 入荷日・賞味期限はyyyy/m/dの日付型、ロットNoは文字列です。

 どのようにすればよいのでしょうか。

 恐れ入りますがご教授くださいm(__)m


 出荷指示->引当 ときて 入荷処理。いずれは在庫更新なんかにも広がっていくとすると本格的なWMSの様相だね。
もちろん、それは可能で、がんばってほしいと思うし、今回のトピも、状況によっては、お手伝いできるかもしれないけど
ちょっと心配なのは、在庫という結構大きなサイズになるデータ、さらに出荷依頼データ、出荷指示書、商品一覧といった
データと、「マクロ」が「同じブック」に存在しているという部分。
大きなサイズのデータ+マクロブックを更新、更新としていくと、ブックが壊れてしまうというトラブルの報告は少なくない。

 どこかで、マクロブックとデータブックの分離も検討しておいたほうがいいかもしれないよ。

 さらにいえば、以前から指摘しているように、現在のシート(特に在庫シート)の構えは
データ管理という面で見ると、きわめて扱いにくいというか、データ処理としては、「不適切」なレイアウト。
現在までの「手作業」による、レイアウトを、そのまま引きずって、システムを構築していくと
どこかで、「どつぼ」にはまりそうな心配もあるねぇ。

 (ぶらっと)

 ぶらっと様

 >マクロブックとデータブックの分離
 はい、私もそう思います。
 毎日新しいブックを作るのでデータ量が大きくなってしまって…

 あと前トピに書くかどうか迷ったのですが、同じ賞味期限・同じロット番号のものが2行以上あった場合の引当更新で少し不思議なことが起きました

 賞味期限  ロットNo 引当可能数
 2012/10/2  A     1
 2012/10/2  A     50

 とあって、出荷指示が21個来た場合、出荷指示書には

 賞味期限  ロットNo  数量
 2012/10/2  A     1
 2012/10/2  A     20

 と2行に分かれて出力されるのですが、引当時は在庫シートが

 賞味期限  ロットNo 引当可能数  出荷数
 2012/10/2  A     1
 2012/10/2  A     30      21

 と下のものにまとめられてしまい、上の1個が残ったままになるんです…

 同じ賞味期限で同じロット番号というのは「コメント」の有無で2行に分かれてしまったものです。

 すみません、これも後だしみたいになってしまいました…

 レイアウトの変更はこちらのやりやすいように変えてもいいと言われたのですがどう変えればいいかと悩んでおります。
 これは翌日出荷、賞味期限は古いものから、出荷コードの履歴は残して、など制約が多いもので…

 実際に運用してみて他にもいくつか考えなければならないことがあったので、それも含めて考えます…

 (らんきち)

 上記の現象に追記です。

 賞味期限  ロットNo 引当可能数
 2012/10/2  A     50
 2012/10/2  A     1

 だった場合、引当時に在庫シートが

 賞味期限  ロットNo 引当可能数  出荷数
 2012/10/2  A     50
 2012/10/2  A     -20      21

 とマイナスになってしまいます…

(らんきち)


 >同じ賞味期限・同じロット番号のものが2行以上あった場合の引当更新で少し不思議なことが起きました

 あちらのほうにコメントいれておくね。

 (ぶらっと)

 >入力時または入力後に入力した全ての商品のデータを賞味期限の昇順に並べ替える必要があります。

 とりあえず、ここだけコメントすると、いったん追加した後、前スレでアップしたコード内の
io商品のfnSort機能を使えばいいと思う。
実際にはアップ済みのコードでは、fnSortを使っていない。将来のために書いておいただけ。
ただし!

 >G列以降の項目の最後の行にはSUM関数でそれぞれの合計が入っています。

 こういうことを想定していなかったので、そのままでは使えないけど。

 (ぶらっと)

 ありがとうございます。

 各列ごとの合計は各出荷コードごとの合計で、特に最後尾でなければならないというわけではなく、例えば
 行の一番最初に持ってきてもいいです。

 ただ前トピにご回答いただいた「引当更新時の数が〜」の件で、現状手入力で修正しているので、修正した
 内容が合計とあっているかどうかの確認のために列ごとの合計は必要です。
 他にも入力後に出荷数の訂正があった場合にやはり手入力で修正しているので。

 商品によってあまりにも行数が極端に違うことがあり、「多いものに合わせる」のも難しいです…

 レイアウトを変えるとしてもどうやったらいいのか今色々考えていますが、こういう「賞味期限」などの基準で先入れ先出しする場合、普通はどんなレイアウトなんでしょうか…

 今までは会社ごとの専門ソフトがあるところばかりだったのでなかなかいい案が思いつきません…

(らんきち)


 私は前のトピからのおつきあいなので、提示されている要件や、「提示されていないけど本当は必要だろうな」という要件について
イメージを持ちやすいんだけど、初めててこのトピをご覧になる回答者さんたちは???なんだろうね。

 まず、そちらで、処理のイメージ(コードとかロジックではなく流れ)を
「新規」「取消」「訂正」にわけて、最初にフォームにはどんな状態で何が表示されているか、
そこで○○を選ぶと□□が表示され、そこで「何かをすると」入力項目に△△△がセットされて、
その入力項目を入れた後、「どうすると」「シートがどう更新されるか」、そういったシナリオを
きちんと整理した上で説明したほうがいいねぇ。
(私は、私なりに、前トピの段階から、このあたりのイメージは、もってるけど)

 それと、在庫シートは、
・合計列は最終行ではなく、どこか別のところのほうがいいようにも思うけど、現状のレイアウトだと
 上のほうがいっぱい、いっぱいなので、最終行でやむなしとして、これは、マクロでセットしたほうがいい。
 じゃないと、その合計行を意識してコード処理しなきゃいけないので、
・各行の中に引当可能数等、計算式がはいっているところがあるよね。
 行追加する場合、その式もセットしなきゃいけない。なので、これも「雛形シート」を用意しておいて
 その雛形シートは5行目までのタイトル行と6行目に計算式だけをセットしておく。
 マクロでは、そこを参照する。
 新規シートになる場合もありうるなら、その雛形シートをシートコピー。
 こんなようにしておいたほうがいいよ。
 で、いずれにしても、今回できるマクロで、書き込んだ後、fnSortで、必要な順番に並び替えればいい。

 (ぶらっと)

 こちらのイメージしている処理の流れですが、入荷処理に関しては「新規入荷登録」のイメージはありますが例えば入荷したものの訂正・キャンセルが、
 「どの入荷分を訂正・キャンセルするのか」と特定できるユニークなキーが無いのでそこも悩むところです。
 「入荷コード」というものを作って(例えば11/11/22入荷は111122Aなど)入力していく、というステップを作ってもいいですが、またレイアウトがごちゃごちゃになりますよね…
 現状は「賞味期限」「ロットNo」で特定してその数字を直接いじってます(入荷日の項目がなかったので)

 なのでとりあえず「入荷の取消・訂正」は考えるとして、入荷の新規登録ですが、入荷データは商品ごとに別の伝票で届きます

 ★新規入荷登録
 ・入荷日入力(テキストボックスで日付型)
  入荷日は最初か登録する当日をセットしておいてもOK
  空白は「入荷日が入力されていません」などのエラーを返す
 ・商品選択(コンボボックスで商品マスタシートから「商品名(または略称)」を選択)
  「商品ID」は私が今回作ったもので、商品IDを選ぶようにすると混乱すると思うので、もし在庫シートへの転記などで商品IDが必要であれば
 「商品ID+商品名」でコンボボックスに表示するか、商品名を選択した時点で自動的に商品IDも別のオブジェクトに表示されるような形で…
 ・ロットNo、賞味期限、入荷数入力(3つともテキストボックス、賞味期限は日付型)
  一度に複数行のデータを入力するので各8個ほど縦に並べる
  入荷データを見ていると、商品によっては「同じ賞味期限・同じロット」のものがあります。
  今は入荷入力する時に手計算していますが、
  「入荷日」--「賞味期限」--「ロットNo」
  この3項目が一致していれば一行にまとめていい
  例)
   入荷日  賞味期限 ロット 数量
  2011/11/22 2012/5/5  A   20
  2011/11/22 2012/5/5  A   30
  2011/11/22 2012/5/5  A   40
   ↓
   入荷日  賞味期限 ロット 数量
  2011/11/22 2012/5/5  A   90

  理想では上記3項目が一致しているものは入力した時(在庫シートに転記した時)に自動計算して合計を出せればいいですが、無理ならここは手元で計算して入力します。

 上記内容をフォームに入力したら「登録」ボタンで在庫シートに転記、同時にフォームもクリア(二重登録を防ぐため)

 それから次の商品を入力…
 フォームには「クリア」(フォームの内容をクリア)、「閉じる」ボタンを置いておく。
 入力後に並べ替えするのであれば、「登録」ボタンの横に「並べ替え」ボタンを配置

 このようなイメージですがどうでしょうか。
 「こうした方が…」というところがあれば指摘してください。

 在庫シートですが、よく考えると上の3行はなくてもいいんですよね…

    A   B   C    D    E   F    G    H      I      J     K    L   M 〜 
 1  商品名(見出し)
 2 商品ID 入荷日 出荷保留 賞味期限 備考 ロットNo 入荷数 前日在庫 引当可能在庫 倉庫在庫 キャンセル 空白 出荷履歴 〜

 にしてN列以降は1行目に出荷日、でもいいのですが、またコード大幅変更でお手数かけるようであれば現状で構いません
 (少しすっきりするかと思ったんですが)
 もしこれでいけるのなら合計列を3行目あたりにあらかじめセットしておくのもいいかと…

 合計列をマクロでセットする件と雛形の件は了解いたしました。

 並べ替えの優先順位は「賞味期限」→「入荷日」→「ロットNo」(いずれも昇順)です。

 必要な情報はまた補足します。

 あと出荷の方の取消・訂正もイメージは持っているのですがちょっと考えてまた追記します

(らんきち)


 あっちらのほうで引当更新ロジックの改善コードをアップしているので、以降のこのトピのやりとりは
それを反映したコードベースで。

 いずれ(ほどなく?)入荷処理コード追加分をアップするけど、その前に、前触れとして構想を。
この構成が、運用面で「いやだ」ということなのか、「まぁ、いいかな」ということなのか、関係者と
よく打合せをしておいて欲しい。

 ★ところで、前にもふれたけど、ちょっと、やりすぎというか、この種の掲示板の主旨から大きく逸脱している。
 本来は、わからないところを、参考コードとしてアップして、それを質問者側で咀嚼吸収して、肉付けしていくべき。
 今回のような、そこそこのアプリ要件を伴ったコードの提供はやるべきではなかったなぁと。
 乗りかかった舟なので、提示したコードの「バグ対応」はやるけど、今後は、その範囲にとどめるつもり。

 1.「新規」入力のみ。訂正、あるいは取消については、やるとすれば、全く別のコードが必要になる。
  できないことはないけど、引当済みのものとの関係等々、かなり「エラー処理」も、その条件を
  熟考した上で取り組むことが必要で、将来、そちらで、がんばって追加するということで、当面は
  在庫シート上での「手入力」による訂正・取消として運用願いたい。
 2.8行程度の入力ということだったけど、ユーザーフォームで複数行対応をすると、ロジックも煩雑に
  なるし、また、実際に操作すると、結構、操作手順にルールがでたりして、そんなに便利でもない。
  (当方で同じようなことを処理しているけど、その経験から)
 3.なので、ユーザーフォーム上では1行1行入力し、入力したものをユーザーフォーム上のリストで表示。
  入力が終了したら、その(複数行の)リストを在庫シートに反映させる。
  (これが、うざったいということなら、ユーザーフォームは使わず、出荷依頼データのように、
  入荷データシートに手打ちをして、それを在庫シートにマクロで反映させるようにしたほうがいい)
 4.在庫シートへの反映は、既に存在する行の下に「追加」される。
 5.ユーザーフォーム上は、基本は、リストへ「追加」していく。
 6.リストに追加したデータを修正したい場合や、取り消したい場合は、リストの該当行を選んで
  「置き換え」モードで対応するようにしてある。(3項目が空白なら削除)
 7.ユーザーフォームでの処理の単位は、「1つの商品、1つの入荷日」
  これが異なるものについては、処理をわけて入力必要。
 8.別件。在庫シートのレイアウト、データが3行目からということに関しては、コードで
  在庫シートのデータ開始行を、例のConst で規定し、コードは、それを参照するようにしたので
  必要ならどうぞ。後ほどアップするコードでは、ここを 3 にしてある。
 9.在庫シートの合計行は、データ行の最終の下に1行、空白行をおき、その下の行に列合計式をいれて。
  で、雛形シートは、タイトル行までのコンスタント、各列の書式を設定した上で、たとえば開始行が3だとして
  G列に列合計式がセットされるとしたら、
  ・3行目の式をいれておく。
  ・4行目は空白行。
  ・5行目が列合計行。からなずA列になにかしらの文字(合計 等 なんでもOK)をいれておき
   G5には =SUM(G3:G4) といれておく。
  ・空白行、合計行については、既存の在庫シートも、そのように直しておいてほしい。
 10.雛形シートのシート名は任意(Constで規定。アップ予定のコードでは"tplCom"にしてある)
      出荷指図書テンプレートと同様、非表示で保護でもOK。
 もう1つ、前触れでユーザーフォームについて。(アップするコードではUserForm2 にしている。これは好きな名前で)

 ComboBox1  左上あたりに配置。商品を選択。列は、略称と正式名称の2列なので、ちょっと幅は長めに。
 TextBox1   その右あたりに配置。入荷日。
 TextBox2〜TextBox4  賞味期限、ロット、数量。配置は、そちらの好みの場所に。
 CommandButton1  賞味期限、ロット、数量 をリストに登録(または置換、削除) 場所はそちらの好みのところに。
 ListBox1 入力データが格納され表示される。3列なので、幅は充分に長めに。
 CommandButton2  最終的に、リストから在庫シートに反映させる。場所は右下あたり。

 上記の説明順はタブオーダを意識している。なので、この順番にコントロールを追加していってほしい。
もちろん、タブオーダの設定で上記の順序にしてくれてもいい。

 以上、とりあえず。

 (ぶらっと)

 で、コード。
ところで、やっぱり、処理ごとにブックを保存すると、こちらの数種類の商品在庫シートでも、結構な待ち時間。
前にも言ったけど、各ユーザーフォームモジュールの"処理が終了しました"の前あたりの、ThisWorkbook.Save を消し
処理ごとには保存せず、最後に、操作者がエクセルを終了させる時に、エクセルからの、「保存する?」のメッセージで
ブックの保存をしたほうがいいかもね。(操作者が保存しなかったら、処理結果が全てパーになるという心配はあるけど)

 【ユーザーフォーム UserForm1 の Activate ルーティン。今回の追加には関係がないけど、引当更新で無駄な動きがあったので】

 Private Sub UserForm_activate()
    Dim k As Long
    Dim sh As Worksheet
    Dim dic As Object
    Dim c As Range
    Dim v As Variant
    Dim i As Long
    Select Case Me.Tag
        Case "A"
            Call io商品(fnOpen)
            If Not make出荷指示書(fnOpen) Then
                CommandButton1.Enabled = False
                CommandButton2.Enabled = False
                CommandButton3.Enabled = False
                Exit Sub
            End If
            Me.Caption = "出荷指示書作成(指示書を作成する出荷コードを選んでください)"
            Call make出荷指示書(fnGetList, v)
            ListBox1.ColumnCount = 3
        Case "B"
            Call make引当更新データ(fnOpen)
            Me.Caption = "引当更新(引当可能在庫の更新を行います。対象の出荷データを選んでください)"
            If Not make引当更新データ(fnGetList, v) Then
                CommandButton1.Enabled = False
                CommandButton2.Enabled = False
                CommandButton3.Enabled = False
            Else
                ListBox1.ColumnCount = 1
            End If
    End Select
    ListBox1.List = v

    '以下はユーザーフォームのプロパティで設定すればコードは不要
    ListBox1.MultiSelect = fmMultiSelectExtended
    CommandButton1.Caption = "実行"
    CommandButton2.Caption = "全て選択"
    CommandButton3.Caption = "全て解除"

 End Sub

 【ユーザーフォーム UserForm2 新設】

 Option Explicit

 Dim ng As Boolean
 Dim updMode As Boolean
 Dim updIndex As Long
 Dim skip As Boolean

 Private Sub UserForm_Initialize()

    CommandButton1.Caption = "追加"
    ComboBox1.List = io商品(fnGetList)
    Call Reset

    '以下はプロパティでセットすれば不要
    Me.Caption = "入荷登録"
    CommandButton2.Caption = "更新"
    ListBox1.ColumnCount = 3
    ComboBox1.ColumnCount = 2
    ComboBox1.MatchRequired = True

 End Sub

 Private Sub CommandButton1_Click()
    Dim comAbbr As String
    Dim dlDate As String
    Dim syomi As String
    Dim lot As String
    Dim qty As String
    Dim idx As Long
    Dim delFlag As Boolean

    comAbbr = ComboBox1.Value
    dlDate = TextBox1.Value
    syomi = TextBox2.Value
    lot = TextBox3.Value
    qty = TextBox4.Value

    ng = False

    If Len(TextBox2.Value) + Len(TextBox3.Value) + Len(TextBox4.Value) = 0 _
                                                And updMode Then delFlag = True
    If Not delFlag Then
        If Not IsNumeric(qty) Then NGSet TextBox4, "入荷数量を正しく入力してください"
        If lot = "" Then NGSet TextBox3, "ロットNOは必須です"
        If Not IsDate(syomi) Then NGSet TextBox2, "賞味期限を正しく入力してください"
        If Not IsDate(dlDate) Then NGSet TextBox1, "出荷日を正しく入力してください"
        If comAbbr = "" Then NGSet ComboBox1, "商品が選択されていません"
    End If

    If ng Then Exit Sub

    skip = True

    If delFlag Then
        ListBox1.RemoveItem updIndex
    Else
        If updMode Then
            idx = updIndex
        Else
            ListBox1.AddItem
            idx = ListBox1.ListCount - 1
        End If
    End If

    ListBox1.List(idx, 0) = TextBox2.Value
    ListBox1.List(idx, 1) = TextBox3.Value
    ListBox1.List(idx, 2) = TextBox4.Value
    skip = False

    TextBox2.Value = ""
    TextBox3.Value = ""
    TextBox4.Value = ""
    updMode = False
    CommandButton1.Caption = "追加"
    TextBox2.SetFocus

 End Sub

 Private Sub CommandButton2_Click()
    Dim i As Long
    Dim v As Variant
    Dim comAbbr As String
    Dim syomi As Date
    Dim lot As String
    Dim qty As Long
    Dim dl As Date

    If Len(TextBox2.Value) + Len(TextBox3.Value) + Len(TextBox4.Value) > 0 Then
        If MsgBox("入力項目がまだリストに反映していませんが無視していいですか?", vbYesNo) = vbNo Then Exit Sub
    End If

    If ListBox1.ListCount = 0 Then
        MsgBox "まだ入荷入力がなされていません"
        Exit Sub
    End If

    v = ListBox1.List
    For i = LBound(v, 1) To UBound(v, 1)
        comAbbr = ComboBox1.Value
        dl = TextBox1.Value
        syomi = v(i, 0)
        lot = v(i, 1)
        qty = v(i, 2)
        Call io商品(fnPut, comAbbr:=comAbbr, qty:=qty, dlDate:=dl, lot:=lot, syomi:=syomi)
    Next

    Call io商品(fnSort, comAbbr:=comAbbr)
    Call Reset
    ThisWorkbook.Save
    MsgBox "処理が終了しました"

 End Sub

 Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    If TextBox1.Value = "" Then TextBox1.Value = Date
 End Sub

 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If ListBox1.ListCount = 0 Then Exit Sub
    If MsgBox("入力したデータを更新していませんがいいのですか?", vbYesNo) = vbNo Then Cancel = True
 End Sub

 Private Sub ListBox1_Click()

    If skip Then Exit Sub

    If Len(TextBox2.Value) + Len(TextBox3.Value) + Len(TextBox4.Value) > 0 Then
        If MsgBox("入力項目がまだリストに反映していませんが無視していいですか?", vbYesNo) = vbNo Then Exit Sub
    End If

    With ListBox1
        updIndex = .ListIndex
        TextBox2.Value = .List(.ListIndex, 0)
        TextBox3.Value = .List(.ListIndex, 1)
        TextBox4.Value = .List(.ListIndex, 2)
    End With

    updMode = True
    CommandButton1.Caption = "置換"
    TextBox2.SetFocus

 End Sub

 Private Sub Reset()
    TextBox1.Value = Date
    TextBox2.Value = ""
    TextBox3.Value = ""
    TextBox4.Value = ""
    With ListBox1
        .Clear
        .Tag = ""
    End With
    updMode = False
    ComboBox1.SetFocus
 End Sub

 Private Sub NGSet(tx As MSForms.Control, msg As String)
    MsgBox msg
    With tx
        .SelStart = 0
        .SelLength = Len(.Value)
        .SetFocus
    End With
    ng = True
 End Sub

 【Module1】

 '標準モジュール Module1

 Option Explicit

 Enum func
    fnOpen
    fnInitial
    fnGet
    fnGetList
    fnPut
    fnRegister
    fnAllocate
    fnSort
    fnClose
 End Enum

 'シート名規定
 Public Const shnMenu As String = "menu"
 Public Const shn商品一覧 As String = "商品一覧"
 Public Const shn出荷依頼 As String = "Sheet2"
 Public Const tpl出荷指示 As String = "Sheet3"
 Public Const tpl商品在庫 As String = "tplCom"
 '商品一覧列規定
 Public Const IDCol As String = "A"   '商品ID列
 Public Const ABBRCol As String = "C" '商品略称列
 Public Const NameCol As String = "B" '商品名列

 '在庫シート規定
 Public Const 商品略称セル As String = "A1"
 Public Const 商品名セル As String = "B1"
 Public Const 開始Row As Long = 3
 Public Const 商品IDCol As String = "A"
 Public Const 履歴開始Col As String = "R"
 Public Const 履歴終了Col As String = "AR"
 Public Const 指示PMCol As String = "O"
 Public Const 指示PM2Col As String = "P"
 Public Const 引当可能Col As String = "I"
 Public Const 保留Col As String = "C"
 Public Const 賞味期限Col As String = "D"
 Public Const ロットCol As String = "F"
 Public Const 入荷日col As String = "B"
 Public Const 入荷数量col As String = "G"

 Sub 出荷指示()
    If IsFormLoaded Then Exit Sub
    With UserForm1
        .Tag = "A" '出荷指図
        .Show vbModeless
    End With
 End Sub

 Sub 引当更新()
    If IsFormLoaded Then Exit Sub
    With UserForm1
        .Tag = "B" '引当更新
        .Show vbModeless
    End With
 End Sub

 Sub 入荷登録()
    If IsFormLoaded Then Exit Sub
    UserForm2.Show vbModeless
 End Sub

 【Module2 の io商品 プロシジャ】

 Function io商品(fc As func, Optional cd As String, Optional comAbbr As String, _
                Optional qty As Long, Optional dlDate As Date, _
                Optional lot As String, Optional syomi As Date) As Variant
    Static dicM As Object
    Dim first As Boolean
    Dim c As Range
    Dim sh As Worksheet
    Dim comID As String
    Dim comName 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
    Dim i As Long
    Dim d保留 As Variant
    Dim d賞味期限 As Variant
    Dim dロット As Variant
    Dim d引当可能 As Variant
    Dim dm As Long
    Dim w As Variant
    Dim x As Long
    Dim myCol As Long
    Dim myflag As Boolean
    Dim minQ As Long
    Dim maxQ As Long
    Dim addFlag As Boolean

    Select Case fc

        Case fnOpen
            Set dicM = 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(商品IDCol & 開始Row, sh.Range(商品IDCol & sh.Rows.Count).End(xlUp).Offset(-2))
                        i = c.Row
                        With sh
                            d保留 = .Cells(i, 保留Col).Value
                            d賞味期限 = .Cells(i, 賞味期限Col).Value
                            dロット = .Cells(i, ロットCol).Value
                            d引当可能 = .Cells(i, 引当可能Col).Value
                        End With

                        If Len(d保留) = 0 And Len(d賞味期限) > 0 Then '保留マーク空白/賞味期限あり
                            dicM(comAbbr)(dicM(comAbbr).Count + 1) = Array(d賞味期限, dロット, d引当可能)
                        End If
                    Next
                End If
            Next

        Case fnGetList

            With Sheets(shn商品一覧)
                x = .Range(ABBRCol & .Rows.Count).End(xlUp).Row
                ReDim v(1 To x - 1, 1 To 2)
                For i = 2 To x
                    v(i - 1, 1) = .Cells(i, ABBRCol).Value
                    v(i - 1, 2) = .Cells(i, NameCol).Value
                Next
            End With

            io商品 = v

        Case fnPut

            If Not IsObject(Evaluate("'在庫" & comAbbr & "'!A1")) Then
                Sheets(tpl商品在庫).Copy After:=Sheets(Sheets.Count)
                addFlag = True
                With Sheets(Sheets.Count)
                    .Visible = True
                    .Name = "在庫" & comAbbr
                    .Unprotect
                End With
            End If

            With Sheets(shn商品一覧)
                x = WorksheetFunction.Match(comAbbr, .Columns(ABBRCol), 0)
                comName = .Cells(x, NameCol).Value
                comID = .Cells(x, IDCol).Value
            End With

            With Sheets("在庫" & comAbbr)
                .Range(商品略称セル).Value = comAbbr
                .Range(商品名セル).Value = comName

                If addFlag Then
                    x = 開始Row
                Else
                    x = .Range(商品IDCol & .Rows.Count).End(xlUp).Row - 1
                    .Rows(x).Insert shift:=xlDown
                    .Rows(x - 1).Copy
                    .Rows(x).PasteSpecial Paste:=xlPasteFormulas, operation:=xlNone, _
                                                skipblanks:=False, Transpose:=False
                    Application.CutCopyMode = False
                    On Error Resume Next
                    Set c = .Rows(x).SpecialCells(xlCellTypeConstants)
                    On Error GoTo 0
                    If Not c Is Nothing Then c.ClearContents
                    Set c = Nothing
                End If

                .Cells(x, 商品IDCol).Value = comID
                .Cells(x, 入荷日col).Value = dlDate
                .Cells(x, 賞味期限Col).Value = syomi
                .Cells(x, ロットCol).Value = lot
                .Cells(x, 入荷数量col).Value = qty

            End With

        Case fnGet
            If Not dicM.exists(comAbbr) Then Exit Function
            first = True
            reqQty = qty
            comID = "登録なし"
            wk = Application.Match(comAbbr, Sheets(shn商品一覧).Columns(ABBRCol), 0)
            If IsNumeric(wk) Then
                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)) = dLot
                    v(5, UBound(v, 2)) = setQty
                    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
                v = WorksheetFunction.Transpose(v)
                dm = getDimension(v)
                If dm = 1 Then   '1次元配列なら1行の2次元に
                    ReDim w(1 To 1, 1 To UBound(v))
                    For x = 1 To UBound(v)
                        w(1, x) = v(x)
                    Next
                    v = w
                End If
                io商品 = v
            End If

        Case fnSort
            With Sheets("在庫" & comAbbr)
                With .Rows(開始Row & ":" & .Range(商品IDCol & .Rows.Count).End(xlUp).Offset(-2).Row)
                    .Sort Key1:=.Columns(賞味期限Col), Order1:=xlAscending, _
                          Key2:=.Columns(入荷日col), Order2:=xlAscending, _
                          key3:=.Columns(ロットCol), order3:=xlAscending, _
                          Header:=xlNo
                End With
            End With

        Case fnRegister

            myflag = False

            With Sheets("在庫" & comAbbr)
                x = .Range(商品IDCol & 開始Row, .Range(商品IDCol & .Rows.Count).End(xlUp).Offset(-2)).Rows.Count
                If cd = "PM" Or cd = "PM2" Then
                    If cd = "PM" Then
                        myCol = Columns(指示PMCol).Column
                    ElseIf cd = "PM2" Then
                        myCol = Columns(指示PM2Col).Column
                    End If
                    minQ = WorksheetFunction.Min(.Cells(開始Row, myCol).Resize(x))
                    maxQ = WorksheetFunction.Max(.Cells(開始Row, myCol).Resize(x))

                    If minQ <> 0 Or maxQ <> 0 Then
                        If MsgBox(comAbbr & "-" & cd & "はすでに引当済みです" & vbLf & _
                                "上書きしますか?", vbYesNo) = vbYes Then myflag = True
                    Else
                        myflag = True
                    End If
                Else
                    For myCol = Columns(履歴開始Col).Column To Columns(履歴終了Col).Column
                        If Len(.Cells(開始Row - 2, myCol)) = 0 Then
                            myflag = True
                            Exit For
                        End If
                        If .Cells(開始Row - 2, myCol).Value = dlDate And .Cells(開始Row - 1, myCol).Value = cd Then
                            If MsgBox(comAbbr & "-" & cd & "-" & dlDate & "はすでに引当済みです" & vbLf & _
                                "上書きしますか?", vbYesNo) = vbYes Then myflag = True
                            Exit For
                        End If
                    Next
                End If

                If myflag Then
                    .Cells(開始Row, myCol).Resize(x).ClearContents
                    If cd <> "PM" Or cd <> "PM2" Then .Cells(開始Row - 2, myCol).Value = dlDate
                    .Cells(開始Row - 1, myCol).Value = cd
                End If

                io商品 = myflag

            End With

        Case fnAllocate
            '在庫シート
            myflag = False
            With Sheets("在庫" & comAbbr)
                If cd = "PM" Or cd = "PM2" Then
                    myflag = True
                    If cd = "PM" Then
                        myCol = Columns(指示PMCol).Column
                    ElseIf cd = "PM2" Then
                        myCol = Columns(指示PM2Col).Column
                    End If
                Else
                    For myCol = Columns(履歴開始Col).Column To Columns(履歴終了Col).Column
                        If .Cells(開始Row - 2, myCol).Value = dlDate And .Cells(開始Row - 1, myCol).Value = cd Then
                            myflag = True
                            Exit For
                        End If
                    Next
                End If

                reqQty = qty

                For i = 開始Row To .Range(商品IDCol & .Rows.Count).End(xlUp).Offset(-2).Row
                    d賞味期限 = .Cells(i, 賞味期限Col)
                    dLot = .Cells(i, ロットCol)
                    dQty = .Cells(i, 引当可能Col)
                    If syomi = d賞味期限 And dQty > 0 Then
                        If dQty >= reqQty Then
                            setQty = reqQty
                            dQty = dQty - setQty
                        Else
                            setQty = dQty
                            dQty = 0
                        End If
                        reqQty = reqQty - setQty
                        .Cells(i, myCol).Value = .Cells(i, myCol).Value + setQty
                    End If
                    If reqQty = 0 Then Exit For
                Next

                If reqQty > 0 Then
                    MsgBox "引当可能数量不足により以下の内、" & reqQty & "が引当されませんでした" & vbLf & _
                           cd & " " & comAbbr & " " & " " & syomi & " " & lot
                End If

                io商品 = myflag

            End With

        Case fnClose
            If Not dicM Is Nothing Then
                dicM.RemoveAll
                Set dicM = Nothing
            End If

    End Select

 End Function

 【Module4 の 引当実行 プロシジャ 指示書にデータがなかった場合にエラーになるバグがあったので修正】

 Sub 出荷引当実行(dlSheets As Variant)
    Dim i As Long
    Dim ans As Variant
    Dim c As Range
    Dim wk As Variant
    Dim k As Long
    Dim shn As String
    Dim cd As String
    Dim dl As Date
    Dim syomi As Date
    Dim qty As Long
    Dim lot As String
    Dim comAbbr As String
    Dim dicA As Object
    Dim aKey As Variant
    Dim sKey As Variant

    Set dicA = CreateObject("Scripting.Dictionary")
    '引当必要データの商品別格納
    For Each wk In dlSheets
        k = k + 1
        shn = wk
        If Not IsObject(Evaluate("'" & shn & "'!A1")) Then
            MsgBox shn & "シートがありません。処理をスキップします"
        Else
            With Sheets(shn)  '出荷依頼データ
                If Len(.Range("B2").Value) = 0 Then
                    MsgBox shn & "シートにはデータがありません。処理をスキップします"
                Else
                    For Each c In .Range("B2", .Range("B" & Rows.Count).End(xlUp))
                        If Len(Trim(c.Value)) > 0 Then
                            comAbbr = c.Value
                            i = c.Row
                            cd = .Cells(i, "A").Value
                            syomi = .Cells(i, "C").Value
                            lot = .Cells(i, "D").Value
                            qty = .Cells(i, "E").Value
                            dl = .Cells(i, "F").Value

                            aKey = comAbbr & vbTab & cd & vbTab & CDbl(dl)

                            If Not dicA.exists(aKey) Then Set dicA(aKey) = _
                                                CreateObject("Scripting.Dictionary")
                            dicA(aKey)(dicA(aKey).Count + 1) = _
                                            Array(syomi, lot, qty)
                        End If
                    Next
                End If
            End With
        End If
    Next
    '引当処理開始
    For Each aKey In dicA

        wk = Split(aKey, vbTab)
        comAbbr = wk(0)
        cd = wk(1)
        dl = CDate(wk(2))

        ans = io商品(fnRegister, cd, comAbbr:=comAbbr, dlDate:=dl)

        If ans Then

            For Each sKey In dicA(aKey)
                wk = dicA(aKey)(sKey)
                syomi = CDate(wk(0))
                lot = wk(1)
                qty = wk(2)
                io商品 fnAllocate, cd, comAbbr, qty, dl, lot, syomi
            Next

        End If
    Next

    dicA.RemoveAll
    Set dicA = Nothing

 End Sub

 (ぶらっと)

ぶらっと様

 本当に、本当にありがとうございます。
 おっしゃる通り、私はぶらっと様に甘えすぎていました。
 本当は「分からないところだけ」を教えていただくもので、コードを全部作っていただくなんて厚かましいですよね…
 分かっていながらもつい甘えてしまい、本当に申し訳ございませんでした。
 今後は自分で努力します。

 最後に一つだけ教えてください。

 上記で教えていただいた入荷処理で「入荷登録」→「賞味期限順に並べ替え」までうまくいったのですが、追加された分の
 行の書式(罫線など)が追加された行には入らないので、自分でマクロの記録で試してみました。

     Selection.Copy
     Rows(x - 1).Select
     Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
         SkipBlanks:=False, Transpose:=False

 これをコードに入れ込めばよいのかと思って試してみましたが「コピーする行の幅が違う」「型式が違う」などのエラーが出てどこに入れればよいのかが分かりません。
 Paste:=xlPasteFormats, を
   .Rows(x).PasteSpecial Paste:=xlPasteFormulas, operation:=xlNone, _
         skipblanks:=False, Transpose:=False

 の中に入れてみたりしたのですが見当違いだったようで…
 ※Rows(x - 1).Select の (x - 1)自体合っているのか自信ないですが

 本当にすみません。ここだけで良いのでお教えください…

 (らんきち)


 >最後に一つだけ教えてください。
 >本当にすみません。ここだけで良いのでお教えください…

 あぁ、ちょっと「過剰」に伝わったかな?
上でも書いたけど、とにかくアップしたものが、その要件内で、ちゃんと機能するまでは
お手伝いするよ。いいたかったのは、たとえば、それ以外に、現場の人の新しい要望で、このようにしたいとか
そういったことは、今後も出るだろうけど、まず、今アップしている仕様のものがきちんと動くようにしよう。
その後、追加の要望については、できるだけそちらでがんばってほしいということ。

 おそらくは、次に、「出荷」と、在庫反映のテーマに取り組むんだろうなと思うので、そこは、まず
自助努力でがんばって、壁にぶつかったら、また質問してくれればお手伝いもするよ。
(根が「プログラム好き」なので、また、その時もコード書くかもしれないけど)

 で、質問の件だけど、fnPut の
                    .Rows(x).PasteSpecial Paste:=xlPasteFormulas, Operation:=xlNone, _
                                                SkipBlanks:=False, Transpose:=False
このあとに続けて、
                    .Rows(x).PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
                                                SkipBlanks:=False, Transpose:=False
これを入れて試してみて。

 (ぶらっと)

 ありがとうございます。
 書式、うまくコピーできました。

 その後またテストしたんですが、雛形にも既存の在庫シートにも各列ごとにSUM関数を入れているのですが、追加された行の分がSUM関数の中に入りません。
 たとえば今「=SUM(G3:G30)」という関数が G32 に入っていたとして、そこに2行追加すると関数は「=SUM(G3:G32)」にならなければならないのですが
 「=SUM(G3:G30)」のままなので合計が正しく出ないのです。

 雛形には書かれていたようにG5に =SUM(G3:G4) と入れています。

 もう一つですが、マクロでデータサイズが大きくなったせいか「ファイルが開きにくい」という苦情(?)が出るようになりました
 「とりあえず在庫だけ見たいから(マクロ動かさなくていいから)ファイルを開きたい」という声もあり、マクロブックとデータブックの分割を考えてます。

 これはVBAのコードを記述したファイルをネットワーク上に置いてデータブックの方にマクロブックを呼び出すコマンドボタン(?)を置けばいいでしょうか。

 最後とか言いながらまた色々お聞きしてすみません。
 自分でも今分割については調べていますが個人用マクロの記事ばかりヒットして…

 ネットワーク上で使うので個人用マクロではまずいですよね…

 (らんきち)

 もう一つ追加でコードの内容についてお聞きしてもいいですか?

 モジュール2のio商品に

                    MsgBox "引当可能数量不足により以下の内、" & reqQty & "が引当されませんでした" & vbLf & _

 という記述がありますが、現段階ではこのメッセージボックスは出ないのが普通ですか?

 引当可能数より多い出荷指示を出しましたがメッセージボックスが出なかったので、今後のための記述なのか
 今でも本来は出る仕様になっているのか疑問に思いまして…

 本当にすみません…

 (らんきち)

 >たとえば今「=SUM(G3:G30)」という関数が G32 に入っていたとして、そこに2行追加すると関数は「=SUM(G3:G32)」にならなければならないのですが
 「=SUM(G3:G30)」のままなので合計が正しく出ないのです。
 >雛形には書かれていたようにG5に =SUM(G3:G4) と入れています。

 う〜ん・・こちらでは、ちゃんと式の範囲が拡張されるけどねぇ・・
そのために式の行とデータの最終行の間に空白行をいれてもらった・・
その式の行の商品ID列(ここでデータの行を把握している)には、"合計"といった文字列があるんだよね?
で、たとえば商品一覧にあって、在庫シートがない商品を商品一覧に追加して、雛形からコピーしても式は拡張されない?

 >という記述がありますが、現段階ではこのメッセージボックスは出ないのが普通ですか?

 原則、「でないのが正常」
でるとしたら、出荷指図書作成時点では、引当可能だったけど、その出荷指図書の数量が
マニュアル修正されて大きくなったとか、そんな場合のために、「念のために」いれてある。

 マクロブックとデータブックの分離方法は、凝れば、メチャメチャ高度なものができるけど
ごくごく現在の構成を活かせる、シンプルな方法を、後ほど、提案する。

 (ぶらっと)

 マクロブックとデータブックの分離

 1.まず、現在のマクロブックのシートの内、メニュー、非表示の雛形2つをのぞき、他のシートを別ブックに。
 たとえば、商品在庫Data.xlsx 。保存先はマクロブックと同じフォルダ。

 2.マクロブックを以下のように。
 (処理後とのブック保存もやめた。もし、やりたければ、しかるべきタイミングのところで DataBook.Save をいれると保存される)

 3.なお、オープンするのはマクロブック。データブックは、自動的に読み込まれる。
  
 (ThisWOrkbookモジュール)

 Private Sub Workbook_Open()
    Set DataBook = Workbooks.Open(ThisWorkbook.Path & "\商品在庫Data.xlsx")
    ThisWorkbook.Activate
 End Sub

 (Module1)

 宣言部に追加。
 'データブック
 Public DataBook As Workbook

 各プロシジャを以下のように。

 Sub 出荷指示()
    If IsFormLoaded Then Exit Sub
    DataBook.Activate
    With UserForm1
        .Tag = "A" '出荷指図
        .Show vbModeless
    End With
 End Sub

 Sub 引当更新()
    If IsFormLoaded Then Exit Sub
    DataBook.Activate
    With UserForm1
        .Tag = "B" '引当更新
        .Show vbModeless
    End With
 End Sub

 Sub 入荷登録()
    If IsFormLoaded Then Exit Sub
    DataBook.Activate
    UserForm2.Show vbModeless
 End Sub

 (UserForm1)

 以下2つのプロシジャをいれかえ。

 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    Call io商品(fnClose)
    If Me.Tag = "A" Then
        Call make出荷指示書(fnClose)
    Else
        Call make引当更新データ(fnClose)
    End If
    ThisWorkbook.Activate
 End Sub

 Private Sub CommandButton1_Click()
    Dim v() As String
    Dim w() As String
    Dim i As Long
    Dim k As Long
    Dim ans As Long
    Dim s As String

    With ListBox1
        ReDim v(1 To .ListCount)
        ReDim w(1 To .ListCount)
        For i = 0 To .ListCount - 1
            If .Selected(i) Then
                k = k + 1
                v(k) = .List(i)
                If Me.Tag = "A" Then w(k) = .List(i, 1)
            End If
        Next
        If k = 0 Then
            MsgBox "出荷データが選択されていません"
            Exit Sub
        Else
            CommandButton1.Enabled = False
            ReDim Preserve v(1 To k)
            If Me.Tag = "A" Then
                ReDim Preserve w(1 To k)
                s = "出荷指示書作成"
                Call 出荷指示書作成(v, w)
            Else
                s = "引当更新"
                Call 出荷引当実行(v)
            End If
            CommandButton1.Enabled = True

            With ListBox1
                For i = 0 To .ListCount - 1
                    .Selected(i) = False
                Next
            End With

        End If
    End With

    MsgBox s & "処理が終了しました"

 End Sub

 (UserForm2)

 以下2つのプロシジャをいれかえ

 Private Sub CommandButton2_Click()
    Dim i As Long
    Dim v As Variant
    Dim comAbbr As String
    Dim syomi As Date
    Dim lot As String
    Dim qty As Long
    Dim dl As Date

    If Len(TextBox2.Value) + Len(TextBox3.Value) + Len(TextBox4.Value) > 0 Then
        If MsgBox("入力項目がまだリストに反映していませんが無視していいですか?", vbYesNo) = vbNo Then Exit Sub
    End If

    If ListBox1.ListCount = 0 Then
        MsgBox "まだ入荷入力がなされていません"
        Exit Sub
    End If

    v = ListBox1.List
    For i = LBound(v, 1) To UBound(v, 1)
        comAbbr = ComboBox1.Value
        dl = TextBox1.Value
        syomi = v(i, 0)
        lot = v(i, 1)
        qty = v(i, 2)
        Call io商品(fnPut, comAbbr:=comAbbr, qty:=qty, dlDate:=dl, lot:=lot, syomi:=syomi)
    Next

    Call io商品(fnSort, comAbbr:=comAbbr)
    Call Reset
    MsgBox "処理が終了しました"
 End Sub

 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If ListBox1.ListCount > 0 Then
        If MsgBox("入力したデータを更新していませんがいいのですか?", vbYesNo) = vbNo Then
            Cancel = True
            Exit Sub
        End If
    End If
    ThisWorkbook.Activate
 End Sub

 (io商品)

 Sheets(tpl商品在庫).Copy After:=Sheets(Sheets.Count) これを

 ThisWorkbook.Sheets(tpl商品在庫).Copy After:=Sheets(Sheets.Count)

 (make出荷指示書)

 Sheets(tpl出荷指示).Copy After:=Sheets(Sheets.Count) これを

 ThisWorkbook.Sheets(tpl出荷指示).Copy After:=Sheets(Sheets.Count)

 (ぶらっと)

 ↑ 念のため追記。

 データブックのみ開けばマクロは動かない。
 マクロを動かすときには、マクロブックを開く。(データブックはマクロブックが自動的に読み込んでいる)

 (ぶらっと)

ぶらっと様

ありがとうございます。

 >その式の行の商品ID列(ここでデータの行を把握している)には、"合計"といった文字列があるんだよね?

 はい、全部の在庫シートにあります。

 >で、たとえば商品一覧にあって、在庫シートがない商品を商品一覧に追加して、雛形からコピーしても式は拡張されない?

 雛形からだとちゃんと拡張されました。
 雛形と在庫シートを見比べて、違うのは在庫シートの方は「入荷日」が空欄のセルがあるということです。

 ブック分割の件もありがとうございます。

 2点お聞きしてもよいですか。

 @現在、在庫ファイルは日ごとに作成しているのでファイル名を「商品在庫表 2011.11.25.xlsm」というように日付をつけた名前にしています。
 教えていただいた分割方法では、データブックの方の名前を例えば「商品在庫Data.xlsx」で固定するのですよね?
 「商品在庫Data2011.11.25.xlsx」「商品在庫Data2011.11.26.xlsx」などに変えてもいいようにするには
     Set DataBook = Workbooks.Open(ThisWorkbook.Path & "\商品在庫Data.xlsx")
 これをどのように変更すればよいでしょうか。
 また、前にちょっと触れましたが同じレイアウトで同じ処理をする別のファイルはファイル名自体が違います。(これも日ごとに作るので「新規転送 2011.11.25.xlsm」のように日付が入っています)
 これにマクロを適用するにはマクロブックをもう一つ用意する必要がありますか?

 A実はこちらで出荷依頼データを入力するユーザーフォームと、商品一覧に新規商品を登録するためのユーザーフォームを作って
 「処理メニュー」シートにそのフォームを呼び出すコマンドボタンを置いています。
 出荷依頼データフォームは出荷依頼シートに転記させるだけのフォームで、新規商品登録フォームは登録後、商品IDで並べ替えするようなコマンドボタンを置いています。
 どちらも 標準モジュールにあるユーザーフォーム呼び出しの部分に

 Sub 出荷入力画面表示()

   '出荷依頼入力
    If IsFormLoaded Then Exit Sub
    DataBook.Activate
    SyukkaForm.Show vbModeless

 End Sub

 Sub 登録画面表示()

  '商品新規登録
    If IsFormLoaded Then Exit Sub
    DataBook.Activate
    TourokuForm.Show vbModeless

 End Sub

 のように記述しましたがその後の定義の仕方が分からず頓挫しています。
 (まず画面が呼び出せないことと、そこからデータシートへの転記の際の定義の仕方が分からない)

 申し訳ありませんがご助力ください…

 (らんきち)


 あ!
 上記の質問@はもしかして、「商品在庫Data.xlsx」をテンプレートとしてフォルダに置いておき、その都度名前を付けて別ファイルで保存するのでしょうか?
 あ、でも名前を付けて別ファイルにしたらそのファイルをマクロブックで呼び出して内容を更新することはできませんよね…

 すみません、やっぱり私の考え方が違うかも…


 追記です。

 入荷処理なんですが、例えば「A商品」の入荷内容を「追加」した後「B商品」を「追加」したらどちらも「B商品」に入るのは仕様ということで大丈夫でしょうか。
 商品は商品ごとに「更新」を押して次の商品入力をする、ということですよね。
 すみません、ただの確認です

 あと計算式が拡張されない件、完全にこちらのミスでした…
 既存の在庫シートの計算式に、空白行を含めていませんでした…
 大変お手数をおかけしまして申し訳ございません;;

 (らんきち)

 >あと計算式が拡張されない件、完全にこちらのミスでした…

 了解。

 >在庫ファイルは日ごとに作成しているのでファイル名を「商品在庫表 2011.11.25.xlsm」

 この形であれば、対象にするデータブックのなかから、処理すべきデータブックを選ぶという方式がいいね。
・マクロブックを開く
・メニューシートにデータブック選択ボタンを配置し、まず、ここからデータブックを開く
・この方式でよければ、アップした構えをほんのちょっといじるだけですむ。
・あと、呼び出したブックは、どのタイミングで「保存」したいか、意見ください。

 >出荷依頼データを入力するユーザーフォームと、商品一覧に新規商品を登録するためのユーザーフォームを作って
 「処理メニュー」シートにそのフォームを呼び出すコマンドボタンを置いています。
 ・・・・・・・・
 >のように記述しましたがその後の定義の仕方が分からず頓挫しています。

 SyukkaForm、TourokuForm に UserForm_QueryClose ルーティンの記述がなければ追加し
 その最後に、ThisWorkbook.Activate をいれるといい。

 >(まず画面が呼び出せないことと、

 画面が呼び出せないというのは?ユーザーフォームが表示されない?あるいはデータブックが表示されない?
 データブックであれば、記述されている DataBook.Activate で表示されるはずだけど?

 >そこからデータシートへの転記の際の定義の仕方が分からない)

 データシートへの転記コードがわからないということ?
 現在のユーザーフォームモジュールのコードをアップしてもらえるかな?

 >入荷処理なんですが、例えば「A商品」の入荷内容を「追加」した後「B商品」を「追加」したら
 >どちらも「B商品」に入るのは仕様ということで大丈夫でしょうか。
 >商品は商品ごとに「更新」を押して次の商品入力をする、ということですよね。

 説明したと思うけど、処理の単位は、商品、入荷日。この単位で TextBox2,3,4 の内容が在庫シートに
 書き込まれる。商品、入荷日が異なれば、一度、更新をしてからね。

 それと、このスレも長くなって、書き込んだ内容を編集で呼び出して追記しようとすると、なかなか大変。
 続編のスレたてたほうがいいかな?

 (ぶらっと)

[[20111125130033]]で続きを立てました

(らんきち)


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.