[[20180606145245]] 『vbaでデータを別シートの該当箇所に転記』(ちちんぷりぷり) ページの最後に飛ぶ

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

 

『vbaでデータを別シートの該当箇所に転記』(ちちんぷりぷり)

ワークシートが3枚あります。

それぞれのシート名(オブジェクト名)は
・請求先(wsClient)
・請求データ(wsData)
・請求書(wsTemplate)
             です。

請求先シートにはtestデータとして1行1得意先で、11行のデータを入れています。

A列 B列 C列
得意先コード 得意先名 得意先正式名称

こちらは転記の処理がうまくいくようになったら、住所や担当者名などの列も増やす予定で、今は3列だけ入力しています。

請求データのシートにはこちらもテストデータとして12行分のデータを入れています。
A B C D E F
得意先コード 得意先名 商品コード 商品名 伝票番号 金額

請求書シートは、コピーして使う為のテンプレートです。
最終的には

	A12セルに得意先コード
	A13セルに得意先正式名称
	D28セルから商品名(下方向に6行・D33まで)
	J28セルから金額(下方向に6行・J33まで)

	J35にJ28からJ33の合計が入ります。

今はテストなので、D28から複数行の商品名のみを転記しようと思っています。


やりたいこと

・請求書(テンプレート)を請求がある請求先の数だけコピーして、シート名を請求先の名前にする。
・請求データのA列(得意先コード)を見て、先にコピーしてある請求先名のシートの該当箇所に転記する。


やったこと

当方、マクロ初心者です。
Webと本を見て調べながらVBAを書いています。
その為1行ごとに「何をやってるか」をメモしているのですが、間違った解釈があるかもしれません。

自分で組んだマクロは以下の通りです。


Sub 得意先毎にデータを転記()

'
Dim rowsData As Long, rowsClient As Long '行数カウント用に変数を宣言
rowsData = wsData.Cells(Rows.Count, 1).End(xlUp).Row '請求データの最終行数
rowsClient = wsClient.Cells(Rows.Count, 1).End(xlUp).Row '請求先の最終行数

Dim n As Long '変数「n」を整数で宣言
For n = 1 To rowsClient '請求先の行数(1行目から開始)

    Dim client As String    '変数「client」を文字列で宣言
    client = wsClient.Cells(n, 1).Value     'n行のA列から
    wstemplate.Copy After:=wstemplate   'wsTemplateをコピーしwsTemplateの後に追加する

    Dim ws As Worksheet     '変数「ws」をワークシートで宣言
    Set ws = ActiveSheet     'アクティブシートに変数「ws」をセットする
    ws.name = client           'アクティブシート「ws」の名前をclientに変える

    Dim i As Long, k As Long    '変数 i (請求データの対象行), k (請求書ひな形の対象行)を整数で宣言
    k = 28      'k (請求書ひな形)28行目から開始
    For i = 2 To rowsData    'rowsDataはシートの行数を表す

        If wsData.Cells(i, 2).Value = client Then
                     wsData.Range(wsData.Cells(i, 2), wsData.Cells(i, 3)).Copy ws.Cells(k, 4)
                            '請求データの i行の2列目(B列)から3列目(C列)までをコピーして、コピーしたひな形シートのk行4列目(A列)から

貼り付ける

                k = k + 1
        End If

    Next i

Next n

End Sub


今の問題

・請求データの転記が出来ていない

他にも問題があるのかもしれませんが、見た目は、
シートの請求書テンプレートのコピーは出来て、シート名の名前も変えられた!と思っています。

エラーは出ていないのですが、なぜ転記されないのかがさっぱりわかりません。

また、本当は「請求がある請求先だけ」シートを作成したいのですが、やり方がわからなかった為、請求先として請求先シートに入力してあるすべての請求先のシートをコピーして作成しました。

上記教えて頂けますでしょうか?
宜しくお願い致します

< 使用 Excel:Excel2010、使用 OS:Windows7 >


if文のコメント間違ってましたので念の為

        If wsData.Cells(i, 2).Value = client Then
        wsData.Range(wsData.Cells(i, 2), wsData.Cells(i, 3)).Copy ws.Cells(k, 4)
        '請求データの i行の2列目(B列)から3列目(C列)までをコピーして、コピーしたひな形シートのk行4列目(D列)から貼り付ける
(ちちんぷりぷり) 2018/06/06(水) 15:10

 こんばんは ^^ 気が付いた点だけですが。

 実際は
Dim wsData As Worksheet
Dim wsClient As Worksheet
Dim wstemplate
Set wsData = Worksheets("wsData")
Set wsClient = Worksheets("wsClient")
Set wstemplate = Worksheets("wstemplate")
と
コーディングされているのですね。
でなければエラーのはずですが。
If wsData.Cells(i, 2).Value = client Then
。。。
コードと得意先名で条件判定になっていますので、該当するデーターが無いです。
故に何もコピーされないのだと想像されます。
外していましたらお許しを。
。。。
項目名のシートが一枚出来ませんか?
(隠居じーさん) 2018/06/06(水) 16:52

 追伸  ^^

 三行目
 Dim wstemplate As Worksheet
の間違いですね ^^;

 >また、本当は「請求がある請求先だけ」シートを作成したいのですが
は
wsClientの得意先コードか得意先名が
wsDataに有るか確認して一件でも有ればシートを作成
とかすれば可能かもです。
(隠居じーさん) 2018/06/06(水) 17:19

[[20180601163036]] 『自動で転記するマクロを作りたい』(尾崎真っ黒)

↑本当は、こちらの質問と同様に、オートフィルタを使うと
得意先ごとに、まとめて転記できてよいです。
できれば、フィルタオプションだともっとよいかもしれません。
さがせば、過去の質問にも近いものがみつかるはずです。

もちろん、完成間近のようですので
今のままでも問題ありません。

気になるのは、転記するデータの数が多くて、
1ページにおさまらないといったことは
考えなくてもよいのでしょうか。
実際には、そこまで多くなることはないとか。

>また、本当は「請求がある請求先だけ」シートを作成したい

請求データから、「重複の削除」で
「請求がある請求先だけ」のリストを作成できるので
実際は、以下の2つのシートしか必要ないはずです。

・請求データ(wsData)
・請求書(wsTemplate)

(マナ) 2018/06/06(水) 19:53


フィルタオプション(AdvancedFilter)だとこんな感じになります。

 Option Explicit

 Sub test()
    Dim tbl As Range
    Dim c As Range

    Set tbl = wsData.Cells(1).CurrentRegion
    Set c = tbl(1).Offset(, tbl.Columns.Count + 1)

    tbl.Columns(1).AdvancedFilter xlFilterCopy, , c, True

    Do While c(2).Value <> ""
        wstemplate.Copy After:=wstemplate
        With ActiveSheet
            .Name = c(2).Value
            tbl.AdvancedFilter xlFilterCopy, c.Resize(2), .Range("D27:E27")
        End With
        c(2).Delete xlShiftUp
    Loop

    c.Resize(2).ClearContents

 End Sub

(マナ) 2018/06/06(水) 20:40


隠居じーさん 様

>コーディングされているのですね
>でなければエラーのはずですが。

VBAをそのままコピーして貼り付けましたので
上記のまんまで、他の記述はありません。
そもそもの記述が間違っているということなのでしょうか?

>Set wstemplate = Worksheets("wstemplate")

このような記述もしていません。

シート名は
  請求書・請求データ・請求先で
シートのオブジェクト名が
  wsTemplate・wsData・wsClientです。

ちなみに「""」で区切るのはシート名だと思っていました。

>項目名のシートができませんか?

自動で出来るはずだということでしょうか?
特にそのようなシートは出来ていません。

>コードと得意先名で条件判定になっていますので、該当するデーターが無いです。
うむむ、これが難しいのですが。

If文のところですよね。
     If wsData.Cells(i, 2).Value = client Then
請求データシートの(i,2)を仮にA2のセルだとすると、そこに得意先コードが入っています。
=で見ている”client”が、得意先コードで作成されたシートの名前のつもりでした。
(A2のセルと同じ名前のシートが作成されているので)

ここの条件の書き方が違うということですよね。
難しい…。

コードと得意先名で判定している、と仰っていただいている部分が謎でして
私の記述だと、どこを参照していることになるのでしょうか。
教えて頂けると幸いです。

宜しくお願い致します。

(ちちんぷりぷり) 2018/06/07(木) 09:42


マナ 様

[[20180601163036]] 参照致しました。
オートフィルターやフィルタオプションを使うことを考えていませんでした。

転記するデータは、請求書のフォーム(定型の物がある)関係上
6行までしか使用できる行が無い為
請求データを作成する際にも6行を超える場合は調整をしているようです。
(請求データの作成に関しては私はノータッチです)

今作成しているマクロに
請求データから、「重複の削除」というものを行えば
「請求がある請求先だけ」のリストが作成出来るということで合っていますか?

請求先のシートを別に設ける必要はないということなのですね。

マナさんに教えて頂いたtestを実行してみましたところ
実行時エラー1004が出ました。
>抽出した範囲にはフィールド名が無いか、または無効なフィールド名です。
デバッグしたところ
>tbl.AdvancedFilter xlFilterCopy, c.Resize(2), .Range("D27:E27")
がハイライトされました。

初心者なもので、1行ずつ理解するのにも時間がかかるのですが
変数宣言されている「tbl」と「c」について教えて頂けると嬉しいです。

.CurrentRegionというのは空白のセルで囲まれた範囲を読み取り、参照するプロパティと確認しました。

    Set tbl = wsData.Cells(1).CurrentRegion

Cellsの後の(1)ですが、Cellsの後のカッコは範囲の指定(セルの位置?)ではないのでしょうか?
tbl(1)とか、c(2)とかでそもそもつまずいてしまっています。

…完成までの道のりが非常に遠く感じていますが
なんとかやり遂げたいと思いますのでお力お貸しいただければ幸甚です。

(ちちんぷりぷり) 2018/06/07(木) 10:06


 え〜と ^^
シートの件
大変失礼いたしました。理解致しました。当方の勘違いでした。済みません m(__)m
変数、client には 得意先コードが格納されています。
wsData.Cells(i, 2)には得意先名が格納されています。
なので=は成り立たない。
と推測しました。
どちらかに合わせてください。
例えば
wsData.Cells(i, 1)に変更するとかだと。。。得意先コードで確認になると思います。
只、実際のデーターがそうなっていればの話ですが。

 マナさんのコードも試されると良いと思います。他の回答者の方もそうですが、
私などとは違い、常に、かなりハイレベルで無駄の無いコーディングを
解りやすく、教えて下さっていますよ。
(隠居じーさん) 2018/06/07(木) 10:19

横入り失礼します。

 >変数宣言されている「tbl」と「c」について教えて頂けると嬉しいです。
これは気づいておられるように「ただの」変数名ですから、
書く人が勝手に付けてますので、意味を問うてもしょうがないです。
ただし、

tbl → Table → 表
c → Cell → 単体のセル(セル範囲ではない)

の略であることはコード中での利用のされ方で、想像に難くないと思います。

 >Cellsの後の(1)ですが、Cellsの後のカッコは範囲の指定(セルの位置?)ではないのでしょうか?
入門書などには解説が無い書き方で、
(理屈を説明しだすと、本線から話がせれるから省略されるんだと思いますが^^;)

wsData.Cells(1)

のwsDataは特定のシートを示します。
で、
wsData.cells
と書くとシート上の全部のセルの意味になります。

で入門書では(1,1)と書けとなっていると思いますが、
これは全部のセルの中の1行目の1列目という意味になりますが、
これを(1)と書くと全部のセルの内の1番目という意味になります。
この何番目というのはどういう順番かは公開はされてませんが、
セル範囲の左上が1番で行方向優先で数えて、
右下のセルは、wsData.cells(wsData.cells.count)
となっているようです。
(これはシートの場合の一番右のシートを示す時にも有効な手段になります。worksheets(worksheets.count)

なので、
wsData.Cells(1) は、
wsData.Range("A1") と同意になります。
あとは、お好みで、
wsData.Cells(1,1)と書くかどうかはご自分で判断されたらよろしいと思います。

ちなみに僕はセル範囲の左上は.Cells(1)と書く派です。
同様にブックにシートが一枚しかないとわかっているときは、Worksheets(1)と書く派です。

 >…完成までの道のりが非常に遠く感じていますが
果てしなく遠いですよ。覚悟しておいてください。

(まっつわん) 2018/06/07(木) 10:39


僕なりに添削してみました。
参考になれば。。。

Sub 得意先毎にデータを転記2()

    Dim ws As Worksheet         '取引先別シート
    Dim rowsData As Long        '請求データ最終行
    Dim client As String        '各取引先名
    Dim i As Long               'データ行インデックス

    rowsData = wsdata.Cells(Rows.Count, 1).End(xlUp).Row    '請求データの最終行数

    'データを繰り返し見て行く
    For i = 2 To rowsData
        'データの中の取引先を取得
        client = wsdata.Cells(i, 2).Value   '2列目が取引先?
        '書き出すシートの取得
        'ワークシートを取引先名で変数に代入してみる(まだ取引先名のシートが存在しなければエラールーチンへ)
        On Error GoTo ErrH
        Set ws = Worksheets(client)
        On Error GoTo 0

        'データの転記
        With ws
            .Cells(.Rows.Count, 4).End(xlUp).Offset(1).Value = wsdata.Cells(i, 2).Resize(, 2).Value
        End With
    '次のデータ行へ
    Next

    'プログラムを抜ける(=終わり)
    Exit Sub

'エラー処理ルーチン
ErrH:

    wstemplate.Copy After:=wstemplate   'wsTemplateをコピーしwsTemplateの後に追加する
    Set ws = ActiveSheet     'アクティブシートに変数「ws」をセットする
    ws.Name = client           'アクティブシート「ws」の名前をclientに変える
    Resume Next
End Sub
(まっつわん) 2018/06/07(木) 11:00

 訂正です。

       'データの転記(書き出すシートの4列目の最終データの1行下に)
        With ws
            .Cells(.Rows.Count, 4).End(xlUp).Offset(1)Resaize(,2).Value = wsdata.Cells(i, 2).Resize(, 2).Value
        End With

(まっつわん) 2018/06/07(木) 11:18


まっつわん 様

ありがとうございます。
cやtblが変数名であることはお察しいただいた通り、認識しておりました。
(1)、なるほどです。
A1ではなく(1,1)と書く、という入門書しか読んでいなかった為驚きました。
かっこいいですね。

教えて頂いたマクロを実行してみました。
取引先は1列目なので、そこは修正して、訂正版の前の物を実行したところ
エラーが出ずに新しい請求書のシートの作成が出来ました。
データの転記は「D28」から始めたいのですが「D4」からになっていたので

            .Cells(.Rows.Count, 28).End(xlUp).Offset(1).Value = wsData.Cells(i, 2).Resize(, 2).Value

の変数「i」の定義を直さなくてはいけないということですかね?


と、書き込みをプレビューしようと思ったら
その間にまっつわん様から転記の訂正の書き込みいただいたようです。
今気付いたので、これから試してみますね。
(ちちんぷりぷり) 2018/06/07(木) 13:05


まっつわん 様

連投すみません。

訂正で教えて頂きました部分

        With ws
            .Cells(.Rows.Count, 4).End(xlUp).Offset(1)Resaize(,2).Value = wsdata.Cells(i, 2).Resize(, 2).Value
        End With

ですが、エラーが出ております。

「Resaize」のスペルかな?とResizeにしてみましたが

コンパイルエラー
修正候補:ステートメントの最後

となりました。

Offsetの後のResize(,2)が増えたんですよね?
う〜ん…

(ちちんぷりぷり) 2018/06/07(木) 13:12


まっつわん 様

自分で書いていた時に請求書ひな形の対象行をkという変数で入れていたのですが

    Dim k As Long    'k (請求書ひな形の対象行)を整数で宣言
    k = 28      'k (請求書ひな形)28行目から開始

を、どこかに追記して、
且つ、転記させる開始セルの指定に使うということになりますか?

それとも、転記はD28と決め打ちなので変数は使わず
valueで貼り付ければ良いということで良いのでしょうか?

再度々の質問申し訳ありません。

(ちちんぷりぷり) 2018/06/07(木) 13:19


 >.Cells(.Rows.Count, 4).End(xlUp).Offset(1)Resaize(,2).Value
 .Cells(.Rows.Count, 4).End(xlUp).Offset(1).Resize(,2).Value

ですね^^;
VBEのインテリセンス機能がないとまともな単語が打てないのがばればれですね^^;

 >且つ、転記させる開始セルの指定に使うということになりますか? 
いいえ、27行目に項目行がある前提で書いてます。
つまり、
.Cells(.Rows.Count, 4).End(xlUp)
↑ここで、シートの最大行数目の4列目のセルから上方向に最初に何か入っているセルを検索しています。
ので、
4列目に何も入っていなければ
D2セルが取得されます。
それで都合が悪ければ、他の列で27行目に何か入っている列から、
転記する行を探すか、そういう探し方で都合が悪ければ、
別のアプローチをする必要があります。
が、2回目以降はその探し方でいいはずですし、
項目行が27行目にないのも普通に考えておかしな話でので、
入れてもらうようにするとか、そこはそちらの考えでお願いします。

(まっつわん) 2018/06/07(木) 13:30


D4に入ってしまうということは、
D3より下に何もないんですね。

ということは

    Dim rngTaraget As Range     '転記先セル

と変数を一つ追加し、

        'データの転記
        With ws
            Set rngTaraget = .Cells(.Rows.Count, 4).End(xlUp).Offset(1).Resize(, 2)
            If rngTaraget.row < 28 Then Set rngTaraget = .Range("D28")
            rngTaraget.Value = wsdata.Cells(i, 2).Resize(, 2).Value
        End With

と転記位置の初期値を微調整しましょうか。

(まっつわん) 2018/06/07(木) 13:42


まっつわん 様

ありがとうございます。
転記位置の初期値 <28 のところで指定でしょうか?
ばっちり転記が出来ました。

うちの請求書の書式が元がWORDの物をExcelに移植したもののようで
請求項目の転記の部分がD27から始まる不思議な書式になっています。
(最初は行のサイズを1行ずつ調整してWORDに合わせていたようで、酷い体裁のものでした)
項目行が無く、ベタ打ちで空白に入れていく形なのできちんと取得出来なかったものと思われます。

ですので、今回教えて頂いた、転記位置の設定を行うのがベストのようです。

今回初めて「Offset」と「Resize」を知りました。
範囲を指定することが出来るんですね。

転記をするという当初の目標は、まっつわん様のおかげでなんとか形になりそうです。

今回教えて頂いたOffsetやResize、や、
マナ様に教えて頂いたフィルタ等も勉強し、よりよく改善出来るように頑張ります。

教えて頂きありがとうございました。

(ちちんぷりぷり) 2018/06/07(木) 14:07


 >請求項目の転記の部分がD27から始まる不思議な書式になっています。
まぁ、イレギュラーな形でも定型ならどうにでもなります。

 >今回初めて「Offset」と「Resize」を知りました。
http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_cell.html

こことかまとめてあって読みやすいと思います^^参考になれば^^

(まっつわん) 2018/06/07(木) 14:21


まっつわん様

早速ありがとうございます!
勉強させていただきます。

まだちょっと転記がうまくいかない箇所があり(D列はOKなのにほかがおかしくなる)
試行錯誤しています。
自分でトライしてみて、お手上げになったらこちらでまたご相談させていただきますね。

(ちちんぷりぷり) 2018/06/07(木) 15:07


隠居じーさんさん>>

 >実際は
 >Dim wsData As Worksheet
 >と
 >コーディングされているのですね。
 >でなければエラーのはずですが。

最初に、

 >それぞれのシート名(オブジェクト名)は
 >・請求先(wsClient)
 >・請求データ(wsData)
 >・請求書(wsTemplate)
 >             です。
と、明示されてます。

wsData
は変数名ではなくオブジェクト名です。

つまりプロジェクトエクスプローラーで、
Sheet1(請求先)
となっていれば、

Sub test()

    MsgBox Sheet1.Name
End Sub

で、

請求先

と表示されるはずです。

(まっつわん) 2018/06/07(木) 16:33


ちちんぷりぷり さん 割り込みすみません m(__)m
>>まっつわん さんへ

はい! ^^
ご教示、ありがとうございます。 m(__)m
いろいろ、方法があるのですね。
また
お願い致します。^^v

(隠居じーさん) 2018/06/07(木) 17:21


こちらでまっつわん様に教えて頂いたセル範囲の指定方法を見ながら
データの範囲などを調整していたのですが
すっきりとうまく転記することが出来なくて悩んでいます。

元々、請求データのシートには(例)
 A      B     C     D    E     F
得意先コード 得意先名 商品コード 商品名 伝票番号 金額
EHM      愛媛   722103   みかん 146274  3830
NGN      長野   920325   りんご 512104  2504



と12行のテストデータを入れていました。

実際に張り付けたい場所(D28から)に必要になるのは
D列に入っている商品名と、F列に入っている金額になるので
請求データのシートのデータを前段階で
 A      B     C     D    E     F
得意先コード 商品名 金額
EHM      みかん  3830
NGN      りんご  2504

の3列に減らしてみました。

貼り付け先の請求書のテンプレートのD28に商品名が入り、
E28に金額が入ればOKです。

その他の項目は別の位置に転記したいのですが、
商品名と金額が入ることが第一歩なので今回はまだテストしていません。

教えて頂いたVBAで、得意先コードを見て得意先毎にテンプレートのコピーを作成し、
その作成したシートは得意先コードに変更されています。
D28・D29・・・と、下方向に、得意先名が同じものは転記されています。

ただ、E列に金額が入らないのです。

ResizeとOffsetの理解が出来ていないからだとは思うのですが…。

頂いたコード


Sub 得意先毎にデータを転記2まっつわん様()

    Dim ws As Worksheet         '取引先別シート
    Dim rowsData As Long        '請求データ最終行
    Dim client As String        '各取引先名
    Dim i As Long               'データ行インデックス
    Dim rngTaraget As Range     '転記先セル

    rowsData = wsData.Cells(Rows.Count, 1).End(xlUp).Row    '請求データの最終行数
                                   '.Cells(Rows.Count, 1).End(xlUp)
                                   '↑ここで、シートの最大行数目の1列目のセルから上方向に最初に何か入っているセルを検索

    'データを繰り返し見て行く
    For i = 2 To rowsData
        'データの中の取引先を取得
        client = wsData.Cells(i, 1).Value   '1列目が取引先なので修正
        '書き出すシートの取得
        'ワークシートを取引先名で変数に代入してみる(まだ取引先名のシートが存在しなければエラールーチンへ)
        On Error GoTo ErrH
        Set ws = Worksheets(client)
        On Error GoTo 0

        'データの転記
        With ws
            Set rngTaraget = .Cells(.Rows.Count, 4).End(xlUp).Offset(1).Resize(, 2)
            If rngTaraget.Row < 28 Then Set rngTaraget = .Range("D28")
                                                                                                     '↑転記位置の初期値をD28に指定。
            rngTaraget.Value = wsData.Cells(i, 2).Resize(, 2).Value
        End With

    Next

    'プログラムを抜ける(=終わり)
    Exit Sub

'エラー処理ルーチン
ErrH:

    wstemplate.Copy After:=wstemplate   'wsTemplateをコピーしwsTemplateの後に追加する
    Set ws = ActiveSheet     'アクティブシートに変数「ws」をセットする
    ws.name = client           'アクティブシート「ws」の名前をclientに変える
    Resume Next

End Sub


Set rngTaraget = .Cells(.Rows.Count, 4).End(xlUp).Offset(1).Resize(, 2) の部分ですが
混乱してきたのでSet rngTaragetの部分をばらして考えていたのですが

   .Cells(.Rows.Count, 4)  ←Rows.Countで下方向に見ていて、4列目(D列)に入れたいから

,4」になっているという理解でよろしいでしょうか?
   .End(xlUp)  ←最終行から上方向にデータの入っているセルを見ているということでしょうか?
   .Offset(1)  ←そのデータの入っているセルを基準として「(1)」は左上のセル(1,1)を指定しているということでしょうか?
   .Resize(, 2) ←その基準セルから、(, 2)は、下方向にあるだけ、2列分、でよろしいでしょうか?

であれば、あってるのに、なぜ転記されるのはD列
(請求データのB列)のみで、C列に入れている金額が入らないのだろうか?と。

ここをクリアしてから、他のセル(連続していない位置にある)に
商品コードや伝票番号を転記するようVBAを追加しようと思っていたので
しょっぱなでつまずいてしまった、という状態です。

「わかった!これでうまくいく!」なんて、簡単にはいかないものですね。
ですがここでただなんとなくわかったつもりで進んでしまうと
エラーが生じたり、レイアウト変更したときなどに自分で解決出来ないと思うので
なんとかきちんと身に着けたいと思っています。

お手数おかけいたしますが、またお教えいただきたく、
宜しくお願い致します。

(ちちんぷりぷり) 2018/06/11(月) 10:40


Offset(1)  ←そのデータの入っているセルを基準として「(1)」は基準セルから1ずれた場所、ですね。
失礼いたしました。

(ちちんぷりぷり) 2018/06/11(月) 10:50


 >「わかった!これでうまくいく!」なんて、簡単にはいかないものですね。
そうですね最初に言及しました。

 >>…完成までの道のりが非常に遠く感じていますが
 >果てしなく遠いですよ。覚悟しておいてください。

つまり、サンプルコードがあれば、
それを眺めて傾向と対策で、「ここをこうすればいい。」というような話になかなかならないのです。
やはり、「私はこうしたい!」という明確な意思あるいは意図を、
一行一行、VBA語で表現できるようにならなければなりません。

 >.Cells(.Rows.Count, 4)  ←Rows.Countで下方向に見ていて、4列目(D列)に入れたいから
 >,4」になっているという理解でよろしいでしょうか?
ちょっと理解が違うかな?
Rows.Count でセル範囲の行数を取得します。
で、With句で省略しているので分かり難いですが、
ws.Rows.Count という意味でしかも変数wsには、ワークシートが入ってます。
つまりシートには1048576行あるので、「1048576」という数値が返ってきます。
で、Cells(.Rows.Count, 4)としているので、
シートの1048576行目の4列目のセル、つまりは、D列のシート上の最後の行のセルという意味になります。

 >.End(xlUp)  ←最終行から上方向にデータの入っているセルを見ているということでしょうか?
そういうことです。

 >.Offset(1)  ←そのデータの入っているセルを基準として「(1)」は
 >左上のセル(1,1)を指定しているということでしょうか?
違います。
列数を省略してますが.Offset(1,0)の意味です。

最終行から上に見て行って、最初に何か入っているを見つけたセルの「1行下」
という意味です。

たとえば、
sub test()

 Range("D5").Offset(1).Select
end sub
などと書いて実際にテストしてみてください。
そして、
sub test2()
  Range("D5").Cells(1).select
end sub
とか、
sub test3()
  Range("D5").Range("C3").select
end sub

などと実験コードを書いて、どの位置が選択できるんだろう?と調べて見識を深めてください。

 >.Resize(, 2) ←その基準セルから、(, 2)は、下方向にあるだけ、2列分、でよろしいでしょうか?
う〜ん。
与えられたセル範囲を2列分に変えるということです。

例えば、
Range("C3").Resize(,2).select
とか
Range("C5:F10").resize(,2).select
とか
やってみてください。

>であれば、あってるのに、なぜ転記されるのはD列
>(請求データのB列)のみで、C列に入れている金額が入らないのだろうか?と。
んと、相対位置と絶対位置の違いを理解されるといいと思います。

絶対位置というのは、
シート上のD5セル
という感じで絶対変わらない表現ですよね?
指定のセルの1行下の2列右
これが相対位置の表現になります。
今までの例も含めて実験してみてください。

セル位置の調整は結構めんどくさいので、僕もよくミスしますし、
デバッグがかなり苦痛になります^^;;

(まっつわん) 2018/06/11(月) 11:45


まっつわん様

丁寧な解説をありがとうございます。

Range("B7").Offset(1).Select
と書けばB8が選択されるので、(1)は、1つ下を見てるんだな、等に推測していました。
セル単体でOffsetやResizeとするとなんとなく動きが見えるのですが
「範囲」が入ってくるとなかなか難しいですね。
セル範囲の指定方法のページの解説を見ながらOffsetやResizeもやってみていたのですが
一つずつ動かすと今回のマクロのようにいろいろ組み合わさってくると難しいなぁと思っています。
相対位置も同様に…。

果てしなく遠いですが整理しながら理解していきたいと思います。
ありがとうございました。

(ちちんぷりぷり) 2018/06/11(月) 13:17


まっつわん 様

再度質問させてください。

データの転記


        With ws
            Set rngTaraget = .Cells(.Rows.Count, 4).End(xlUp).Offset(1, 0).Resize(, 2)
            '    ↑ 転記先セル   ↑D1048576からCtrl↑で見つけたセルの 1行下のセルから DE2列を範囲指定
            If rngTaraget.Row < 28 Then Set rngTaraget = .Range("D28") '
                                                                                                     '↑転記位置の初期値をD28に指定。
           rngTaraget.Value = wsData.Cells(i, 2).Resize(, 2).Value
          '↑転記先のセルは(値)で貼り付ける = 請求データのi行2列を 2列分にリサイズし 値で貼り付け
        End With


転記先はD列の最終行の1行下のセルからDE2列分で、
転記元である、請求データのi行B列を基準に、リサイズで「2列」にして値で貼り付けという指示だと解釈したのですが、
何故か転記元のB列の値のみが転記されており、金額を入れてあるC列が反映致しません。
何かやはり考え方が違っているのでしょうか。

お昼を挟んでずっと考えたりテストをしたりしているのですがうまくいかず…。
教えて頂けたら幸甚です。
(ちちんぷりぷり) 2018/06/11(月) 15:34


全部読んでないので、外してたらごめんなさいですが
        If rngTaraget.Row < 28 Then Set rngTaraget = .Range("D28")
            '↓
        If rngTaraget.Row < 28 Then Set rngTaraget = .Range("D28:E28")
     または、
        If rngTaraget.Row < 28 Then Set rngTaraget = .Range("D28").Resize(, 2)

じゃないですか?

(もこな2) 2018/06/11(月) 16:27


 仕用データ
得意先コード   商品名   金額
   EHM         みかん    3,830
   NGN         りんご    2,504

 (ちちんぷりぷり) 2018/06/11(月) 10:40
でご提示の まつっわん さん
のコードで
ちちんぷりぷり さんのご説明により私が作成した情報では
転記できていますよ。
情報の配置かなにか、ちょっとした事に違いがあるのかもしれませんね。
なにかの
参考まで。。。^^
EHMシート
     D         E
27  商品名    金額
28  みかん    3830
(隠居じーさん) 2018/06/11(月) 19:15

 >「範囲」が入ってくるとなかなか難しいですね。 

そうですね。
基本、コードの中に普通はセルを選択するコードは書かないのですが、
(不要なうえに処理速度で不利になったり、画面がチラチラしたりする。)
デバッグ中はわざとセルを選択してみて可視化し、
ステップインでセル範囲が意図通りに取得できているか確認したりするといいと思います。

あと、ウォッチウィンドウで、
ウォッチ式を
rngtarget.Address(0, 0)
などとして、変数に今どのセル範囲が確認する方法もあります。

 > If rngTaraget.Row < 28 Then Set rngTaraget = .Range("D28")
 > '↓
 > If rngTaraget.Row < 28 Then Set rngTaraget = .Range("D28:E28")
ですね。
しつれいしました。

(まっつわん) 2018/06/12(火) 08:10


みなさん おはようございます。^^
すみません。私のテスト環境では
> If rngTaraget.Row < 28 Then Set rngTaraget = .Range("D28") は通っていません。
なので
表示されたのでしょう。理由に関わらず。皆さんを惑わすような書込みになりましたこと。
をお詫びいたします。私の記事は全て没、と言う事で。。。
(ちちんぷりぷり)さん
(まっつわん)  さん
(もこな2) さん
済みませんでした。 m(__)m

(隠居じーさん) 2018/06/12(火) 08:56


隠居じーさん様

testしてくださってありがとうございます。
test環境下によっては問題なく表示されるんですね。
自分の環境をうまく伝えられていなくて申し訳ありませんでした。

もこな2様
教えて頂いたコードで問題なく転記が出来ました。
Rangeで指定したセルがD28のみになっていたから、ということなのでしょうか。
D28を先頭に貼り付け、という意味にとらえていたので気付きませんでした。
ありがとうございます。

まっつわん様
F8で1行ずつ見たりはしていたのですが
なんで表示されないんだろう…というところで止まっていました。
ウォッチウィンドウ、というものもあるのですね。
また勉強させて頂きます。

皆様にお聞きして、少しずつ自分の中でも理解が出来てきていると実感しています。
まだまだお世話になるかと思いますが、頑張りますので宜しくお願い致します。

(ちちんぷりぷり) 2018/06/12(火) 09:20


コメント返信:

[ 一覧(最新更新順) ]


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