[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『指定セルへの値貼付け』(T1604)
お世話になります。
内容)
ブック(W)シート(W)の内容を以下条件例に従いブック(A)シート(A)に「値貼付け」したいです。
シート(W)は番号を“ひと塊”にして行方向に並んでいます。
番号は最大で「18」までで不定です。
条件例)
・シート(W)のA列をシート(A)のL列とAA列に値貼付け
・シート(W)のE列〜I列をシート(A)のN列〜R列に値貼付け
・シート(A)の“ひと塊”の先頭行は1,21,41,...と20行あける
ブック(W)シート(W) A B C … E 1 番号 項目1 項目2 … 項目5 2 1 ア1 ア2 … ア5 … 12 11 オ1 オ2 … オ5 13 番号 項目1 項目2 … 項目5 14 1 カ1 カ2 … カ5 … 31 18 コ1 コ2 … コ5 32 番号 項目1 項目2 … 項目5 33 1 サ1 サ2 … サ5 … … 16 ソ1 ソ2 … ソ5 ブック(A)シート(A) L M N … AA 1 番号 項目1 項目5 … 番号 2 1 ア1 ア5 … 1 … … 11 オ1 オ5 … 11 … … … 21 番号 項目1 項目5 … 番号 22 1 カ1 カ5 … 1 … 39 18 コ1 コ5 … 18
自作のマクロはシート(W)の“ひと塊”の開始行と終了行をi,j、シート(A)の開始行をkとして
Do〜Loopで“ひと塊”毎に貼付け処理をしており、目で確認できるほど処理が遅いです。
貼付けを「一括処理」するにはどうしたらいいでしょうか?
よろしくお願いします。
< 使用 Excel:Excel2010、使用 OS:Windows7 >
手抜きです。ブロックは、かならず18行以内(タイトルあわせて19行以内)としています。 とりあえず、セルに直接転記しています。遅ければ手を入れます。
★列の位置、質問文とサンプルが食い違っていますが質問文にあわせました。
16:16 使わなくなったコードをそのままにしてあったので消去。
Sub Test() Dim shW As Worksheet Dim shA As Worksheet Dim tR As Range Dim dR As Range Dim x As Long Dim a As Range
Application.ScreenUpdating = False
Set shW = Workbooks("W.xlsx").Sheets("W") Set shA = Workbooks("A.xlsx").Sheets("A") shA.UsedRange.ClearContents
With shW.Range("A1", shW.Range("A" & Rows.Count).End(xlUp)) .Replace What:="番号", LookAt:=xlWhole, Replacement:=Empty Set tR = .SpecialCells(xlCellTypeBlanks) Set dR = .SpecialCells(xlCellTypeConstants) tR.Value = "番号" End With
x = 1
For Each a In dR.Areas a.Columns(1).Offset(-1).Resize(a.Rows.Count + 1).Copy shA.Cells(x, "L") a.Offset(-1, 1).Resize(a.Rows.Count + 1, 5).Copy shA.Cells(x, "N") x = x + 20 Next
shA.Columns("L").Copy shA.Range("AA1") Application.Goto shA.Range("A1")
End Sub
(β) 2016/04/18(月) 15:22
ReplaceやtR,dRなど、未だコードの理解には至っていません。
取り急ぎお礼とさせていただきます。
これからもよろしくお願いします。
(T1604) 2016/04/18(月) 18:30
先ず確認ですが、提示いただいたコードは以下の理解でよろしいでしょうか?
・「Replace」でA列にある“番号”を“空欄?”に置換することにより、“番号”を含まないコピー対象セル(dR)を得る
・「dR」は“飛び地”の“ひと塊”となる?
・「Areas」により“ひと塊”ずつのセル範囲を得て、「For Each〜」で順にシート(A)に貼付ける
また、高速化に貢献しているのは、
・「Application.ScreenUpdating = False」で画面表示を「OFF」している
・Do-Loop ではなく、For Each-Next を使用している
・Range(Cells(i, 1), Cells(j, 1)).Copy (自作コードで使用)ではなく、「Areas」を使用している
このような理解でよろしいでしょうか?
他にもあるかと思いますが、最も高速化に寄与しているのは何でしょうか?
SpecialCells(...) や Areas の使い方も参考になりましたし、しっかりと
理解しておきたいと思います。
よろしくお願いします。
(T1604) 2016/04/20(水) 09:55
●先ず確認ですが、提示いただいたコードは以下の理解でよろしいでしょうか?
・「Replace」でA列にある“番号”を“空欄?”に置換することにより、“番号”を含まないコピー対象セル(dR)を得る
はい。A列で、"番号" となっているセル(ブロックの先頭行のセル)を取得するため、いったん空白にしています。 こうしておいて、Set tR = .SpecialCells(xlCellTypeBlanks) とすることで、tR がブロックの最初の各セルの集合体になります。 なお、同様に Set dR = .SpecialCells(xlCellTypeConstants) これで、A列の 値がある領域を取得しています。 なかみは、A2:A12,A14:A31,・・・・ となっています。
なお、SpecialCellsメソッドは、一般機能で、条件を選択してジャンプ(S) の機能です。
で、tR,dRを取得した後、tR.Value = "番号" で、tR領域に "番号" を書き戻しています。
・「dR」は“飛び地”の“ひと塊”となる?
前述の通り、とびとびのひと塊の集合体です。
・「Areas」により“ひと塊”ずつのセル範囲を得て、「For Each〜」で順にシート(A)に貼付ける
はい。実際に貼り付けている領域は a.Columns(1).Offset(-1).Resize(a.Rows.Count + 1) dR 内の 各Areaの1行上(番号行)も含めた領域です。
●また、高速化に貢献しているのは、 ・「Application.ScreenUpdating = False」で画面表示を「OFF」している ・Do-Loop ではなく、For Each-Next を使用している ・Range(Cells(i, 1), Cells(j, 1)).Copy (自作コードで使用)ではなく、「Areas」を使用している
Application.ScreenUpdating = False は、確かにそうですね。 xl2003 までは、極端にいえば、実行時間が 何もしないときに比べて半減しました。 いまは、そうでもありませんが、かなりの効果はあります。
Do/Loop と For/Netx は、そんなに変わりませんね。
なにより、貢献しているのは、セルへの書き込み回数です。 エクセル上の処理で最も重いものの1つがセルへの書き込み。 2007以降、セルの属性が大幅に増えたこともあって、かなり重い処理になります。
【書き込み回数】と表現しました。たとえば 1セルずつ100回書きこむのと 100セル一度に書きこむのとでは 極端にいえば処理負荷は 1/100 になります。(実際には 書きこみ領域が大きければそれなりに少しかかりますが) 今回のコードでは1行ずつ書きこまず、1ブロック(Area) ずつの書き込みにしています。
(β) 2016/04/20(水) 10:45
ご丁寧な説明ありがとうございます、書き込み「回数」がキモなんですね。
確かに自作コードをよく見てみると1行ずつ書き込んでいました _ _ ;
いい勉強になりました..改めてお礼申し上げます。
これからもよろしくお願いします。
(T1604) 2016/04/20(水) 13:33
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.