• 締切済み

エクセルのマクロを教えてください。

マクロの初心者です。 特に変数が全く使えず、下記もどのように記載していいのかわからないため教えていただけないでしょうか。 ユーザーフォームのtextbox2に開始番号があります。 textbox3に本数があります。 sheet1のB12セルには開始番号が入ります。 開始番号から本数分+1したものを順番にセルに入っていくようにしたいです。 ただ、入れたいセルが横→左下(開始番号の列)→横→左下(開始番号の列)・・・としたいため、どのように書いていいのかわかりません。 地道に書くのであれば、下記のようになると思うのですが、変数を使って書く場合はどのようになるのか教えていただけないでしょうか。 Worksheets("Sheet1").Range("B12").Value = TextBox2.Value If TextBox3.Value = 2 Then Worksheets("Sheet1").Range("G12").Value = TextBox2.Value * 1 + 1 ElseIf TextBox3.Value = 3 Then Worksheets("Sheet1").Range("G12").Value = TextBox2.Value * 1 + 1 Worksheets("Sheet1").Range("B13").Value = TextBox2.Value * 1 + 2 ElseIf TextBox3.Value = 4 Then Worksheets("Sheet1").Range("G12").Value = TextBox2.Value * 1 + 1 Worksheets("Sheet1").Range("B13").Value = TextBox2.Value * 1 + 2 Worksheets("Sheet1").Range("G13").Value = TextBox2.Value * 1 + 3 ElseIf TextBox3.Value = 5 Then Worksheets("Sheet1").Range("G12").Value = TextBox2.Value * 1 + 1 Worksheets("Sheet1").Range("B13").Value = TextBox2.Value * 1 + 2 Worksheets("Sheet1").Range("G13").Value = TextBox2.Value * 1 + 3 Worksheets("Sheet1").Range("B14").Value = TextBox2.Value * 1 + 4 ・ ・ ・ End If

みんなの回答

  • kkkkkm
  • ベストアンサー率66% (1745/2621)
回答No.6

No.5の補足です。 Range("B12")と Range("G12") は Worksheets("Sheet1").Range("B12") Worksheets("Sheet1").Range("G12") とするか With Worksheets("Sheet1") For i = 1 To cnt If i Mod 2 >= 1 Then .Range("B12").Offset(Int(i / 2), 0).Value = snum + i - 1 Else .Range("G12").Offset(Int(i / 2) - 1, 0).Value = snum + i - 1 End If Next End With としてください。Rangeの前にドットがあります。

すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率66% (1745/2621)
回答No.5

フォームのコマンドボタンで以下を実行して試してみてください。 Private Sub CommandButton1_Click() Dim i As Long Dim cnt As Long, snum As Long If IsNumeric(StrConv(Me.TextBox3.Value, vbNarrow)) Then cnt = Val(StrConv(Me.TextBox3.Value, vbNarrow)) Else MsgBox Me.TextBox3.Name & "の値が数値ではありません", vbCritical Exit Sub End If If IsNumeric(StrConv(Me.TextBox2.Value, vbNarrow)) Then snum = Val(StrConv(Me.TextBox2.Value, vbNarrow)) Else MsgBox Me.TextBox2.Name & "の値が数値ではありません", vbCritical Exit Sub End If For i = 1 To cnt If i Mod 2 >= 1 Then Range("B12").Offset(Int(i / 2), 0).Value = snum + i - 1 Else Range("G12").Offset(Int(i / 2) - 1, 0).Value = snum + i - 1 End If Next End Sub

すると、全ての回答が全文表示されます。
  • imogasi
  • ベストアンサー率27% (4737/17070)
回答No.4

#2です。補足はありがとうございます。 (1)テキストボックスの値の数値化は*1してあったのですね(当方見落とし)。   エクセル関数などでは、数値を掛ける(変化させないため*1が多い)とすると、数値化してくれるので、便利ですが、プログラムでは数値化関数(VBAのValやPythonのintにような関数)を使う方がよいと思う。 エクセルでは背後で、出来るだけ数値になるようなサポートがあるように推測するが。 (2)補足によると、 B12セルに「15」、G12セルに「16」、B13セルに「17」、G13セルに「18」と入力されるようにしたいです. 同行の第12行には、B列とG列に連番15,16をそれぞれ入れるは判りました。 テキストボックスが2個(2系列分か、B,G列の2つのためか)あるのは、どうなったのですか?補足ではなにも説明がないが。 しかし、この質問のプログラム実行を行うのは、どういうタイミングですか? 始に(このシート作成当初など)にB、G列に連番を(一斉に)入れてしまうのですか? その場合は、どの行まで止める、というのも決めにくい。目障りになるようにも思う。 ーー そうじゃなくて、最終番号を覚えておいて、何かのその行を(上記例で第12行のB列など)入力するときなどに、 bに15、G列に16(またはA列に識別データなどを入力した時などか?)ををセットするのか?実行前は、B12,G12は空白行(未使用)なのでしょう。 これはシートのイベントなどを使わなければできないように思う。 または、何かのきっかけで、データ最終行を割り出してその次の行などに、付番するとか。 VBAコードレベルの単純質問ではなく、仕組を考える話になるように思うが、それについて何も書いて・説明はない。 時間的な順に沿って、人間の作業手順とプログラムで行う処理を一歩一歩箇条書きにして説明すべきだ。 初めて向き合う、読者にはそれは「常識」ではなく、質問者の頭の中でしか判らない。 これの説明がない、質問者が多く、回答が変な方に向いてしまう場合がある。 親切な回答者は、聞かれた方向で、素直に回答している例が多いが、小生は表現不足に疑問を感じることがある。 ーー もしそれなら、B,Gグループの採番のための最終番号(か次回番号)の値を保持しなければならない。B,G列の番号は、意味的に、セット(組)なのか? ブックを閉じても、こういう値(今までの最終番号など)を保持(次へ渡す)するのは、セルに最終番号を記録(保持)しかないと思う。 もう一つの方法の変数のスコープで解決する(できる場合)のは、難しい課題で、初心者の問題ではない。変数のスコープは、大切だが、理解しずらい。 つい注意を忘れる場合があるので、勉強と慣れが必要です。

RT123456789
質問者

補足

imogasiさん 引き続き回答、コメントありがとうございます。 1)に関しては調べると*1とValが出てきました。*1の方が覚えやすく、今後も使っていけそうかなと思い使用していました。ただ、アドバイス頂いたようにValを使っていけるように頑張ります。 2)引き続きつたない説明でご迷惑おかけして申し訳ありません。 製造現場での作業報告書の作成を簡単に出来ないかとの取り組みがそもそもの発端です。 やりたいのはロット№を必要な行に必要な分だけ入力できるようにしたいです。 1個1個入力したらいいのですが、開始のロット№と何本製作するかを入力し、コマンドボタンを押せば必要な分だけロット№が報告書に入力されるようにと思って作っています。 テキストボックスが2個あるのは開始番号(textbox2)と、何本製作するか(textbox3)になります。 報告書に準備されているロット№の入力枠は12個までです。 それに関しては12より大きい数字を入れたらexit subとなるようにすればいいのかと思っています。 実行前は記載していただいた通り入力前は空欄です。 コマンドボタンを押して入力するようにしていますが、コマンドボタンを押すといったん入力に必要な場所(ロット№を入れる予定の最大12個の枠、B列とG列)をクリアするようにしています。 また、以降に書いていただいている指摘はごもっともで、ほんとに申し訳ないです。 表現が下手なくせに、具体的に細かく書いていないことで、回答者の皆さんにご迷惑おかけしています。 泥臭くても良いので、出来るだけ細かくしっかりと記載するように注意します。 普段人に説明するときに注意していることが、全く出来ていません。 シンプルに伝えられないなら、泥臭くてもしっかりと。申し訳ありません。 重ね重ね申し訳ないのですが、長期連休中に続きを行うことが出来ません。 質問を投稿するタイミングを間違えました。 本日最終日でバタバタしており、最初の回答いただいた分もまだ咀嚼出来ていない状態です。 休み明け改めて内容確認する必要があります。 ほんとにいろいろ申し訳ありません。また、いろいろありがとうございます。 よろしくお願いします。

すると、全ての回答が全文表示されます。
  • kon555
  • ベストアンサー率51% (1849/3570)
回答No.3

 コードへの細かい指摘は置いといて、まず概念的な説明からいきます。  VBAに限らず『プログラム』というのは、マニュアルや作業手順書のようなものです。どの順番で何をするか、どこの数値をどうするか、という手順の列挙です。  日本語の分からない外国人作業者に、彼(または彼女)の分かる言葉で書いたマニュアルを渡して作業させるようなもの、と思って下さい。  例えば貴方の下記の書いたコードを日本語に翻訳すると 「If TextBox3.Value = 2 Then Worksheets("Sheet1").Range("G12").Value = TextBox2.Value * 1 + 1」 ↓ 「もし"TextBox3"の値が2ならば、ワークシート1のG12セルの値を、"TextBox2"の値に1を掛け1足した数にしろ」  となります。  このように考えたとき、変数というのは『作業者に用意させるメモ帳』にあたります。  例えば貴方の書いたコードでは、「TextBox2.Value * 1+〇」という指示が繰り返し出てきます。日本語では「"TextBox2"の値に1を掛け、〇足した数にしろ」の部分です。貴方はここの〇の部分が変わっていくので、その分全て記述しようとしています。  どれだけの数値を見込むかにもよりますが、無限にマニュアルを書く必要が出てきます。  しかし例えば下記のようになっていても、作業手順としては成立しますよね? 1.メモ帳Aに"TextBox3"の数を記録する。 2.メモ帳Bに『1』という数字を書き込む 3.ワークシート1のG12セルの値を、TextBox2の値に1を掛けメモ帳Bの数を足した数にする。 4.メモ帳Bの数に1を足す。 5.メモ帳Bの数とメモ帳Aの数が等しくなるまで、手順3~4を繰り返す。  このような手順にすれば、どれだけ数値が巨大になっても対応可能です。つまりマニュアルとして合理的なわけです。  VBA的に書くとFor文で可能です。 https://valmore.work/excel-vba-for/  もちろんこのままでは延々と「ワークシート1のG12セルの値」という部分を書き換え続けてしまうので、ここも変数を使って都度指示を変更する必要があります。  セル指定をRangeではなくCellsで指定する事で、これも簡単に対応できます。 https://www.sejuku.net/blog/28260

RT123456789
質問者

補足

kon555さん 回答ありがとうございます。 細かく記載いただいてほんとにありがとうございます。 教えていただいたページの内容を理解するのもちょっと時間かかりそうですので、ますはお礼まで。 よろしくお願いします。

すると、全ての回答が全文表示されます。
  • imogasi
  • ベストアンサー率27% (4737/17070)
回答No.2

>数分+1したものを 「もの」は何を意味するのか?連続した番号の1つの数か? 「もの」は濫用しない方がよい。 ーー 初心者なのに、なぜUserFormを、ユーザーの指定内容を採るのに 使うのか。Inputboxやシートのセルに(開始番号を)入れさせる方式でよいのでは? こういうコントロールを使うのは、イベントという仕組みや、コントロールの情報を採るという勉強が必要で、中級以後でよいのでは。 もっとWEBに出てくる、コントロールの使用例題を勉強すべきでしょう。 >入れたいセルが横→左下(開始番号の列)→横→左下(開始番号の列)・・・とし よくわからない。実例を数行挙げれば、よく読者に伝わるのでは。 実例は、一つのケースしか表現できなくても、その方が考え方を正確に伝えられるというケースを、エクセルの質問の回答経験から学びました。 VBAのコードよりその表現技能を磨く方が、大切と思う。 そうしないとWEBを調べて勉強できない。 == 全体にごたごたしている印象で、そうしなければならない感が湧かない。 >TextBox2.Value * 1 + 3 などは、1回 n=TextBox2.Value としてその後はnを使って表現するのだ。 それが普通の変数の使い方です。ただし TextBox2.Valueはたとえ数字でも数字文字列が返されるものなので、n=Val(TextBox2.Value)として、数値化しておくことになる。 また連番は 本件=前者+1のように表現して繰り返す場合が多く、+1、+2、+3の書き方は稀かと? エクセル関数の学習だけでは、この変数に当たるものが、式の中で使えない不便さがある。それで使わないままに今に至ったのかも。でもエクセル出現以前からコンピュータプログラムは組まれていて、変数はメモリの情報を扱うときの、まず使う概念です。エクセルからコンピュータ―利用・学習を始めるとすると、その基礎的なことが飛ばされてしまうのかなと感じた次第です。

RT123456789
質問者

補足

imogasiさん 回答、コメントありがとうございます。 指摘、コメントが胸に突き刺さります。うまく表現できていないこと含め申し訳ありません。 現場での報告書や書類関係を簡単に作業者が記載できるようにマクロを使い始めました。私自身が使うのであれば、エクセルシート自身に数式を入れて使用するのですが、パソコン自体に不慣れな作業者が入力するので、間違いが起きないようにユーザーフォームを使用するようにしています。 ただ、まわりに聞ける人もおらず、ネットで調べながら切り貼りして使用しているのが現状です。そのうえでどうしてもわからないことがあれば、このように投稿させていただき、それを見ながら勉強させていただいております。 2個を1セットで製作しているため、横に対しては+1した連番を振る必要があり、1セットが終われば行を下にずらして入力されるようにしたいです。 texbox2に「15」、textbox3に「4」が入っていた場合はB12セルに「15」、G12セルに「16」、B13セルに「17」、G13セルに「18」と入力されるようにしたいです。 変数の使い方もありがとうございます。トライしてみます。 よろしくお願いします。

すると、全ての回答が全文表示されます。
回答No.1

この目的なら「if」文ではなく 「switch case 」を使ったほうが可読性が良くなります。 あと、算術式の優先順位は確かに「*」が「+」より高いですが、 先々色々な計算式を書くのであれば、VBAの仕様による 優先順位に頼らず()を使用して、プログラマが明示的に 優先順位を指定したほうが良いでしょう。 更に申し上げれば、このプログラムの部分的な意味は 理解できますが、全体として何故このロジックが必要なのかが 分かりません。 そこがわかれば、もっと簡潔かつBUG発生率の低い構文を 提示できるかも知れません。 またまた、更に申し上げれば、 「マクロの初心者です」であれば、 フォームを使用せず、 全部セルに記述して、テストしてからフォームを使うほうが、 間違えた際の手戻りが少ないと思います。

RT123456789
質問者

補足

Ultra-Hetareさん 回答、コメントありがとうございます。 もの作りの報告書で使用したいと思っています。 2本1セットで加工するため同じ行に2つのロット№を入力されるようにしたいと思って投稿させていただきました。 2本セットで横方向にロット№が並び、次のセットで下の行に移る感じです。説明が下手で申し訳ありません。 正直、自分で使用するのみであればエクセルシートに数式を入れておいてそれで使用するのですが、パソコン自体にかなり不慣れな作業者が入力するので、フォームを使用した入力の方法を行っています。 私自身、マクロ自体もよくわからず、ネットで調べたものを切り貼りしながらトライ&エラーで作っていっている感じです。まわりにも聞ける人がおらず、どうししても困った際にこのように投稿させてもらっています。教えていただいたものを理解できるように調べながら勉強させていただいています。 長い返信申し訳ありません。 よろしくお願いいたします。

すると、全ての回答が全文表示されます。

関連するQ&A