プロが教える店舗&オフィスのセキュリティ対策術

ExcelVBAにて日次業務の登録をそれぞれ個人がユーザーフォームからデータを登録し、データベースの一覧に蓄積されていくようなシステムを作成しています。

ユーザーフォームの「登録」(CommandButton1)をクリックすると、入力したデータが「一覧」というシートのA列(A4が最初のデータ)に日付が入り、その横(J4、K4、L4... ※1)にその日のデータがすべて蓄積され、日付をキーにして1つずつ下の行に転記されていくというところまでは、作業が完了して実際に使えるようになりました。
※1 事情によりB~I列は使用していません。

その後、一度ユーザーフォームから登録されたデータを編集のため、ユーザーフォームの日付(仮にTextbox1)だけを入力し、「検索」(CommandButton3)というボタンを押した時に、該当する「一覧」のシートに入力されているデータを再度フォームの各項目にに転記しなおして、それを修正した場合に、「上書き保存」(CommandButton4)押すと上書き保存ができるようにしたいと思っているのですが、なかなかうまくいきません。

独学でしか触ったことがない初心者のため、使えそうなFindもいまいちどのように利用したらよいかわからず、相談させていただきました。

念のため、下記に詳細を記載させていただきましたが、足りない情報などあれば教えていただけると嬉しいです。


---------------------------------------------------------------------------------------------------------
【詳細】
ブック:日次報告(仮)
シート:①「日次登録(仮)」…このシート上に登録ボタンがあり、そこからフォームを開きます。
              フォームには、日時(手入力)、天候(プルダウン)、作業内容
              (手動入力)、各項目の評価1,2,3,4...(数字手入力)等があり、
              項目がとても多く100項目以上あります…。
    ②「一覧」…ユーザーフォームから登録したデータを蓄積していくシートです。
          上記で記載したように、先頭行がA4でB~Iが空白のJ4,K4,L4...と続きます。
---------------------------------------------------------------------------------------------------------


※登録は下記のような方法で登録しています。

Private Sub CommandButton1_Click()  ’「登録」ボタンを押して「一覧」のシートに転記

With Worksheets("入力").Cells(Rows.Count, 1).End(xlUp)

.Offset(1, 0) = TextBox1.Value       '「日時」
.Offset(1, 9) =ComboBox1.Value     '「天候」
    .Offset(1, 10) = TextBox2.Value     ’「作業内容」
        :               ’これ以降100項目以上同様にに記載しています
End With

Unload UserForm1

End Sub
---------------------------------------------------------------------------------------------------------
↑ユーザーフォームへの転記は、ComboBox1.Value= .Offset(1, 9) で登録時と反対にすればよいのかなと思っているのですが、間違いでしょうか?

質問者からの補足コメント

  • うれしい

    ご回答いただきましたお二方、本当にありがとうございました。
    どちらも、ベストアンサーにさせていただきたいところなのですが、
    今回の内容に即しているという観点で、決めさせていただきました。
    本当に、どうもありがとうございました。

      補足日時:2018/07/23 14:59

A 回答 (3件)

取りあえず前の回答の修正とお詫び


「TextBox1.Value =.Offset(1, 0) 'A列の値を日付表示用に入れる」
は既に検索キーとして入力済であるので、不要でしたね。

もう1つ
「With Worksheets("入力").Cells(データ既存行, 1).End(xlUp)」
は間違いで、「上書き保存」の時は
「With Worksheets("入力").Cells(データ既存行, 1)」
で良いでしょう。
※本題の「データ既存行」の検索方法は下に記述しています。

>ユーザーフォームへの転記は、ComboBox1.Value= .Offset(1, 9) で登録時と反対にすればよいのかなと思っているのですが、間違いでしょうか?
表示される内容によって細かい修正は必要になる可能性はありますが、その方法でいけるはずです。
単なるTextデータでしたら問題ないでしょう。
気になるようでしたら、
「データ既存行=○○」のようにダミーの値を決定しておいて、下記のようなプロシージャーの動作を確認しておくことをお勧めします。

さて本題
実は「日付」をキーとする検索はちょっと面倒です。
「日付を検索する」
http://officetanaka.net/excel/vba/tips/tips131d. …
http://www.moug.net/tech/exvba/0050163.html
などを読んでいただいた方が良いのですが、要するに
検索キーとなる「TextBox1.Value」は実は単なる文字列であり、セルの表示は「○/〇」のように一見同じ文字列のように見えるが、実際のセル内の情報はシリアル値なので一筋縄ではいかない!
という事です。不可能ではありませんので、工夫してみてください。

最後に「データ既存行」検索方法のアドバイス
基本的な構文としては

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Option Explicit
Dim データ既存行 as long 'モジュール全体(検索時と上書き保存時)で同じ変数を使用するため、Subプロシージャーの外(モジュールの最初)に定義しておく必要があります。

Private Sub ユーザーフォームへの転記
Dim 日付検索用 as Range
Dim 検索日付 as String

検索日付=TextBox1.Value
Set 日付検索用=Worksheets("入力").Columns(1).Find (What:=検索日付,・・・・・・・・・・)'(←ここがちょっと厄介)
If 日付検索用 Is Nothing then
'------見つからない場合の処理----
データ既存行=0 ’複数個修正する場合に前の値が残らないようにする。

Else ’無事見つかった場合の処理
データ既存行=日付検索用.Row
With Worksheets("入力").Cells(データ既存行, 1)
'ここは、ユーザーフォームへの転記処理を記述
End With
End If
End Sub


Private Sub 上書き保存 'ユーザーフォームからSheets("入力")への転記
’「データ既存行」はフォームへの転記時に決定されているので、こちらでは日付で検索する必要は無い。
If データ既存行<>0 then 
With Worksheets("入力").Cells(データ既存行, 1)
'ここは、ユーザーフォームからシートへの転記処理を記述=ほとんど「登録」と同じです。

End With
End If

End Sub
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
ザックリとこんな感じの構文になるでしょう。
一応、日付はA列にあるという事ですので、Findする範囲を
.Columns(1).Find
のように「.Columns(1)=A列のみを探せ!」としてみました。

以上、参考にしてください。
    • good
    • 0
この回答へのお礼

度々申し訳ありません、本当にありがとうございます。
今お伺いしたもので試しに少しずつやってみているのですが、下記の段階まで入力した際になぜかキーの日付の1行下を読み込んで転記されていました…
転記自体はすべてできていたので、Findの中身の問題かなと思うのですが...
※ちなみに日付部分は断念して(20180101)のような入力方法にしてしまいましたので、シリアル値の件は問題なくなったかと思います。

ただここまでできただけでもとてもありがたいです。
ありがとうございます!もう少し自分でも調べてみます。

---------------------------------------------------
Private Sub CommandButton3_Click() 'ユーザーフォームへの転記()
Dim 日付検索用 As Range
Dim 検索日付 As String

検索日付 = TextBox1.Value

Set 日付検索用 = Worksheets("入力").Columns(1).Find(What:= 検索日付)

If 日付検索用 Is Nothing Then

データ既存行 = 0
Else
データ既存行 = 日付検索用.Row

With Worksheets("入力").Cells(データ既存行, 1)

      ComboBox1.Value = .Offset(1, 9)
       ....

   End if
End sub

お礼日時:2018/07/20 17:00

横から失礼します。

質問に対する回答ではないのですが、私の経験談です。
同じようにユーザフォームから入力するツールがあったのですが、とっても使いにくかったので、ユーザフォームをやめて、1日分(1件分)のデータを入力するシートに変更しました。
ユーザフォームの何が不便かというと、例えば、入力してる最中に別のExcelの資料を参照しようとするとユーザフォームを一旦閉じる必要があるからです。これを解決するのは、ユーザフォームをモーダレスで作る必要があります。また、ユーザフォームではオートフィルや範囲選択のコピペもできません。1項目づつ、ひたすら入力する業務であれば仕方ないのですが、100以上の項目があるということは、コピペできないと大変なのではないでしょうか。すでに単純な登録はできるようなので、ご自分で何件か登録してみて、使い勝手を検証してみることをお勧めします。
それから、プログラムを作成する上でも、フォーム上のコントロールをハンドリングするより、シート上のセルをハンドリングする方が簡単ですよ。
利用者の皆さんに「使いやすい」って言ってもらえると良いですね。
    • good
    • 0
この回答へのお礼

なるほど、シートへの入力でもマクロが利用できるのですね…
確かにそちらの方が、利用者のの使い勝手はいいような気もします!
こういった登録といえば、ユーザーフォームかな?と思い、他に方法があるとは知らずに、
必死になってユーザーフォームの使い方を調べてしまっていました…!笑

ただ基本的に、項目はすべて入力するわけではなく、当日の業務内容によって複数件入力するような内容でしたので、
利用者側はおそらくそこまで時間のかかるものではないと思っています。(おそらくですが...)

もし次作成する機会がありましたら、その方法で頑張ってみたいと思います。
取り急ぎ今回は、使いやすいと思ってもらえるようなユーザーフォームを作れるよう、
あと少しがんばってみたいと思います。
ありがとうございました!

お礼日時:2018/07/23 14:54

すみません。

完全に見落としていました。
>Worksheets("入力").Cells(Rows.Count, 1).End(xlUp)
は、最終行を検出しているだけでしたね。
私はいつも「+1」で新規追加用の記入行を決定したので気が付きませんでした。
ですから、追加の時は「.Offset(1, ○)」で良いのですが、変更するときは「データ既存行」そのものを検出していますので、「.Offset(0, ○)」としないといけません。
これで、「キーの日付の1行下を読み込んで転記されていました…」は解決するでしょう。
では、御健闘を!
    • good
    • 0
この回答へのお礼

出来ました!!
本当にそのあたりの単純な部分もわかっておらず、単純なことを何度も伺ってしまい、申し訳ありません。
Zincerさんのおかげで、無事形になりそうです。
あとは項目の細かい設定等を利用者にわかりやすく作りこんでいきたいと思います。
本当に何度お礼を言っても言い尽くせません、ありがとうございました…!

お礼日時:2018/07/23 14:48

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!