• ベストアンサー

エクセル:マクロの起動条件

お世話になります。 以下の条件でのマクロを起動する方法、及びそのマクロを教えてください。 《条件》 ブックを開いた時、あるシートのC列でデータが入っている最下行の行番号とA列のデータが入って最下行の行番号の差が100以下だった場合、マクロを実行する。 (なおC列の行番号の方が必ず大きいです) ちなみに実行したいマクロは1~6の手順です。 1.ブックを開いたとき 2.「入力用」という名前のシートのC列でデータが入っている最下行の行番号とA列のデータが入っている最下行の行番号の差が100以下だった場合 3.「入力用」というシートにかかっているシートの保護をはずし 4.データが入っているC列の最下行のA~Z列を選択して、50行分 下にコピーする。  (例えば、C列の最下行が350行の場合、A350~Z350まで を選択したあと400行まで下にコピーする。) 5.再度シートの保護をかけ 6.A列でデータが入っている最下行の1つ下のセルを選択する ちなみに、2の条件に当てはまらないときはマクロを実行しません。 またC列の最下行よりA列の最下行が大きい数字になることはないはずですが、もし同じかA列の方が大きい場合、「エラー:C列よりA列が大きくなっています」と画面に表示させたい。 なお、行番号の差:100、選択するA~Z行、50行分下にコピー は変わる可能性があるので、修正する場合どの部分を修正すればよいかも教えてください。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.4

No.1です。 フィルダウン(Ctrl+D)だったのですね。マクロを修正してみました。  ActiveSheet.Unprotect の下の、  Range(Cells(ERowC, SCol), Cells(ERowC, ECol)).Copy Cells(ERowC + CopyTo, SCol) を削除して、  Range(Cells(ERowC, SCol), Cells(ERowC + CopyTo, ECol)).Select  Selection.FillDown に置きかえてください。 それから、もう一点私のミスがありました。  ElseIf ERowC - ERowA > 100 Then という行があるのですが、これは  ElseIf ERowC - ERowA > DiffRows Then の誤りです。(容易に数値を変更できるように、最初にパラメータを定義していたのに、それを使ってませんでした) これで試していただけますか?

HGK
質問者

お礼

ありがとうございました。 期待通りの動きをしてくれました。

その他の回答 (3)

  • 134
  • ベストアンサー率27% (162/600)
回答No.3

#2ですが、Changeに勝手に変えてしまったのが敗因かもしれません。 chenge セルを書き換えるとVBA起動 ということで、セルを追加する。 追加した結果、最終C行の行数とA行の行数が等しいので、100以下を満たし、再びVBA起動… というループを考えていました。 openなら、開いた瞬間に行を追加。書き換えて終了なので、問題ないのかもしれません。 でも、というか、やっぱり、コードの記述方法は、#1様の方がすっきりして見返しやすいですね ^^;)

  • 134
  • ベストアンサー率27% (162/600)
回答No.2

実はこの問題、結構やっかいなんじゃないかと思ったりします。 イベントプロシージャとしては、bookのopen ではなく、sheetのchangeだろうと思うのですけど、 Private Sub Worksheet_SelectionChange(ByVal Target As Range) if range("A65535").end(xlup).row > range("C65535").end(xlup).row then msgbox("エラー:C列よりA列が大きくなっています",vbOKOnly) if range("c65535").end(xlup).row - range("a65535").end(xlup).row <=100 then workshhet("入力用").unprotect Range(Range("C65535").End(xlUp).Offset(0, -2), Range("C65535").End(xlUp).Offset(0, 23)).Copy Range(Range("c65535").End(xlUp).Offset(1, -2), Range("C65535").End(xlUp).Offset(50,23)).PasteSpecial xlPasteAll '後のoffset(50,23)の50を増減させるかも? worksheet("入力用").protect end if range("A65535").end(xlup).select End Sub というのが、基本でしょうけど、ペーストした瞬間に、VBAの開始条件となり、無限ループに陥るように思います。 無限ループを回避する条件が、ちょっと思いつかないです。

HGK
質問者

お礼

ありがとうございました。

HGK
質問者

補足

ご回答ありがとうございます。正直考えの足りない部分がかなりあったようです。難しいことはわからないのですが、回答者さんの疑問については、50行分を増やすのを100以上にすれば解決するでしょうか? また、閉じる際には「入力用」シートを選んだ上で上書き保存後閉じるというマクロを使っていますので、bookのopenで対応できるのかなという感じです。

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.1

とりあえず書かれた通りに作ってみました。 Alt+F11でVBAの画面を開き、左のThisWorkbookをダブルクリックすると右に白い画面が新たに開くので、そこに以下のマクロをコピーして貼り付けてください。 なお、選択する列の左端Aと右端Z、50行分下にコピー、行番号の差100の部分は、最初の4行の該当する箇所を書き換えてください。 Private Sub Workbook_Open()  Const SCol As String = "A" 'コピーする行の左端の列  Const ECol As String = "Z" 'コピーする行の右端の列  Const CopyTo As Integer = 50 'コピーする行の間隔  Const DiffRows As Integer = 100 'A列とC列の最後の行番号の差  Dim ERowA As Long, ERowC As Long    Worksheets("入力用").Activate  ERowA = Cells(Rows.Count, "A").End(xlUp).Row  ERowC = Cells(Rows.Count, "C").End(xlUp).Row  If ERowA > ERowC Then   MsgBox "エラー:C列よりA列が大きくなっています", vbExclamation   Exit Sub  ElseIf ERowC - ERowA > 100 Then   Exit Sub  End If  ActiveSheet.Unprotect  Range(Cells(ERowC, SCol), Cells(ERowC, ECol)).Copy Cells(ERowC + CopyTo, SCol)  ActiveSheet.Protect  Cells(ERowA + 1, "A").Select End Sub 保存していったんブックを閉じ、再度開くとマクロが条件にしたがって実行されるはずです。 エラーが出たり、ご希望の動作と違うときは補足をお願いします。

HGK
質問者

補足

早速のご回答ありがとうございます。説明が少々足りませんでした。50行下にコピーという点なのですが、質問の例だと350行目の内容を400行目にコピーするのではなく、350行目から400行目までを選択して Ctrl+D を行うという意味です。

関連するQ&A