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

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

ただいまの
回答率

87.61%

2つのデータ(csvファイル)を比較し差異がある行のみを確認するには

受付中

回答 5

投稿 編集

  • 評価
  • クリップ 3
  • VIEW 12K+

score 13

現状

2つのcsvファイルを比較し、差異のある行を確認したいと考えており、
excelのマクロで比較処理をかけてみましたが、
1時間たっても終わらず、今現在も処理中です。
※これを書いている間に、 応答なしでExcelがフリーズしておりました。

ファイル内部の状態

・1列目から100列目まで比較元のデータが入っている。
・101列目から201列目まで比較先のデータが入っている。
・データは比較先・比較元各々で約170000行存在します。
・各セルのデータは日付・最大8桁の数値・任意の文字列、空のセルと複数存在する。

マクロ内容

Option Explicit
Sub 2019_cros()

Dim X As Long
Dim Y As Long
Dim Z1 As Long

Application.ScreenUpdating = False

X = 2
Y = 1
Z1 = 2

Do Until Cells(X, Y) = "" '比較元が空白である事を確認したら全処理を止める
'比較元を左、比較先を右とする。
If Cells(X, Y + 1) = Cells(Z1, Y + 110) And Cells(X, Y + 2) = Cells(Z1, Y + 111) And Cells(X, Y + 3) = Cells(Z1, Y + 112) And Cells(X, Y + 4) = Cells(Z1, Y + 113) And Cells(X, Y + 5) = Cells(Z1, Y + 114) And Cells(X, Y + 6) = Cells(Z1, Y + 115) And _
Cells(X, Y + 7) = Cells(Z1, Y + 116) And Cells(X, Y + 8) = Cells(Z1, Y + 117) And Cells(X, Y + 9) = Cells(Z1, Y + 118) And Cells(X, Y + 10) = Cells(Z1, Y + 119) And Cells(X, Y + 11) = Cells(Z1, Y + 120) And Cells(X, Y + 12) = Cells(Z1, Y + 121) And _
Cells(X, Y + 13) = Cells(Z1, Y + 122) And Cells(X, Y + 14) = Cells(Z1, Y + 123) And Cells(X, Y + 15) = Cells(Z1, Y + 124) And Cells(X, Y + 16) = Cells(Z1, Y + 125) And Cells(X, Y + 17) = Cells(Z1, Y + 126) And Cells(X, Y + 18) = Cells(Z1, Y + 127) And _
Cells(X, Y + 19) = Cells(Z1, Y + 128) And Cells(X, Y + 20) = Cells(Z1, Y + 129) And Cells(X, Y + 21) = Cells(Z1, Y + 130) And Cells(X, Y + 22) = Cells(Z1, Y + 131) And Cells(X, Y + 23) = Cells(Z1, Y + 132) And Cells(X, Y + 24) = Cells(Z1, Y + 133) And _
Cells(X, Y + 25) = Cells(Z1, Y + 134) And Cells(X, Y + 26) = Cells(Z1, Y + 135) And Cells(X, Y + 27) = Cells(Z1, Y + 136) And Cells(X, Y + 28) = Cells(Z1, Y + 137) And Cells(X, Y + 29) = Cells(Z1, Y + 138) And Cells(X, Y + 30) = Cells(Z1, Y + 139) And _
Cells(X, Y + 31) = Cells(Z1, Y + 140) And Cells(X, Y + 32) = Cells(Z1, Y + 141) And Cells(X, Y + 33) = Cells(Z1, Y + 142) And Cells(X, Y + 34) = Cells(Z1, Y + 143) And Cells(X, Y + 35) = Cells(Z1, Y + 144) And Cells(X, Y + 36) = Cells(Z1, Y + 145) And _
Cells(X, Y + 37) = Cells(Z1, Y + 146) And Cells(X, Y + 38) = Cells(Z1, Y + 147) And Cells(X, Y + 39) = Cells(Z1, Y + 148) And Cells(X, Y + 40) = Cells(Z1, Y + 149) And Cells(X, Y + 41) = Cells(Z1, Y + 150) And Cells(X, Y + 42) = Cells(Z1, Y + 151) And _
Cells(X, Y + 43) = Cells(Z1, Y + 152) And Cells(X, Y + 44) = Cells(Z1, Y + 153) And Cells(X, Y + 45) = Cells(Z1, Y + 154) And Cells(X, Y + 46) = Cells(Z1, Y + 155) And Cells(X, Y + 47) = Cells(Z1, Y + 156) And Cells(X, Y + 48) = Cells(Z1, Y + 157) And _
Cells(X, Y + 49) = Cells(Z1, Y + 158) And Cells(X, Y + 50) = Cells(Z1, Y + 159) And Cells(X, Y + 51) = Cells(Z1, Y + 160) And Cells(X, Y + 52) = Cells(Z1, Y + 161) And Cells(X, Y + 53) = Cells(Z1, Y + 162) And Cells(X, Y + 54) = Cells(Z1, Y + 163) And _
Cells(X, Y + 55) = Cells(Z1, Y + 164) And Cells(X, Y + 56) = Cells(Z1, Y + 165) And Cells(X, Y + 57) = Cells(Z1, Y + 166) And Cells(X, Y + 58) = Cells(Z1, Y + 167) And Cells(X, Y + 59) = Cells(Z1, Y + 168) And Cells(X, Y + 60) = Cells(Z1, Y + 169) And _
Cells(X, Y + 61) = Cells(Z1, Y + 170) And Cells(X, Y + 62) = Cells(Z1, Y + 171) And Cells(X, Y + 63) = Cells(Z1, Y + 172) And Cells(X, Y + 64) = Cells(Z1, Y + 173) And Cells(X, Y + 65) = Cells(Z1, Y + 174) And Cells(X, Y + 66) = Cells(Z1, Y + 175) And _
Cells(X, Y + 67) = Cells(Z1, Y + 176) And Cells(X, Y + 68) = Cells(Z1, Y + 177) And Cells(X, Y + 69) = Cells(Z1, Y + 178) And Cells(X, Y + 70) = Cells(Z1, Y + 179) And Cells(X, Y + 71) = Cells(Z1, Y + 180) And Cells(X, Y + 72) = Cells(Z1, Y + 181) And _
Cells(X, Y + 73) = Cells(Z1, Y + 182) And Cells(X, Y + 74) = Cells(Z1, Y + 183) And Cells(X, Y + 75) = Cells(Z1, Y + 184) And Cells(X, Y + 76) = Cells(Z1, Y + 185) And Cells(X, Y + 77) = Cells(Z1, Y + 186) And Cells(X, Y + 78) = Cells(Z1, Y + 187) And _
Cells(X, Y + 79) = Cells(Z1, Y + 188) And Cells(X, Y + 80) = Cells(Z1, Y + 189) And Cells(X, Y + 81) = Cells(Z1, Y + 190) And Cells(X, Y + 82) = Cells(Z1, Y + 191) And Cells(X, Y + 83) = Cells(Z1, Y + 192) And Cells(X, Y + 84) = Cells(Z1, Y + 193) And _
Cells(X, Y + 85) = Cells(Z1, Y + 194) And Cells(X, Y + 86) = Cells(Z1, Y + 195) And Cells(X, Y + 87) = Cells(Z1, Y + 196) And Cells(X, Y + 88) = Cells(Z1, Y + 197) And Cells(X, Y + 89) = Cells(Z1, Y + 198) And Cells(X, Y + 90) = Cells(Z1, Y + 199) And _
Cells(X, Y + 91) = Cells(Z1, Y + 200) And Cells(X, Y + 92) = Cells(Z1, Y + 201) And Cells(X, Y + 93) = Cells(Z1, Y + 202) And Cells(X, Y + 94) = Cells(Z1, Y + 203) And Cells(X, Y + 95) = Cells(Z1, Y + 204) And Cells(X, Y + 96) = Cells(Z1, Y + 205) And _
Cells(X, Y + 97) = Cells(Z1, Y + 206) And Cells(X, Y + 98) = Cells(Z1, Y + 207) And Cells(X, Y + 99) = Cells(Z1, Y + 208) And Cells(X, Y + 100) = Cells(Z1, Y + 209) And Cells(X, Y + 101) = Cells(Z1, Y + 210) And Cells(X, Y + 102) = Cells(Z1, Y + 211) And _
Cells(X, Y + 103) = Cells(Z1, Y + 212) And Cells(X, Y + 104) = Cells(Z1, Y + 213) And Cells(X, Y + 105) = Cells(Z1, Y + 214) And Cells(X, Y + 106) = Cells(Z1, Y + 215) And Cells(X, Y + 107) = Cells(Z1, Y + 216) And Cells(X, Y + 108) = Cells(Z1, Y + 217) Then

Range(Cells(X, Y), Cells(X, Y + 108)).Interior.ColorIndex = 45
Range(Cells(Z1, Y + 110), Cells(Z1, Y + 217)).Interior.ColorIndex = 42
'全セルが一致したので比較元にオレンジ、比較先に水色を塗る

X = X + 1
Z1 = 2

ElseIf Cells(Z1, Y + 110) = "" Then

X = X + 1
Z1 = 2
Else
Z1 = Z1 + 1

End If
Loop

配列変数を組んで入れていけば何とかなるのではないかと思いながら、
組むことができず、取り急ぎで組んだものです。

比較データをどう使うか

差異のあるデータ・片方にしか存在しないデータを元に、ここには登場しない別のcsvファイルを点検修正する予定です。

教えていただきたい事

・データの数的にマクロで比較する事が現実的かどうか。
(そもそも上記マクロがひどい内容だという事は重々承知しておりますが、書き直す時間なかなか取れず、件数の少ない別のcsvファイル間で処理ができ、最後に残ったこの大きなファイルに困っております。)

・Excel以外で同様の処理を行う方法はありますでしょうか?

以上となります。どなたかお知恵を拝借できないでしょうか?

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • NextSt

    2019/03/01 11:50

    ありがとうございます。
    仰られている内容を確認し比較データの構成部分に追記が必要だとわかりましたので、補足を致します。

    キャンセル

  • NextSt

    2019/03/01 12:11

    追記というよりコード自体修正が必要ですね。
    If Cells(X, Y + 1) = Cells(Z1, Y + 101)…に修正して後に続くものも値も修正します。
    これだと全部対象なしになってしまう…。

    逆に前のファイルがなんでうまく処理されてたのかわからなくなってきました。
    ご指摘ありがとうございます、コードを編集してみます。

    キャンセル

  • Zuishin

    2019/03/01 12:23

    コードに修正は必要でしょうが、どのみちそれが意図した通り動くかどうかはわからないわけですよね?
    これまでの回答が意図した動作になっているかどうかと、違っていれば数行のサンプルデータが必要ではないかと思います。

    キャンセル

回答 5

+3

これは明らかにawkの得意分野ですね。windowsでは馴染みが薄いかもしれませんが、今は簡単に使えるようにできます。

インストール不要!WindowsでLinuxコマンドを使う

次に以下のような感じのスクリプトをテキストエディタで書いてたとえばtest.awkというテキストファイルにセーブします。

BEGIN{FS=","; n=100}
{
    for(i=1; i<=n; i++){
        x=$i; y=$(i+n);
        if(x!=y){
            printf "line %d: col %d = '%s'; col %d = '%s'\n",  NR, i, x, i+n, y;
        }
    }
}

上記に従えばawk -f test.awk 対象ファイル
とコマンドを入力すると値の不一致なデータとその行・列番号が出力されるはずです。
入力元ファイルはCSVファイルにコンバートしてあるものとこのコードは仮定していますが、本来はtab区切りデータを推奨したいところです。

やってみないと分かりませんが、たぶんvbaよりは速く結果が返ってくるんじゃないかなと思います。慣れればVBAなんてバカバカしくて使ってられなくなる…はず。

gnu awk4 on windows

さらに調べてみたところ、https://www.klabaster.com/freeware.htmで、gawk4.0のwindows版実行ファイルが配布されています。
gawk4.0にはFPATという組み込み変数が追加されており、「値の中に,が含まれるcsvを扱おうとすると困ってしまう」問題を実質的に解決できるようになっています。
参考:GNU AWKでCSVファイルを楽々あつかう組込変数FPATと、関数のインダイレクト呼び出し

ダウンロードしてexeファイルをpathの通ったところに置くだけですので、導入の簡単さではbusyboxと変わらず、機能面を考えるとこちらが良いでしょう。

これを利用して上記スクリプトを書き換えたものを示しておきます。

BEGIN{FPAT="([^,]+)|(\"[^\"]+\")"; n=100}
{
    for(i=1; i<=n; i++){
        x=$i; y=$(i+n);
        if(x!=y){
            printf "line %d: col %d = '%s'; col %d = '%s'\n",  NR, i, x, i+n, y;
        }
    }
}

追記: 上記サイトから引用します。

このパターンでは、CSVファイルの規格にある「ダブルクォートで括られた中に改行を含めることが可能」というルールに対応することはできません。
このような中途半端な状態なのにCSVファイルを扱えると明言するのはおかしいのではないかという意見もありますが、gawkの開発は「完全を目指すのではなく9割をサクサクこなし、フィールドに改行を含むようなCSVファイルは専用のツールで処理すれば良い」という思想で進められました。

ようするに、いつでも使えるわけではないが、使えるときには使って簡単に片づけたらいいじゃんという発想です。awkとはそういうものです。awkが本件ではうまく使えない可能性はあるし、もっといい方法がある可能性もあります。

私はこれを唯一絶対最高の解決策だと主張したいわけではありません。しかし、条件が合うなら最短距離で問題を片づけられる可能性はあると考えています。何かごちゃごちゃ言っている人がいますが、まどわされず、ご自分の案件に使えるかどうかは質問者さんご自身が淡々と判断していただければと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/01 15:15

    きちんと正面から回答してください。4つとも全く回答できていませんよ。
    質問者が判断すればいいと言いつつ、「どこまで使えるのか全く判断材料がないもの」をどうしてあなたが勧め続けるのか、理由に見当が付かないのです。9割なんてとんでもない。
    問題の把握ができているなら正面から回答してください。問題点を提示しています。自分がどの程度使えるのか全く把握できてないものを、他人に勧めるなんて、無責任にも程がある、ただの詐欺だと言っているのです。

    キャンセル

  • 2019/03/01 15:43

    あなたの質問にこれ以上逐一反応する必要を認めません。

    キャンセル

  • 2019/03/01 16:03

    クリティカルな問題に対する回答すらできないのであれば、始めから勧めないでください。

    キャンセル

+2

・データの数的にマクロで比較する事が現実的かどうか。
(そもそも上記マクロがひどい内容だという事は重々承知しておりますが、書き直す時間なかなか取れず、件数の少ない別のcsvファイル間で処理ができ、最後に残ったこの大きなファイルに困っております。)

難しくはないと思うのですが件数が多い&条件が複数ある(というか多すぎる)ので時間がかかるのは仕方ないように思えます。
条件はすべてAndのようですので条件部分を書き直すといくらか時間が短縮される&処理が軽くなるかもしれません。
ちなみに私なら比較元が空白である事を確認したら全処理を止める記述のあとに
以下のように先に全セルが一致するか判定し、その判定結果をさらに判定するようにします。

    Dim i As Long
    Dim j As Long

    i = 1
    j = 110

    Dim flg As Boolean
    flg = True

    ' すべて同じなのか先に判定してしまう。
    Do While flg

        '比較元を左、比較先を右とする。
        If Cells(X, Y + i) = Cells(Z1, Y + j) Then

            ' 比較元と比較先が同じ場合
            ' 隣の列に移動
            i = i + 1
            j = j + 1

            'iが109になった場合は処理を抜ける
            If i = 109 Then

                Exit Do

            End If

        Else

            ' 比較元と比較先が同じではない場合
            flg = False

        End If

    Loop


flgがfalseになった場合は全セルが一致しなかった、ということになります。
たくさん書いたIf文の条件はこのflgに置き換えれば良いと思います。

・Excel以外で同様の処理を行う方法はありますでしょうか?

差分を比較するツール(例えばWinMergeとか)を使えば差分の確認だけならできます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/27 20:25

    すべての動作までは確認していないのでもし何かありましたらこちらにコメントを投稿してくだされば。

    キャンセル

  • 2019/02/28 17:05

    お返事ありがとうございます。

    昨日の晩に別業務をしながら、お返事内容をざっくり読ませていただき、
    行丸ごとしなくともいいというのは、確かに仰られている通りだなぁ…と思いながら、
    別の業務に押されてお返事が書けませんでした。

    今晩改めて確認させていただきます。

    キャンセル

  • 2019/02/28 21:47

    お忙しいなかコメントありがとうございます。
    もし引き続きVBAで実現したい(改良したい)と考えているのであれば力になりますのでコメントください。よろしくお願いいたします。

    キャンセル

+2

VBAでやるような処理ではないと思いますが、100セルが全て同じかどうかしか見ていないようですし、csvファイルといっても両ファイルの出力形式が同じなら、ファイルのテキスト比較でも要件を満たすのではないですか?

片方の行抜けは想定せず、同一行同士のテキスト比較しかしないのであれば、VBAでも容易に書くことはできます。

    Open "比較元csvファイル名" For Input As #1
    Open "比較先csvファイル名" For Input As #2

    Do Until EOF(1)
        Line Input #1, hoge1

        If Not EOF(2) Then
            Line Input #2, hoge2
        Else
            hoge2 = ""
        End If

        If hoge1 <> hoge2 Then
            'ここに不一致時の処理を書く
        End If
    Loop

    Close #1
    Close #2


とはいえ、安易すぎるコードかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/28 03:08

    CSVにはダブルクォートでエスケープする記述が書けるのと、Excelがアホみたいに読み込み時に変換をかけるので、Excelでセル値を比較する場合と結果が異なる可能性があります。
    何を正しい仕様とするかによりますが、そこの前提も必要です。

    キャンセル

  • 2019/02/28 07:33

    そうですね。
    その辺りの説明が面倒になってしまい、出力形式が同じとかテキスト比較とかの表現に含めてしまいましたが、説明不足だったかもしれませんね。

    キャンセル

  • 2019/02/28 17:00

    お返事ありがとうございます。

    定例処理が重なってしまい、お返事が返せず申し訳ありません。
    今晩確認させていただきます。

    キャンセル

+2

何か音沙汰がないし、質問者さんは他のやり方も模索してるとのことであり、また質問者さんのマクロを配列にしたバージョンを誰も作ってないので、awk方式ではカンマ付き数字あるだけで終わるし、いろいろ考慮した結果、回答することにしました。

■サンプルデータ作成用powershell

$fixedRow= New-Object PSObject
$fixedRow | Add-Member -MemberType NoteProperty -Name "dummy" -Value 'ダミー'

$colCount=109
$rowCount=17000

foreach($pat in @("left", "right")) {
    for ($col=0; $col -lt $colCount; $col++) {
        $fixedRow | Add-Member -MemberType NoteProperty -Name ($pat+($col+1)) -Value (([string]$col) + ",000")
    }
}

@(for ($row = 0; $row -lt $rowCount; ++$row) {
    $fixedRow
}) | ConvertTo-Csv -NoTypeInformation | select -Skip 1 | Out-File -Encoding Default data.csv


最左列をダミー、次の109列分のデータが左側、次の109列分のデータを右側として、17000行(1/10サイズ)のデータをdata.csvに作成している。ファイルサイズで32MB程度。
これをcreate_data.ps1とした場合、

powershell -ExecutionPolicy RemoteSigned -File create_data.ps1

とかで実行できるはず。

■CSV左右比較同一行削除フィルタpowershell

$header=New-Object System.Collections.ArrayList
#$leftColName=New-Object System.Collections.ArrayList
#$rightColName=New-Object System.Collections.ArrayList

$header.add('dummy') > $null
$colCount=109

$left = "left"
$right = "right"

foreach($colPrefix in @($left, $right)) {
    for ($i = 0; $i -lt $colCount; ++$i) {
        $header.add($colPrefix + $i) > $null
    }
}
# 汎用コード(A)...遅いので未使用
#for ($i = 0; $i -lt $colCount; ++$i) {
#    $leftColName.Add($left+$i) > $null
#    $rightColName.Add($right+$i) > $null
#}

Import-Csv -Encoding default -Path '.\data.csv' -Header $header |
where {
    # 汎用コード(B)...遅いので未使用
    #$result = $false
    #for ($i = 0; $i -lt $colCount; ++$i) {
    #    $result = $result -or ($_.($leftColName[$i]) -ne $_.($rightColName[$i]))
    #}
    #$result;

    $_.left0 -ne $_.right0 -or
    $_.left1 -ne $_.right1 -or
    $_.left2 -ne $_.right2 -or
    $_.left3 -ne $_.right3 -or
    $_.left4 -ne $_.right4 -or
    $_.left5 -ne $_.right5 -or
    $_.left6 -ne $_.right6 -or
    $_.left7 -ne $_.right7 -or
    $_.left8 -ne $_.right8 -or
    $_.left9 -ne $_.right9 -or
    $_.left10 -ne $_.right10 -or
    $_.left11 -ne $_.right11 -or
    $_.left12 -ne $_.right12 -or
    $_.left13 -ne $_.right13 -or
    $_.left14 -ne $_.right14 -or
    $_.left15 -ne $_.right15 -or
    $_.left16 -ne $_.right16 -or
    $_.left17 -ne $_.right17 -or
    $_.left18 -ne $_.right18 -or
    $_.left19 -ne $_.right19 -or
    $_.left20 -ne $_.right20 -or
    $_.left21 -ne $_.right21 -or
    $_.left22 -ne $_.right22 -or
    $_.left23 -ne $_.right23 -or
    $_.left24 -ne $_.right24 -or
    $_.left25 -ne $_.right25 -or
    $_.left26 -ne $_.right26 -or
    $_.left27 -ne $_.right27 -or
    $_.left28 -ne $_.right28 -or
    $_.left29 -ne $_.right29 -or
    $_.left30 -ne $_.right30 -or
    $_.left31 -ne $_.right31 -or
    $_.left32 -ne $_.right32 -or
    $_.left33 -ne $_.right33 -or
    $_.left34 -ne $_.right34 -or
    $_.left35 -ne $_.right35 -or
    $_.left36 -ne $_.right36 -or
    $_.left37 -ne $_.right37 -or
    $_.left38 -ne $_.right38 -or
    $_.left39 -ne $_.right39 -or
    $_.left40 -ne $_.right40 -or
    $_.left41 -ne $_.right41 -or
    $_.left42 -ne $_.right42 -or
    $_.left43 -ne $_.right43 -or
    $_.left44 -ne $_.right44 -or
    $_.left45 -ne $_.right45 -or
    $_.left46 -ne $_.right46 -or
    $_.left47 -ne $_.right47 -or
    $_.left48 -ne $_.right48 -or
    $_.left49 -ne $_.right49 -or
    $_.left50 -ne $_.right50 -or
    $_.left51 -ne $_.right51 -or
    $_.left52 -ne $_.right52 -or
    $_.left53 -ne $_.right53 -or
    $_.left54 -ne $_.right54 -or
    $_.left55 -ne $_.right55 -or
    $_.left56 -ne $_.right56 -or
    $_.left57 -ne $_.right57 -or
    $_.left58 -ne $_.right58 -or
    $_.left59 -ne $_.right59 -or
    $_.left60 -ne $_.right60 -or
    $_.left61 -ne $_.right61 -or
    $_.left62 -ne $_.right62 -or
    $_.left63 -ne $_.right63 -or
    $_.left64 -ne $_.right64 -or
    $_.left65 -ne $_.right65 -or
    $_.left66 -ne $_.right66 -or
    $_.left67 -ne $_.right67 -or
    $_.left68 -ne $_.right68 -or
    $_.left69 -ne $_.right69 -or
    $_.left70 -ne $_.right70 -or
    $_.left71 -ne $_.right71 -or
    $_.left72 -ne $_.right72 -or
    $_.left73 -ne $_.right73 -or
    $_.left74 -ne $_.right74 -or
    $_.left75 -ne $_.right75 -or
    $_.left76 -ne $_.right76 -or
    $_.left77 -ne $_.right77 -or
    $_.left78 -ne $_.right78 -or
    $_.left79 -ne $_.right79 -or
    $_.left80 -ne $_.right80 -or
    $_.left81 -ne $_.right81 -or
    $_.left82 -ne $_.right82 -or
    $_.left83 -ne $_.right83 -or
    $_.left84 -ne $_.right84 -or
    $_.left85 -ne $_.right85 -or
    $_.left86 -ne $_.right86 -or
    $_.left87 -ne $_.right87 -or
    $_.left88 -ne $_.right88 -or
    $_.left89 -ne $_.right89 -or
    $_.left90 -ne $_.right90 -or
    $_.left91 -ne $_.right91 -or
    $_.left92 -ne $_.right92 -or
    $_.left93 -ne $_.right93 -or
    $_.left94 -ne $_.right94 -or
    $_.left95 -ne $_.right95 -or
    $_.left96 -ne $_.right96 -or
    $_.left97 -ne $_.right97 -or
    $_.left98 -ne $_.right98 -or
    $_.left99 -ne $_.right99 -or
    $_.left100 -ne $_.right100 -or
    $_.left101 -ne $_.right101 -or
    $_.left102 -ne $_.right102 -or
    $_.left103 -ne $_.right103 -or
    $_.left104 -ne $_.right104 -or
    $_.left105 -ne $_.right105 -or
    $_.left106 -ne $_.right106 -or
    $_.left107 -ne $_.right107 -or
    $_.left108 -ne $_.right108
} | ConvertTo-Csv -NoTypeInformation | select -Skip 1 | Out-File -Encoding Default diff.csv


data.csvを読んで左右を比較し、同一行はフィルタして、違ってるものをdiff.csvとして吐き出す。ぶっちゃけ遅い。
これをfilter_data.ps1とした場合、

powershell -ExecutionPolicy RemoteSigned -File filter_data.ps1
とかで実行できるはず。

■CSV左右比較同一行削除フィルタpython3スクリプト

import csv

target_file = 'data.csv'
diff_file   = 'diff.csv'
encoding    = 'cp932'
delimiter   = ','

with open(target_file, 'r', encoding=encoding, newline='') as f:
    reader = csv.reader(f, delimiter=delimiter)
    with open(diff_file, 'w', encoding=encoding, newline='') as g:
        writer = csv.writer(g, delimiter=delimiter)

        offset = 1
        count = 109
        for row in reader:
            result = False
            for i in range(count):
                result = result or (row[offset + i] != row[offset + count + i])
            if result:
                writer.writerow(row)


同じことをするpython3スクリプト。CSVのクォート仕様が最小限なので、出力は少し異なる。
実行にはpython3.Xが必要。これをdiff.pyとした場合、

python diff.py

で実行できる(環境によってはpythonでなくpython3。適宜読み替え)。

■読込形式と出力を揃えたawkスクリプト

BEGIN{FS=","; n=109}
{
    is_diff = 0;
    for(i=1; i<=n; i++){
        x=$(i+1); y=$(i+n+1);
        if(x!=y){
            is_diff = 1;
            break;
        }
    }
    if (is_diff == 1) {
        printf $0 "\n";
    }
}


クォートを処理できないので、正しくparseできず、全てを異なる判定にしてしまう。動かしたければフィールド値にカンマを入れないように元データを修正しないとダメ。オススメは全くしないが、実行にはbusyboxを使いたいらしい。
これをdiff.awkとした場合、

busybox64.exe awk -f diff.awk data.csv > diff.csv

のように実行できる(インストールすると邪魔なファイルができるのでしてない)。

■1/10サイズの測定(32MB)
awk: 1,660ms
python: 1,647ms
powershell: 14,272ms
※ただしawk版は正しく処理できていない
※測定は繰り返し行い、最低値を使用(ディスクアクセスはキャッシュされたものが使われ、外部の影響も最小に)。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/28 16:59

    お返事ありがとうございます。

    タイミング悪く定例処理が重なってしまい、
    お返事を多くの方からいただいているのは確認していたのですが、
    お返事が返せずじまいでした。
    今日の夜に再度確認させていただきます。

    [PS]
    pythonの例を書き込んでいただきありがとうございます。
    実は勉強したくて積み本にしてる1冊がpython本です。
    後で必ず確認させていただきます。

    キャンセル

0

こんにちは。よろしくおねがいいたします。
比較対象のA.csvとB.csvで、それぞれの行が単純に完全一致しているかどうかを見るだけでいいなら、1~100列目のデータをつないでしまって、すごく長〜い文字列にしてしまい、それをA.csv対B.csvで比較してしまえばいいのでは?と考えました。
CSVに入っているデータは日付や数値や文字列などさまざまある、ということですが、CSVであるかぎりは全部”文字列"なので、単純比較が可能なのでは?と考えました。

それで考えてみたのが、以下のコードです。
A.CSVとB.CSVを、GetOpenFilenameで選択して開くようにしています。

不一致が発見されたら、"レポートシート"の1~100列目にA.CSVの内容を、101~200列目にB.CSVの内容を転記します。
さらに、不一致の発見されたデータのペアにおいて、セルを黄色にしています。

これで私のほうで、1000行100列ぐらいのCSVでテストしましたが、成功しています。

Option Explicit

Sub Compare2CSVs()
'2個のCSV(PartA_CSV、PartB_CSV)の、それぞれ1~100列目の内容を比較する
'不一致があれば、その行をレポートシートに出力する
'不一致のある部分のセルを黄色にする

Dim ReportSheet As Worksheet
Set ReportSheet = ThisWorkbook.Worksheets("レポートシート")

Dim PartA_CSV As String
Dim PartB_CSV As String

Dim I As Long, J As Long

Dim r As Long 'レポートシートの行番号です

'CSVの1行ぶんの文字列です
Dim strCSV_A As String
Dim strCSV_B As String

'CSVの1行ぶんを、配列に格納するためのものです
Dim ArrCSV_A As Variant
Dim ArrCSV_B As Variant

'100列分の内容を、ひとかたまりにします
Dim VeryLongString_A As Variant
Dim VeryLongString_B As Variant


'PartA_CSVを開きます
PartA_CSV = Application.GetOpenFilename("CSVファイル,*.csv", Title:="PartAのCSVを選択してください")

'うっかりキャンセルボタンを押された場合の処理
If PartA_CSV = "False" Then
  MsgBox "キャンセルされました"
  Exit Sub
End If

'PartB_CSVを開きます
PartB_CSV = Application.GetOpenFilename("CSVファイル,*.csv", Title:="PartBのCSVを選択してください")

'うっかりキャンセルボタンを押された場合の処理
If PartB_CSV = "False" Then
  MsgBox "キャンセルされました"
  Exit Sub
End If

r = 1

'PartAのCSVファイルを開きます
Open PartA_CSV For Input As #1

'PartBのCSVファイルを開きます
Open PartB_CSV For Input As #2

Do Until EOF(1)

  VeryLongString_A = ""
  VeryLongString_B = ""

  Line Input #1, strCSV_A

  'PartA_CSVの一行分を、100個の配列に格納します
  ArrCSV_A = Split(strCSV_A, ",")

  For I = 0 To CSVColumnLength - 1
    '100個の配列の内容を、一個の長〜い文字列にします
    VeryLongString_A = VeryLongString_A & ArrCSV_A(I)
  Next I

  Line Input #2, strCSV_B

  'PartB_CSVの一行分を、100個の配列に格納します
  ArrCSV_B = Split(strCSV_B, ",")

  For I = 0 To 100 - 1
    '100個の配列の内容を、一個の長〜い文字列にします
    VeryLongString_B = VeryLongString_B & ArrCSV_B(I)
  Next I

  '2つの長〜い文字列を比較します
  If VeryLongString_A <> VeryLongString_B Then

    For J = 1 To 100
      '1~100列目に、PartAの内容を転記します
      ReportSheet.Cells(r, J) = ArrCSV_A(J - 1)
      '101~200列目に、PartBの内容を転記します
      ReportSheet.Cells(r, 100 + J) = ArrCSV_B(J - 1)

      '不一致している部分がわかりやすいようにセルを黄色にします
      If ArrCSV_A(J - 1) <> ArrCSV_B(J - 1) Then
        ReportSheet.Cells(r, J).Interior.Color = vbYellow
        ReportSheet.Cells(r, 100 + J).Interior.Color = vbYellow
      End If

    Next J

    'ここで行送りします
    r = r + 1
  End If

  'CSVファイルの次の行へシフトします
Loop

'PartAのCSVファイルを閉じます
Close #1

'PartBのCSVファイルを閉じます
Close #2

'結果のレポートシートをアクティベートします
ReportSheet.Activate

End Sub

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る