• ベストアンサー

空白を埋めるマクロについて

マクロで教えて下さい! A B C D    ...... 数量 名前 種類 購入者  .... 1  2  あ  A 2    く 3 5 DD 4          まま 5    さ 6          ぱぱ と右は何十項目・下は何千行と項目が続くデータがあります。 この空白に上の文字をコピーし埋めて行くマクロを作成するにはどうしたら良いでしょうか? ただし以下の条件があります。 (1)D列の様に1行目が空白のセルは4行目の様に文字が入っている所までは空白のまま (2)A列はそのファイルにより何行目までデータが入っているかは不明 A B C D     数量 名前 種類 購入者   1  2  あ  A       2  2  く A 3 5 く DD 4  5  く DD   まま 5  5  さ DD まま 6  5  さ DD   ぱぱ 宜しくお願い致します。

  • akcot
  • お礼率72% (48/66)

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

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.8

こんばんは。Wendy02です。 KenKen_SPさんへ >今までエラー値が原因となる失敗はなかったのですが、どんなときに失敗するのでしょう? これは、ワークシートの場合は、配列変数は、Variant 型ですから、ワークシート上のエラー値でも入りますが、それ以外に、ワークシート上では、別のエラーを持っていることがあります。例えば、バイナリエディタで、その中をみると、まったくExcelとは関係のないデータが入り込んでいたりします。セルのオブジェクトから、Value プロパティに流し込めようとすると、異質なものとしてエラーが発生するのではないでしょうか?はっきりと断言できるわけではありませんが、Copy メソッドは、そういうものに直接触れずにできます。 >Excelの場合は、物理メモリは関係ありません この件は、たぶん、疑問になっているのかと思います。これは、私は、ずっと数年同じ考えでいます。実際にマイクロソフトなどのデータで、はっきりしたものではありません。 ExcelのVBAの場合は、バージョンごとに、その上限は違うようですが、Excelの割り当てられた仮想メモリが直接に影響を与えているのだと思っています。もちろん、コンパネからシステム-> [仮想メモリ]を大きくすれば、Excelの使用メモリは広がります。 >配列数式を多用したり、VBA で大きな配列を使う場合などは物理メモリを消費するし、 それは、Excel全体での上限があって、そこから、配列に使用するメモリなどの割り振りがあるのだと思います。 配列変数のメモリの理論値は、途方もない大きさですが、私の計算では、数メガ程度しかないと思っています。(Excelの配列変数の仕様は、60次元ですが、その数値は、現実的ではありません。) Excel 97 では配列の要素の最大数は 6,553 まででした。Excel 2000 以上は、名目的にはなくなりました。しかし、配列を利用したものは、Win98で、現実には、 SUM関数で、5,400個程度です。 仮に、5,500 個として、 1セルが、25 (標準 22 BYTE ) *5,500 =137,500 137,500 ÷1,024÷1,024 =0.13 M byte あくまでも、Variant型でと考えた場合ですが、これで上限ということは、どう考えてもあり得ません。 これは、VBAでも、セルの配列を利用したものは、同じような制限があると考えています。(Excel 2002 では、通常の範囲ではエラーはないはずですが。) また、別に、ファイルの大きさも、ブック全体の大きさよりも、ワークシートのセル自体の使い方などに依存することが多いです。セルには、複合的な要素があります。書式、数式、文字列など、それぞれに、メモリの割り振りがあり、それぞれに制限があるので、物理的メモリ自体を増やしても、よほどのことがない限りは、ほとんど影響を受けていないのではないか、と考えています。 ※ メモリとして使用しているもの ・値を入れたセル + 文字列 ・書式設定の種類 ・関数の参照範囲の種類(R1C1方式で見ると良く分ります) ・オブジェクト類(ブックを含む) ・フォントの種類 ・1シートの計算過程で一時に使用するメモリ ・VBAのモジュールを格納する各々のプロシージャ ・アドイン、プリンタドライバ ・Excelで使われるユーティリティ このようなものの中に割り振りされ細分化して、メモリの上限枠が存在しているのではないでしょうか?1つの例としては、書式の種類(組み合せ)の上限数が決められていますね。これは、あくまでも、私の推論ですが、そうしないと、説明がつかないことが出てくるように思いますが、いかがでしょうか? 何か、確証のない話で納得は出来ないでしょうけれども。

その他の回答 (7)

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.7

解決されたみたいで、よかったですね。あとは参考になってしまいますが、この機に Wendy02 さんに教えてほしいことがあります。 >配列でエラーになるのは、エラー値が混入していることがありますね。 データ内にエラー値と数式がある可能性は考慮してました。その場合でも次のようなコードで、今までエラー値が原因となる失敗はなかったのですが、どんなときに失敗するのでしょう? Dim BUF as Variant BUF = rngTARGET.Value rngTARGET.Value = BUF んーー。。なら BUF = rngTARGET.Value の部分を BUF = rngTARGET.Text にしてみるとどうでしょうか? これでもエラーになる可能性はありますか? 自分でテストする限りでは、Value も Text もエラーにならず、情報を得ることができません。教えて下さい。 >Excelの場合は、物理メモリは関係ありません ワークシートを増やしたり、配列数式を多用したり、VBA で大きな配列を使う場合などは物理メモリを消費するし、メモリが不足するとスワップが発生しそうな気がしますが、この場合も関係ないのでしょうか? 物理メモリが関係ない、、というのはどのような意味するところを教えて下さい。 今回はメモリではなく、CPU の処理速度かな?と考えてましたが、ご質問主様の PC スペックを見る限り、原因は別のところにありそうですね。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

こんにちは。 Wendy02です。 >データ量により、マクロが変わるんですか?知りませんでした。。 本来は、バージョンに依存しているのですが、一応、Excelのワークシートから取り出した配列変数は、正確に言うと多段階配列といいますが、これは、5,000個程度に留めておいたほうが、無難のようです。(これは、私個人のルールで、全ての人に当てはまるとはいいません) 純粋な1次元の配列変数は、もともと、データ型を決められるので、そのような制限は存在していませんし、もっと処理スピードも速いはずです。ところが、全部配列で処理すると、コードがややこしくなってしまうということがあります。 それと半分ジョークですが、 #  まま #  ぱぱ でしたので、そんなに多い量だと思いませんでした。(^^ゞ 私は、データ量によって、だいたい、3種類にコードを分けています。「最適化」といいますが、ほんのちょっとしたことで、処理スピードが速くなることもあります。

akcot
質問者

お礼

出来ましたぁ!!!頂いたコードをD列以降も処理出来る様に書き換え、無事完成致しました。本当に本当に本当にありがとうございました!!!!!もう、直接お会いしてお礼を言いたい位感謝の気持ちでいっぱいです!嬉涙 私は超ど初心者で書店の本を片手にマクロを勉強した為、参考書に載っていないコードはサッパリで全く応用が利きません。Wendy02さんの様に臨機応変にマクロを考えられる方達がとっても不思議なんですが、普通にキーボードを打って書いてるのですか?それとも何かソフトとか本とか簡単にマクロが組める優れツールとか持ってらっしゃるんですか?何か特別な勉強をされたのか、とかとっても疑問に思っちゃいます(笑)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.5

こんにちは。 Wendy02です。 >メモリの調べ方が分からないのですが、恐らく512はあったと思います。 Excelの場合は、物理メモリは関係ありませんが、 >2000行弱、60列弱に空白以外は文字がびっしり書かれています。 これを知っていたら、そのようには作りませんでしたが、各列で範囲を取っているので、2000行で、メモリ枠でエラーが出る可能性は低いです。私の知っている限りですと、配列でエラーになるのは、エラー値が混入していることがありますね。たぶん、Copy ですと、エラー値もコピーできるような気がします。 一応、第2段のコードも用意はしていますが、一度、以下を試してみてください。 '---------------------------------------------------------- Sub BlankCellsEntering2()   Dim r As Range   Dim rb As Range   Dim cl As Range   Dim a As Variant   Dim MaxRow As Long   Dim c As Range   Application.ScreenUpdating = False     '最初の基点場所   '範囲の取得   For Each c In Range("A1:D1")    If Cells(65536, c.Column).End(xlUp).Row > MaxRow Then      MaxRow = Cells(65536, c.Column).End(xlUp).Row    End If   Next   Set r = Range("A1").Resize(MaxRow, 4)     Application.ScreenUpdating = False   '縦切りで取る   For Each cl In r.Columns        On Error Resume Next    Set rb = cl.SpecialCells(xlCellTypeBlanks)    On Error GoTo 0    If Not rb Is Nothing Then      For Each a In rb.Areas 'Areas で取る       With a         If .Row > r.Cells(2, 1).Row Then          .Cells(1, 1).Offset(-1).Copy .Cells         End If       End With      Next a    End If   Next cl   Application.ScreenUpdating = True   Set rb = Nothing:  Set r = Nothing End Sub

akcot
質問者

お礼

早速のお返事ありがとうございます!お忙しい中私なんかの為に本当にありがとうございます。涙 データ量により、マクロが変わるんですか?知りませんでした。。言葉足らずで申し訳ございません。 頂いたもので試した所、凄いスピードでA~D列まで空白が埋まりました! 今まで出ていたエラーのマクロで、行数を大幅に減らして試したところ、そのデータファイルにもよるんですが、大体200~500行までですと正常に軌道してくれました。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.4

こんにちは。KenKen_SP です。 面白そうなので、参加させて下さい。 Wendy02 さんのロジックは非常に面白いですね。SpecialCells と 数式の活用は発想できませんでした。試してみましたが、6000行ぐらいのテストデータでうまくいきましたよ。 テスト環境: WindowsXP P4(2.4GHz)512M Excel2002 ご質問主様の環境ではエラーがでるみたいですが、データ量が多すぎたり、PC のスペックが低いのかもしれません。どうも数式の書き込みと、その参照結果を反映させるのに時間がかかり、その処理が間に合わないのかも。。 別回答として、配列を使った例を考えてみました。お試し下さい。 行数・列数ともに特にExcelで扱える範囲内であれば制限はありません。 Sub SampleMacro()   Dim SH    As Worksheet   Dim rngTARGET As Range   Dim BUF    As Variant   Dim r As Long   Dim c As Long   '2行目以下の使用済セル範囲の値を配列化   Set SH = ActiveSheet   Set rngTARGET = Intersect(SH.UsedRange, SH.Range("A2:IV65536"))   BUF = rngTARGET.Value   'ブランクを埋める   For r = 2 To UBound(BUF) '※一行目は無視なので2から     For c = 1 To UBound(BUF, 2)       If IsEmpty(BUF(r, c)) Then         BUF(r, c) = BUF(r - 1, c)       End If     Next c   Next r   'データ書き出し   rngTARGET.Value = BUF   '後始末   Erase BUF   Set rngTARGET = Nothing   Set SH = Nothing End Sub

akcot
質問者

お礼

ご回答ありがとうございます。 PC環境:WindowsXP P4(3.40GHz) Excel2003 メモリの調べ方が分からないのですが、恐らく512はあったと思います。 データ量は多いかもしれません。2000行弱、60列弱に空白以外は文字がびっしり書かれています。 教えて頂いたものをコピーし試させて頂いたのですが、やはり「rngTARGET.Value = BUF」の部分で同じ様なエラーが出てしまいます。。涙 これもデータ量が多いせいなのでしょうか??

  • myeyesonly
  • ベストアンサー率36% (3818/10368)
回答No.3

いやはやお恥ずかしい。 No2 さんのおっしゃるとおりですね。こういう場合、力づくでやるのはあまりよくないようです。 今、エクセルを引っ張り出してやってみたら、ますを埋めるのはうまくできたようですが、見事に無限ループになっちゃいました。(爆) 書き加えたのは一行だけですが、修正版を書いておきます。 sub 修正版() '開始位置はA2だけどループの都合上A1から開始。 Range("a1").Select '終了検出用変数 n$ を空っぽじゃなくしておく '始めの一個目で終わりに飛ばない為。 n$ = "はじめ" While n$ > "" Application.StatusBar = n$ 'y はこれから作業する行 '注意!選択されてるセルは一つ上 y = ActiveCell.Row + 1 If Cells(y, 1) = "" Then '空白なので前のデータが入る Cells(y, 1) = y1 Else '空白じゃないので保持用変数y1 を新しくする y1 = Cells(y, 1) End If If Cells(y, 2) = "" Then '空白なので前のデータが入る Cells(y, 2) = y2 Else '空白じゃないので保持用変数y2 を新しくする y2 = Cells(y, 2) End If If Cells(y, 3) = "" Then '空白なので前のデータが入る Cells(y, 3) = y3 Else '空白じゃないので保持用変数y3 を新しくする y3 = Cells(y, 3) End If If Cells(y, 4) = "" Then '空白なので前のデータが入る Cells(y, 4) = y4 Else '空白じゃないので保持用変数y4 を新しくする y4 = Cells(y, 4) End If 'この行の作業が終わったので、現在の選択されてる行(セル)を一つ下げる Cells(y, 1).Select y = y + 1 '←これが抜けてました。 'n$ はループ終了検出用 n$ = Cells(y, 1) & Cells(y, 2) & Cells(y, 3) & Cells(y, 4) Wend end sub

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんばんは。 このご質問は、そのままExcelのある仕様そのものに任せてしまえば簡単で、ヘンにロジックで考えないほうが簡単ですね。 つまり、範囲を縦の列に切り分けて、それで、SpecialCellsのブランクを取って、そのブランクのところに数式で埋めてしまえば、そのブランクは一回で済みます。ひじょうに単純です。(ただし、別な要件が加わっていたら分りません(^^;) (範囲を縦の列に切り分け.....そのままブランクを取り出すと、縦と横がなくなってしまうから、切り分けないとできない。) Sub BlankCellsEntering() 'No.1964591 の変形版   Dim r As Range   Dim rb As Range   Dim cl As Range   Dim a As Range     Application.ScreenUpdating = False     '最初の基点場所   Set r = Range("A1").CurrentRegion     Application.ScreenUpdating = False   '縦切りで取る   For Each cl In r.Columns      On Error Resume Next    Set rb = cl.SpecialCells(xlCellTypeBlanks)    On Error GoTo 0    If Not rb Is Nothing Then     For Each a In rb.Areas 'Areas で取る       If a.Row > r.Cells(2, 1).Row Then '2行目を避ける         a.FormulaLocal = "=R[-1]C"      End If       a.Value = a.Value     Next a     End If   Next cl  Application.ScreenUpdating = True  Set rb = Nothing:  Set r = Nothing End Sub

akcot
質問者

お礼

ご回答本当にありがとうございます。私には中身がサッパリなので教えて頂いたものをそのまま貼り付けてやってみました。30行程度ですとバッチリうまく行ったのですが、2000行位で試した所30秒ほど砂時計マークが出たと思ったら、「a.Value = a.Value」の所で「実行時エラー1004、アプリケーション定義またはオブジェクト定義のエラーです。」と出てしまいます。何故だかおわかりになりますか? 申し訳ございません、宜しくお願い致します。。涙

  • myeyesonly
  • ベストアンサー率36% (3818/10368)
回答No.1

こんにちは。 横方向に全項目空欄というレコードはないという前提でいいでしょうか? いちおう、こんなの考えてみました。 データはバックアップしてからやってくださいね。(笑) あと、解答欄のサイズの関係で、変な所に改行が入っちゃう場合がるので注意してください。 sub うまくいく保証はありません() '開始位置はA2だけどループの都合上A1から開始。 range("a1").select '終了検出用変数 n$ を空っぽじゃなくしておく '始めの一個目で終わりに飛ばない為。 n$="はじめ" while n$<>"" 'y はこれから作業する行 '注意!選択されてるセルは一つ上 y = activecell.row + 1 if cells(y,1) = "" then '空白なので前のデータが入る cells(y,1) = y1 else '空白じゃないので保持用変数y1 を新しくする y1 = cells(y,1) end if if cells(y,2)="" then '空白なので前のデータが入る cells(y,2) = y2 else '空白じゃないので保持用変数y2 を新しくする y2 = cells(y,2) end if if cells(y,3) = "" then '空白なので前のデータが入る cells(y,3) = y3 else '空白じゃないので保持用変数y3 を新しくする y3 = cells(y,3) end if if cells(y,4) = "" then '空白なので前のデータが入る cells(y,4) = y4 else '空白じゃないので保持用変数y4 を新しくする y4 = cells(y,4) end if 'この行の作業が終わったので、現在の選択されてる行(セル)を一つ下げる cells(y,1).select 'n$ はループ終了検出用 n$=cells(y,1) & cells(y,2) & cells(y,3) & cells(y,4) wend end sub

akcot
質問者

お礼

投稿時は表がうまく見えてたのですが、こう見るとズレてて分かり難いですね。。こんなわかりにくい質問にお返事下さいまして、本当にありがとうございます。 調べましたら、項目によっては1列まるまる空白のものもありました。 そして修正版を貼り付けて試させて頂いたのですが、A列の一番最初の空白しかコピーされず、残りは全て空白のままでした。。私のやり方が悪いのでしょうか??申し訳ございませんが、もう少しご教授願えますでしょうか? 宜しくお願い致します。

関連するQ&A

  • エクセルマクロ、空白行(セル)の挿入

    データがA、B、C、D、E列100行まであります。 このうちD、E列を除き、エクセルのマクロで1行ごとに空白で10行挿入したいです。 (A、B、C、D列のデータに空白セルを10行分挿入し、下にシフトするイメージ。D、E列はそのまま。) ご教授頂きたく、お願いします。

  • エクセルのマクロ(指定列の空白にひとつ上の文字を入力し続ける)

    エクセルのマクロを教えてください。 指定列の空白にひとつ上の文字を入力し続けるマクロです。 A列指定 A2からスタートし、1000行くらいあるデータ 空白があった場合ひとつ上の文字を入力 空白は、2行連続・3行連続となることもあるが大抵は1行空白 この場合、空白セルの上で一番近いデータをコピーする A列のデータは、文字・数字・日付と様々 1000行ある場合もあるが、それ以下の場合もあるので、10行空白が続いたらマクロが自動的に終了 エクセル2003使用 よろしくお願いいたします。

  • 【マクロ】クリックすると空白を含む列を非表示に

    上司にExcelのデータが見づらいと言われて困っています。 下記のようなマクロやVBAを教えていただけないでしょうか? 例えば、 A2のセルをクリックすると、その行(2行目)から空白セルを検索して、そのセルを含む列を非表示にして、データが入っている列だけを表するようなマクロってないでしょうか? (要は、C2とE2が空白セルのとき、A2をクリックして、A/B/D/F~の列だけ表示されるようになるマクロです。 同様に3行目でも、空白セルがB3、C3なら、A3をクリックした時、A/D/E…列だけ表示されて、B・C列が非常時になるような。) 似たような機能があれば、A2クリックでなく別にボタン等を作っても構いません。 ややこしくて、申し訳ございませんが、本当に困っているので、 どうかよろしくお願いいたします。

  • エクセル2003のVBAを教えて

    エクセル2003のVBAを教えてください。 次の対象データで、(1)(2)(3)の作業が出来るエクセルVBAを教えて下さい。 (1)(2)(3)個々のVBAでお願いします。 ●対象データ:種類(A列)、文字(B列)、    データの行数:不特定なので、データのある最終行までとします。 ●教えていただきたい項目  (1):種類だけを(C列)に取り出す。  (2):種類の先頭に空白の行を3行入れて、追加の2行目の種類(A列)に文字(B列)を入れる。  (3):種類が5行以上あるときは、5行ごとに空白行を追加する。 ●対象データ 種類(A列)   文字(B列) AA       あああ BB       いいい BB       いい BB       いいい CC       うう CC       うう DD       ええええ DD       ええええ DD       ええええ DD       ええええ DD       ええええ DD       ええええ DD       ええええ ●(1)のVBAの結果(このようになるVBAを教えてください。) (C列) AA BB CC DD ●(2)、(3)のVBAの結果(このようになるVBAを教えてください。) 種類(A列)    文字(B列) あああ AA        あああ いいい BB        いいい BB        いいい BB        いいい うう CC        うう CC        うう ええええ DD        ええええ DD        ええええ DD        ええええ DD        ええええ DD        ええええ DD        ええええ DD        ええええ

  • COUNTBLANKのような役割を持つマクロ

    COUNTBLANKとはちょっと違うのですが、 行 ↓ A B C D ←列 1  AB AC AD AA 2 BB 3 C CC 4 DD 上記のようなデータがあります。 2,4行目みたいにA列とB列とC列が空白だったら、E2、E4セルに ○っていのを表示させるようなマクロってできないでしょうか。 また、Dのセルに値がある限り、その行数分上記の処理を繰り返す 方法があったら教えてください

  • マクロにて空白のセルを一括して消去でなく削除したい

    空白のセルを一括して、空白セルについた色も含めてマクロで全て削除したい。 現在のデータ(仕様)について 1.Sheet2に列ごとにセルに色をつけ、データもあるとします。 2.A列10行・B列6行・C;列18行というように、列によってデータの入った範囲が違います。 3.どの行も途中に空白セルはなく、詰めたデータです。 以上です マクロで一括処理したいと思いますが、このようなことができるコードを教えて頂けませんか。よろしくお願いします。

  • 削除して空白になった行を下から詰めたい

    A行には項目の名前があり、A列には番号が上から1,2,3・・と振られています。 そして、B2からR999までにはそれぞれデータが入っています。 このとき、任意のR列のセルを選択したまま、マクロを実行すれば、 任意の行のB列からR行が削除されて、下から上に詰めるように(空白にならないように) するマクロを作りたいです。(A行に割り振っている番号を消してしまうと 連番が崩れるので、B列からR列までを詰めていくような感じです) 例: 今、R11のセルを選択しています。希望のマクロを実行すると、C11~R11が削除されて    C12以降のデータが丁度上に移行するような感じです。 どのようなコードを作れば良いのか、お力をかしていただければ幸いです(/_;)

  • エクセルのマクロでデータを左につめていく

    お世話になります。エクセル2002でマクロを作成しようと思っています。 毎回同じ処理をしているので、良いサンプルがあったら教えてください。 やりたいこと  A列からF列にランダムにデータが入力されています。  このデータをA列、B列、C列と、左に詰め表示させたいです。  ※G列以降にもデータが入力されていますが、処理したい列範囲はA列~F列です。  ※行数は、都度変わります。(UsedRange.Rows.Countで値を取得) イメージ(処理前)  -  : 空白セル  *** : データが入力されているセル     A列   B列  C列  D列  E列   F列 1行目 項目1 項目2 項目3 項目4 項目5 項目6 2行目 ***  ***  -   ***  *** - 3行目 - -   -  *** *** *** 4行目 ***  -   -   -   -   -  5行目 *** *** -   *** -   -  イメージ(処理後)     A列  B列  C列   D列  E列  F列 1行目 項目1 項目2 項目3 項目4 項目5 項目6 2行目 ***  ***  -   ***  *** - 3行目 *** *** *** - -   - 4行目 ***  -   -   -   -   -  5行目 *** *** *** -   -  -

  • エクセルマクロ、集計行の上に空白行挿入

    エクセルデータがA、B、C、D、E列1000行まであります。 C列基準でE列を合計するマクロを作成しましたが(集計行はデータの下に挿入)、実行の結果、新たに挿入される集計行の上に空白行を1行挿入していくということを、作成したマクロに付加できるでしょうか? ご教授頂きたく、お願いします。

  • 複数列の重複と空白を削除するマクロ(VBA)

    マクロの初心者です。 添付写真のように、複数列の重複セルと空白セルの両方を削除し、各列のデータを10列目から並べたいのですが、この場合、どのようなマクロを書けばよいでしょうか。 データの個数: 列によりますが、最大1000行程度 列数: A~J(空白列はありません)

専門家に質問してみよう