- ベストアンサー
エクセルでマクロを作成して別シートへ自動転記する方法
- エクセルで元データシートからアルファベット毎に自動で別シートに転記するマクロを作成する方法を教えてください。
- ファイルを開いた時に自動的に更新されるようにしたいです。
- 基準はローマ字で書かれている部品名で、それをアルファベットごとのシートに自動転記します。データは追加されていきます。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
jinjin020さんはバックアップはとられていましたか? 大変申し訳ないのですが、前回のマクロの不具合は非常に致命的で、 最悪の場合マクロを組み込んだエクセルのデータのほとんどが失われてしまったかもしれません。 原因は、再読み込み時に番号の割り振りが変わることを考慮していませんでした。 その不具合を修正し、要望どおりのソースを作りましたので、マクロを組み込む前にバックアップをとり、お試しください。 (幅変更のため、少々処理時間がかかるかもしれません) --------------------------------------------------------------- Dim LName As String Const Prefix As String = "" ' Page_A~Zの26シートが出力されます Const SearchTarget As String = "部品名" '「部品名」と書いてあるセルの真下から空白セルまでを検索対象にします。 Const CopyColumnNumber As Integer = 0 ' 0は元のページの書式でコピーします。そのほかは相対値 Const CopyRowNumber As Integer = 0 ' 0は元のページの書式でコピーします。そのほかは相対値 Dim RAsc As Integer Dim BaseCol As Integer Dim BaseRow As Integer Dim Sheet_ As Object Dim Pgn(2 To 27) As Integer ' 整理番号 kb = -1 For k = 1 To Worksheets.Count - kb If Worksheets.Count - kb < k Then Exit For If Len(Worksheets.Item(k).Name) > 1 Then If kb >= 0 Then Worksheets.Item(k).Move , Worksheets.Item(Worksheets.Count) Else Worksheets.Item(k).Move Worksheets.Item(1) End If kb = kb + 1 If kb > 0 Then k = k - 1 End If Next k Worksheets.Item(1).Select 'ワークシートが非対応なら終了 Set Sheet_ = Worksheets.Item(1).Cells If Sheet_.Find(SearchTarget) Is Nothing Then Exit Sub BaseCol = Sheet_.Cells.Find(SearchTarget).Column BaseRow = Sheet_.Cells.Find(SearchTarget).Row 'ワークシートが既に構成されていたら、初期処理を飛ばす For i_ = 1 To Worksheets.Count If Len(Worksheets.Item(i_).Name) = Len(Prefix) + 1 Then LName = Left(LCase(Worksheets.Item(i_).Name), Len(Prefix)) RAsc = Asc(Right(UCase(Worksheets.Item(i_).Name), 1)) If LName = LCase(Prefix) And RAsc >= Asc("A") And RAsc <= Asc("Z") Then Exit For End If Next i_ If i_ = Worksheets.Count + 1 Then Worksheets.Add Null, Worksheets.Item(1), 26 For i = 1 To 26 Worksheets.Item(i + 1).Name = Prefix + Chr(i + Asc("A") - 1) Next i Else '過去の情報書き込み領域をクリア For i = 1 To 26 Worksheets.Item(i + 1).Range(Cells(BaseRow + CopyRowNumber, BaseCol + CopyColumnNumber).Address, Cells(65536, 256).Address).Clear Next i End If '書式をコピー jmax = 0 Do While (Sheet_(BaseRow, BaseCol + jmax) <> "") For i = 1 To 26 Sheet_(BaseRow, BaseCol + jmax).Copy Worksheets.Item(i + 1).Cells(BaseRow + CopyRowNumber, BaseCol + jmax + CopyColumnNumber) Next i jmax = jmax + 1 Loop '各情報をセルに割り振り i = 0 Do While (Sheet_(BaseRow + i, BaseCol) <> "") LName = Sheet_.Cells(BaseRow + i, BaseCol) RAsc = Asc(Left(UCase(LName), 1)) - Asc("A") If RAsc >= 0 And RAsc <= 25 Then Pgn(RAsc + 2) = Pgn(RAsc + 2) + 1 For j = 0 To jmax - 1 Sheet_(BaseRow + i, BaseCol + j).Copy Worksheets.Item(RAsc + 2).Cells(BaseRow + Pgn(RAsc + 2) + CopyRowNumber, BaseCol + j + CopyColumnNumber) Next j End If i = i + 1 Loop i = i - 1 For k = 1 To 26 For j = 0 To jmax If Pgn(k + 1) > 0 Then Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) = Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) Sheet_(BaseRow + i, BaseCol + j).Copy Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) = Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) = "" End If Next j Next k '行幅・列幅コピー For k = 1 To Worksheets.Count For i = 1 To 256 Worksheets.Item(k).Cells(1, i).ColumnWidth = Sheet_.Cells(1, i).ColumnWidth Next i Next k
その他の回答 (4)
だめでしたか・・・ いろいろ状況を試したのですが、申し訳ありませんが自分の環境では 不具合が起きてくれず、よってどこが悪いのか分かりかねる状態です。 (仮に仕分けする前の元の名前がアルファベットや数字1文字だったとしても、エラーが起こるだけで固まるはずはないですし・・・) お使いのバージョンと自分のバージョン(私はoffice2000です)が違うことが問題かもしれませんし、そもそもシートのスタイルが全く想定外なのかもしれません。 そんなわけで中途半端で本当にすみませんふぁ、現状では頂いた不具合について対処ができませんでした。
お礼
Corutenさん色々とご対応いただき本当にありがとうございました!!感謝してます。マクロ初心者の私がここまでできただけで満足です。 今回のマクロを試してみたのが私のパソコンでバージョンはXPです。会社の端末は確かoffice2000だったと思いますので、会社で再度試してみます(^^)お忙しいのになんどもVBA書いていただいて本当にありがとうございました(__)
補足
今日会社のパソコンでもう一度試してみたら、イメージ通りのシートができ不具合も起きませんでした!!!素晴らしい出来栄えです!!! Corutenさん本当にありがとうございました(__)おかげ様で部内でも喜ばれました^^大変助かりました。
せっかくですので、改変後の全ソース載っけます。連投失礼。 Dim LName As String Const Prefix As String = "" ' Page_A~Zの26シートが出力されます Const SearchTarget As String = "部品名" '「部品名」と書いてあるセルの真下から空白セルまでを検索対象にします。 Const CopyColumnNumber As Integer = 0 ' 0は元のページの書式でコピーします。そのほかは相対値 Const CopyRowNumber As Integer = 0 ' 0は元のページの書式でコピーします。そのほかは相対値 Dim RAsc As Integer Dim BaseCol As Integer Dim BaseRow As Integer Dim Sheet_ As Object Dim Pgn(2 To 27) As Integer ' 整理番号 'ワークシートが非対応なら終了 Set Sheet_ = Worksheets.Item(1).Cells If Sheet_.Find(SearchTarget) Is Nothing Then Exit Sub BaseCol = Sheet_.Cells.Find(SearchTarget).Column BaseRow = Sheet_.Cells.Find(SearchTarget).Row 'ワークシートが既に構成されていたら、初期処理を飛ばす For i_ = 1 To Worksheets.Count If Len(Worksheets.Item(i_).Name) = Len(Prefix) + 1 Then LName = Left(LCase(Worksheets.Item(i_).Name), Len(Prefix)) RAsc = Asc(Right(UCase(Worksheets.Item(i_).Name), 1)) If LName = LCase(Prefix) And RAsc >= Asc("A") And RAsc <= Asc("Z") Then Exit For End If Next i_ If i_ = Worksheets.Count + 1 Then Worksheets.Add Null, Worksheets.Item(1), 26 For i = 1 To 26 Worksheets.Item(i + 1).Name = Prefix + Chr(i + Asc("A") - 1) Next i Else '過去の情報書き込み領域をクリア For i = 1 To 26 Worksheets.Item(i + 1).Range(Cells(BaseRow + CopyRowNumber, BaseCol + CopyColumnNumber).Address, Cells(65536, 256).Address).Clear Next i End If '書式をコピー jmax = 0 Do While (Sheet_(BaseRow, BaseCol + jmax) <> "") For i = 1 To 26 Sheet_(BaseRow, BaseCol + jmax).Copy Worksheets.Item(i + 1).Cells(BaseRow + CopyRowNumber, BaseCol + jmax + CopyColumnNumber) Next i jmax = jmax + 1 Loop '各情報をセルに割り振り i = 0 Do While (Sheet_(BaseRow + i, BaseCol) <> "") LName = Sheet_.Cells(BaseRow + i, BaseCol) RAsc = Asc(Left(UCase(LName), 1)) - Asc("A") If RAsc >= 0 And RAsc <= 25 Then Pgn(RAsc + 2) = Pgn(RAsc + 2) + 1 For j = 0 To jmax - 1 Sheet_(BaseRow + i, BaseCol + j).Copy Worksheets.Item(RAsc + 2).Cells(BaseRow + Pgn(RAsc + 2) + CopyRowNumber, BaseCol + j + CopyColumnNumber) Next j End If i = i + 1 Loop i = i - 1 For k = 1 To 26 For j = 0 To jmax If Pgn(k + 1) > 0 Then Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) = Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) Sheet_(BaseRow + i, BaseCol + j).Copy Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) = Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) = "" End If Next j Next k
補足
早速のご回答ありがとうございました。早速試してみました! 最初マクロを実行した時はちゃんとシートが出来、見出しも綺麗に元データと同じ書式になっていました。 ただデータを追加し、もう一度マクロを実行すると固まってしまいます。何か不具合がでてしまっているのでしょうか? また、大変申し訳ないのですが、もし可能であればセルの大きさも元データと同じにしたいのですが。。色々していただいて申し訳ございませんが、ヘルプどうぞお願いいたします(__)すみません。
すぐにできる内容だけお答えして、後は妥協かなと思いましたが、割と要望どおりできましたので載せますね。 1)Page_の部分はわざとそうしてしまいました。Page_の部分は自由に設定できまして、上部のConst Prefix As String = "Page_"を""にするだけでアルファベットのみのシートが作れます。 (その場合、申し訳ないですが、変更後は既に作ってしまったPage_A-Zの26枚は手動で削除してください。) また余談ですが、その下の"部品名"を変更すれば見出しのターゲットも変更できます。 2)下記の部分を差し替えてください。 Worksheets.Item(i + 1).Cells(BaseRow + CopyRowNumber, BaseCol + jmax + CopyColumnNumber) = Sheet_(BaseRow, BaseCol + jmax) から Sheet_(BaseRow, BaseCol + jmax).Copy Worksheets.Item(i + 1).Cells(BaseRow + CopyRowNumber, BaseCol + jmax + CopyColumnNumber) 3)下記の部分を差し替えてください。 Worksheets.Item(RAsc + 2).Cells(BaseRow + Pgn(RAsc + 2) + CopyRowNumber, BaseCol + j + CopyColumnNumber) = Sheet_(BaseRow + i, BaseCol + j) から、 Sheet_(BaseRow + i, BaseCol + j).Copy Worksheets.Item(RAsc + 2).Cells(BaseRow + Pgn(RAsc + 2) + CopyRowNumber, BaseCol + j + CopyColumnNumber) それから、コードの最後に i = i - 1 For k = 1 To 26 For j = 0 To jmax If Pgn(k + 1) > 0 Then Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) = Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) Sheet_(BaseRow + i, BaseCol + j).Copy Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + CopyRowNumber, BaseCol + j + CopyColumnNumber) = Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) Worksheets.Item(k + 1).Cells(BaseRow + Pgn(k + 1) + 1 + CopyRowNumber, BaseCol + j + CopyColumnNumber) = "" End If Next j Next k を付け加えてください。あまり格好の良いコードではないですし、結構穴が多いとは思いますが;^^
とりあえず即興で作ってみました。これをThisWorkbook内のWorkbook_Open()に貼り付けたらどうでしょう。 Dim LName As String Const Prefix As String = "Page_" ' Page_A~Zの26シートが出力されます Const SearchTarget As String = "部品名" '「部品名」と書いてあるセルの真下から空白セルまでを検索対象にします。 Const CopyColumnNumber As Integer = 0 ' 0は元のページの書式でコピーします。そのほかは相対値 Const CopyRowNumber As Integer = 0 ' 0は元のページの書式でコピーします。そのほかは相対値 Dim RAsc As Integer Dim BaseCol As Integer Dim BaseRow As Integer Dim Sheet_ As Object Dim Pgn(2 To 27) As Integer ' 整理番号 'ワークシートが非対応なら終了 Set Sheet_ = Worksheets.Item(1).Cells If Sheet_.Find(SearchTarget) Is Nothing Then Exit Sub BaseCol = Sheet_.Cells.Find(SearchTarget).Column BaseRow = Sheet_.Cells.Find(SearchTarget).Row 'ワークシートが既に構成されていたら、初期処理を飛ばす For i_ = 1 To Worksheets.Count If Len(Worksheets.Item(i_).Name) = Len(Prefix) + 1 Then LName = Left(LCase(Worksheets.Item(i_).Name), Len(Prefix)) RAsc = Asc(Right(UCase(Worksheets.Item(i_).Name), 1)) If LName = LCase(Prefix) And RAsc >= Asc("A") And RAsc <= Asc("Z") Then Exit For End If Next i_ If i_ = Worksheets.Count + 1 Then Worksheets.Add Null, Worksheets.Item(1), 26 For i = 1 To 26 Worksheets.Item(i + 1).Name = Prefix + Chr(i + Asc("A") - 1) Next i Else '過去の情報書き込み領域をクリア For i = 1 To 26 Worksheets.Item(i + 1).Range(Cells(BaseRow + CopyRowNumber, BaseCol + CopyColumnNumber).Address, Cells(65536, 256).Address).Clear Next i End If '書式をコピー jmax = 0 Do While (Sheet_(BaseRow, BaseCol + jmax) <> "") For i = 1 To 26 Worksheets.Item(i + 1).Cells(BaseRow + CopyRowNumber, BaseCol + jmax + CopyColumnNumber) = Sheet_(BaseRow, BaseCol + jmax) Next i jmax = jmax + 1 Loop '各情報をセルに割り振り i = 0 Do While (Sheet_(BaseRow + i, BaseCol) <> "") LName = Sheet_.Cells(BaseRow + i, BaseCol) RAsc = Asc(Left(UCase(LName), 1)) - Asc("A") If RAsc >= 0 And RAsc <= 25 Then Pgn(RAsc + 2) = Pgn(RAsc + 2) + 1 For j = 0 To jmax - 1 Worksheets.Item(RAsc + 2).Cells(BaseRow + Pgn(RAsc + 2) + CopyRowNumber, BaseCol + j + CopyColumnNumber) = Sheet_(BaseRow + i, BaseCol + j) Next j End If i = i + 1 Loop
補足
早速のご回答ありがとうございます!!完璧にシートに分かれていました! ただもう少しお願いがございまして、可能であれば、シート名がpage_XXとなっていますが、アルファベッドのみのシート名にすることは可能でしょうか? また元データのみだし部分(部品名、詳細、金額・・・)がセルが青、太文字、でかかれおり、アルファベッドのシートにも同じ書式設定で反映させたいのですが。。あとデータ全体的に格子もついています。 (見出し部分) 部品名 詳細 金額 社名 その他 このようなものは無理でしょうか? もし難しいようであれば、部品の隣のセルにLEFT関数で、アルファベット頭文字を反映させて、それをシート名で使用するようなマクロでも結構なのですが。 マクロ初心者で申し訳ございませんが、どうぞよろしくお願いいたします。お忙しいところすみません。
補足
毎回ご回答ありがとうございます^^とても助かっています。バックアップはとってありましたのでデータは大丈夫です! 早速、新しく作っていただきましたマクロで試してみました。一度目は完璧に動作しましたが、データを追加してマクロを実行するとやはり固まってしまいました。”いくつかのマクロが失われる可能性がありますが実行しますか?”とテロップがでてきました。 私が言っているようなマクロは無理があるのでしょうか??どうすればいいのかご教示お願いいたします!(__ 本当にすみません!