Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

マクロでDo while...Loop を連続で記述する方法

549 views
Skip to first unread message

ぴんくー

unread,
Mar 15, 2010, 11:23:01 AM3/15/10
to
マクロ初心者です。
一つのループが終わった後、次のループに移って作業を続行させるマクロを
記述したいのですが、方法を教えていただけないでしょうか。
簡単なことだとは思うのですが…、マニュアルをいろいろ読んでも
わかりません。
お願いします。

T. Sugita

unread,
Mar 16, 2010, 7:11:57 AM3/16/10
to
In message news:9B35FFCA-CE9B-449E...@microsoft.com
"ぴんくー" <????@discussions.microsoft.com> wrote ...

> 一つのループが終わった後、次のループに移って作業を続行させるマクロを
> 記述したいのですが、方法を教えていただけないでしょうか。
> 簡単なことだとは思うのですが…、マニュアルをいろいろ読んでも
> わかりません。

ちょっとどう処理したいのかわからなかったのですが、
どのようにうまく記述できなかったのでしょうか?

1)

初期化1
Do While 条件1
初期化2
Do While 条件2
処理
Loop
Loop

2)

初期化1
Do While 条件1
処理
Loop

初期化2
Do While 条件2
処理
Loop

--
杉田
nws-...@bp.iij4u.or.jp

ぴんくー

unread,
Mar 16, 2010, 12:18:01 PM3/16/10
to
ご回答ありがとうございます。
で…、
初期化するのに何を記述すればいいのでしょうか?
一つのループだけのときには、必要ないのだとしたら、
きっと使ったことがないと思います。

Do while... Loop の後にそのまま続けてDo While... Loop
と記述してあるのですが、
リストからデータを取り込んでループで連続印刷して、
次のリストを続けて印刷したいのですが、一つ目の
リストで作業が終わってしまっていました。


"T. Sugita" からの元のメッセージ:

> .
>

T. Sugita

unread,
Mar 17, 2010, 11:29:48 AM3/17/10
to
In message news:D0D21CF9-6CF9-478D...@microsoft.com
"ぴんくー" <@discussions.microsoft.com> wrote ...

> 一つのループだけのときには、必要ないのだとしたら、
> きっと使ったことがないと思います。

通常は1つのループであっても、記述されていると思います。
詳細は、下記を参照ください。


> Do while... Loop の後にそのまま続けてDo While... Loop
> と記述してあるのですが、

1: Do While 条件1
2: Do While 条件2
3: 処理
4: Loop
5: Loop
6:

続けて記述したというのは上記のような状態でしょうか?

この場合、

条件1 が成立する間、1~5を実行
条件2 が成立する間、2~4を実行

となりますが、たとえば、2 回「処理」を実行したあとで
条件2 が成立しなくなったと仮定した場合、

1 条件1が成立しなければ、6 へジャンプ <== 条件成立で 2 へ移る
2 条件2が成立しなければ、5 へジャンプ <== 条件成立で 3 へ移る
3 「処理」を実行
4 2へジャンプ
2 条件2が成立しなければ、5 へジャンプ <== 条件成立で 3 へ移る
3 「処理」を実行 <== ここで条件2 が不成立になった場合
4 2へジャンプ
2 条件2が成立しなければ、5 へジャンプ <== 条件成立で 5 へ移る
5 1へジャンプ
1 条件1が成立しなければ、6 へジャンプ <== 条件成立で 2 へ移る
2 条件2が成立しなければ、5 へジャンプ <== 条件2は不成立のまま
5 1へジャンプ

と実行されている可能性があります。

上記のような状態を回避するための初期化の例として、
以下のような、単純な 2 重の For ループ

For i = 1 To 3
For j = 1 To 2
' 処理
Next
Next

を Do While … Loop に置き換えると以下のようになり、
条件1、条件2 を判定する前に、ループの初期値を初期化
しています。

i = 1 ' 初期化1
Do While i <= 3 ' 条件1
j = 1 ' 初期化2
Do While j <= 2 ' 条件2
' 処理
j = j + 1
Loop
i = i + 1
Loop

また、もし以下のようにしていた場合でも、同様に、2回目の
Do While…Loop の部分の条件が既に不成立になっていないかが
問題になります。

1: Do While 条件1
2: 処理
3: Loop
4:
5: Do While 条件1
6: 処理
7: Loop
8:

マクロを実行する際、対象となるマクロにカーソルを合わせた
状態で、F8 キーで実行することで、どのような順番で実行
されているか 1 ステップずつ確認できますので、
一度確認されてみてはどうでしょうか。


> リストからデータを取り込んでループで連続印刷して、
> 次のリストを続けて印刷したいのですが、一つ目の
> リストで作業が終わってしまっていました。

リストがどのように並んでいて、それをどう判定しているのか
によって記述内容が変わります。
実際に記述中のマクロを簡略化して、Do While Loop の前後を
含む部分を投稿することは可能でしょうか?

とりあえず、Do While Loop が実行される前にリストの先頭を
指すように、なんらかの初期化を行う必要があるのではないか
という気がします。

--
杉田
nws-...@bp.iij4u.or.jp

ぴんくー

unread,
Mar 18, 2010, 11:32:06 AM3/18/10
to

できました!
いろいろいじっていたら、リストの連続印刷ができたので、
何が原因でダメだったのかはわからずじまいなのですが…。
2つ目以降のループ内のセルの指定が間違っていたのかもしれません。
初期化とは、新たな変数の宣言ということでよかったでしょうか?

一応、私が記述したマクロを表示します。
もし、何かアドバイスがありましたら、遠慮なくお願いします。

_________________________


Sub 印刷()

ActiveSheet.Unprotect

印刷 = MsgBox("印刷しますか?", vbOKCancel, "印刷")

If 印刷 = vbOK Then

Dim a As String
Dim b As String
Dim c As String

a = 3
b = 3
c = 3

Do While Sheets("A").Cells(c, 5) <> ""

Sheets("B").Select

Sheets("B").Cells(5, 32).Value = Sheets("A").Cells(a, 2).Value
Sheets("B").Cells(5, 61).Value = Sheets("A").Cells(b, 4).Value
Sheets("B").Cells(5, 87).Value = Sheets("A").Cells(c, 5).Value

ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True

a = a + 1
b = b + 1
c = c + 1

Loop

Dim d As String
Dim e As String
Dim f As String

d = 24
e = 24
f = 24

Do While Sheets("A").Cells(f, 5) <> ""

Sheets("B").Select

Sheets("B").Cells(5, 32).Value = Sheets("A").Cells(d, 2).Value
Sheets("B").Cells(5, 61).Value = Sheets("A").Cells(e, 4).Value
Sheets("B").Cells(5, 87).Value = Sheets("A").Cells(f, 5).Value

ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True

d = d + 1
e = e + 1
f = f + 1

Loop


Range("DH5").Select

End If

ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True

End Sub

T. Sugita

unread,
Mar 19, 2010, 10:53:30 PM3/19/10
to
In message news:D1BDB9FB-7BE6-45CF...@microsoft.com
"ぴんくー" <@discussions.microsoft.com> wrote ...

> 初期化とは、新たな変数の宣言ということでよかったでしょうか?

変数の宣言ではなく、24 を代入している部分になります。

> d = 24
> e = 24
> f = 24

なので、同じ変数(a,b,c)を利用して、24 に初期化しても
問題ありません。
内容を見る限りでは、a,b,c の 3 つの変数に分ける必要は
ありませんので、1 つの変数にまとめて良いと思います。


> 一応、私が記述したマクロを表示します。
> もし、何かアドバイスがありましたら、遠慮なくお願いします。

ちょっと気になったのは、
Sheets("B").Select
の実行位置で、シート"A" を選択した状態でマクロを実行して
しまうと、ActiveSheet.Unprotect がうまく機能しないと思います。

あと、このようなケースでは、1 つのリスト印刷を行う部分を
サブモジュールにして共通化して扱うと、後で変更する場合に、
便利かと思います。

以下は、これらを考慮した例です。
(初期化(初期値)はリスト印刷の引数として、印刷マクロ側から
3 と 24 を与えています)

Sub リスト印刷(rowIdx As Long)

Sheets("B").Select

ActiveSheet.Unprotect

Do While Sheets("A").Cells(rowIdx, 5) <> ""

Cells(5, 32).Value = Sheets("A").Cells(rowIdx, 2).Value
Cells(5, 61).Value = Sheets("A").Cells(rowIdx, 4).Value
Cells(5, 87).Value = Sheets("A").Cells(rowIdx, 5).Value

ActiveSheet.PrintOut Copies:=1, Collate:=True

rowIdx = rowIdx + 1

Loop

Range("DH5").Select

ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True

End Sub

Sub 印刷()

Dim ret As Integer

ret = MsgBox("印刷しますか?", vbOKCancel, "印刷")

If ret = vbOK Then

リスト印刷 3

リスト印刷 24

End If

End Sub

--
杉田
nws-...@bp.iij4u.or.jp

ぴんくー

unread,
Mar 20, 2010, 12:06:01 PM3/20/10
to
ありがとうございました。
教えていただいたマクロを最初見たときは、『モジュールが2つになっていると
ボタンにどうやって登録するんだろう…』と思いましたが、実際ためしてみて
やっと理解できました。

ただ、参照リストの列が違う場合は、私が使っていた方法になってしまうん
でしょうか…?


T. Sugita

unread,
Mar 21, 2010, 8:58:24 AM3/21/10
to
In message news:3F9EA4F7-2094-49A6...@microsoft.com
"ぴんくー" <@discussions.microsoft.com> wrote ...

> ただ、参照リストの列が違う場合は、私が使っていた方法になってしまうん
> でしょうか…?

もしまったく違う形で参照しているのであれば、無理に統合せず、
もともとやられていた方法の方が良いと思います。

相対位置が異なるだけで処理内容が同じということであれば、
たとえば左上の位置を指定するといった形で表現できると
思います。

Sub リスト印刷(rowIdx As Long, colIdx As Long)

Sheets("B").Select

ActiveSheet.Unprotect

Do While Sheets("A").Cells(rowIdx, colIdx + 3) <> ""

Cells(5, 32).Value = Sheets("A").Cells(rowIdx, colIdx).Value
Cells(5, 61).Value = Sheets("A").Cells(rowIdx, colIdx + 2).Value
Cells(5, 87).Value = Sheets("A").Cells(rowIdx, colIdx + 3).Value

ActiveSheet.PrintOut Copies:=1, Collate:=True

rowIdx = rowIdx + 1

Loop

Range("DH5").Select

ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True

End Sub

Sub 印刷()

Dim ret As Integer

ret = MsgBox("印刷しますか?", vbOKCancel, "印刷")

If ret = vbOK Then

リスト印刷 3, 2

リスト印刷 24, 7

End If

End Sub

もしくは、右端の列がループの判定基準になっているようなので、
右端を指定して、colIdx-3, colIdx-1 等を参照しても良いと思います。

--
杉田
nws-...@bp.iij4u.or.jp

ぴんくー

unread,
Mar 22, 2010, 7:26:01 AM3/22/10
to
スギタ様、
いろいろありがとうございました。

参照先が10箇所ある印刷なのですが、相対的に作成してあるリストだったので、
作業がずいぶん楽になりました。

本当にお世話になりました。

0 new messages