• ベストアンサー

エクセル VBA データ並び替えと行削除

エクセル2003にて VBA初心者です。 以下のようなデータがあります。  列A    列B     列C  識別   部品番号  ユニット         A10000   *100         A10001   *101         A10002   *102  *     A10002   *103         A10003   *104  *     A10003   *105  *     A10003   *106  ・        ・      ・  ・        ・      ・  ・        ・      ・ 列Bには部品番号が、列Cにはユニット名が記入されています。 同じ部品番号でもユニットが異なる場合には、列Aに*が記入されています。 このようなデータが20,000行ほどあります。 上記のようなデータを以下のように並べ替えたいと考えております。  列A    列B      列C     列D     列E  識別   部品番号   ユニット   ユニット  ユニット        A10000    *100        A10001    *101        A10002    *102     *103        A10003    *104     *105     *106 VBAを利用すればできるんだろうなーと思っていますが、 見当もつきません。 どうぞよろしくお願いいたします。

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

  • ベストアンサー
  • xls88
  • ベストアンサー率56% (669/1189)
回答No.1

サンプルです。 Sub Macro()   Dim rng As Range   Dim i As Long   Dim j As Long      Set rng = Range("A3", "A" & Range("B" & Rows.Count).End(xlUp).Row)   Set rng = rng.SpecialCells(xlCellTypeConstants, 2)   For i = 1 To rng.Areas.Count     For j = 1 To rng.Areas(i).Count       With rng.Areas(i).Item(j)         .Offset(-j, j + 2).Value = .Offset(, 2).Value       End With     Next j   Next i   rng.EntireRow.Delete End Sub >VBAを利用すればできるんだろうなーと思っていますが、 >見当もつきません。 手作業ではどうしますか? 手作業を「マクロの記録」すれば参考コードが得られます。

nankoro_x
質問者

お礼

さっそくのご回答ありがとうございます。 このサンプルを実行すると、 C列のデータが一行目のD列から最終列(IV列)まで転写され エラーメッセージが出てしまいます。 私のやり方がどこかまずいのでしょうか? それともサンプルはあくまでもサンプルであり、 このサンプルをベースにIF文等を加えないと問題は解決できない ということなのでしょうか? 重ね重ねの質問で申し訳ありませんがよろしくお願い致します。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (7)

  • xls88
  • ベストアンサー率56% (669/1189)
回答No.8

Wendy02さん >rng.Columns(1).Value = rng.Columns(1).Value 「参考になった」ボタンをClickしました。 ありがとうございました。 ""以外に、スペース、Alt+Enter、CHAR(10)等にも対応できないか考えてみました。 nankoro_xさんの補足によれば「*」セル以外は「空白」セルという認識で問題ないようです。 「セル選択」で「選択オプション」にある「アクティブ列との相違」を利用し Dim frng As Range Set rng = Range("A4", "A" & Range("B" & Rows.Count).End(xlUp).Row) With rng   Set frng = .Find(what:="*", After:=.Cells(.Count), LookIn:=xlValues) End With rng.ColumnDifferences(frng).ClearContents Set rng = rng.SpecialCells(xlCellTypeConstants, 2) と、こんな風にしてみましたが、どうでしょうか。

全文を見る
すると、全ての回答が全文表示されます。
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.7

xls88さん nankoro_xさん こんばんは。 xls88さん、私の書いたものを読んでいただきありがとうございました。 #1のコードを試して、私が試した方法は、一旦、数式を作っておいて、それを値貼り付けしてみました。目では、"" は消えているのですが、SpecialCells を試してみると、Area が、ひとつにまとまってしまいました。 そこで、私の一案ですが、 Set rng = Range("A3", "A" & Range("B" & Rows.Count).End(xlUp).Row)  rng.Columns(1).Value = rng.Columns(1).Value '←このコードを入れてみました。 Set rng = rng.SpecialCells(xlCellTypeConstants, 2) 私の作ったサンプルの場合は、成功しました。 ご質問者さんに対しては、必ず上手くいくとは保証できないのですが、「"" 」残っている場合は、.Value = .Value で消せるのです。

nankoro_x
質問者

お礼

ご指摘ありがとうございます。 無事に問題を解決することができました。

全文を見る
すると、全ての回答が全文表示されます。
  • xls88
  • ベストアンサー率56% (669/1189)
回答No.6

>先ほどのプログラムの意味を調べる所から始めてみます。 是非そうしてください。 その姿勢があれば、必ずVBAの使い手として上達されると思います。 解らないところがあれば、遠慮なく補足してください、解る範囲でお答えしたいと思います。 私が提示したコードは、A列で、文字(「*」に限らない)が入力されているセルを抽出し、その後の処理の基準にしています。 問題は、Wendy02さんが指摘されているように、空白セルは、実は空白ではなく空白に見えているセルだということだと思います。 1行目ではなく、2行目に転記されるということは、A2セルのみ真正の空白セルだと思います。 先のコードに、★のところを追加してみてください。 Set rng = rng.SpecialCells(xlCellTypeConstants, 2) MsgBox rng.Address '★ 実行すると、メッセージボックスにセル範囲アドレスが表示されます。 空白に見えるセルが、表示されたセル範囲に含まれていると思います。 対応策が、他の方々から提案されています。参考にしてください。 他には、検索で、*セルを抽出する手もあるとおもいます。 ご存知かもしれませんが VBEのコードウィンドウで、調べたい単語の中に文字カーソルを置いた状態で、F1キーを押してください。 目的の単語のページにジャンプして、ヘルプが表示されます。 デバッグについて http://members.jcom.home.ne.jp/rex-uchida/vba110.htm ブレークポイント http://www.vba-world.com/breakpoint.html

nankoro_x
質問者

お礼

いろいろとご教授頂きありがとうございます。 無事に解決することができました。 本当にありがとうございます。 A列ですが、 =IF(COUNTIF($B$2:B2,B2>1),"*","") という関数で二個目以降の同一部品番号に*をつけた後、 値コピーしたものです。 値コピーすれば空白か*のみになると考えておりました。 私の前提条件の提示が足りませんでした。 申し訳ございませんでした。 xls88様のコードに、Wendy02様の提示された1行を追加したところ うまくいきました。 本当にありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.5

>このサンプルをベースにIF文等を加えないと問題は解決できない ということなのでしょうか? そうですね。そう思います。 質問文にあるとおりのデータを手で入力して、#01さんのマクロを実行すればちゃんと動きます。試されましたか? それが動かないとすれば「実際のデータには質問文に書かれていない『何か』があるから」ではないでしょうか。 例えば「部品番号が昇順になっていなくて同じ番号が繰り返し出現する」、「一つの部品番号が256以上のユニットで利用されている」、「A列の*は関数で表示している」などです。 実際のデータが分からないのでB列、C列のデータだけで処理するようにしてみました。A列のデータに意味があるならご自身で書き換えてください Sub Macro1() Dim ws As Worksheet Dim idx, ptr As Long Dim trg As Range   Set ws = ActiveSheet   On Error GoTo end0   Application.ScreenUpdating = False   Worksheets.Add after:=ws   With ws     .Rows(1).Copy Destination:=Rows(1)     For idx = 2 To .Range("B65536").End(xlUp).Row       If .Cells(idx, "B").Value <> "" Then         Set trg = ActiveSheet.Columns(2).Find(what:=.Cells(idx, "B").Value, _               LookIn:=xlValues, Lookat:=xlWhole)         If trg Is Nothing Then           Range("B65536").End(xlUp).Offset(1, 0).Value = .Cells(idx, "B").Value           ptr = Range("B65536").End(xlUp).Row         Else           ptr = trg.Row         End If         If Application.CountIf(Rows(ptr), .Cells(idx, "C").Value) = 0 Then           If Cells(ptr, "IV").Value = "" Then             Cells(ptr, "IV").End(xlToLeft).Offset(0, 1).Value = _               .Cells(idx, "C").Value           Else             MsgBox "列数が256を超えるので処理できません"             Exit For           End If         End If         Set trg = Nothing       End If     Next idx   End With end0:   Application.ScreenUpdating = True End Sub

nankoro_x
質問者

お礼

無事に問題を解決することができました。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

こんにちは。 まず、#1さんのコードは、問題ないはずなのですが、その「識別」が付けられた過程を考えたときに、数式でできていたのではないでしょうか。仮に、文字として、定数になっていても、空白部分が完全に空白になっていないのではないか、と思います。値貼り付けでは、どうやら痕跡が残るようですから、SpecialCells 以外のマクロによる、完全空白する処理が必要かもしれません。 そこで、私は、その質問の表を見たときに、その「識別」をまったくアテにしないことを考えました。2万行ということになると、最後まで信頼置けないような気がしました。そこで、「識別」を頼りにせず、独自に、配列で確保しながら、配列を使って、表を作ることにしました。データが、20,000件ですから、まあ、そこそこに動くレベルだと思います。それ以上のスピードを稼ぐものは、あまり思い当たらないです。 以下は、シート2に書き出すようにはなっていますが、その設定は、任意にしてください。 Sub ArrangeLines()   '部品番号はソートされていることが条件   Dim sh1 As Worksheet   Dim sh2 As Worksheet   Dim rng As Range   Dim i As Long, j As Long, k As Long   Dim mx As Integer   Dim v As Variant   Dim ar As Variant   Dim ar2 As Variant   Dim art()   Dim arb() As String   Dim buf As String   Dim flg As Boolean   '-------------------------------------------   Set sh1 = Worksheets("Sheet1") 'オリジナル・データシート   Const O As String = "A1" 'オリジナルデータの左上端      Set sh2 = Worksheets("Sheet2") 'データの書き出しシート   Const P As String = "A1" 'データの書き出し場所端   '-------------------------------------------   With sh1     Set rng = .Range(O).Range("B1", .Range("B65536").End(xlUp))   End With   sh2.Range(P).CurrentRegion.ClearContents   ar = Application.Transpose(rng.Offset(1).Value)   ar2 = Application.Transpose(rng.Offset(1, 1).Value)         For i = LBound(ar) To UBound(ar) - 1     If buf = "" Then       buf = Trim(ar(i))     End If     If ar(i) <> ar(i + 1) Then       buf = buf & "," & ar2(i)       j = j + 1       ReDim Preserve art(j)       flg = True     Else       buf = buf & "," & Trim(ar2(i))     End If     If flg Then       k = Len(buf) - Len(Replace(buf, ",", ""))       If mx < k Then         mx = k       End If       art(j) = buf       buf = ""       flg = False     End If   Next i   ReDim arb(mx, UBound(art))   j = 0   For i = LBound(art) To UBound(art)     If Not IsEmpty(art(i)) Then       For Each v In Split(art(i), ",")         arb(j, i - 1) = v         j = j + 1       Next v     End If     j = 0   Next i   With sh2     If k > 256 - Range(P).Row - 1 Then k = 256 - Range(P).Row - 1 'Ver.2003 まで     sh1.Range(O).Resize(, 3).Copy .Range(P)     .Range(P).Offset(, 2).Copy .Range(P).Offset(, 3).Resize(, k - 1)     .Range(P).Offset(1, 1).Resize(UBound(arb, 2) + 1, k + 1).Value = _     Application.Transpose(arb())   End With End Sub

nankoro_x
質問者

お礼

無事に問題を解決することができました。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.3

>見当もつきません。 表の体裁の組み換え(VBAで)は結構難しく中級以上の者の課題です。まだ早すぎる。だから丸投げになってしまうが、本質問コーナーに回答者にコードを書かせるのは規約違反です。下請け機関ではない。 ーー 本件には、ソート法が良かろう。 A1002の行を処理しているとき、次にA1000が出てきては困るからです。結果表を見れば判るとおり、 部品番号+ユニットの順に出てきてほしいのでその2列で昇順にソートする。同じ部品番号で同じユニットが複数出てくるのか質問に書いてないが、重要ポイントで、経験のなさを示している。無いとして、 Sheet2の列C、数字で言うと3からSheet1を1行読むごとにSheet2の列に順次ずらして書き出す。そのためには、書き出す列を示すポインター(変数)を持つ。Sheet1の1行読むごとに、ポインターを+1する。しかし Sheet1で部品番号が変わったら、ポインターをC列数字で3にリセットする。 そのために直前の部品番号を記憶する変数を作り、次の行を呼んだとき毎回前行と比較して、変わったか判定する。 (A)部品番号が変わった 次行をさす。そして列はC列 に書く (B)部品番号が変わらない 右隣列 に書く == ほかに ●Cells(i、j)の使い方知ってますか。 ●最終行まで上記の処理を繰り返しますが、最終行の捉え方を知ってますか。 ●現データと別の他シートへ結果表(Sheet2)書き出すを希望するなら その表現法(コード)を知ってますか。 判らないなら、人のコードを盗めば何てこと無いものだが、判らないまま使うということになる。こういう本番のずっと前に、日ごろから後日に備え、他人の書いたコードを勉強して、頭に整理して無いと出来ないのです。

nankoro_x
質問者

お礼

おっしゃる通りだと思います。 今回の教訓を糧に勉強に勤しみます。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • xls88
  • ベストアンサー率56% (669/1189)
回答No.2

提示された例題が、現状をありのままに表現されていればサンプルでも結果が得られるはずです。 もしかすると、A列に空白セルはなく、*以外のデータで埋まっているということでしょうか? もし例題が仮定だとすると、実際に合わせて編集する必要があります。 編集できないのなら、実際の情報を現状に則して提供してみてください。

nankoro_x
質問者

お礼

さっそくのご回答ありがとうございます。 実行結果ですが、先ほどは1行目のD列から・・・と 記述いたしましたが、2行目のD列からの間違いでした。 申し訳ございません。 実際のデータも例と同じく、 1行目のA列に"識別"、B列に"部品番号"、C列に"ユニット"と見出しがあり、 データは2行目から始まっています。 また、A列は空白セルか*しかありません。 先ほどご教授頂きましたプログラムの意味が理解できていないので、 どこが問題なのか全く把握できていないのが現状です。 自分で理解しようともせずに xls88様にあまりにも丸投げしていましたので、 先ほどのプログラムの意味を調べる所から始めてみます。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • エクセル VBAにて行削除をしたい…

    エクセル2003にて VBA初心者です。 A列1~100に101~200までに番号が振ってあります。 Z列に記入がない場合はその行を削除するVBAを教えてください。 例  A  B  C  D  E  F …… Z 1  101               文字有り 2  102               ブランク 3  103               ブランク 4  104               文字有り 5  105               文字有り … 99  199              文字有り 100  200              ブランク この様な場合2,3,100の行ごと削除をするという形式のものです。 また、この場合A列の番号も自動で変われば(104が102になる等)最高です。 詳しい方教えてください。よろしくお願いします。

  • エクセル 複数行にまたがっているデーターを一つの行

    以前に似たようなVBAの質問を元にさらにやりたいVBAがあるのですが、 (前の質問者のURL:http://okwave.jp/qa/q4955096.html)       A列  B列   C列   D列   E列 ~ R列 1行目  佐藤 北海道 りんご S 100 105 2行目  佐藤 北海道 ばなな M 100 105   3行目 伊藤  東京  いちご S 100 105 4行目  伊藤  東京  ばなな M 100 105 上記のようなデーターがあります。これを2行目と4行目を削除し下記のようにしたいのですが       A列  B列      C列      C列 1行目  佐藤 北海道  りんご,ばなな  S,M 2行目  伊藤  東京   いちご,ばなな  S,M A列とB列とE列~R列のデーターが同じでC列,D列,のデータが異なる場合、上記のように一行にまとめたいのです。関数やVBAで上記の処理を出来る方法がありますでしょうか。 

  • エクセルデータの並び替え

    A列とB列に文字列ばかりのデータがあります。 C列に、A列の1データに対してB列の5データが続くように並べたいのです。 A列  B列  C列 a    1   a b    2     1 c    3     2 d    4     3 e    5     4 f    6     5 g    7     b h    8     6 i    9     7 j    10     8 k    11     9 l    12     10   以下、C列には、  c 11 12 13 14 15 d 16 17 18 19 20 e 21 ・・・・と続きます。 こんなことは関数処理で可能でしょうか。 手作業でやりだしたのですが、手間がかかるので質問させていただきました。どうぞ、よろしくお願いします。

  • マクロで行の並び替え+整列させる

    (1)以下の様にセルにデータが入っているとします。 (C列のデータが1行ずれて入っています。かつD列には1種類OR2種類のデータが入ってます。) A B C D E F 1 ● ● ● ● ● 2       ☆ 3   ● 4 ○ ○ ○ ○ ○ 5   ○ 6 ● ● ● ● ● 7 ☆ (2)これを以下の通りに並び替え+整列します。 (C列のデータが1行ずれて入っています。 かつD列に2種類のデータが入っている場合、改行して整列します。) A B C D E F 1 ● ● ● ● ● ● 2 ☆ 3 ○ ○ ○ ○ ○ ○ 4 ● ● ● ● ● ● 5       ☆    こんな説明で分かるでしょうか?ご指南よろしくお願いします。 m(_ _)m

  • エクセルまたはVBAで重複行を削除

    例えば、 A B 1 1 a 2 2 b 3 3 c 4 4 d 5 4 d 6 5 e 7 6 g 8 6 g といった表があるとします。 A列をキーに、昇順にされた一覧表です。 ここで番号が重複している行、この例では4行目と5行目、7行目と8行目がそうです。 こういった重複した行を検索して、行削除したいのですがどんな方法が可能でしょうか? 最終的にはVBAでのイベントになるでしょうが、それ以前にエクセルで前準備などしておくようなことは必要でしょうか? 表自体はかなり膨大な量のデータベースです。 よろしくお願いします。

  • VBA,二つのExcelのsheetにデータ保存

    VBA初心者です。 皆様のお力をお貸し頂きたく質問させて頂きます。よろしくお願いいたします。 質問内容は、下記になります。 Excelのsheet1には、縦列A,B,C・・・とデータが入っております。 sheet1の例 A B C sheet2は、入力するsheetです。 今回はA列の3行目からとします。 問題は、sheet1の縦の列をA,B,C,Dとすればデータの更新は、出来るのですが sheet1のデータのA,B,C一つ飛んでEまた一つ飛んでGという感じでsheet1のデータを 飛ばしてsheet2に表示、更新(保存)をしたいと思います。 ですので、sheet2のA列の3行目からA,B,C,飛んでE飛んでGとsheet1からデータを 表示させ、さらにsheet2の入力値が変更されると、sheet1のデータが入っている A,B,C,E,Gに更新される仕様です。 sheet1(データが入っています) A , B , C , E , G , 値1 , 値2 , 値3   , 値4 , 値5 sheet2(入力する、入力したデータは、sheet1へ更新される) A列 3行目 、sheet1の値1(A列)が入ります。 4行目 、sheet1の値2(B列)が入ります。 5行目 、sheet1の値3(C列)が入ります。 6行目 、sheet1の値4(E列)が入ります。 7行目 、sheet1の値5(G列)が入ります。 以上です。申し訳ございませんが、ご教授よろしくお願いいたします。

  • Excel VBAにてデータのある列の指定とブック間コピーについて

    初めまして。Excel VBA初心者です。よろしくお願いします。 以下の表の状態で、たとえば、B列の2行目からデータが使用されている行(以下の例では40行目ですが、ブックの内容により行数が変化します)まで、別のブックにコピーする方法があれば教えて頂きたいです。 すみませんが、よろしくお願いいたします。 A B C D E ------------------------------- 1 あ い う え お 2 い う え お か     ・     ・ ・ 40 a b c d e

  • エクセル 複数行にまたがっているデーターを一つの行にまとめたい

          A列  B列   C列 1行目  佐藤 北海道 りんご 2行目  佐藤 北海道 ばなな   3行目 伊藤  東京  いちご 4行目  伊藤  東京  ばなな  上記のようなデーターがあります。これを2行目と4行目を削除し下記のようにしたいのですが       A列  B列      C列 1行目  佐藤 北海道  りんごばなな 2行目  伊藤  東京   いちごばなな A列とB列のデーターが同じでC列のデータが異なる場合、上記のように一行にまとめたいのです。関数やVBAで上記の処理を出来る方法がありますでしょうか。 

  • エクセルVBAで重複データの削除

    A列、B列、C列・・・とデータが入っていて、B~D列の5行目から10行目が関連の有るデータのかたまりとします。 C~D列の全てのデータが重複している場合に、最初のほうのデータ(行番号が小さいほう)を残すものとして、重複データを削除したいのです。 削除するときは、 B~Dの範囲で削除する。A列等は削除しない。 削除したらデータは上に詰める。 データはソートしない。 ということをやりたいのですが、簡単に出来ますでしょうか? 良く覚えていないのですが、ネット上で色々探してみても、必ずソートしている気がしたので、ソートしない方法が知りたいのですが。

  • Excelで、同一データ行を知るには

    Excel2000で、 A列からD列までまったく同じデータの場合、色をつけてくれる方法を教えてください。 例えば、 A20=A100 かつ B20=B100 かつ C20=C100 かつ D20=D100 の場合、同じデータとして、20行目と100行目に色をつけるようにしたいです。 次善の策として、 A列からD列だけでなく、E列以降もすべてまったく同じデータの場合でもいいです。 なお、ソートしたり、行の順番を変えるのはナシにしてください。 また、A列からD列のデータをくっつけるのも、できれば避けたいです。(それぞれの列を比較して異なる場合でも、くっつけたら同じになる場合もありうるので。)

専門家に質問してみよう