質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

7回答

1241閲覧

デシクショナリーオブジェクトを利用して、重複データを格納したい

maimikan

総合スコア1

VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

1グッド

0クリップ

投稿2023/03/23 06:20

編集2023/03/26 00:54

実現したいこと、前提

エラーを解消し、デシクショナリーオブジェクトを利用して、重複データを意図通りに格納したい(下記に記載)

normalDic⇒重複しない、一意の社員番号(employeeNum)と給料(kyu)とインフラ手当(teate)を格納したい
myDic⇒normalDicに格納されており、重複している社員番号と給料とインフラ手当を格納したい
dupDic⇒normalDicに格納されており、重複している社員番号を格納したい

myDicは、今回のソースコードに記載のvalsを見て、normalDicにすでに格納されていれば、重複と認識し、myDicに格納する

dupDicは、今回のソースコードに記載のemployeeNumのみを見て、normalDicにすでに格納されていれば、重複と認識し、myDicに格納する

★myDicではじかれた重複の人は、dupDicに格納したくないです
⇒myDicの内容は、削除処理をいれても問題ないです

発生している問題・エラーメッセージ

プロシージャの呼び出し、または引数が不正です

該当のソースコード

vba

1 Dim normalDic, dupDic, myDic As Object 2 3Set normalDic = CreateObject("Scripting.Dictionary") 4 Set dupDic = CreateObject("Scripting.Dictionary") 5 Set myDic = CreateObject("Scripting.Dictionary") 6 7 'データ行まで読み飛ばし 8 Line Input #1, buf 'ヘッダー行1読込 9 Line Input #1, buf 'ヘッダー行2読込 10 Line Input #1, buf 'ヘッダー行3読込 11 Line Input #1, buf 'カラムID行読込 12 Do Until EOF(1) 13 Line Input #1, buf 14 tmp = Split(buf, ",") 15 16 employeeNum = tmp(11) 17 teate = tmp(45) 18 kyu = tmp(40) 19'配列なので、実際のcsvのカラムから-1のカラム番号 20 Dim vals As Variant 21 vals = Array(employeeNum, teate, kyu) 22 23 ' 正常辞書に社員番号が存在しない場合、追加 24 If Not normalDic.Exists(vals) Then 25 normalDic.Add employeeNum, vals 26 ' 正常辞書に社員番号が存在する場合、重複辞書に追加 27 ElseIf normalDic.Exists(vals) Then 28 myDic.Add employeeNum, vals 29 ElseIf normalDic.Exists(employeeNum) Then 30 dupDic.Add employeeNum, employeeNum 31 32 'Else 33 ' dupDic.Add employeeNum, employeeNum 34 End If 35 Loop 36 37 Close #1 38 39 40

該当のソースコードver2(修正後)

下記コードは、正常終了していますが、実現したいことに記載のある通りには機能しませんでした。

vba

1 employeeNum = tmp(11) 2 teate = tmp(45) 3 kyu = tmp(40) 4 Dim vals As Variant 5 vals = Array(employeeNum, shokusekiTeate, hyoukaKyu) 6 7 ' normalDicに社員番号が存在しない場合、追加 8 If Not normalDic.Exists(employeeNum) Then 9 normalDic.Add employeeNum, vals 10 ' normalDicに社員番号が存在する場合、重複辞書に追加 11 ElseIf normalDic.Exists(employeeNum) And myDic.Exists(employeeNum) = normalDic.Exists(employeeNum) Then 12 myDic.Add employeeNum, vals 13 ElseIf normalDic.Exists(employeeNum) And Not myDic.Exists(employeeNum) Then 14 dupDic.Add employeeNum, employeeNum

該当のソースコード(更新)

vba

1 Dim employeeNum, shokusekiTeate, hyoukaKyu, tanjikan As String 2 Dim normalDic, dupDic, myDic As Object 3 Dim vals As Variant 4 5 Set normalDic = CreateObject("Scripting.Dictionary") 6 Set dupDic = CreateObject("Scripting.Dictionary") 7 Set myDic = CreateObject("Scripting.Dictionary") 8 9 'データ行まで読み飛ばし 10 Line Input #1, buf 'ヘッダー行1読込 11 Line Input #1, buf 'ヘッダー行2読込 12 Line Input #1, buf 'ヘッダー行3読込 13 Line Input #1, buf 'カラムID行読込 14 Do Until EOF(1) 15 Line Input #1, buf 16 tmp = Split(buf, ",") 17 18 19 Select Case Val(ArySyoriSet(Pos_SyoriType)) 20 Case Inta, Intb 21 employeeNum = tmp(11) 22 teate = tmp(16) 23 24 vals = Array(employeeNum, teate) 25 'normalDicに社員番号が存在しない場合、追加 26 If Not normalDic.Exists(employeeNum) Then 27 normalDic.Add employeeNum, vals 28 Else 29 30 If Not myDic.Exists(employeeNum) Then 31 nvals = normalDic(employeeNum) 32 'normalDicの登録内容と全て一致するなら、追加 33 If vals(0) = nvals(0) And vals(1) = nvals(1) Then 34 myDic.Add employeeNum, vals 35 'dupDicに登録済みなら削除 36 If dupDic.Exists(employeeNum) Then 37 dupDic.Remove employeeNum 38 End If 39 End If 40 End If 41 'dupDic未登録かつmyDic未登録なら、追加 42 If Not dupDic.Exists(employeeNum) Then 43 If Not myDic.Exists(employeeNum) Then 44 dupDic.Add employeeNum, employeeNum 45 End If 46 End If 47 End If 48 49 Case Intc, Intd 50 employeeNum = tmp(11) 51 teate = tmp(45) 52 kyu = tmp(40) 53 54 vals = Array(employeeNum, shokusekiTeate, hyoukaKyu) 55 56 ' normalDicに社員番号が存在しない場合、追加 57 If Not normalDic.Exists(employeeNum) Then 58 normalDic.Add employeeNum, vals 59 Else 60 ' myDicに社員番号が存在せず、normalDicに社員番号、インフラ手当、給料が同一のデータが登録されていたらmyDicに追加 61 If Not myDic.Exists(employeeNum) Then 62 nvals = normalDic(employeeNum) 63 'normalDicの登録内容と全て一致するなら、追加 64 If vals(0) = nvals(0) And vals(1) = nvals(1) And vals(2) = nvals(2) Then 65 myDic.Add employeeNum, vals 66 'dupDicに登録済みなら削除 67 If dupDic.Exists(employeeNum) Then 68 dupDic.Remove employeeNum 69 End If 70 End If 71 End If 72 'dupDic未登録かつmyDic未登録なら、追加 73 If Not dupDic.Exists(employeeNum) Then 74 If Not myDic.Exists(employeeNum) Then 75 dupDic.Add employeeNum, employeeNum 76 End If 77 End If 78 End If 79 End Select 80 Loop 81 82 Close #1 83 84 85 wi = 0 86 87 'データ行まで読み飛ばし 88 Line Input #1, buf 'ヘッダー行1読込 89 Line Input #1, buf 'ヘッダー行2読込 90 Line Input #1, buf 'ヘッダー行3読込 91 Line Input #1, buf 'カラムID行読込 92 Do Until EOF(1) '縦方向ループ 93 Line Input #1, buf '1行読込 94 buf = "," & buf 'ダミー列を追加 95 tmp = Split(buf, ",") 96 97 Select Case Val(ArySyoriSet(Pos_SyoriType)) 98 Case Inta, Intb 99 100 employeeNum = tmp(12) 101 teate = tmp(17) 102 tanjikan = tmp(21) 103 104 If (tanjikan = "") And (teate = "") Or (teate = 0) And dupDic.Exists(employeeNum) Then 105   ’ご質問の箇所↓ 106 If Not myDic.Exists(employeeNum) Then 107 GoTo Continue 108 End If 109 End If 110 111   Case Intc, Intd 112 employeeNum = tmp(12) 113 teate = tmp(46) 114 kyu = tmp(41) 115 tanjikan = tmp(20) 116 117 ' インフラ手当が空白で、かつ社員番号が重複している場合、レコードをスキップする 118 If (teate = "") Or (teate = 0) And (kyu = "") Or (kyu = 0) And dupDic.Exists(employeeNum) Then 119 GoTo Continue 120 ElseIf (teate = "") Or (teate = 0) And dupDic.Exists(employeeNum) And (tanjikan = "") Then 121 GoTo Continue 122 End If 123 End Select 124 125 126 127 128### 試したこと 129 130 131 132### 補足情報(FW/ツールのバージョンなど) 133 134ここにより詳細な情報を記載してください。
tatsu99👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsu99

2023/03/23 07:45

各デシクショナリーオブジェクトのキーと値を明確にしてください。 nomalDic キー :employeeNum 値:vals myDic キー :employeeNum 値:vals dupDic キー :employeeNum 値:employeeNum であってますか。(.addをみて想像しました) If Not normalDic.Exists(vals)の文は誤りです。()内に記述できるのはキーだけです。 If Not normalDic.Exists(employeeNum)と記述してください。
maimikan

2023/03/23 07:50

ありがとうございます。 キーと値はご認識の通りです。 ご指摘の通り、employeeNumに変更してみて、正常終了はしたものの、「実現したいこと、前提」に記載がある通りには、うまくいきませんでした。
tatsu99

2023/03/23 08:16

myDicの格納要件ですが、 ①社員番号がnormalDicに存在する。 ②社員番号(employeeNum)と給料(kyu)とインフラ手当(teate)が全て同じものが normalDicに存在する。 上記の①②が共に成立する場合、myDicに格納する。 dupDicの格納要件ですが、 ①社員番号がnormalDicに存在する。 上記の①が成立する場合、dupDicに格納する。 上記であってますか。 myDicではじかれた重複の人は、dupDicに格納したくないです・・・この意味がよくわかりません。 myDicの格納要件を満たさなかった場合は、dupDicにも登録しないということでしょうか。
maimikan

2023/03/23 08:45

記載不足で申し訳ありません。 格納要件を再度記載いたします。 ①normalDicに、社員番号、給料、インフラ手当が格納されている ②myDicは、normalDicに格納済みの社員番号、給料、インフラ手当があった場合にmyDic格納する ③dupDicは、normalDicに格納済みの社員番号が合った場合に格納する  ただし、myDicに格納された上記の対象者は、dupDicには格納されないこととする 上記が格納要件です。なので、myDicとdupDicの対象者はかぶらないイメージとなります。  
maimikan

2023/03/23 08:46

すみません、vba初心者なもので、他によい考え方などあればご指摘ください。よろしくお願いいたします。
sazi

2023/04/11 02:38

powerqueryを使ってみてはどうですか
guest

回答7

0

Case Intc, d側だけですが、
★社員番号、インフラ手当、給料が同一の2つの重複したレコードは、[myDic]
★社員番号、インフラインフラ手当、給料で、インフラ手当のみ値が空白か0の場合は、出現する順番にかかわらず、インフラ手当が0か空白のほうをdupDicに格納
★normalDicは一意の社員番号を格納する(インフラ手当は0または空白でも、社員番号が一意ならnormalDicに格納だけれど、重複する社員番号の場合は、インフラ手当が0か空白をdupDicに格納する)
の実装版です。

VBA

1 Case Intc, d 2 employeeNum = tmp(11) 3 teate = tmp(45) 4 kyu = tmp(40) 5 6 vals = Array(employeeNum, teate, kyu) 7 8 If Not normalDic.Exists(employeeNum) Then 9 normalDic.Add employeeNum, vals 10 Else 11 nvals = normalDic(employeeNum) 12 '当該レコードの手当とnomalDicの手当を比較 13 If nvals(1) = vals(1) Then 14 'nomalDicと同じなら、myDicへ登録(社員番号と給料は必ず同じはずなので比較せず) 15 If Not myDic.Exists(employeeNum) Then 16 myDic.Add employeeNum, vals 17 End If 18 Else 19 'normalDicと異なるなら 20 If Kuhaku(vals(1)) = True Then 21 '当該レコードの手当が空白なら、dupDicへ登録 22 dupDic(employeeNum) = vals 23 Else 24 '当該レコードの手当が空白でないなら、normalDicへ登録しなおす 25 normalDic(employeeNum) = vals 26 dupDic(employeeNum) = nvals 27 End If 28 End If 29 End If 30 End Select 31 Loop 32 Close #1 33

投稿2023/03/27 13:55

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maimikan

2023/03/28 23:17 編集

ご回答戴きありがとうございます。 inta,bはうまく動いたのですが、intc,dは下記のデータがあることが判明しました 社員番号123 給料0円    手当0円 (dupDicに格納したい) 社員番号123 給料23,000円 手当0円 (normalDicに格納したい) (↑データの出現順は変わる) そのため、教えて戴いたコードを下記のように修正してみました。 '当該レコードの手当とnomalDicの手当を比較 If nvals(1) = vals(1) Then 'nomalDicと同じなら、myDicへ登録(社員番号と給料は必ず同じはずなので比較せず) If (nvals(1) = vals(1)) and (nvals(2) = vals(2))Thenに修正。 また、該当データの手当は両方0円なので、下記のコードも修正が必要かと思いました。 けれど下記のコードに If (Kuhaku(vals(1))= True) and (Kuhaku(vals(2))= True) Then のような判定基準をつけてしまうと、 社員番号124 給料23,000円 手当0円 (dupDicに格納したい) 社員番号124 給料23,000円 手当33,000円 (normalDicに格納したい) (↑データの出現順は変わる) のひとがうまくいかなくなってしまうかと思います。すみません、なにか方法があればご教示いただけますでしょうか。 申し訳ありません。よろしくお願いいたします。
guest

0

VBA

1 Case Intc, d 2 employeeNum = tmp(11) 3 teate = tmp(45) 4 kyu = tmp(40) 5 6 vals = Array(employeeNum, teate, kyu) 7 8 If Not normalDic.Exists(employeeNum) Then 9 normalDic.Add employeeNum, vals 10 Else 11 nvals = normalDic(employeeNum) 12 '当該レコードの手当及び給料とnomalDicの手当及び給料を比較 13 If nvals(1) = vals(1) And nvals(2) = vals(2) Then 14 'nomalDicと全て同じなら、myDicへ登録(社員番号は必ず同じはずなので比較せず) 15 If Not myDic.Exists(employeeNum) Then 16 myDic.Add employeeNum, vals 17 End If 18 Else 19 'normalDicと異なるなら 20 If (Kuhaku(nvals(1)) = True And Kuhaku(nvals(2)) = True) Or (Kuhaku(vals(1)) = False And Kuhaku(vals(2)) = False) Then 21 'nomalDicの手当と給料が共に空白 又は 22 '当該レコードの手当と給料が共に空白でないなら、normalDicへ登録しなおす 23 normalDic(employeeNum) = vals 24 dupDic(employeeNum) = nvals 25 Else 26 dupDic(employeeNum) = vals 27 End If 28 End If 29 End If 30 End Select 31

投稿2023/03/29 01:23

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsu99

2023/03/29 01:25

>社員番号124 給料23,000円 手当0円 (dupDicに格納したい) >社員番号124 給料23,000円 手当33,000円 (normalDicに格納したい) >(↑データの出現順は変わる) >のひとがうまくいかなくなってしまうかと思います。すみません、なにか方法があればご教示いただけますでしょうか。 に対する回答です。
guest

0

nomalDicの内容をSheet1へ出力します。シート名は適当に変えてください。
本体のClose#1のあとへ、Call print_EMP(normalDic)を追加します。
本体の外へPrivate Sub print_EMP(ByVal normalDic As Object)を定義します。
そうすると、Sheet1へnormalDicの内容が全て出力されます。

VBA

1 Close #1 2 3 Call print_EMP(normalDic) 4

VBA

1Private Sub print_EMP(ByVal normalDic As Object) 2 Dim ws As Worksheet 3 Dim wrow As Long 4 Dim seq As Long 5 Dim key As Variant 6 Dim vals As Variant 7 Set ws = Worksheets("Sheet1") 8 ws.Cells.ClearContents 9 ws.Range("A1").Value = "通番" 10 ws.Range("B1").Value = "社員番号" 11 ws.Range("C1").Value = "給料" 12 ws.Range("D1").Value = "手当" 13 wrow = 2 14 seq = 1 15 For Each key In normalDic.keys 16 ws.Cells(wrow, 1).Value = seq 17 ws.Cells(wrow, 2).Value = key 18 vals = normalDic(key) 19 ws.Cells(wrow, 3).Value = vals(1) 20 ws.Cells(wrow, 4).Value = vals(2) 21 seq = seq + 1 22 wrow = wrow + 1 23 Next 24End Sub 25

投稿2023/03/27 07:53

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maimikan

2023/03/27 08:47 編集

ありがとうございます、
tatsu99

2023/03/27 09:08

>いまデバッグを行っているのですが、valsに入っているemployeeNumsは文字型で、teateとkyuは数値型なのですが、ここに原因がある気がします。 >employeeNumにはしっかりと社員番号がはいっているのですが、teateとkyuには<型が違います>と表示されています。 teateとkyuをstring型にすることはできますか。
maimikan

2023/03/27 09:54 編集

すみません、上記とは関係なかったみたいです。 Stringで問題なかった用ですが、結局うまくいきませんでした。デバッグで、normalDicに一意に格納されていることはわかったのですが。。 質問の内容は変わるのですが、 出現する順番にかかわらず、dupDicにインフラ手当の値が0を格納する方法はありますでしょうか? ①社員番号 123 インフラ手当 0円 ②社員番号 123 インフラ手当 123円 出出現したら、①をdupDicに、②をnormalDicに格納したいです。 この場合のケースは給料は同額です。考慮しなくて問題ないです。 ただし、myDicの内容は変えたくないです。 (社員番号、インフラ手当、給料が同一のもを格納) これでGotoを以前のように入れれば、反映できるかと思いまして。。
maimikan

2023/03/27 10:02 編集

ただ、重複しない社員番号で、インフラ手当が0円や空白の場合もあるので、normalDicに0や空白ではない、を条件として入れるのは難しいです。
tatsu99

2023/03/27 10:12

①社員番号 123 インフラ手当 0円 ②社員番号 123 インフラ手当 0円 の場合も、あるのですか。 その場合は、normalDicに①を格納し、dupDicに②を格納ですか? 又、 ①社員番号 123 インフラ手当 0円 のレコードが1件のみの場合は、どうなりますか。 normalDicに①を格納し、dupDicには格納なしですか。
tatsu99

2023/03/27 10:20 編集

結局のところ、kyuとteateの型はstring型にしますか、それともLong型にしますか。どちらの型なのかによりコードも変わってきます。
maimikan

2023/03/27 10:18

①社員番号 123 インフラ手当 0円 ②社員番号 123 インフラ手当 0円 の場合も、あるのですか。 ⇒こちらはケース2の場合で、2023/03/23 18:09に投稿いただいた内容の処理で問題ございません(myDicに格納) ①社員番号 123 インフラ手当 0円⇒ ⇒ご認識の通り、normalDicに①を格納し、dupDicには格納なしです
maimikan

2023/03/27 10:20 編集

結局のところ、teateの型はstring型にしますか、それともLong型にしますか。どちらの型なのかによりコードも変わってきます。 ⇒Stringで大丈夫でした。すみません、 2023/03/23 18:09に投稿いただいた内容でうまく動いています。
tatsu99

2023/03/27 10:30

①社員番号 123 インフラ手当 0円 ②社員番号 123 インフラ手当 123円 >出出現したら、①をdupDicに、②をnormalDicに格納したいです。 >この場合のケースは給料は同額です。考慮しなくて問題ないです。 >ただし、myDicの内容は変えたくないです。 >(社員番号、インフラ手当、給料が同一のもを格納) mydic の手当は0円ということでしょうか。
tatsu99

2023/03/27 10:35

すみません。上記のケースではmyDicにレコードは格納されません。 ①社員番号 123 インフラ手当 0円 ②社員番号 123 インフラ手当 0円 ③社員番号 123 インフラ手当 123円 の場合は、myDicに②が格納されます。 この場合、最終的に ①の内容がdupDicに格納、②の内容がmyDicに格納、③の内容がnormalDicに格納であってますか。
maimikan

2023/03/27 10:58 編集

myDicは、2023/03/23 18:09に投稿いただいた内容の動作で変更なくて大丈夫です。 (ケース2の社員番号、手当、給料が同一の場合、myDicに格納される) 社員番号は最大2つの重複なので、ご提示いただいたケースはデータにございません。よろしくお願いいたします。 以下のようなかたちです。 ★社員番号、インフラ手当、給料が同一の2つの重複したレコードは、[myDic] ★社員番号、インフラインフラ手当、給料で、インフラ手当のみ値が空白か0の場合は、出現する順番にかかわらず、インフラ手当が0か空白のほうをdupDicに格納 ★normalDicは一意の社員番号を格納する(インフラ手当は0または空白でも、社員番号が一意ならnormalDicに格納だけれど、重複する社員番号の場合は、インフラ手当が0か空白をdupDicに格納する)
tatsu99

2023/03/27 10:57

一旦、休憩します。返信は23時ごろになります。
maimikan

2023/03/27 10:59

承知しました、ご連絡戴きありがとうございます。承知しました。
guest

0

やりたいことが以下のような仕様だと想像し、その想定のもとでコードを記述しました。

INPUT(ファイル)

社員番号給料手当
0001100
000110
00011000
0001010
  • 同じ社員番号で複数レコードが存在する
  • 給料および手当には、「正しい値」「空白」「0」のいずれかが入っている

OUTPUT(ディクショナリ)

社員番号給料手当
000110010
  • 社員番号で重複したデータを取り除き一意となった結果を出力
  • 一意にする際、給料および手当は「正しい値」を採用

VBA

1Sub sample() 2 Open ファイル名 For Input As #1 3 4 Dim dic As Object 5 Set dic = CreateObject("Scripting.Dictionary") 6 7 Dim buf As Variant 8 Dim tmp As Variant 9 Dim employeeNum As String 10 Dim teate As Long 11 Dim kyu As Long 12 13 Line Input #1, buf 14 Line Input #1, buf 15 Line Input #1, buf 16 Line Input #1, buf 17 18 Do Until EOF(1) 19 Line Input #1, buf 20 tmp = Split(buf, ",") 21 22 employeeNum = tmp(11) 23 teate = Val(tmp(45)) 24 kyu = Val(tmp(40)) 25 26 If dic.Exists(employeeNum) Then 27 If teate = 0 Then teate = dic(employeeNum)(1) 28 If kyu = 0 Then kyu = dic(employeeNum)(2) 29 End If 30 31 dic(employeeNum) = Array(employeeNum, teate, kyu) 32 33 Loop 34 35 Close #1 36 37 Dim k, v 38 For Each k In dic.Keys 39 v = dic(k) 40 Debug.Print k, Join(v, vbTab) 41 Next 42 43End Sub 44

投稿2023/03/24 15:44

編集2023/03/26 04:32
jinoji

総合スコア4585

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

1.normalDicに未登録の場合は、無条件に格納。
2.normalDicに登録済みの場合は、valsを更新する。
dicのvals(1)が空白で取得レコードのvals(1)が空白以外なら、レコードのvals(1)で更新(給料)
dicのvals(2)が空白で取得レコードのvals(2)が空白以外なら、レコードのvals(2)で更新(インフラ手当)
上記で、取得したnormalDicを出力する。(myDic,dupDicは作成しない)
実装例です。
空白判定ルーチン Kuhakuを呼び出しています。
Kuhakuは、内容が""又は"0"の場合、Trueを返します。以外は、Falseを返します。

VBA

1 Dim normalDic, dupDic, myDic As Object 2 3 Set normalDic = CreateObject("Scripting.Dictionary") 4 5 'データ行まで読み飛ばし 6 Line Input #1, buf 'ヘッダー行1読込 7 Line Input #1, buf 'ヘッダー行2読込 8 Line Input #1, buf 'ヘッダー行3読込 9 Line Input #1, buf 'カラムID行読込 10 Do Until EOF(1) 11 Line Input #1, buf 12 tmp = Split(buf, ",") 13 14 employeeNum = tmp(11) 15 teate = tmp(45) 16 kyu = tmp(40) 17 '配列なので、実際のcsvのカラムから-1のカラム番号 18 Dim vals As Variant 19 20 vals = Array(employeeNum, teate, kyu) 21 22 ' 正常辞書に社員番号が存在しない場合、追加 23 If Not normalDic.Exists(employeeNum) Then 24 normalDic.Add employeeNum, vals 25 Else 26 '正常辞書に社員番号が存在する場合、給料、インフラ手当が空白でないなら、その値で更新 27 nvals = normalDic(employeeNum) 28 If Kuhaku(nvals(1)) = True And Kuhaku(vals(1)) = False Then 29 nvals(1) = vals(1) 30 End If 31 If Kuhaku(nvals(2)) = True And Kuhaku(vals(2)) = False Then 32 nvals(2) = vals(2) 33 End If 34 normalDic(employeeNum) = nvals 35 End If 36 Loop 37 38 Close #1 39

VBA

1Private Function Kuhaku(ByVal val As String) As Boolean 2 Kuhaku = True 3 If val = "" Then Exit Function 4 If val = "0" Then Exit Function 5 Kuhaku = False 6End Function 7

投稿2023/03/24 09:05

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maimikan

2023/03/25 01:38

ありがとうございます。こちらの方法で試したところ、「End Functionが必要です」となってしまいました。コピーしているのでEndfunctionは記載してあるし、また#closeの後に記載しているので、入れ子にもなっていのですが。。 また、Private Function Kuhaku(ByVal val As String) As Booleanは、Private Function Kuhaku(ByVal vals As String) As Booleanでしょうか?すみません、よろしくお願いいたします。
tatsu99

2023/03/25 01:50

あなたが、マクロを抜粋して提示されているので、関数の開始と終了の箇所がありませんが、実際には 以下のようになっているはずです。 public sub XXXX()・・・・① ・・・あなたが提示したマクロ・・・ end sub・・・・② ①②の部分が提示されていない。 従って、Kuhakuは、②の後に書きます。②の前に書いてはいけません。 以下のように書いてください。 public sub XXXX()・・・・① ・・私が回答したマクロ・・ end sub・・・・② Private Function Kuhaku(ByVal val As String) As Boolean Kuhaku = True If val = "" Then Exit Function If val = "0" Then Exit Function Kuhaku = False End Function
tatsu99

2023/03/25 01:55

Private Function Kuhaku(ByVal val As String) As Booleanですが、 valが正しいのかvalsが正しいのかということですが、引数なので、どちらにしても正しく動作します。 但し、valsは3つの変数をまとめてvalsとなってます。ここでは、1つの変数を対象にしているので、valのほうがネーミングとしては適切かと思います。 尚、valのかわりに変数名をhogeとしても正しく動作します。(不適切な名前ですが・・・)
maimikan

2023/03/25 03:36 編集

ありがとうございます。 おかげでそちらのエラーは解決いたしました。
maimikan

2023/03/26 00:52

すみません、最後の質問です。 最初にご回答戴いたコードを参考にして、該当のソースコード(更新)のコードを書いてみました。 (最新のご回答内容でも作成いたし、問題ないこと確認いたしました。) Case Inta, Intbには取り込むcsvに給料データがなく、Case Intc, Intdには給料があります。 Case Intc, Intdは想定通りに動いていたので、、Case Inta, Intbからは給料を削除しさえすれば、 Case Intc, Intdと同じ動作をする想定でした(employeeNumとteateがoまたは空白の重複するレコード(ケース2の給料ないバージョン)をもつ対象者が重複して出力される)。 ですが、Case Inta, Intbでは、employeeNumとteateがoまたは空白の重複するレコード(ケース2の給料ないバージョン)をもつ対象者が消えてしまうのです。 Case Intc, Intdは消えなかったです。 もしかしたらCase Inta, Intbのteateがoまたは空白の対象者は、dupDicにも追加されてしまっているのでは、と 思い、該当のソースコード(更新)のコードにあるコメントアウトの「ご質問の箇所↓」にある条件を追加したところ、 teateがoまたは空白の対象者は消えずに出力されました。そのため、dupDicとmyDicに該当の対象者が登録されていることがわかりました。 ただ、① 'dupDic未登録かつmyDic未登録なら、追加という処理を実施しているので、なぜteateがoまたは空白の対象者がdupDicに 登録されているのか疑問です。②また、Case Intc, Intdより、給料以外はコピペにもかかわらず、なぜ動作がことなってしまうのかがわかりません。 上記2点について、教えていただけないでしょうか。よろしくお願いいたします。
tatsu99

2023/03/26 02:33 編集

>Case Inta, Intbでは、employeeNumとteateがoまたは空白の重複するレコード(ケース2の給料ないバージョン)をもつ対象者が消えてしまうのです。 myDicに登録されていないということと理解しました。 元のデータ(CSVファイル)自体が、そのようになっているのではないでしょうか。 CSVファイルの内容を確認すれば良いかと思います。 ①社員番号=123 給料=空白 ②社員番号=123 給料=空白 ③社員番号=123 給料=10万 上記の順番にレコードが出現すると、mydicに②のレコードが登録されます。 normalDicには①のレコードが登録されます。 dupdicには登録されません。 ④社員番号=123 給料=10万 ⑤社員番号=123 給料=空白 ⑥社員番号=123 給料=空白 上記の順番にレコードが出現すると、mydicにはレコードが登録されません。 normalDicには④のレコードが登録されます。 dupDicには⑤のレコードが登録されます。
tatsu99

2023/03/26 02:53

すみません。前のコメントに誤りがありました。給料は手当の間違いでした。 正しくは、以下のようになります。前のコメントは無視してください。 >Case Inta, Intbでは、employeeNumとteateがoまたは空白の重複するレコード(ケース2の手当ないバージョン)をもつ対象者が消えてしまうのです。 myDicに登録されていないということと理解しました。 元のデータ(CSVファイル)自体が、そのようになっているのではないでしょうか。 CSVファイルの内容を確認すれば良いかと。 ①社員番号=123 手当=空白 ②社員番号=123 手当=空白 ③社員番号=123 手当=10万 上記の順番にレコードが出現すると、mydicに②のレコードが登録されます。 normalDicには①レコードが登録されます。 dupdicには登録されません。 ④社員番号=123 手当=10万 ⑤社員番号=123 手当=空白 ⑥社員番号=123 手当=空白 上記の順番にレコードが出現すると、mydicにはレコードが登録されません。 normalDicには④レコードが登録されます。 dupDicには⑤のレコードが登録されます。
maimikan

2023/03/26 07:34 編集

書き方が悪くすみません。 >Case Inta, Intbでは、employeeNumとteateがoまたは空白の重複するレコード(ケース2の手当ないバージョン)をもつ対象者が消えてしまうのです。と記載したのは ケース2の対象者がdupDic「にも」登録されているためと考えています。 dupDicに登録されているために、ケース2の給料がない対象者はIf (tanjikan = "") And (teate = "") Or (teate = 0) And dupDic.Exists(employeeNum) Thenの処理にひっかかり、消えてしまうのだと思います。 上記想定で、コメントアウトした’ご質問の箇所↓ If Not myDic.Exists(employeeNum) Thenを追加したら、ケース2の対象者は条件にひっかからずになるため、出力されました。 理由は、dupDicに登録されている社員番号が同一で、インフラ手当が同一の対象者は、myDicとdupDicに登録されているため、という認識です。 ただ、そもそも 以下の処理をしているので、dupDicとmyDicに登録される理由がわかりません。 よろしくお願いいたします。 'dupDic未登録かつmyDic未登録なら、追加 If Not dupDic.Exists(employeeNum) Then If Not myDic.Exists(employeeNum) Then dupDic.Add employeeNum, employeeNum
maimikan

2023/03/26 07:36

出現しているレコードは、以下です。 ①社員番号=123 手当=空白 ②社員番号=123 手当=空白
tatsu99

2023/03/26 08:20

①社員番号=123 手当=空白 ②社員番号=123 手当=空白 上記のレコードの場合、 normalDicに①のレコードが登録され、myDicに②のレコードが登録されます。 normalDicは、最初に出現した社員番号のレコードを無条件に登録します。(よって①を登録) myDicは、myDicに該当社員番号が未登録であり、かつ、その社員番号と手当の両方が、normalDicに登録されている社員番号と手当が一致すれば、myDicに登録します。(よって②を登録)
tatsu99

2023/03/26 08:41

If (tanjikan = "") And (teate = "") Or (teate = 0) And dupDic.Exists(employeeNum) Then の箇所ですが、これは、 if ((tanjikan = "") And (teate = "")) or ((teate = 0) And dupDic.Exists(employeeNum)) then と同じことです。 よって、tanjikan が空白かつteateが空白なら、dupDicに社員が登録されていようがいまいが、成立することになります。以下のようにすべきです。 If (tanjikan = "") And ((teate = "") Or (teate = 0)) And dupDic.Exists(employeeNum) Then
maimikan

2023/03/27 05:32

ご回答いただきありがとうございました。 では、ご提示いただいた空白判定ルーチンKuhakuを呼び出す方法が最も適切だということですね。 空白判定ルーチンKuhakuですが、正常終了は確認できたのですが、重複が解消しておらず、すべて重複のまま出力されている状態です(ご回答内容をそのままコピペしました)。エラーがないので原因がわからないのですが、すみません、なにか他に追加しなければいけない条件などありますでしょうか?よろしくお願いいたします。
tatsu99

2023/03/27 05:49

>空白判定ルーチンKuhakuですが、正常終了は確認できたのですが、重複が解消しておらず、すべて重複のまま出力されている状態です(ご回答内容をそのままコピペしました)。 「重複が解消しておらず」とは、どういうことでしょうか? Kuhaku判定ルーチンを使用するということは、nomalDicだけを使用するということです。(myDic,dupDicは使用しない) nomariDicには、同じ社員番号は1つしか登録できません。したがって重複する(=2つ以上の同じ社員番号が登録される)ことはあり得ません。「重複が解消しておらず」とは、どのような状態なのでしょうか?
maimikan

2023/03/27 06:02 編集

Case Intc, dのほうを回収いたしました 社員番号含め、すべてのケースにおいて、重複したデータが出力されてしまします Set normalDic = CreateObject("Scripting.Dictionary") 'データ行まで読み飛ばし Line Input #1, buf 'ヘッダー行1読込 Line Input #1, buf 'ヘッダー行2読込 Line Input #1, buf 'ヘッダー行3読込 Line Input #1, buf 'カラムID行読込 Do Until EOF(1) Line Input #1, buf tmp = Split(buf, ",") Select Case val(ArySyoriSet(Pos_SyoriType)) Case Inta, Intb employeeNum = tmp(11) teate = tmp(16) vals = Array(employeeNum, shokusekiTeate) If Not normalDic.Exists(employeeNum) Then normalDic.Add employeeNum, vals Else If Not myDic.Exists(employeeNum) Then nvals = normalDic(employeeNum) '正常辞書の登録内容と全て一致するなら、追加 If vals(0) = nvals(0) And vals(1) = nvals(1) Then myDic.Add employeeNum, vals 'dupDicに登録済みなら削除 If dupDic.Exists(employeeNum) Then dupDic.Remove employeeNum End If End If End If If Not dupDic.Exists(employeeNum) Then If Not myDic.Exists(employeeNum) Then dupDic.Add employeeNum, employeeNum End If End If End If Case Intc, d employeeNum = tmp(11) teate = tmp(45) kyu = tmp(40) vals = Array(employeeNum, teate, kyu) If Not normalDic.Exists(employeeNum) Then normalDic.Add employeeNum, vals Else nvals = normalDic(employeeNum) If Kuhaku(nvals(1)) = True And Kuhaku(vals(1)) = False Then nvals(1) = vals(1) End If If Kuhaku(nvals(2)) = True And Kuhaku(vals(2)) = False Then nvals(2) = vals(2) End If normalDic(employeeNum) = nvals End If End Select Loop Close #1
maimikan

2023/03/27 05:58

ファンクションも、いただいたそのままでコピペしております
tatsu99

2023/03/27 06:18

>社員番号含め、すべてのケースにおいて、重複したデータが出力されてしまします 具体的にどういうことでしょうか。例えば、CSVファイルに ①社員番号=111 給与=空白 手当=空白 ②社員番号=111 給与=空白 手当=空白 ③社員番号=111 給与=20万 手当=10万 のレコードがあると、nomardicには、③のレコードが登録されます。 (正確には最初に①のレコードが登録され、値の部分(給与、手当)が③の内容で置き換わります) このことを重複したデータが出力されるというのでしたら、その通りですが、 普通は、重複しているとは言わないかと思います。
maimikan

2023/03/27 06:23 編集

ケース2を例にとると、 ①社員番号=111 給与=空白 手当=空白 ②社員番号=111 給与=空白 手当=空白 で出力されます。 社員番号は3つ以上の重複はないです。よろしくお願いいたします。
tatsu99

2023/03/27 06:31

Close #1 の後の行に、下記を追加すると、normalDicの内容を全て印字することが可能です。 For Each employeeNum In normalDic.keys vals = normalDic(employeeNum) Debug.Print vals(0), vals(1), vals(2) Next debug.print文で出力しているので、イミデイト・ウインドウに表示されます。 それで出力された内容を確認してください。
tatsu99

2023/03/27 06:35

>ケース2を例にとると、 >①社員番号=111 給与=空白 手当=空白 >②社員番号=111 給与=空白 手当=空白 >で出力されます。 本当にnormalDicの内容を出力すると、①②のように2件同じものが出力されるのでしょうか。 出力している個所のソースを提示していただけると、原因が判るかと思います。
maimikan

2023/03/27 06:40

上記と同じく、重複して出力されました。 ディクショナリがうなくいっていないのでしょうか。dimもsetもsetもあっているのですが。。
maimikan

2023/03/27 06:42

ただいまソースを提示するので、お時間ください
tatsu99

2023/03/27 06:44

>上記と同じく、重複して出力されました。 実際に出力している個所のソースを提示していただけませんでしょうか。
maimikan

2023/03/27 06:49

Case Intc, Intd nWs.Rows(Data_Start + 1 & ":" & Data_Start + 1).Copy 'If wi > 1 Then If wi > 0 Then Rows(Data_Start + 3 & ":" & wi + Data_Start + 3 - 1).Select Selection.PasteSpecial Paste:=xlPasteFormats '書式 Selection.PasteSpecial Paste:=xlPasteValidation '入力規則 End If BefType = val(wTmp(0, Pos_w_kitei)) StRow = 0 For i = 0 To wi - 1
tatsu99

2023/03/27 06:55

すみません。normalDicの内容に基づいて、出力しているはずかと思うのですが、提示されたソースでは normalDicを一切使っておりません。従って、noramlDicの内容とは、無関係にデータを出力しているように見えますが、いかがでしょうか。
maimikan

2023/03/27 06:56

subなど使用していないのですが、(15:02に提示した通り)それも原因のひとつになりうるでしょうか?
maimikan

2023/03/27 06:58

このマクロのコードがかなり長いので、すべてを記載するのは難しいのですが、 dupDicなどを使用していた際には反映され、なぜ今回は反映されないのかわからないです。 出力は上記のまま変えていないです
tatsu99

2023/03/27 07:15

>dupDicなどを使用していた際には反映され、なぜ今回は反映されないのかわからないです。 dupDicを使っていた場合も、関係ないとは思いますが、dupDicの内容に従い、とこかへGOTO文で飛んでいくような処理があるなら、それが影響している可能性があります。 何れにしろ、ソース全体がみえないので、私の方からは、これ以上の解決方法は提示できません。 ちなみに、データは何件ほどありますか。(重複を含めない社員番号の数です) すくないなら、normalDicのdebug.printで表示すれば済みますが、多いなら、どこかのシートへ出力したほうが良いかと思います。あなたが望まれるなら、回答欄にnormadicの内容をシートへ出力するマクロを提示します。
maimikan

2023/03/27 07:25

>dupDicを使っていた場合も、関係ないとは思いますが、dupDicの内容に従い、とこかへGOTO文で飛んでいくよう>な処理があるなら、それが影響している可能性があります。 これが原因な気がします。Gotoはありましたが、スキップする処理のため、削除してしまったので。。変更前は、該当のソースコード(更新)の通り、Gotoがあります データは3万件ほどあります。
guest

0

回答ではありません。ケース1、2はあなたが提示したケースでの判定です。
○:出力する ×:出力しない
ケース3、ケース4では、どのような判定結果になることを望んでますか?
ケース3はケース1と同じですが、最初にインフラ手当=8万のレコードが出現したケースです。
ケース4は、社員番号が同じで、給料とインフラ手当が異なるレコードが多数出現したケースです。
○と×で判定を入れてください。

社員番号給料インフラ手当判定
ケース1
000120万8万
000120万0万×
ケース2
000120万0万
000120万0万×
ケース3
000120万0万
000120万8万
ケース4
000120万0万
000120万8万
000120万30万
000130万30万

給料とインフラ手当は"20万"のように数字と万の文字から構成されいているのでしょうか。
万のほかに、千とか百とか十とかの文字もあるのでしょうか。

投稿2023/03/24 07:24

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maimikan

2023/03/24 07:43

社員番号 給料 インフラ手当 判定 ケース3 0001  20万  0万 × 0001  20万  8万 ○ ケース4 下記のように、インフラ手当と給料の両方に金額が入っている場合、かならず同額での重複です。 その場合、出力レコードは全く同じデータ内容なので、どちらが出力されても問題ございません。 (ケース2も、どちらが出力されてもよいです) 下記はインプットデータとして存在しないです 0001  20万  30万 0001  30万  30万 ↓ 下記の場合は存在します 0001  30万  30万 0001  30万  30万 (どちらが出力されてもOK) また、構成は数値ですので、万や十などの文字列はございません よろしくお願いいたします。
maimikan

2023/03/24 07:48

苦戦しておりましたのは、同額の場合の重複の削除でした。myDicを導入前は、 If (teate = "") Or (teate = 0) And (kyu = "") Or (kyu = 0) And dupDic.Exists(employeeNum) Then GoTo Continue ElseIf (teate = "") Or (teate = 0) And dupDic.Exists(employeeNum) And (tanjikan = "") Then GoTo Continue のコードで消えてしまっていたので(ケース2)。。 なので、myDicを作成し、dupDicに格納されないようにして、出力されないことは免れたのですが、今度は重複して出力されることになってしまいました、
maimikan

2023/03/24 07:51

なので、いま時点で解決できていないのは、ケース2の場合の重複回避のみです。
guest

0

以下のようにしてください。

VBA

1 Dim normalDic, dupDic, myDic As Object 2 3 Set normalDic = CreateObject("Scripting.Dictionary") 4 Set dupDic = CreateObject("Scripting.Dictionary") 5 Set myDic = CreateObject("Scripting.Dictionary") 6 7 'データ行まで読み飛ばし 8 Line Input #1, buf 'ヘッダー行1読込 9 Line Input #1, buf 'ヘッダー行2読込 10 Line Input #1, buf 'ヘッダー行3読込 11 Line Input #1, buf 'カラムID行読込 12 Do Until EOF(1) 13 Line Input #1, buf 14 tmp = Split(buf, ",") 15 16 employeeNum = tmp(11) 17 teate = tmp(45) 18 kyu = tmp(40) 19 '配列なので、実際のcsvのカラムから-1のカラム番号 20 Dim vals As Variant 21 22 vals = Array(employeeNum, teate, kyu) 23 ' 正常辞書に社員番号が存在しない場合、追加 24 If Not normalDic.Exists(employeeNum) Then 25 normalDic.Add employeeNum, vals 26 Else 27 ' 正常辞書に社員番号が存在する場合、重複辞書に追加 28 If Not myDic.Exists(employeeNum) Then 29 nvals = normalDic(employeeNum) 30 '正常辞書の登録内容と全て一致するなら、追加 31 If vals(0) = nvals(0) And vals(1) = nvals(1) And vals(2) = nvals(2) Then 32 myDic.Add employeeNum, vals 33 'dupDicに登録済みなら削除 34 If dupDic.Exists(employeeNum) Then 35 dupDic.Remove employeeNum 36 End If 37 End If 38 End If 39 'dupDic未登録かつmyDic未登録なら、追加 40 If Not dupDic.Exists(employeeNum) Then 41 If Not myDic.Exists(employeeNum) Then 42 dupDic.Add employeeNum, employeeNum 43 End If 44 End If 45 End If 46 47 Loop 48 49 Close #1 50

投稿2023/03/23 09:09

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsu99

2023/03/23 09:10

ソースが抜粋なので、こちらで動作確認はしておりません。
maimikan

2023/03/23 23:21

ご回答いただき誠にありがとうございます。 質問です。 社員番号、給料、インフラ手当が2レコード重複するとして、以下のようなイメージでした。 normalDicに追加 (1レコード目) 10000(社員番号) 20万(給料) 3万(インフラ手当) myDicにない社員番号、かつnormaldicに格納されている3項目と同一のため、 myDicに追加する (2レコード(重複)) 10000(社員番号) 20万(給料) 3万(インフラ手当) 結果、normalDicとmyDicに登録されるため、出力結果は2レコードになる 上記の重複を1レコードにしたかったので、 myDicに登録されている社員番号は削除する動作をいれました。 結果は、出力結果が0になってしまいました。 こちら、認識がまちがっているのでしょうか? よろしくお願いいたします。
maimikan

2023/03/23 23:27 編集

入れた処理は、以下になります。 教えていただいた処理の後に実施いたしました(クローズの後に再度ファイルをオープン後)。 If myDic.Exists(employeeNum) Then GoTo Continue
tatsu99

2023/03/24 00:37

私が提示したマクロをそのまま、組み込めば、 normalDicに1レコード登録され、 myDicに1レコード登録されるため、出力結果は計2レコードになる 上記のようになるはずですが、ならなかったのでしょうか。 もし、そのようになっていれば、myDicのレコードを削除する必要はないはずですが、 何故削除されたのでしょうか。
tatsu99

2023/03/24 00:49

>入れた処理は、以下になります。 >教えていただいた処理の後に実施いたしました(クローズの後に再度ファイルをオープン後)。 なぜ、クローズした後、再度ファイルをオープンして、読み込むのかが判りません。 ソースの全体、及びなさりたいことの全体像を提示していただければ、もっと良い回答ができるかもしれません。 又、normalDic,myDic,dupDicの目的を提示していただければ(3のdicを使って本当にやりたいこと)、 もっと簡単なdicの持ち方を回答できるかもしれません。
maimikan

2023/03/24 05:26 編集

>normalDicに1レコード登録され、 >myDicに1レコード登録されるため、出力結果は計2レコードになる この処理があってので、社員番号、給料、インフラ手当が同一の場合は重複レコードとして出力される認識でよろしいでしょうか。 私は↑の前提でしたので、myDicオブジェクト自体削除してしまえば、normalDicに登録された1レコードのみがのこり、社員番号、給料、インフラ手当が同一のデータがあったとしても、重複しない想定でした。 >normalDic,myDic,dupDicの目的を提示していただければ(3のdicを使って本当にやりたいこと)、 normalDic ⇒csvを読み込む際に、重複しない一意のデータを格納 dupDic ⇒normalDicと社員番号がかぶった対象者を格納する  dupDicに格納された社員に対し、給料、インフラ手当に条件をつけて出力しないように処理をする 例①(csvで取り込むレコード) 社員番号 給料 インフラ手当 00001 20万 8万 社員番号 給料 インフラ手当社員番号 00001 20万 0万 ⇒出力したくない(インフラ手当が0の場合は出力する処理をスキップすることにより重複したレコードの出力を回避) 例②(csvで取り込むレコード) ⇒社員番号 給料 インフラ手当 00002 20万 0万 社員番号 給料 インフラ手当社員番号 00002 20万 0万 上記データで、ひとつは出力したいのに、インフラ手当が0円かつ重複した社員番号となり、出力自体されなくなってしまう しかし、1レコードは出力させたい (わからないこと) ⇒どうやって、社員番号 給料 インフラ手当社員番号が全く同一の2レコードを1レコードだけ出力させられるか
maimikan

2023/03/24 05:34 編集

Set normalDic = CreateObject("Scripting.Dictionary") Set dupDic = CreateObject("Scripting.Dictionary") Set myDic = CreateObject("Scripting.Dictionary") 'データ行まで読み飛ばし Line Input #1, buf 'ヘッダー行1読込 Line Input #1, buf 'ヘッダー行2読込 Line Input #1, buf 'ヘッダー行3読込 Line Input #1, buf 'カラムID行読込 Do Until EOF(1) Line Input #1, buf tmp = Split(buf, ",") employeeNum = tmp(11) teate = tmp(45) kyu = tmp(40) '配列なので、実際のcsvのカラムから-1のカラム番号 Dim vals As Variant vals = Array(employeeNum, teate, kyu) ' 正常辞書に社員番号が存在しない場合、追加 If Not normalDic.Exists(employeeNum) Then normalDic.Add employeeNum, vals Else ' 正常辞書に社員番号が存在する場合、重複辞書に追加 If Not myDic.Exists(employeeNum) Then nvals = normalDic(employeeNum) '正常辞書の登録内容と全て一致するなら、追加 If vals(0) = nvals(0) And vals(1) = nvals(1) And vals(2) = nvals(2) Then myDic.Add employeeNum, vals 'dupDicに登録済みなら削除 If dupDic.Exists(employeeNum) Then dupDic.Remove employeeNum End If End If End If 'dupDic未登録かつmyDic未登録なら、追加 If Not dupDic.Exists(employeeNum) Then If Not myDic.Exists(employeeNum) Then dupDic.Add employeeNum, employeeNum End If End If End If Loop Close #1 wi = 0 'データ行まで読み飛ばし Line Input #1, buf 'ヘッダー行1読込 Line Input #1, buf 'ヘッダー行2読込 Line Input #1, buf 'ヘッダー行3読込 Line Input #1, buf 'カラムID行読込 Do Until EOF(1) '縦方向ループ Line Input #1, buf '1行読込 buf = "," & buf 'ダミー列を追加 tmp = Split(buf, ",") Case IntSyokyu_HK, IntSyokyu_K employeeNum = tmp(12) shokusekiTeate = tmp(46) hyoukaKyu = tmp(41) tanjikan = tmp(20) ' インフラ手当が空白で、かつ社員番号が重複している場合、レコードをスキップする If (teate = "") Or (teate = 0) And (kyu = "") Or (kyu = 0) And dupDic.Exists(employeeNum) Then GoTo Continue ElseIf (teate = "") Or (teate = 0) And dupDic.Exists(employeeNum) And (tanjikan = "") Then GoTo Continue End If End Select
tatsu99

2023/03/24 07:45

Continueのラベルが見当たりませんので、どこに戻るのかがよくわかりません。 回答欄に質問を書きましたので、それに返信をお願いします。 今までの話を伺うと、どうも、以下のようなことに思えます。 1.社員番号が同じレコードが複数存在した場合、 どれか1件のレコードのみを出力したい。 2.どのようにして、その1件のレコード決めるのかが、不明。 手当が0万と0万でない場合は、0万でないほうを採用・・・これは例①で提示されている。 給料が異なるレコードがあった場合、どちらを採用するのかが不明。(給料が多い方?) 手当が異なるレコードがあった場合、どちらを採用するのかが不明。(手当が多い方?)
tatsu99

2023/03/24 07:59

>⇒どうやって、社員番号 給料 インフラ手当社員番号が全く同一の2レコードを1レコードだけ出力させられるか myDicを参照しなければ良いだけです。 normalDicには、社員番号が同じものが複数格納されることはありません。 normalDicだけを順に処理すれば、1レコードだけ出力が可能になります。 但し、以下のようなケースでは、normalDicに手当が0円のレコードが格納されます。 1件目 社員番号=0001 給料=20万 インフラ手当=0万 2件目 社員番号=0001 給料=20万 インフラ手当=8万 この場合、現在の処理では、1件目がnomalDicに格納されるので、 2件目のレコードをnormalDicに格納し直す必要があります。
tatsu99

2023/03/24 08:09

要件を整理すると以下のようなことで良いでしょうか。 1.社員番号が同じレコードが複数存在する。 2.社員番号が同じレコードの給料は必ず全て、同じ金額である。 3.社員番号が同じレコードのインフラ手当は、空白の場合と金額が記述されている場合がある。 金額が記述されている場合は、必ず同じ金額が記述されている。 インフラ手当の金額が記述されている場合は、そのレコードを出力する。 社員番号が同じ全レコードのインフラ手当が空白の場合は、どれか1レコードを出力する。 インフラ手当が空白の判定は、tmp(45)="" で良いですか。(又はteate="") temp="0" (又はtemp="0")のケースもあるのですか?
maimikan

2023/03/24 08:26 編集

インフラ手当の空白の判定に変更はないです。(teate=""もtemp="0"のばあいもあり、両方空白として認識して問題ないです) 1.社員番号が同じレコードが複数存在する。  ⇒ご認識の通りです 2.社員番号が同じレコードの給料は必ず全て、同じ金額である。  ⇒片方が0の場合もございます   0001 0万 0万   0001 20万 0万 3.社員番号が同じレコードのインフラ手当は、空白の場合と金額が記述されている場合がある。  ⇒ご認識の通りです。 いま時点で、ケース2の場合の対象者をdupDicに格納しないようにし、かつ重複しないようにすればよいのかわからないです。myDicを参照しないとなると、dupDicに格納されてしまい、そのあとの If (teate = "") Or (teate = 0) And (kyu = "") Or (kyu = 0) And dupDic.Exists(employeeNum) Then GoTo Continue ElseIf (teate = "") Or (teate = 0) And dupDic.Exists(employeeNum) And (tanjikan = "") Then GoTo Continue の判定で2レコードすべて消えてしまい、ケース2の対象者がいなくなってしまうので難しいです。 判定はいま時点で問題なくうごいているので、変更したくなく、myDicに格納されている対象者はnormalDicにも格納されているので、myDicをそれごと削除してしまえば重複しない発送だったのですが、このようなコードがうまくかけません
tatsu99

2023/03/24 08:38

使うのはnomalDicのみとして、以下の手順で処理してはいかがでしょうか。 1.normalDicに未登録の場合は、無条件に格納。 2.normalDicに登録済みの場合は、valsを更新する。 dicのvals(1)が空白で取得レコードのvals(1)が空白以外なら、レコードのvals(1)で更新(給料) dicのvals(2)が空白で取得レコードのvals(2)が空白以外なら、レコードのvals(2)で更新(インフラ手当) 上記で、取得したnormalDicを出力する。(myDic,dupDicは作成しない)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問