[[20210808203024]] 『Resizeの範囲指定方法』(VBA初心者) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『Resizeの範囲指定方法』(VBA初心者)

VBAの初心者です。

先日、別の問題を質問し、皆様のおかげで無事解決したのですが、
また新たな問題に直面しています。

下記のようなコードを書きたいのですが、
Resizeの範囲指定の方法が分からず、悪戦苦闘しています。
解決方法をご教示頂きたくお願いいたします。

Sub Input1()

        Dim ws As Worksheet
        Dim c As Range
            For Each ws In Worksheets
               If ws.Name <> "マスタ" Then
                    Set c = ws.Cells(4, ws.Columns.Count).End(xlToLeft).EntireColumn
                    Worksheets("マスタ").Range("C39").Copy
                    c.Offset(2, -7).Resize(Rows.Count, ).PasteSpecial Paste:=xlPasteValues
                    Worksheets("マスタ").Range("C41").Copy
                    c.Offset(2, -6).Resize(Rows.Count, ).PasteSpecial Paste:=xlPasteFormulas
                End If
        Next
End Sub

>>c.Offset(2, -7).Resize(Rows.Count, ).PasteSpecial Paste:=xlPasteValues
まずこの部分で、実行エラー'1004'
アプリケーション定義またはオブジェクト定義のエラーと表示されてストップします。

マスタ以外の複数のシートの指定範囲へ、
マスタシートの2つの指定セルのデータをコピーすることが目的です。

各シートの最終列から左側へ指定列数分移動し、
行を下側へ指定行数分移動した箇所を起点として、
その列の最終行まで範囲選択し、
マスタシートのセルのデータをペーストします。
値と数式のデータです。

但し、複数のシートの最終列は、全シート毎に一定数増加していきますが、
最終行はそれぞれのシート毎にバラバラに増加していく為、
一定ではありません。

< 使用 Excel:Office365、使用 OS:Windows10 >


>.Resize(Rows.Count, )
↑どういう意味になるか理解できてますか。
ヒント:「Rows.Count」は「ActiveSheeet.Rows.Count」と解釈されてます。

(もこな2) 2021/08/08(日) 21:21


追加で。
問題の箇所を直したとしてもう一点。

 ws.Cells(4, ws.Columns.Count).End(xlToLeft).EntireColumn.Offset(2, -7).Resize(Rows.Count)
                                             ~~~~~↑~~~~~       ~↑~
                                                 これは正しいですか?

(もこな2) 2021/08/08(日) 21:27


もこな2様、回答ありがとうございます。

Resize(Rows.Count, ) → 選択範囲の変更(最終行まで範囲指定, 列範囲指定無し)、
という形になるのかと考えておりましたが、違うのでしょうか。。。?

ws.Cells(4, ws.Columns.Count).End(xlToLeft).EntireColumn.Offset(2, -7).Resize(Rows.Count)
→ 試してみたところ動かなかったので、恐らく間違いなのかと思いますが、、、

1)4行目の最終列から、任意の列まで移動し、
 Cells(4, ws.Columns.Count).End(xlToLeft).EntireColumn.?
2)指定列の任意の行まで移動し、
 Offset(2, -7)?
3)指定セルから最終行まで選択、
 ???
4)C?Bへ指定データを貼り付け。
 ???
(VBA初心者) 2021/08/08(日) 22:54


Rowsに親オブジェクトの指定がないです
エラーは出ないと思いますが、ws.が必要では?

entirecolumnは列全体を指すので、オフセットで行位置を上下させるような動かし方はできないかと

やり続ければ、すぐ上達すると思います
がんばってください
(観覧車) 2021/08/09(月) 00:46


Resize(Rows.Count, ) → 選択範囲の変更(最終行まで範囲指定, 列範囲指定無し)、
は最終行まで「範囲指定」ではなくて、Resizeはセル領域のサイズを変更する

Dim Rng As Range
Set Rng = Range("A1").Resize(Rows.Count) '---(A)

Set Rng = Range("A2").Resize(Rows.Count) '---(B)

(A)は実行時エラーにならないが、(B)は実行時エラーになる。
なぜかといえば、ワークシートの最大行数を超えたセル範囲だから

(傍観者) 2021/08/09(月) 05:23


既にアドバイス頂いているようですが、乗りかかったなんとやらなので投稿しておきます。

■1
ヒントで書いたように「Rows.Count」は「ActiveSheeet.Rows.Count」と解釈されてます。
すなわち、Office365なら「1048576」となりますね。

■2

 Rangeオブジェクト.Resize(行数,列数)

↑は、セル(範囲)を、指定した行数、列数に拡張(縮小)する命令です。
この時、行数(列数)を省略すると、そのまま変更しないの意味になります。
したがって、例えば↓のようになります。

 Range("A1:B3").Resize(4,1)・・・・・・・・・・A1:A4
 Range("A1:B3").Resize(4,)・・・・・・・・・・・A1:B4

したがって「■1」を踏まえて考えれば、例えば Range("A4").Resize(1048576)としたらシートの外に3行分あふれちゃいますよね?
なので、「.Resize(Rows.Count, )」で本当に正しいのか確認しました。

■3
次に↓について考えてみましょう

     ws   .    Cells(4, ws.Columns.Count).End(xlToLeft)         .  EntireColumn
 wsシート の   XDF4セルから左方向にみて最初にデータのあるセル  の  列全体

という意味になっています。
これを踏まえて、例えば↓がどうなるか考えてみましょう。

 Range("H:H").Offset(2, -7)

列のほうは7列左へずらすからA列ということになり、問題ないですね。
しかし行のほうは、列全体を2行下げることはできませんよね?(2行はみ出しちゃうので)

ということを踏まえると↓は

 ws.Cells(4, ws.Columns.Count).End(xlToLeft).EntireColumn.Offset(2, -7).Resize(Rows.Count)

 ・「列全体を2行下げろ」という命令に対して、Excel君がそんなことできないとエラーを出している
 ・【列】全体の【行】をResize(1048576)にしようとしてるので、命令は実行できるが意味はない

というところが問題であろうと思われます。

■4
この質問は↓の続きですよね。
[[20210807131746]] 『都度変化する最終列から指定列までのコピーと挿入』(VBA初心者)

↑のまっつわんさんのコードをよく研究されるべきだと思います。例えば↓に着目してみましょう。

 ws.Cells(4, ws.Columns.Count).End(xlToLeft).EntireColumn.Offset(, -7).Resize(, 4).Copy

↑について、「ws.Cells(4, ws.Columns.Count).End(xlToLeft)」がで得られるセルが【H4セル】だとしたら↓のようになります。

 ws.Range("H4").EntireColumn    .Offset(, -7)      .Resize(, 4)                  .Copy
 H列全体                        7列右にずらして    行はそのまま4列に拡張して    コピーしなさい

すなわち↓のような意味でした。

 ws.Range("A:D").Copy

■5
しかし、今回のケースでは↓のような条件ですから列全体の話はではないですよね。したがって「EntireColumn」のことは忘れましょう。

 各シートの最終列から左側へ指定列数分移動し、
 行を下側へ指定行数分移動した箇所を起点として、
 その列の最終行まで範囲選択し、
 マスタシートのセルのデータをペーストします。
 値と数式のデータです。

さて、条件を順番にみていくと

 各シート → ループで回した時の 「ws」
 最終列 →「.Cells(4, ws.Columns.Count)」
 から左側へ指定列数(7列)分移動→「.Offset(, -7)」

ここまでは大体理解できているとおもいますが、↓の対応ができていません。

 箇所を起点として、その列の最終行まで

ここで、最終行の求め方について考えてみましょう。
列のほうは【最大列】から【左】に見ていってデータのある個所を調べたのですから、同じ理屈で【最大行】から【上】に見ていけば、目的のセルにたどり着くのは理解できますよね?
これをコードにするとこんな感じです

 ws.Cells(  ws.Rows.Count,   ws.Cells(4, ws.Cells(4, ws.Columns.Count).End(xlToLeft).Column)  .Offset(, -7)            .End(Xlup)
             wsの最大行           wsのXDF4セルから左に見てデータのある最初のセルの列         から左に7列ずらしたセル   から【上】に見てデータのある最初のセル

ちょっとわかりづらいので分解するとこうです。

    Sub 研究01()
        Dim ws As Worksheet
        Set ws = ActiveSheet
        Dim 行 As Long, 列 As Long

        列 = ws.Cells(4, ws.Columns.Count).End(xlToLeft).Offset(, -7).Column
        行 = ws.Cells(ws.Rows.Count, 列).End(xlUp).Row

        MsgBox "得られたセルは " & ws.Cells(行, 列).Address(0, 0) & " です"
    End Sub

このようにすれば、指定した列の【最終行】を求めることができることがわかりますね。

■6
さて、「■5」までで、コピー対象となるセル範囲のうち、最初のセルと最後のセルの求め方は分かったと思います。
では、【セル範囲】をExcel君に伝えるのはどうしたらよいかという話になります。
方法はいくつかありますが、Resizeを使うなら、起点をベースに何行、何列に拡張すればよいかを考えます。
今回のケースで考えると起点が4行目なっています。つまり既に3行分下に下がったセルからスタートしているわけですから、その分は引かなければ正しくありません。
よって、こんな感じになるでしょう。

    Sub 研究02()
        Dim ws As Worksheet
        Set ws = ActiveSheet
        Dim 行 As Long, 列 As Long

        列 = ws.Cells(4, ws.Columns.Count).End(xlToLeft).Offset(, -7).Column
        行 = ws.Cells(ws.Rows.Count, 列).End(xlUp).Row

        MsgBox "得られたセル範囲は " & ws.Cells(4, 列).Resize(行 - 3).Address(0, 0) & " です"
    End Sub

また、Resizeを使わずともApplication.Range(起点セル,終点セル)のように指定することでもセル範囲を表現することが可能です。

    Sub 研究03()
        Dim ws As Worksheet
        Set ws = ActiveSheet
        Dim 行 As Long, 列 As Long

        列 = ws.Cells(4, ws.Columns.Count).End(xlToLeft).Offset(, -7).Column
        行 = ws.Cells(ws.Rows.Count, 列).End(xlUp).Row

        MsgBox "得られたセル範囲は " & Application.Range(ws.Cells(4, 列), ws.Cells(行, 列)).Address(0, 0) & " です"
    End Sub

なお、いずれの場合も行が4未満になるときは、データがないということですから処理してはダメですよね。

■7
ということを踏まえるとこんな風に修正すればよいでしょう。

    Sub Input1_修正1()
        Dim ws As Worksheet
        Dim 列 As Long, 行 As Long

        For Each ws In Worksheets
            If ws.Name <> "マスタ" Then
                列 = ws.Cells(4, ws.Columns.Count).End(xlToLeft).Offset(, -7).Column
                行 = ws.Cells(ws.Rows.Count, 列).End(xlUp).Row

               If 行 >= 4 Then
                    Worksheets("マスタ").Range("C39").Copy
                    ws.Cells(4, 列).Resize(行 - 3).PasteSpecial Paste:=xlPasteValues

                    Worksheets("マスタ").Range("C41").Copy
                    ws.Cells(4, 列).Resize(行 - 3).PasteSpecial Paste:=xlPasteFormulas
                End If
            End If
        Next ws
    End Sub

ただし、このままではC39セルの値貼付は、C41の数式貼付で上書きされるので意味がないですね。
本当はどのようにしたいのか、こちらではわかりませんのでぜひご自身で修正してみてください。
(わからなけれれば、修正後のコードを提示したうえで、○○になるはずが××になるというように状況を説明するとアドバイスが得られると思います。)

(もこな2) 2021/08/09(月) 18:08

誤字訂正しました。
(もこな2) 2021/08/09(月) 20:26


まずは人にに聞かないで自分で調べろ。

例えばB2セルに色を塗っておいて、

range("B2").offset(2,3).select
range("B2").resize(1,5).select
range("B2").EntireColumn.select

とかのコードを書いてどんな動きをするのか自分で確認しなさい。
(vba) 2021/08/09(月) 23:13


 >Resizeの範囲指定方法

Offsetする場合は、シートからはみ出す可能性が常にあるから、
Resizeは丁寧にしないとだめですね。

Option Explicit

Sub test()

    Dim ws As Worksheet
    Dim strFormula1 As String
    Dim strFormula2 As String
    Dim wsマスタ As Worksheet
    Dim Rng As Range
    Dim i As Long

    '基本となる数式の取得
    With Worksheets("マスタ")
        strFormula1 = .Range("C39").Formula
        strFormula2 = .Range("C41").Formula
        Set wsマスタ = Worksheets(.Index)
    End With

    'シートを巡回して数式を入力
    For Each ws In Worksheets
        If Not ws Is wsマスタ Then
            With ws.UsedRange
                i = .Columns.Count - 7
                Application.Range(.Cells(6, i), Cells(.Rows.Count, i)).Formula = strFormula1
                Application.Range(.Cells(6, i - 1), Cells(.Rows.Count, i - 1)).Formula = strFormula2
            End With
        End If
    Next
End Sub

数式を入れたいならこんな感じです。
セル範囲を指定する言葉をいろいろ覚え、
臨機応変に使い分けましょう。
(まっつわん) 2021/08/11(水) 08:43


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.