[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『ユーザーフォームからの転記がうまくいきません2』(peridot)
の続きです。
データシート「箱サンプル」に「単価マスタ」から必要項目を抜き出し、ユーザーフォームに表示して ユーザーフォームの内容を「箱サンプル」シートに転記するコードを作っています。
★「箱サンプル」シートレイアウト
A B C D E F G H I J K L 1 作業簿_SK 日付 合計 2 記号 媒体名 件数 記号 媒体名 件数 記号 媒体名 件数 3 SK1 HY 82 SK2 KZ 2 SK KZ 2 4 SK1 FR 11 SK2 HY 4 SK HY 86 5 SK FR 11 : 19 20 21 作業簿_KK 22 記号 媒体名 件数 記号 媒体名 件数 記号 媒体名 件数 23 VA1 KK 1516 VA2 KK 224 VA KK 1740 24 VE1 KK 9 VE2 KK 4 VE KK 13 : 35 36 37 作業簿_その他 38 記号 媒体名 件数 記号 媒体名 件数 記号 媒体名 件数 39 VS1 10P 6192 VS2 10P 672 VS 10P 7872 40 VS3 10P 1008 : 49
★「単価マスタ」シートレイアウト A B C D E F G H I J 1 単価表 2 記号 媒体名 基本単価 追加分 付帯業務 区分 基本コスト 単価 分類 3 SK KZ 19 1 1.2 1.5 22.7 17.0 作業簿_SK 4 SK MZ 19 1 1.2 1.5 22.7 17.0 作業簿_SK 5 SK HY 19 2 0 1.5 22.5 16.9 作業簿_SK 6 SK FR 19 0 0 1.5 20.5 15.4 作業簿_SK : 17 SK N7 19 2 1.2 1.5 23.7 17.8 作業簿_SK 18 VO 10P 19 1 12.2 1.5 33.7 25.3 作業簿_KK 19 VR 10P 19 0 12.2 1.5 32.7 24.5 作業簿_KK 20 VA KK 19 2 1.2 1.5 23.7 17.8 作業簿_KK : 28 VG KK 19 0 0 1.5 20.5 15.4 作業簿_KK 29 Sm N7 19 1 0 1.5 21.5 16.1 作業簿_その他 30 Sノ NS 19 1 0 1.5 21.5 16.1 作業簿_その他 : 35 VT L7 19 0 0 1.5 20.5 15.4 作業簿_その他
現在考えているユーザーフォームのレイアウト ※頭がtxtはテキストボックス、lblはラベル、cbxはコンボボックス
txt_Date 日付 cbx_Cls 分類 cbx_No 枝番
lblCode_1〜18 記号 cbxMedia_1〜18 媒体名 txtQty_1〜18 件数
CommandButton1 入力(「箱サンプル」シートへの転記) CommandButton2 クリア(ユーザーフォームの内容をクリア) CommandButton3 閉じる(ユーザーフォームを閉じる)
・「作業簿_SK」のデータは3〜19行に入力 ・「作業簿_KK」のデータは23〜35行に入力 ・「作業簿_その他」のデータは39〜49行に入力 ・枝番(SK1の"1"の部分)が奇数のものはA〜C列に、偶数のものはE〜G列に入力 ・J〜K列には「記号&媒体名」が一致するものの件数の合計を出す
★ユーザーフォームの入力手順
1.日付を入力 2.「分類」を選択(単価マスタより) 3.「枝番」を選択(現在1〜4) 4.ラベル(lblCode_1〜18)に、単価マスタを参照して「分類」に対応する「記号」が全て表示される (「SK」が17個あれば17個表示される) 5.コンボボックス(cbxMedia_1〜18)のリストに、それに対応した「媒体名」がセットされる 6.テキストボックス(txtQty_1〜18)に件数を入力 7.コマンドボタン1を押すと、件数が入力されたものの「記号+枝番」「媒体名」「件数」が「箱サンプル」シートに転記される 8.A〜G列の内容を参照してJ〜K列に同じ「記号&媒体」の組合せの合計件数が表示される
前トピで(Bun)様からコントロールを300個配置する案とコードをご提示いただいたのですが、 コントロールが多すぎると入力者が混乱する恐れがあるので上のコードでも何とかできないかと考えています。
Excel2007です。
それでは、引き続き、私も検討していく。 で、提案なんだけど、Bunさんがリコメンドしておられる構成と、(peridot) さんが考えている構成、 いずれがいいかということは、たぶん「優劣」の問題ではなく、実際にこれを使う現場の人が、このマクロを使用する局面以外の その業務運用の流れも含めて、どちらがマッチしているかを判断することなんだろうと思う。
なので、私は(peridot)さんがイメージしている構成を実現するコードを書く、最終的に、それを 現場の人に判断してもらうということにすればいかが?
Bunさんの構成では、フォームを作るのが大変だと感じるかもしれないけど、たぶん、それは1時間ぐらいで 充分にできる作業だと思うし、もし、大変だということなら、この板でも回答されるichinoseさんが http://www.vbalab.net/vbaqa/c-board.cgi?cmd=ntr;tree=71765;id=excel ここで、(peridot)さんにかわってフォームを作成する手法を提示されているので、それを利用する方法もある。 (実際に、こちらで、(peridot)さんが説明するデザインのフォームを作る時には、ある程度までこの手法で 作成した) これで、作成してしまえば、それは、手作業で作成したものとなんらかわらないので、あとは 手作業で 追加・修正等、なんでもできる。
(ぶらっと)
今思いついたのだけれど? 現状のUserFormでは、横計を表示させる為、txtCodeJ、xtMediaK、txtQtyLの3組*18個のコントロールを 使っていますが、横計を表示を行わないで転記だけにすれば、3組*18個のコントロールは削除出来ますが? もううんざりなら、私は降りますが、必要ならUpします如何しますか?
(Bun)
>ぶらっと様ありがとうございます。
>最終的に、それを >現場の人に判断してもらうということにすればいかが? はい、お願いいたします。
>Bun様
横計は一度には行わず、転記した後合計(別に「合計」用のコードを用意して、それを実行した時に合計するなど) というように考えています。 まずはデータ入力を行ってから、集計という手順になっていますので… (今は関数なので入力の都度合計も更新されますが、ワークシート上に「合計」を実行するボタンを置いて そのタイミングで合計しても問題ないので)
なので3組*18個のコントロールを削除する方向でお願いできますでしょうか。
(peridot)
txtCodeJ、xtMediaK、txtQtyLの3組*18個のコントロールは無しにして下さい 尚、前にも記述しましたが? txtCode、txtMediaの列は、LockedプロパティをTrueに、TabStopプロパティをFalseにし BackColorを変更して下さい
また、CommandButton1:入力/更新、CommandButton2:入力範囲クリア、CommandButton3:閉じる、に成ります
Option Explicit
Private Const clngExtr As Long = 3 '抽出列数
Private wksMark As Worksheet '入力先のシート Private rngList As Range '単価マスタのデータ範囲 Private rngWork As Range '作業用シートの抽出範囲 Private rngCrit As Range '作業用シートの条件範囲先頭セル位置 Private lngRow As Long '抽出行数(最終行位置) Private rngAdd As Range '入力範囲先頭位置
Private Sub UserForm_Initialize()
Dim i As Long
Dim vntData As Variant
Dim lngRows As Long
'入力先のシートを指定
Set wksMark = Worksheets("箱サンプル")
'単価マスタ先頭セル位置を指定
Set rngList = Worksheets("単価マスタ").Range("B2")
'作業用シートの抽出範囲を指定
Set rngWork = Worksheets("抽出").Range("A1")
'作業用シートの条件範囲先頭セル位置を指定
Set rngCrit = rngWork.Parent.Range("F1")
'Listの行数、列数取得
With rngList
'B列で行数の取得
lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
End With
'単価マスタのデータ範囲の再設定
Set rngList = rngList.Resize(lngRows + 1, 9)
'ComboBox1に「分類」を設定(各分類の先頭位置とデータ行数も其々別の列に設定)
With cbxClass
For i = 0 To 2
.AddItem Choose(i + 1, "作業簿_SK", "作業簿_KK", "作業簿_その他")
.List(i, 1) = Choose(i + 1, 2, 22, 38)
.List(i, 2) = Choose(i + 1, 18, 14, 11)
Next i
End With
'枝番の番号設定
For i = 1 To 18
Controls("cbxNum" & i).List = Array("1", "3")
Next i
'日付の読み込み
txtDate.Text = wksMark.Cells(1, "F").Value
If txtDate.Text = "" Then
txtDate.Text = Date
End If
End Sub
Private Sub UserForm_Terminate()
'日付の書き込み
wksMark.Cells(1, "F").Value = txtDate
Set rngList = Nothing
Set rngWork = Nothing
Set rngCrit = Nothing
Set wksMark = Nothing
Set rngAdd = Nothing
End Sub
Private Sub cbxClass_Change()
Dim i As Long
Dim vntData As Variant
Dim vntRows As Variant
If cbxClass.ListIndex = -1 Then
Exit Sub
End If
'「記号」のデータを取得
vntData = GetComboList(cbxClass.Text, 1)
For i = 1 To 18
With Controls("cbxCode" & i)
'抽出行数が0で無いなら
If lngRow > 0 Then
'ComboBox2にListを設定
.List = vntData
Else
'ComboBox2をクリア
.Clear
End If
End With
Next i
'出力範囲のデータを取得
With cbxClass
vntData = .List(.ListIndex, 1)
vntRows = .List(.ListIndex, 2)
End With
'出力範囲先頭を設定
Set rngAdd = wksMark.Cells(vntData, "A")
'入力用コントロールの入力範囲分を表示にし、データを読み込み
For i = 1 To vntRows
ControlsVisible i, True
GetLineData i, rngAdd
Next i
'入力用コントロールの入力範囲範囲外を非表示に
For i = vntRows + 1 To 18
ControlsVisible i, False
Next i
End Sub
Private Sub CommandButton1_Click()
Dim i As Long
Dim vntRows As Variant
With cbxClass
If .ListIndex = -1 Then
Exit Sub
End If
vntRows = .List(.ListIndex, 2)
End With
If MsgBox("データの更新をします!!", vbInformation + vbOKCancel) = vbCancel Then
Exit Sub
End If
'データの書き込み
For i = 1 To vntRows
PutLineData i, rngAdd
Next i
End Sub
Private Sub CommandButton2_Click()
Dim i As Long
Dim vntData As Variant
If MsgBox("シートをクリアします!!", vbInformation + vbOKCancel) = vbCancel Then
Exit Sub
End If
vntData = cbxClass.List
For i = 0 To UBound(vntData, 1)
wksMark.Cells(vntData(i, 1), "A").Offset(1).Resize(vntData(i, 2), 12).ClearContents
Next i
If cbxClass.ListIndex = -1 Then
Exit Sub
End If
'出力範囲先頭を設定
Set rngAdd = wksMark.Cells(vntData(cbxClass.ListIndex, 1), "A")
'入力用コントロールの入力範囲分を表示にし、データを読み込み
For i = 1 To vntData(cbxClass.ListIndex, 2)
ControlsVisible i, True
GetLineData i, rngAdd
Next i
'入力用コントロールの入力範囲範囲外を非表示に
For i = vntData(cbxClass.ListIndex, 2) + 1 To 18
ControlsVisible i, False
Next i
End Sub
Private Sub CommandButton3_Click()
Unload Me
End Sub
Private Sub ChangeSymbol(lngNumb As Long)
Dim vntData As Variant
If Controls("cbxCode" & lngNumb).ListIndex = -1 Then
Exit Sub
End If
'「媒体名」のデータを取得
vntData = GetComboList(Controls("cbxCode" & lngNumb).Text, 2)
With Controls("cbxMedia" & lngNumb)
'抽出行数が0で無いなら
If lngRow > 0 Then
'ComboBoxにListを設定
.List = vntData
Else
'ComboBoxをクリア
.Clear
End If
End With
End Sub
Private Sub ChangeNumbBox(lngNumb As Long)
If Val(Controls("txtQtyG" & lngNumb).Text) > 0 Then
Controls("txtCode" & lngNumb).Text _
= Controls("cbxCode" & lngNumb).Text & (Val(Controls("cbxNum" & lngNumb).Text) + 1)
Controls("txtMedia" & lngNumb).Text = Controls("cbxMedia" & lngNumb).Text
Else
Controls("txtCode" & lngNumb).Text = ""
Controls("txtMedia" & lngNumb).Text = ""
End If
End Sub
Private Sub GetLineData(lngNumb As Long, rngTop As Range)
Dim vntData As Variant
Dim vntTmp As Variant
vntData = rngTop.Offset(lngNumb).Resize(, 12).Value
'A列がEmpty値で無いなら
If Not IsEmpty(vntData(1, 1)) Then 'A列
vntTmp = vntData(1, 1)
'E列がEmpty値で無いなら
ElseIf Not IsEmpty(vntData(1, 5)) Then
vntTmp = vntData(1, 5)
End If
If Not IsEmpty(vntTmp) Then
Controls("cbxCode" & lngNumb).Text = Left(vntTmp, Len(vntTmp) - 1)
vntTmp = Val(Right(vntTmp, 1))
If vntTmp Mod 2 = 0 Then
vntTmp = vntTmp - 1
End If
Controls("cbxNum" & lngNumb).Text = CStr(vntTmp)
Else
Controls("cbxCode" & lngNumb).Text = ""
Controls("cbxNum" & lngNumb).ListIndex = -1
End If
If Not IsEmpty(vntData(1, 2)) Then 'B列
vntTmp = vntData(1, 2)
ElseIf Not IsEmpty(vntData(1, 6)) Then
vntTmp = vntData(1, 6)
End If
Controls("cbxMedia" & lngNumb).Text = vntTmp
Controls("txtQtyC" & lngNumb).Text = vntData(1, 3) 'C列
Controls("txtCode" & lngNumb).Text = vntData(1, 5) 'E列
Controls("txtMedia" & lngNumb).Text = vntData(1, 6) 'F列
Controls("txtQtyG" & lngNumb).Text = vntData(1, 7) 'G列
End Sub
Private Sub PutLineData(lngNumb As Long, rngTop As Range)
Dim vntData As Variant
Dim vntTmp As Variant
ReDim vntData(1 To 12)
'C列の値が有ったなら
If Val(Controls("txtQtyC" & lngNumb).Text) > 0 Then
vntData(1) = Controls("cbxCode" & lngNumb).Text _
& Controls("cbxNum" & lngNumb).Text 'A列
vntData(2) = Controls("cbxMedia" & lngNumb).Text 'B列
vntData(3) = Controls("txtQtyC" & lngNumb).Text 'C列
End If
'G列の値が有ったなら
If Val(Controls("txtQtyG" & lngNumb).Text) > 0 Then
vntData(5) = Controls("txtCode" & lngNumb).Text 'E列
vntData(6) = Controls("txtMedia" & lngNumb).Text 'F列
vntData(7) = Controls("txtQtyG" & lngNumb).Text 'G列
End If
vntData(10) = Controls("cbxCode" & lngNumb).Text 'J列
vntData(11) = Controls("cbxMedia" & lngNumb).Text 'K列
vntTmp = Val(Controls("txtQtyC" & lngNumb).Text) + Val(Controls("txtQtyG" & lngNumb).Text)
If vntTmp = 0 Then
vntTmp = Empty
End If
vntData(12) = vntTmp 'J列
rngTop.Offset(lngNumb).Resize(, 12).Value = vntData
End Sub
Private Sub ControlsVisible(lngNumb As Long, blnVisible As Boolean)
Controls("cbxCode" & lngNumb).Visible = blnVisible 'A列
Controls("cbxNum" & lngNumb).Visible = blnVisible
Controls("cbxMedia" & lngNumb).Visible = blnVisible 'B列
Controls("txtQtyC" & lngNumb).Visible = blnVisible 'C列
Controls("txtCode" & lngNumb).Visible = blnVisible 'E列
Controls("txtMedia" & lngNumb).Visible = blnVisible 'F列
Controls("txtQtyG" & lngNumb).Visible = blnVisible 'G列
End Sub
Private Function GetComboList(vntCrit As Variant, lngNum As Long) As Variant
Dim vntData As Variant
'条件範囲にComboBoxの値を代入(式の形で)
rngCrit.Offset(1, lngNum - 1).Value = "=""" & vntCrit & """"
'AdvancedFilterを実行
DoFilter rngList, rngCrit.Resize(2, lngNum), rngWork.Resize(, clngExtr)
'抽出範囲から
With rngWork
'抽出行数を取得
lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
'列見出し以上の行が在るなら
If lngRow > 0 Then
'指定列からデータを配列に取得
vntData = .Offset(1, lngNum).Resize(lngRow, 2).Value
ReDim Preserve vntData(1 To lngRow, 1 To 1)
GetComboList = Unique(vntData)
End If
End With
End Function
Private Sub DoFilter(rngScope As Range, _
rngCriteria As Range, _
rngCopyTo As Range, _
Optional blnUnique As Boolean)
' AdvancedFilterを実行
rngScope.AdvancedFilter _
Action:=xlFilterCopy, _
CriteriaRange:=rngCriteria, _
CopyToRange:=rngCopyTo, _
Unique:=blnUnique
End Sub
Private Function Unique(vntData As Variant) As Variant
' 値の重複取り
Dim i As Long
Dim j As Long
Dim lngEnd As Long
Dim vntList As Variant
ReDim vntList(1 To UBound(vntData, 1))
'値の重複取り
For i = 1 To UBound(vntData, 1)
For j = 1 To lngEnd
If vntData(i, 1) = vntList(j) Then
Exit For
End If
Next j
If j > lngEnd Then
If Not IsEmpty(vntData(i, 1)) Then
lngEnd = j
vntList(lngEnd) = vntData(i, 1)
End If
End If
Next i
ReDim Preserve vntList(1 To lngEnd)
'戻り値として重複無しの値を返す
Unique = vntList
End Function
’以下のコードは3〜17分のプロシージャが間引いて有りますので補間して下さい
Private Sub cbxCode1_Change()
ChangeSymbol 1
End Sub
Private Sub cbxCode2_Change()
ChangeSymbol 2
End Sub
・
・
Private Sub cbxCode18_Change()
ChangeSymbol 18
End Sub
Private Sub txtQtyG1_Change()
ChangeNumbBox 1
End Sub
Private Sub txtQtyG2_Change()
ChangeNumbBox 2
End Sub
・
・
Private Sub txtQtyG18_Change()
ChangeNumbBox 18
End Sub
(Bun)
(Bun)様ありがとうございます。
ユーザーフォームを作成してコードを入力して試したのですが、操作性の点でいくつか変更したい部分がありまして…
・現在、「分類」を選んだ後「記号」「枝番」の順に入力していきますが… @特に「SK」の場合「記号」は「SK」で統一なので、全部一つ一つ選ぶのはやはり手間がかかります。 最初からコンボボックスに表示しておくのならまだよいのですが… A「枝番」は一度に一つの枝番しか入力しないので、これも選ぶのは一度だけにしたいです。 Bあと、「枝番」が1と3しか表示されないのですが、2や4はどうやって入力するのでしょうか? ・BackColorを変えたtxtCodeC1〜18、txtMedia1〜18、txtQtyG1〜18は今何も表示されませんが、どのように使うのでしょうか? ・コマンドボタン2については私の説明不足でした… これは「ユーザーフォームの内容をクリア」したいボタンなので、こちらで下記のようにコードを書き換えました
Private Sub CommandButton2_Click()
Dim myCtrl As Control
For Each myCtrl In Me.Controls
If TypeName(myCtrl) = "TextBox" Or TypeName(myCtrl) = "ComboBox" Then _
myCtrl.Value = vbNullString
Next
End Sub
特に「記号」「枝番」の入力の部分は選択の回数が少なくて済むように変えたいです…
(peridot)
多分、UserFormの使い方と言うか、シートの入力の考え方が全く違う様ですね? 文面からするとperidotさんが考えているのは、このUserFormに入力してボタンを押すと 既に入力されている、または何も入力されていない行に上から追加されて行く様な考え方なのかと思います
>・現在、「分類」を選んだ後「記号」「枝番」の順に入力していきますが… > @特に「SK」の場合「記号」は「SK」で統一なので、全部一つ一つ選ぶのはやはり手間がかかります。 > 最初からコンボボックスに表示しておくのならまだよいのですが…
私の作った物は、分類「作業簿_SK」で全入力範囲で18行なので、「作業簿_SK」が選択されれば 「作業簿_SK」の入力範囲の全ての行をコントロールに読み込んでいます 詰まり、「作業簿_SK」の範囲にデータが無ければ当然、コントロールは全て空白です またデータで既に入力されているなら其れが読み込まれます 此れに因り、データの追加入力、変更を可能にしています 因って、例えば「分類」で「作業簿_KK」を選択した時に、cbxCodeの値を先に入れて置く様にすると 「VA」や「VE」がが既に入力(表上)に有った場合、置き換えられてしまいますので行っていません
> A「枝番」は一度に一つの枝番しか入力しないので、これも選ぶのは一度だけにしたいです。 > Bあと、「枝番」が1と3しか表示されないのですが、2や4はどうやって入力するのでしょうか? >・BackColorを変えたtxtCodeC1〜18、txtMedia1〜18、txtQtyG1〜18は今何も表示されませんが、どのように使うのでしょうか?
txtQtyG1〜18は入力させますので(txtQtyGは右側E、F、G列のG列の件数入力用)LockedやTabStopのプロパティ 設定はしませんよ(前回からプロパティ指定のコントロールには入れて無い筈です) 「枝番」の入力は左側の欄(A、B、C列)は、前回迄の説明で必ず奇数番が入りまし、右側(E、F、G列)は、 偶数番しか入らない筈だと思っています 因って、枝番のComboBoxでは奇数番しか用意していません、最初のコードをUpした時から書いていますが? 例えば、枝番cbxNumで1を選択した場合、C列件数xtQtyCに0若しくは""が入った場合、A、B、C列の出力は行いません また、xtQtyCに0を超える数値が入った場合、A列には記号+枝番が入り、B列には媒体名cbxMediaの値が入り C列にはxtQtyCの値が入ります 次に、G列件数txtQtyGに0を超える値が入った場合、E列記号txtCode、F列媒体名txtMediaに表示がされます この時、E列記号txtCodeは、記号cbxCode&枝番cbxNum+1(枝番で1が選択されていれば2が、枝番で3が選択されて居れば4が)が表示されます
>・コマンドボタン2については私の説明不足でした… >これは「ユーザーフォームの内容をクリア」したいボタンなので、こちらで下記のようにコードを書き換えました
これも、上記の意味ならUserFormの運用と言う意味なら不要だと思います 何故なら、此れを行って、クリアしたコントロールに値を入力してボタンを押した場合 全て、新規に入力した物に置き換わってしまいます(詰まり、Bookの上書保存と同様な結果に成ります)
(Bun)
後、入力が大変だと言っていますが? もしかしてComboBoxの入力やコントロールの移動をマウスだけで行っているのですか? UserFormのTabOderが適正に設定されていれば殆どキーボードだけで操作が出来るのですが? ComboBoxのList選択は↓↑キーで出来ますし、コントロールの移動はTabキー若しくはShift+Tabキーで出来ます 因って、キーボード主体で操作した方が速いし楽かも?
(Bun)
>文面からするとperidotさんが考えているのは、このUserFormに入力してボタンを押すと >既に入力されている、または何も入力されていない行に上から追加されて行く様な考え方なのかと思います はい、その通りです。
元々、何も入力されていないシートにデータを入力するためのユーザーフォームなので… 現状では、一度入力すればよいものを何度もコンボボックスから選ぶようになっているので、それは操作が大変ですので… 従って、 >詰まり、「作業簿_SK」の範囲にデータが無ければ当然、コントロールは全て空白です これでは入力しづらくなります… 私が想定していたものが「単価マスターに組合せがあるものがコントロールに表示される」というものだったのですが…
>キーボード主体で操作した方が速いし楽かも? 入力する人がほとんどマウスで操作していますので、キーボード操作前提というのはちょっと…
>txtQtyG1〜18は入力させますので(txtQtyGは右側E、F、G列のG列の件数入力用)LockedやTabStopのプロパティ >設定はしませんよ(前回からプロパティ指定のコントロールには入れて無い筈です) これは了解いたしました。 ただ、これも説明不足でしたが「枝番2」しか件数が入らないものがあります(枝番1の件数がない場合がある) その時に「1」が無いと「2」の入力ができないというのは困るんです…
私の説明が悪かったのだと思いますが、「箱サンプル」シートは始めは空白です。 そこにデータを入力するためのユーザーフォームを作っているので、値の更新ではなく追加になります。
なんか色々とすみません…
(peridot)
説明している意味が全く理解されないようなので私は降ります
(Bun)
Bunさんとのやりとりは、詳しく読んでいないけど、 >そこにデータを入力するためのユーザーフォームを作っているので、値の更新ではなく追加になります。 これが目に入ったので。
たとえば、箱シートに SK1 HY 82 があったとする。 で、ユーザーフォーム上でも SK1/HY を入力しようとした。 これをどう考えるか。エラーにするのか、上書きにするのか。 私の構想では、SK1/HYが指定されたとき、箱シートにあれば、それを該当のTextBoxに表示。 そこをなおして実行して上書きということを考えていた。 たとえば箱シートに 10 とはいっていた。で、フォーム上に 10 を表示して、操作者が 12 になおすと 箱シートの行追加ではなく、上書きで 12 にしようかなと。
そこは、どのように考えている?
(ぶらっと)
「予告」
コードアップが遅れていて申し訳なし。 書き殴った状態で、90%ぐらいはできているんだけど、もう少し時間ください。 で、お願い事項。
・↑で質問している、箱サンプルに同じ記号、媒体があったときの措置、そちらの見解を知らせてください。 ・書き殴った状態で、さらにDictionaryが増えたり、18行のコントロールのイベント処理で、コードが大きく、また複雑になっているので そのすべて、あるいは一部をクラスモジュールの移そうと考えている。 あわせて、現在のコードはユーザーフォームを表示するときに負荷がかかる構成なので、一部を ブックを開くときの処理にもっていって 負荷分散をしようかなと思っている。 ★そうすると、ブックを開いた後、単価マスタを変更したり、後述するけど、箱サンプルのレイアウトを変更しても 反映しない。それでいいと思うけど、OKかどうか確認お願い。 ・で、その箱サンプル。 処理対象の分類コードをコードの中で固定であたえるのではなく、箱マスタに存在するコードにする予定。 で、勝手に以下のレイアウト規定にしている。これでOKかどうか、確認お願い。 1)分類コードが記載されたA列の次の行には"記号"と書かれていて、その次の行からデータ行。 そのデータ領域の最後の行の下には1行空白セルがあって、その下の行から、次の分類コードがはじまる。(これは現行通りだよね) 2)最後の分類コードのデータ領域の終わりが見えない。なので、最後のデータ領域行の1つ下の行は空白セルで、その下の行に、何かこれで終わりだというものが欲しい。 なんでもいいけど "END" でもいいし、"終了" でもいいし、もっと気の利いた別の語句でもいいけど。 こういう構えにできるかどうか、確認お願い。
追加確認依頼) ユーザーフォームはモーダル表示?モードレス表示?
(ぶらっと)
(Bun)様、申し訳ございませんでした
(ぶらっと)様
>たとえば、箱シートに SK1 HY 82 があったとする。 >で、ユーザーフォーム上でも SK1/HY を入力しようとした。 >これをどう考えるか。エラーにするのか、上書きにするのか。
上書きになります。
>書き殴った状態で、さらにDictionaryが増えたり、18行のコントロールのイベント処理で、コードが大きく、また複雑になっているので >そのすべて、あるいは一部をクラスモジュールの移そうと考えている。
すみません、クラスモジュールというのが全然わかっていないのでお任せします…
> 1)分類コードが記載されたA列の次の行には"記号"と書かれていて、その次の行からデータ行。 そのデータ領域の最後の行の下には1行空白セルがあって、その下の行から、次の分類コードがはじまる。(これは現行通りだよね)
はい。 ただ、データ領域の最後の行まで必ずしもデータが入るとは限りません。 何故なら、例えば「作業簿_SK」の中で「SK3」が発生するかどうかは日によって違い、発生した時のために 単価マスタにある組合せよりも2行ほど余分にデータ領域を作っています。
A B 1 作業簿_SK 2 SK1 KZ 3 SK1 MZ : 17 SK1 N7 ←ここまでが単価マスタにある組合せの最大行 18 SK3 MZ ←もし「SK3」がある時はここに追加 19 ←想定しているデータ行の最終行 20 21 作業簿_KK 22 VO1
「作業簿_KK」「作業簿_その他」も同様の構成になっています。
>2)最後の分類コードのデータ領域の終わりが見えない。なので、最後のデータ領域行の1つ下の行は空白セルで、その下の行に、何かこれで終わりだというものが欲しい。
では、誰が見ても分かるように「データ行終了」をA51(A49が「作業簿_その他」の最終行)に入れます。
ユーザーフォームはモードレスを考えていましたが、不都合があればモーダルでも構いません。
よろしくお願いいたします。
(peridot)
確認ありがとう。ほぼ、ほぼつかめた。 クラスがよくわからないということなので、クラスそのものは「ブラックボックス」として 後々、「中身を見ないでもすむ」ように、データ処理は、クラスから外に出して、(peridot)さんが 見てわかるような場所、ユーザーフォームモジュールや標準モジュールに移すように、すこし組み変える。
ただ、根本的に、そちらで想定した仕様に「矛盾点」があるような気がしてきた。
>例えば「作業簿_SK」の中で「SK3」が発生するかどうかは日によって違い、発生した時のために >単価マスタにある組合せよりも2行ほど余分にデータ領域を作っています。
つまり、アップされた例で言うと、作業簿_SK に対する単価マスタは、3行目から17行目までの15行。 で、「余裕をみて?」18行用意したということを言っているのかな? たまたま、作業簿_SK の 記号は SK だけなので、ユーザーフォームの18行のラベルに全て SK をいれ 18行分の入力を可能にしている?
これは、ちょっと、おかしいかも。
作業簿_SK の記号は、「たまたまSKだけ」かもしれないけど、理屈(データ構造)としては、作業簿_KK のように 複数の記号が登録されていることもありうるよね。 仮に、単価マスタに作業簿_SKに関して、SKが10行、SXが3行、SWが2行登録されていたとする。 ユーザーフォームの各行のラベルは、どうなると想定している?(SKが何行、SXが何行、SWが何行??)
準備したコードでは、この場合、あらかじめデザインされた18行のうち、上の15行だけを表示、 下の5行は非表示にして、ラベルは上から、SKが10行、SXが3行、SWが2行 となる。 こうせざるを得ないのは理解してくれるかな?
なので、一度に、15行までしか入力(登録)できないので、16行以上ある場合は、2回に分けてということになる。 要は、単価マスタに登録されている記号の数だけユーザーフォームに展開する。それが18行なら、18行をフルに 使うことになるし、いつの日か、単価マスタが20行になった、でもユーザーフォームは18行しか用意していない。 こういうことが発生したら、エラーメッセージを出して処理できないようにしている。
なお、フォーム表示はモーダルでもモードレスでも、どちらでもOKにしておいた。 (数量欄入力にエラーがあった場合のエラーメッセージ処理が、モーダルと、モードレスでは 通常のコードでは、ちょっと結果が異なるんだけど、そこは、少し手を入れて同じ結果になるように 対応した)
それと、このトピも、かなり大きくなったので、編集しづらい場面がでてきている。 No.3 を立ち上げてくれればありがたいかな。
(ぶらっと)
(ぶらっと)様ありがとうございます
で次のトピを立ち上げましたのでよろしくお願いいたしますm(__)m
peridot)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.