アプリ版:「スタンプのみでお礼する」機能のリリースについて

Excel2010を使っている者です。
指定した範囲の値で順番に表①の任意の列にソートをかけて印刷していくVBAを作りたいと思っております。

具体的には、A1からA20の各セルに値が入力してあるのですが、表①(セル範囲はA30からS500)のF列に順番にソートをかけて、順次、印刷したいと思っております。

なお、A1からA20についてですが、上から順番に必要がある場合のみ値を入れるようになっているため、全てのセルは使わない可能性が高いです。(A1からA8のみ値が入っている日もあれば、A1からA15まで値が入っている日もあれば、A1からA3までしか値が入ってないときもあればです)

私はネットで調べながら以下のようにVBAを作ってみたのですが、実行しようとすると「Nextに続くForがありません」というメッセージが出てしまいます。

どのような記述にすれば良いのか、ご教示願います。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

Sub 印刷()

Dim i As Long

For i = 1 To 20
If Cells(i, 1) = "" Then
Exit Sub
Range("A30:S500").AutoFilter Field:=7, Criteria1:=Cells(i, 1).Value
Next i

ActiveSheet.PrintOut

End Sub

A 回答 (6件)

こんばんは!


少しだけコードの説明を!

① For k = 31 To 500  ”31行から500行までKを使ってループを行う
本来であれば最終行を取得しそこまでのループにすればよいのですが、
必ず500行目まではデータがある!という前提のコードでした。

② If Rows(k).Hidden = False Then  ”もし、K行が表示されていれば
myFlg = True  ”myflgにはTrueを入れる。
Exit For  ”ループをやめる?
End If  ”?
Next k  ”次の行の処理に移る?

フィルタを掛けるというコトは30行目は項目行でデータは31行以降にあると思い
31行目からその行が「表示」されているかどうか?を調べています。
>End If  ”?
の部分は
>If Rows(k).Hidden = False Then
に対する「End If」です。
仮に「myFlg」が「FALSE」である場合は「TRUE」になるまで、もしくは500行目までループします。

「myFlg」はBoolean型で宣言していますので、「FALSE」(初期値)か「TRUE」のどちらかになります。
仮に31行目が表示されているというコトは少なくとも1つ以上の該当データがあるので
「myFlg」を「TRUE」とし、それ以降ループしても無意味なのでそこでループを抜けます。
ただ、該当データがない場合は500行目まで「FALSE」となり続けます。

最終的に「myFlg」が「TRUE」なのか?「FALSE」なのかを判定し
「TRUE」の場合 → 該当データが1つ以上はあるので印刷プレビューへ
「FALSE」の場合 → 該当データが存在しないのでメッセージボックスを表示!
といった流れにしています。

最後の
End If  ”?  (あ)
myFlg = False  ”?(い)
End If  "?(う)
Next i

(あ)は
If myFlg = False Then
に対する「If」の「End If」になる。

(い)は
次のループに入り前に「myFlg」を初期値の「FALSE」に戻します。
これを行わないと常に「TRUE」のままになりデータがない場合でも印刷プレビューが表示されてしまう。

(う)の「End If」は
>Next i
の前にあるので
>If Cells(i, j) <> "" Then
に対する「End If」になります。

※ こちらのVBE画面は↓のように記載し、「End If」はどこの「If・・・」にかかっているのか
タブ送りで判りやすく訂正しやすいようにしているのですが
それをそのままこの画面にコピー&ペーストすると
左寄せになってしまうので判りにくいですよね。m(_ _)m
「指定した範囲の値で順番にソートをかけて、」の回答画像6
    • good
    • 0
この回答へのお礼

何度も誠にありがとうございました。
ようやく理解できました。
お手数おかけしましたが、大変助かりました。

お礼日時:2017/01/27 15:52

あぁ~~~!そういうコトだったのですね。



↓のコードに変更してみてください。

Sub Sample3()
Dim i As Long, j As Long, myCol As Long
Dim k As Long, myFlg As Boolean
For j = 1 To 2 '←A~B列まで//
If j = 1 Then
myCol = 6 '←A列の場合はF列で//
Else
myCol = 7 '←B列の場合はG列で//
End If
For i = 1 To 20
If Cells(i, j) <> "" Then
Range("A30:S500").AutoFilter field:=myCol, Criteria1:=Cells(i, j)
For k = 31 To 500
If Rows(k).Hidden = False Then
myFlg = True
Exit For
End If
Next k
If myFlg = False Then
MsgBox "「" & Cells(i, j) & "」のデータなし"
Else
ActiveSheet.PrintPreview '←印刷プレビューでやめています。//
End If
myFlg = False
End If
Next i
ActiveSheet.AutoFilterMode = False
Next j
End Sub

今度はどうでしょうか?m(_ _)m
    • good
    • 0
この回答へのお礼

何度もお付き合いいただき、ありがとうございます。
完璧にうまくいき、大変助かりました。

ただ、コードで理解できない点があったのですが、教えたいただけないでしょうか。書いていただいた以下のコードについてですが、それによってどういった流れの処理になっているのかが理解できなかったのですが、私が「?」を付けた個所が理解できていないのだと思います。

For k = 31 To 500  ”31行から500行までKを使ってループを行う
If Rows(k).Hidden = False Then  ”もし、K行が表示されていれば
myFlg = True  ”myflgにはTrueを入れる。
Exit For  ”ループをやめる?
End If  ”?
Next k  ”次の行の処理に移る?

If myFlg = False Then  "もし、K行が非表示ならば
MsgBox "「" & Cells(i, j) & "」のデータなし"  ”セル番号のデータなし”と表示させる。
Else  ”もし、K行が表示されていれば
ActiveSheet.PrintPreview '←印刷プレビューでやめています。//  ”プリントプレビュー
End If  ”?
myFlg = False  ”?
End If  "?

Next i
ActiveSheet.AutoFilterMode = False  ”行の非表示を解除する。
Next j
End Sub

お礼日時:2017/01/25 20:35

何度もごめんなさい。



No.3を投稿後今一度タイトルが気になったので顔をだしました。
>順番にソートをかけて、指定した表を印刷していく・・・

「ソート=並び替え」 となりますが
要するに順にフィルタをかけて該当データがあれば印刷するという解釈でよいのでしょうか?
その場合は↓のコードにしてみてください。

Sub Sample2()
Dim i As Long, j As Long
Dim k As Long, myFlg As Boolean
For j = 1 To 2
For i = 1 To 20
If Cells(i, j) <> "" Then
Range("A30:S500").AutoFilter field:=6, Criteria1:=Cells(i, j)
For k = 31 To 500
If Rows(k).Hidden = False Then
myFlg = True
Exit For
End If
Next k
If myFlg = False Then
MsgBox "「" & Cells(i, j) & "」のデータなし"
Else
ActiveSheet.PrintPreview '←印刷プレビューでやめています。//
End If
myFlg = False
End If
Next i
Next j
End Sub

※ コードは「印刷プレビュー」でやめていますので、すぐに印刷を実行する場合は
>ActiveSheet.PrintPreview
を変更してください。m(_ _)m
    • good
    • 0
この回答へのお礼

毎度、誠にありがとうございます。
書いていただいたコードを使うと、見事に動きました。
しかし、大変申し訳ないのですが、私の説明不足がありまして、求めていたものをは少し違ったものになってしまいました。

おっしゃるとおり、順にF列にフィルタをかけて、データがあれば印刷プレビューに出したいと思っております。混乱させてしまって申し訳ありませんでした。

しかし、A列とB列には違う条件(A列の値でフィルタをかける場所はF列、B列の値のときはG列でフィルタをかけたいと思っております。つまり、表①で、A1~A20の値のときはその値でF列でフィルタをかけて其々にデータがあれば印刷プレビューにし、B1~B20の値のときはG列でフィルタを・・(以下同様)と思っております)
また、さらにフィルタをかけるためのC列を追加する可能性があるため、A列、B列を並列的に描くのではなく、直列的に上から書いていきたいと思まいます。

書いていただいたコードを以下のように変更してみたのですが、うまく動きませんでした。どのように書けば良いのかご教示いただけると幸いです。

For j = 1 To 2
For i = 1 To 20

If i = 1
If Cells(i, j) <> "" Then
Range("A30:S500").AutoFilter field:=6, Criteria1:=Cells(i, j)
Else
End If
AutoFilterMode = False

If i = 2
If Cells(i, j) <> "" Then
Range("A30:S500").AutoFilter field:=7, Criteria1:=Cells(i, j)
Else
End If
AutoFilterMode = False

For k = 31 To 500
If Rows(k).Hidden = False Then
myFlg = True
Exit For
End If
Next k
If myFlg = False Then
MsgBox "「" & Cells(i, j) & "」のデータなし"
Else

ActiveSheet.PrintPreview
End If
myFlg = False
End If
Next i
Next j
End Sub

お礼日時:2017/01/24 13:31

続けてお邪魔します。



質問内容のコードをもう一度よく見てみると
一つずつフィルタをかけているのでその都度印刷プレビューを表示させるようにしていました。

あくまで憶測ですが・・・
A1~B20にオートフィルタの項目を入力し、複数の条件でフィルタを掛けたい!
というコトなのでしょうか?
↓の画像でいえばA1~B20セルに 「日・月・火・金」がありますので、
6列目(F列)が「日」か「月」か「火」か「金」をキーとしてフィルタを掛ける!
といったことがお望みであれば
今までのコードはお望みの動きにならないはずです。
結構面倒になります。

Excel2007以降で使える(Excel2003まではオートフィルタのキーは三つまでしか設定できない)コードにしてみました。

Sub Sample1()
Dim i As Long, c As Range, myFlg As Boolean
Dim myStr As String, myAry As Variant
For Each c In Range("A1:B20")
If c <> "" Then
myStr = myStr & c & ","
End If
Next c
If myStr <> "" Then
myAry = Array(Split(Left(myStr, Len(myStr) - 1), ","))
Range("A30:S500").AutoFilter field:=6, Criteria1:=myAry, Operator:=xlFilterValues
For i = 31 To 500
If Rows(i).Hidden = False Then
myFlg = True
Exit For
End If
Next i
If myFlg = False Then
MsgBox "該当データなし"
Else
ActiveSheet.PrintPreview
End If
End If
End Sub

これでF列が「日、月、火、金」の行が表示 → 印刷プレビュー
該当データがない場合のみメッセージボックスを表示させるようにしています。

的外れならごめんなさい。m(_ _)m
「指定した範囲の値で順番にソートをかけて、」の回答画像3
    • good
    • 0
この回答へのお礼

お礼が遅くなって申し訳ありません。
複数の条件でオートフィルタをかけたいとは思っているのですが、書かれていることが理解できませんでした。
次のご回答に、不明な点等は書かせていただきます。

お礼日時:2017/01/23 17:26

No.1です。



>当初のとおり「For i = 1 To 20」にしておくと問題があるのでしょうか(?)

前回、余計なお世話で書いたのは
最終行を取得し、そこまでのループでやめるための方法でしたが
A30~S500までデータがあるようなので、この方法は使えません。
また、
>For i = 1 To Cells(Range("A1").End(xlDown).Row, "A")

>For i = 1 To Range("A1").End(xlDown).Row
の間違いでした。どうも失礼しました。

ただこれはA1セルから下へ見ていき、空白セルの前までの行番号取得方法ですが、
データが21行目以降も続いている場合はこちらもダメですね。

今回の質問に関しては20行だけのループなので
まったく問題ないと思います。

ただ、コードを拝見すると30行目が項目行になっているという前提で

Dim i As Long
For i = 1 To 20
If Cells(i, 1) = "" Then Exit Sub
Range("A30:S500").AutoFilter Field:=6, Criteria1:=Cells(i, 1).Value
If MsgBox("印刷プレビューを行って良いですか?", vbYesNo + vbExclamation, "確認") = vbYes Then
ActiveSheet.PrintPreview
End If
Next i

のように最後に「Next i」を持ってこないと
メッセージボックスも表示されないと思います。

※ 上記コードではA1セル以降も印刷プレビューに表示されますが、
印刷範囲は指定しなくてよいのですよね?m(_ _)m
    • good
    • 0
この回答へのお礼

毎度、ありがとうございます。
教えていただいたとおりに修正すると、うまく動きました。

しかし、実は抽出したい値はA1~A20のみでなく、B1~B20にも入っているのですが、どのようにつなげれば良いのか教えていただけないでしょうか。

そのまま以下のようにコードをつなげてもB1~B20の分が動きませんでした。
Dim i As Long
For i = 1 To 20
If Cells(i, 1) = "" Then Exit Sub
Range("A30:S500").AutoFilter Field:=6, Criteria1:=Cells(i, 1).Value
If MsgBox("印刷プレビューを行って良いですか?", vbYesNo + vbExclamation, "確認") = vbYes Then
ActiveSheet.PrintPreview
End If
Next i

For i = 1 To 20
If Cells(i, 2) = "" Then Exit Sub
Range("A30:S500").AutoFilter Field:=6, Criteria1:=Cells(i, 1).Value
If MsgBox("印刷プレビューを行って良いですか?", vbYesNo + vbExclamation, "確認") = vbYes Then
ActiveSheet.PrintPreview
End If
Next i

また、大変申し訳ないのですが、可能であれば、A1~A20,B1~B20の値では何も抽出できなかった場合は処理をしない(印刷プレビューを・・のメッセージが出ない)ようにする方法も教えていただけると幸いです。

お礼日時:2017/01/19 13:11

こんばんは!



そのままのコードで使いたい場合は
>If Cells(i, 1) = "" Then
>Exit Sub
と2行になっているところを
>If Cells(i, 1) = "" Then Exit Sub
のように1行にしてみてはどうでしょうか?

おそらく2行にするとそのあとに
>End If
が必要になるはずです。

※ 私的には
>Exit Sub
ではなく
>Exit For
という使い方をします。
ただその後の処理がないので「Exit Sub」でも問題はないと思いますが・・・

余計なお世話かもしれませんが、
>For i = 1 To 20

>For i = 1 To Cells(Rows.Count, "A").End(xlUp).Row
もしA21セル以降にもデータがある場合は
>For i = 1 To Cells(Range("A1").End(xlDown).Row, "A")
とすれば
空白の場合の処理は不要だと思います。m(_ _)m
    • good
    • 0
この回答へのお礼

お返事ありがとうございます。

>>If Cells(i, 1) = "" Then Exit Sub
のように1行にしてみてはどうでしょうか?

修正いたしました。

>>For i = 1 To Cells(Range("A1").End(xlDown).Row, "A")
とすれば空白の場合の処理は不要だと思います。m(_ _)m

A列においては21行目以降にもデータがあるため(A30:S500に表があります)、書いていただいたようにしましたが、実行しようとすると、型が違うというエラーが出てしまいました。
当初のとおり「For i = 1 To 20」にしておくと問題があるのでしょうか(?)

なお、申し訳ないのですが、質問の際は実際に書こうとしているコードを少し省略してしまいました。
実際は以下のとおりなのですが、どこが問題なのかご教示いただけないでしょうか。


Dim i As Long

For i = 1 To 20
If Cells(i, 1) = "" Then Exit Sub
Range("A30:S500").AutoFilter Field:=6, Criteria1:=Cells(i, 1).Value
Next i

Dim intRet As Integer

intRet = MsgBox("印刷プレビューを行って良いですか?", vbYesNo + vbExclamation, "確認")

If intRet = vbNo Then
Exit Sub
End If

ActiveSheet.PrintPreview

End Sub

お礼日時:2017/01/18 19:58

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