【元データ】から必要な情報を【管理簿】に転記したいのですが
転記するにあたって、複数の条件があるためどのように作成すればいいかわかりません。
皆様のお知恵を拝借できませんでしょうか。
転記対象条件
・「承認」があり、「チェック」が空白のものが対象
・申請1と申請2は「不要」となっているところは転記した際には空白にする
・セイとメイは全角スペース1文字をはさんで連結し、半角の場合は全角に変換しなおす
・列の位置が元データと転記後のデータでは異なる
・転記後の支社は【元データ】の「支社」と「部署」を結合させる
・管理簿には前回転記したものが入力されているのでその下に追加で転記していきたい
実際のデータは1行に100列ぐらいの項目があります
なるべく短時間で処理を行えるようにしたいのですがアドバイスだけでも
いただければと思います。
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
Sub test() Dim srcws As Worksheet Dim dstws As Worksheet Dim i As Long Dim dstrow As Long Dim srcrow As Long On Error GoTo ErrorHandler Set srcws = Worksheets("元データ") Set dstws = Worksheets("管理簿") '管理簿最終行を求める dstrow = dstws.Range("A" & Rows.Count).End(xlUp).Row + 1 '元データ最終行を求める srcrow = srcws.Range("A" & Rows.Count).End(xlUp).Row '元データ行ループ For i = 2 To srcrow If srcws.Cells(i, 11).Value = "承認" Then If srcws.Cells(i, 10).Value = "" Then '番号 dstws.Cells(dstrow, 1).Value = srcws.Cells(i, 1).Value '姓 dstws.Cells(dstrow, 2).Value = srcws.Cells(i, 2).Value '名 dstws.Cells(dstrow, 3).Value = srcws.Cells(i, 3).Value 'カナを全角で結合 dstws.Cells(dstrow, 4).Value = StrConv(srcws.Cells(srcrow, 4).Value & " " & srcws.Cells(srcrow, 5).Value , vbWide) '支社 dstws.Cells(dstrow, 5).Value = srcws.Cells(i, 8).Value & srcws.Cells(i, 9).Value '申請1 If (srcws.Cells(i, 6).Value) = "必要" Then dstws.Cells(dstrow, 6).Value = srcws.Cells(i, 6).Value Else dstws.Cells(dstrow, 6).Value = "" End If '申請2 If (srcws.Cells(i, 7).Value) = "必要" Then dstws.Cells(dstrow, 7).Value = srcws.Cells(i, 7).Value Else dstws.Cells(dstrow, 7).Value = "" End If dstrow = dstrow + 1 End If End If Next '罫線を引く dstws.UsedRange.Borders.LineStyle = True Exit Sub ErrorHandler: MsgBox "元データを追加してください。" End Sub
投稿2019/03/07 04:03
編集2019/03/07 04:58総合スコア16
0
現段階では、どの機能が実現できそうで、どこが厳しそうなのか、想像もつかない状態ではないのでしょうか?
慣れないうちはよく陥ることなのですが、全体ばかりを見てしまうと途方もない大物に思えて最初の一歩が踏み出せなくなります。
大事なのは最終的に実現したいものを、細かな機能にわけて、1つずつ着実に実装していくことです。
慣れてくると2~3機能をまとめて考慮して組めるようになったりしてきますが、基本は1つずつです。
今回の場合、例えば
①元データから1行ずつ対象行を取得するループ処理を作成する ⇒For~Next文など ②管理簿の前回最終行を見つける ⇒ Range.End(xlUp) ③②の1つ下の行に、元データから「番号」「姓」「名」を転記する ④「セイ」と「メイ」を連結して「フリガナ」に出力する ⇒文字列連結 ⑤「支社」と「部署」を結合して「支社」に出力する ⑥「申請1」と「申請2」は「不要」でない場合のみ転記する ⇒IF文など ⑦「承認」がない行は読み飛ばし、次のデータを処理する機能を追加する ⑧「チェック」が空白でない行は読み飛ばし、次のデータを処理する機能を追加する
のような手順に分解して考えてみます。
まずは①~③の機能を作ってみます。
これが実装できると、単純に右から左へ無条件に転記する機能ができあがります。
そこに④⑤のような元の値を加工して出力する機能、⑥のような条件によって異なる値を出力する機能を実装します。
さらに⑦⑧のような条件によっては元データの行を読み飛ばす機能を実装すれば、やりたいことがすべて実装されていると思います。
段階を追って、ひとつずつクリアしていく中で「これの実現方法が調べてもわからない」といったことがわかってくれば、それは大きな進歩です。
わからないことを(自分で調べたことも含めて)質問していただければ、お力添えできると思います。
がんばってみてください。
(追記:2019/03/07 18:00)
解決済みですが、ご自身で作成されたコードが提示されましたので、私からもサンプルコードを提供いたします。
※ttyp03さんのアドバイスを参考に、メンテナンス性を考慮する案を盛り込んだものです。
'コピー元の列番号 Enum ReadCols 番号 = 1 性 名 セイ メイ 申請1 申請2 支社 部署 チェック 承認 End Enum 'コピー先の列番号 Enum WriteCols 番号 = 1 性 名 フリガナ 支社 申請1 申請2 LAST End Enum Sub test() Dim srcws As Worksheet Dim dstws As Worksheet Dim i As Long Dim iCol As Integer Dim dstrow As Long Dim srcrow As Long On Error GoTo ErrorHandler Set srcws = Worksheets("元データ") Set dstws = Worksheets("管理簿") '管理簿最終行を求める dstrow = dstws.Range("A" & Rows.Count).End(xlUp).Row + 1 '元データ最終行を求める srcrow = srcws.Range("A" & Rows.Count).End(xlUp).Row '出力先の各セルについて、コピー元の列を設定する Dim dstcoltbl(100) As Long Call DefineColumns(dstcoltbl) '元データ行ループ For i = 2 To srcrow If srcws.Cells(i, ReadCols.承認).Value = "承認" Then If srcws.Cells(i, ReadCols.チェック).Value = "" Then '出力先1列目~最終列までループ処理 For iCol = 1 To WriteCols.LAST - 1 If dstcoltbl(iCol) <> 0 Then dstws.Cells(dstrow, iCol).Value = srcws.Cells(i, dstcoltbl(iCol)).Value Else '加工する項目 Select Case iCol Case WriteCols.フリガナ dstws.Cells(dstrow, iCol).Value = StrConv(srcws.Cells(srcrow, ReadCols.セイ).Value & " " & srcws.Cells(srcrow, ReadCols.メイ).Value, vbWide) Case WriteCols.支社 dstws.Cells(dstrow, iCol).Value = StrConv(srcws.Cells(srcrow, ReadCols.支社).Value & srcws.Cells(srcrow, ReadCols.部署).Value, vbWide) Case WriteCols.申請1 If (srcws.Cells(i, ReadCols.申請1).Value) = "必要" Then dstws.Cells(dstrow, iCol).Value = srcws.Cells(i, ReadCols.申請1).Value Else dstws.Cells(dstrow, iCol).Value = "" End If Case WriteCols.申請2 If (srcws.Cells(i, ReadCols.申請2).Value) = "必要" Then dstws.Cells(dstrow, iCol).Value = srcws.Cells(i, ReadCols.申請2).Value Else dstws.Cells(dstrow, iCol).Value = "" End If Case Else '処理方法が見つからない列は空欄で出力 dstws.Cells(dstrow, iCol).Value = "" End Select End If Next '出力先の行番号をインクリメント dstrow = dstrow + 1 End If End If Next '罫線を引く dstws.UsedRange.Borders.LineStyle = True Exit Sub ErrorHandler: MsgBox "元データを追加してください。" End Sub 'コピー元の列を設定する関数 Private Sub DefineColumns(ByRef rColsTbl() As Long) 'あえて項目毎に1:1で書いてみた。管理しやすければこれもアリ。 rColsTbl(WriteCols.番号) = ReadCols.番号 rColsTbl(WriteCols.性) = ReadCols.性 rColsTbl(WriteCols.名) = ReadCols.名 rColsTbl(WriteCols.フリガナ) = 0 '加工 rColsTbl(WriteCols.支社) = 0 '加工 rColsTbl(WriteCols.申請1) = 0 '加工 rColsTbl(WriteCols.申請2) = 0 '加工 End Sub
投稿2019/03/04 08:45
編集2019/03/07 09:23総合スコア3013
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/03/08 02:09
2019/03/08 07:12 編集
0
ベストアンサー
基本的な構造だけ書いてみました。
足りないところは適宜足してください。
考え方としては特殊なケース以外は単純コピー、そうでない場合のみ加工している感じです。
元と先で列の順番が入れ替わったりしているところがありそうなので、先に対する元のデータの位置(列番号)をdstcoltblという配列に定義するようにしています。
要素(1)以降が列番号に対応しています。
値が0の要素が特殊ケースという扱いにしています。
フリガナと支社の処理は入れてみたので、他のもご自分でやってみてください。
dstcoltblの定義(Arrayしているところ)や管理簿の最終行を求めるところの実装もしてください。
VBA
1Dim srcws As Worksheet 2Dim dstws As Worksheet 3Dim srcrow As Long 4Dim dstrow As Long 5Dim dstcoltbl() As Variant 6Dim c As Long 7 8Set srcws = Worksheets("元データ") 9Set dstws = Worksheets("管理簿") 10 11'管理簿最終行を求める 12dstrow '= ○○ 13 14'対応テーブル 15dstcoltbl = Array(0, 1, 2, 3, 0, 0) 16 17'元データ行ループ 18srcrow = 2 19Do While srcws.Cells(srcrow, 1).Value <> "" 20 '管理簿列ループ 21 dstcol = 1 22 For c = 1 To UBound(dstcoltbl) 23 If dstcoltbl(c) <> 0 Then 24 '単純コピー 25 dstws.Cells(dstrow, c).Value = srcws.Cells(srcrow, dstcoltbl(c)).Value 26 Else 27 '特殊ケース 28 Select Case c 29 Case 4 ' フリガナ 30 dstws.Cells(dstrow, c).Value = srcws.Cells(srcrow, 4).Value & " " & srcws.Cells(srcrow, 4).Value 31 Case 5 ' 支社 32 dstws.Cells(dstrow, c).Value = srcws.Cells(srcrow, 8).Value & srcws.Cells(srcrow, 9).Value 33 End Select 34 End If 35 Next 36 srcrow = srcrow + 1 37 dstrow = dstrow + 1 38Loop 39
投稿2019/03/04 07:15
総合スコア16998
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/03/04 08:50
2019/03/04 08:56
2019/03/04 09:09
2019/03/04 09:14
2019/03/05 00:56 編集
2019/03/05 00:48 編集
2019/03/07 04:07
0
投稿2019/03/04 06:40
編集2019/03/04 06:43総合スコア25195
0
基本的にプログラムなので一個一個こなしていくしかありません。
1.メンテナンスまで考えると、最初の1列目で必要な情報の列を探索。
2.一つ一つの要素を構造体配列に格納。結合させたらいいだけのデータ等はこの時点で結合させておく。
3.別のエクセル(この場合は管理簿)のシートに構造体配列の情報を登録させる。
VBAの場合はシートの更新を止めてから、シートの情報を書いた方が処理的に早い為、
下記のコードを書いておいた方が処理速度が格段に上がりますよ。
VBA
1'シートに何かを書く前に 2Application.ScreenUpdating = False 3Application.EnableEvents = False 4Application.Calculation = xlCalculationManual
VBA
1'シートに何かを書き終わったあとに、 2Application.ScreenUpdating = True 3Application.EnableEvents = True 4Application.Calculation = xlCalculationAutomatic
投稿2019/03/04 06:09
総合スコア3307
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/03/07 04:04
2019/03/07 04:59
2019/03/07 05:04
2019/03/07 05:10
2019/03/07 07:06
2019/03/07 08:07
2019/03/07 09:18