Excel (VBA) |
![]() ![]() |
(Windows 11全般 : Microsoft 365)
元ファイルの形式のまま、担当名ごとに分けた複数のExcelファイルを作成したいです
投稿日時: 22/11/10 21:39:50
投稿者: y_0770
|
---|---|
大変お世話にお世話になっております。
|
![]() |
投稿日時: 22/11/10 22:29:58
投稿者: WinArrow
|
---|---|
提案
|
![]() |
投稿日時: 22/11/10 23:06:45
投稿者: simple
|
---|---|
(1)元のシートをシートコピーし、一行目だけを残します。 (そのシートを 以下、templateシートと呼びます。) (2)templateシートをシートコピーし、 それに各担当者の情報を含んだ行をコピーします。 (3)それを単独のブックとして保存します 担当者数だけ、(2)(3)を繰り返します。こういった方針で作成されたらいかがですか? まずはインデントをきちんとつけることを推奨しますが、 それだけのコードが書けるのであれば、上記方針によるコードも作成できると思います。 トライされたらいかがでしょうか。 もし詰まったら、その段階で詰まったところを質問されたらいかがですか? |
![]() |
投稿日時: 22/11/11 09:44:02
投稿者: WinArrow
|
---|---|
掲示のコードでは、元ブックに、担当者名のシートを作成していますが、
|
![]() |
投稿日時: 22/11/11 17:57:03
投稿者: WinArrow
|
---|---|
非表示セル(行)の複写のテストをしていて、気が付いたことをアップします。
|
![]() |
投稿日時: 22/11/11 20:58:30
投稿者: WinArrow
|
---|---|
非表示行がある場合の、データ最終行の求め方
|
![]() |
投稿日時: 22/11/11 23:28:33
投稿者: WinArrow
|
---|---|
オートフィルタで非表示になっている行を含む別シートへの複写
Option Explicit 'オートフィルタによる非表示行を含んで別シートへ複写 Sub test() Dim ws1 As Worksheet, ws2 As Worksheet Dim RX1 As Long, RX2 As Long Set ws1 = Sheets(1) Set ws2 = Sheets(2) With ws1 '項目名行複写 .Rows(1).Copy ws2.Range("A1") 'データ行複写(Insert:表示行は表示行で複写、非表示行は非表示行で複写) For RX1 = 2 To .Range("A1").CurrentRegion.Rows.Count .Rows(RX1).Copy '複写先シートのデータの最終行取得 RX2 = ws2.Range("A1").CurrentRegion.Rows.Count + 1 ws2.Rows(RX2).Insert shift:=xlShiftDown Next Application.CutCopyMode = False End With End Sub 前レスで、Insert を使っている利用が分からないと書いてしまいましたが、 表示行(セル)は、Insertで複写できることを知りました。 また、Insert で書式を指定しないとExcelお任せになり、 元データの書式複写は期待できないと書きましたが、 元データの書式も複写されていることを確認しました。 質問者さんの複写先の行取得方法:End(xlup))では、意図した行が取得できなかった。 ことも検証しました。 「非表示行が表示行になっている」については分かりません。 参考コードのため、担当者判断を省いています。 |
![]() |
投稿日時: 22/11/12 05:28:05
投稿者: y_0770
|
---|---|
WinArrow 様
|
![]() |
投稿日時: 22/11/12 05:38:54
投稿者: y_0770
|
---|---|
simple様
|
![]() |
投稿日時: 22/11/12 06:58:01
投稿者: simple
|
---|---|
通じにくいかも知れないので、コード例を示します。
Option Explicit Dim ws As Worksheet Dim template As Worksheet Sub main() Dim k As Long Dim myName As String Application.ScreenUpdating = False '(1)templateシートを作成 Set ws = Worksheets(1) ws.Copy After:=ws Set template = ActiveSheet template.UsedRange.EntireRow.Offset(1).Delete '(2)各行ごとにtemplateに転記し、それをブック保存 With ws For k = 2 To .Cells(Rows.Count,"A").End(xlUp).Row myName = .Cells(k, 1).Value Call makeWorkbook(k, myName) Next End With Application.DisplayAlerts = False template.Delete Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub ' k行目をtemplateにコピーして、ブックとして保存 Function makeWorkbook(k As Long, myName As String) Dim newBook As Workbook Dim fullPath As String ws.Rows(k).Copy template.Range("A2").PasteSpecial xlPasteValues template.Range("A2").PasteSpecial xlPasteFormats Application.CutCopyMode = False Application.Goto template.Range("A1") template.Name = myName template.Copy Set newBook = ActiveWorkbook fullPath = ThisWorkbook.Path & "\" & myName & ".xlsx" newBook.SaveAs fullPath, FileFormat:=xlOpenXMLWorkbook newBook.Close End Function ・コピーすべき行のなかに、他の行を参照している数式があると、 単なるコピーペイストでは値が変わってくる可能性があります。 そこで、それを考慮し、「値貼り付け」と「書式貼り付け」を続けて実行しています。 そうした心配はなく、数式を使っていても当該行の中だけの参照なら、 通常のコピー貼り付けでよいと思います。 ・その他、こちらの勝手解釈や、提示されていないことで支障があるかもしれません。 その場合は適宜修正してください。 (あくまで参考コードです。このまま使えることを保証したものではありません。) |
![]() |
投稿日時: 22/11/12 08:36:01
投稿者: WinArrow
|
---|---|
[quote]
|
![]() |
投稿日時: 22/11/12 11:43:38
投稿者: WinArrow
|
---|---|
参考コード
Option Explicit Sub test() Dim Ws1 As Worksheet, Ws2 As Worksheet Dim Rx As Long, Cx As Long, C As Long Dim 項目1 As String Dim HiddenColumn Set Ws1 = Sheets(1) Set Ws2 = Sheets(2) '非表示列番号を配列変数に格納 With Ws1 ReDim HiddenColumn(1 To 1): C = 0 For Cx = 1 To .UsedRange.Columns.Count If .Columns(Cx).Hidden Then C = C + 1 ReDim Preserve HiddenColumn(1 To C) HiddenColumn(C) = Cx End If Next End With 項目1 = "xxxx" '担当者 With Ws1 For Rx = 2 To .UsedRange.Rows.Count If .Cells(Rx, "A").Value = 項目1 Then .Rows(Rx).Copy Destination:=Ws2.Range("A" & Ws2.Rows.Count).End(xlUp).Offset(1) End If Next End With '配列変数から複写後シートの列を非表示する If C > 0 Then With Ws2 For C = LBound(HiddenColumn) To UBound(HiddenColumn) If C > 0 Then .Columns(HiddenColumn(C)).Hidden = True End If Next End With End If End Sub |
![]() |
投稿日時: 22/11/12 19:02:23
投稿者: y_0770
|
---|---|
皆様
|
![]() |
投稿日時: 22/11/12 19:08:17
投稿者: simple
|
---|---|
最終的にどんなコードになったのでしょうか。
|
![]() |
投稿日時: 22/11/12 19:11:31
投稿者: simple
|
---|---|
私にはオートフィルタがなぜ出てくるのか不明でした。
|
![]() |
投稿日時: 22/11/12 19:30:48
投稿者: simple
|
---|---|
コードが提示されたのですから、少なくとも動作させて検証というのかな、
|
![]() |
投稿日時: 22/11/12 19:49:09
投稿者: y_0770
|
---|---|
simple様
|
![]() |
投稿日時: 22/11/12 20:15:34
投稿者: simple
|
---|---|
改めて、完成したコードをまるまる乗せると、閲覧者の参考にもなると思いますよ。
|
![]() |
投稿日時: 22/11/12 21:32:53
投稿者: WinArrow
|
---|---|
私も、オートフィルタがようわかりません。
|
![]() |
投稿日時: 22/11/13 09:05:37
投稿者: WinArrow
|
---|---|
余計な心配かもしれませんが、
|
![]() |
投稿日時: 22/11/13 09:57:38
投稿者: WinArrow
|
---|---|
余計な心配その2
|
![]() |
投稿日時: 22/11/13 15:14:23
投稿者: y_0770
|
---|---|
simple様
|
![]() |
投稿日時: 22/11/13 15:32:42
投稿者: y_0770
|
---|---|
WinArrow様
|
![]() |
投稿日時: 22/11/13 16:36:30
投稿者: WinArrow
|
---|---|
ドロップダウンリストの参照先
引用: >影響がない所 ではなく、影響がなければ困ることになる・・を心配したのです。 元シートの「セルDC1からDH1など」ということだと思いますが、 各シートの1行目に複写した時、各々がどこを参照しているか? 確認していますか? もう一つ、 非表示列 の件が見当たりませんが・・・・・ オートフィルタを設定(検索有無は無関係)してあると、 非表示セルは複写されないのでは? |
![]() |
投稿日時: 22/11/13 16:37:46
投稿者: simple
|
---|---|
検証頂いた結果はどうだったのでしょうか?
|
![]() |
投稿日時: 22/11/13 18:27:42
投稿者: WinArrow
|
---|---|
ついでのアドバイス
|
![]() |
投稿日時: 22/11/14 08:08:55
投稿者: WinArrow
|
---|---|
少し、厳しいコメントを書きます。
引用: ですよね? コード比較 最初のコード 最後のコード @ ➀ A C 新A 新B ※@→@:全く変わっていない ※A→C:全く変わっていない ※新A:このコードは実質的に、問題解決に寄与していない。 あっても、無くても、無関係 ※新B:後出しの問題解決には寄与したと思うが、最初の問題解決には寄与していない。 結果として、最初の問題解決につながる改善ができていない。 と思います。 前レスにも書きましたが、 >Worksheets.Add after:=Worksheets(Worksheets.Count) を Worksheets(1).Copy after:=Worksheets(Worksheets.Count) に変更し、当該担当者以外の行を削除する ように変更することで、新A新Bは不要です。 但し、最初に担当名テーブルを作成する必要があります。 |
![]() |
投稿日時: 22/11/14 15:00:18
投稿者: WinArrow
|
---|---|
全く発想を変えて
Option Explicit Dim ws1 As Worksheet, ws2 As Worksheet Sub MAIN() Dim TName, TX As Long With ThisWorkbook Set ws1 = .Sheets(1) .Sheets.Add after:=ws1 Set ws2 = ActiveSheet End With With ws1 .UsedRange.Columns("A").Copy ws2.Range("A1") End With ws2.Columns("A").RemoveDuplicates Columns:=1, Header:=xlYes '担当名を配列に格納 TName = Application.Intersect(ws2.UsedRange, ws2.UsedRange.Offset(1)).Value Application.DisplayAlerts = False ws2.Delete Set ws2 = Nothing Application.ScreenUpdating = False For TX = LBound(TName) To UBound(TName) Call SheetSPLIT(TName:=TName(TX, 1)) Next End Sub Private Sub SheetSPLIT(ByVal TName As String) Dim Wb2 As Workbook Dim ws2 As Worksheet, RX As Long 'Sheet1を複写→新しいブック ws1.Copy Set Wb2 = ActiveWorkbook Set ws2 = Wb2.Sheets(1) With ws2 .Name = TName If .AutoFilterMode Then .Range("A1").AutoFilter For RX = .Range("A" & .Rows.Count).End(xlUp).Row To 2 Step -1 If .Cells(RX, "A").Value <> TName Then .Rows(RX).Delete End If Next .Range("A1").AutoFilter field:=1 End With Wb2.SaveAs Filename:=ThisWorkbook.Path & "\" & TName & ".xlsX" Wb2.Close Set Wb2 = Nothing End Sub |
![]() |
投稿日時: 22/11/14 20:12:10
投稿者: simple
|
---|---|
最初からそのような考え方を提示し、実動するコード全体まで提示しているのですが、
|
![]() |
投稿日時: 22/11/14 21:06:18
投稿者: y_0770
|
---|---|
WinArrow様…!
|
![]() |
投稿日時: 22/11/14 21:07:32
投稿者: y_0770
|
---|---|
simple様…!
|