No.2ベストアンサー
- 回答日時:
>配列を入れ子にして順にループ
せっかくエクセルを利用しているのであれば、エクセルに比較部分を処理したらよいと思います。
「EXACT」というエクセルの文字列比較関数を利用しましょう。
それと、エクセルをループで読み取るだけでも時間がかると思いますが、データベースとしてエクセルブックを扱い、相違部分だけのデータを抽出できます。
下の例は
※ブック1に二つのシート「変更前」「変更後」後が存在している
※「変更前」「変更後」のそれぞれのA列を比較する
※比較結果を、別のエクセルブック2として保存する
という処理になっています。
もし「変更前」「変更後」が別のブックである場合は、以下のコードを理解し、改造を加えてください。
Private Const DEF_ブックネタパス As String = "C:\Book1.xls"
Private Const DEF_ブック結果パス As String = "C:\Book2.xls"
Private Const DEF_シート変更前 As String = "変更前"
Private Const DEF_シート変更後 As String = "変更後"
Sub Main()
Dim l_dtb As DataTable = エクセル比較()
Dim l_strMsg As String = ""
If l_dtb.Columns.Count.Equals(0) Then
'カラムが存在しないということは、比較対象のデータ件数が0件
l_strMsg = "データが存在しない"
Else
Dim l_ary As New System.Collections.ArrayList
l_ary.Add(String.Format("データ相違数数{0}件", l_dtb.Rows.Count))
For Each l_drw As DataRow In l_dtb.Rows
Dim l_strWK As String
l_strWK = String.Format("{0}行目", l_drw.Item("F1").ToString())
l_strWK &= vbTab & String.Format("変更前「{0}」", l_drw.Item("F2").ToString())
l_strWK &= vbTab & String.Format("変更後「{0}」", l_drw.Item("F3").ToString())
l_ary.Add(l_strWK)
Next
l_strMsg = Join(CType(l_ary.ToArray(GetType(String)), String()), vbCrLf)
End If
MsgBox(l_strMsg)
End Sub
Function エクセル比較() As DataTable
Dim l_xlsApp As Object = CreateObject("Excel.Application")
l_xlsApp = CreateObject("Excel.Application")
'データの件数を取得する
Dim l_int件数 As Integer = 件数取得(l_xlsApp)
'比較情報ブックを作成する
比較作成(l_xlsApp, l_int件数)
'エクセルを閉じる
l_xlsApp.Quit()
Return 結果読み込み()
End Function
Function 件数取得(ByVal p_xlsApp As Object) As Integer
Dim l_xlsBook As Object = p_xlsApp.Workbooks.Open(DEF_ブックネタパス)
Dim l_xlsSheet1 As Object = l_xlsBook.Worksheets(DEF_シート変更前)
Dim l_xlsSheet2 As Object = l_xlsBook.Worksheets(DEF_シート変更後)
'シートのデータ件数の多い方を件数とする
Dim l_int件数 As Integer = System.Math.Max(データ範囲行(l_xlsSheet1), データ範囲行(l_xlsSheet2))
l_xlsBook.Close()
Return l_int件数
End Function
Function データ範囲行(ByVal p_xlsCells As Object) As Integer
Dim l_xlsCellsTop As Object = p_xlsCells.Cells(1)
Dim l_xlsCellsBottom As Object = l_xlsCellsTop.SpecialCells(11)
Return l_xlsCellsBottom.Row
End Function
Sub 比較作成(ByVal p_xlsApp As Object, ByVal p_int件数 As Integer)
'結果ブックを削除する
If System.IO.File.Exists(DEF_ブック結果パス) Then
Kill(DEF_ブック結果パス)
End If
'件数が存在しない場合、処理を行わない
If p_int件数.Equals(0) Then
Exit Sub
End If
'比較用のワークシート
Dim l_xlsBook As Object = p_xlsApp.Workbooks.Add
'比較用のワークシート
Dim l_xlsSheet As Object = l_xlsBook.Worksheets(1)
Dim l_xlsRangeA As Object = l_xlsSheet.Cells(1, 1)
Dim l_xlsRangeB As Object = l_xlsSheet.Cells(1, 2)
Dim l_xlsRangeC As Object = l_xlsSheet.Cells(1, 3)
Dim l_xlsRangeD As Object = l_xlsSheet.Cells(1, 4)
'A1~D1
Dim l_xlsRangeFil1 As Object = l_xlsSheet.Range(l_xlsRangeA, l_xlsRangeD)
'A1~Dのデータ件数分
Dim l_xlsRangeFil2 As Object = l_xlsSheet.Range(l_xlsRangeA, l_xlsRangeD.Offset(p_int件数))
'ブックのファイル情報
Dim l_intFileInfo As New System.IO.FileInfo(DEF_ブックネタパス)
'ブックファイル名
Dim l_strBookName As String = l_intFileInfo.Name
'ブックファイルパス
Dim l_strBookPath As String = l_intFileInfo.FullName.Substring(0, l_intFileInfo.FullName.Length - l_intFileInfo.Name.Length)
'関数を作成するワーク
Dim l_strRep() As String = New String() {l_strBookPath, l_strBookName, DEF_シート変更前, DEF_シート変更後}
'比較を行うエクセル関数文字列
Dim l_str変更前セル As String = String.Format("'{0}[{1}]{2}'!RC[-1]", New String() {l_strBookPath, l_strBookName, DEF_シート変更前})
Dim l_str変更後セル As String = String.Format("'{0}[{1}]{2}'!RC[-2]", New String() {l_strBookPath, l_strBookName, DEF_シート変更後})
Dim l_str関数書式 As String = "=IF(ISNUMBER({0}),TEXT({0}, ""@""),T({0}))"
'A1に行番号
l_xlsRangeA.FormulaR1C1 = "=Row()"
'B1に変更前シートの情報
l_xlsRangeB.FormulaR1C1 = String.Format(l_str関数書式, l_str変更前セル)
'C1に変更後シートの情報
l_xlsRangeC.FormulaR1C1 = String.Format(l_str関数書式, l_str変更後セル)
'D1に比較結果
l_xlsRangeD.FormulaR1C1 = "=EXACT(RC[-2], RC[-1])"
'オートフィル機能により、比較結果をデータ件数分反映する
l_xlsRangeFil1.AutoFill(l_xlsRangeFil2)
'結果を保存する
l_xlsBook.Close(True, DEF_ブック結果パス)
End Sub
Public Function 結果読み込み() As DataTable
Dim l_dtbRet As New DataTable
If IO.File.Exists(DEF_ブック結果パス) Then
'ブックをデータベースとして接続する文字列
Dim l_strCn As String = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 5.0;HDR=No;'", DEF_ブック結果パス)
'比較結果がFALSEのものだけを抽出(WHERE句をはずすと、全件取得)
Dim l_strSQL As String = "SELECT * FROM [Sheet1$] WHERE F4 = FALSE"
Dim l_fil As New System.Data.OleDb.OleDbDataAdapter(l_strSQL, l_strCn)
l_fil.Fill(l_dtbRet)
End If
Return l_dtbRet
End Function
返事が遅くなり申し訳ありません。
大変参考になりました。
>せっかくエクセルを利用しているのであれば、エクセルに比較部分を処理したらよいと思います。
確かにおっしゃられている通り、EXCELのワークシート関数とか操作を上手く利用したほうが格段に効率が良いですね。
結局、同じシートにデータを貼り付けてソートしてフィルタして実現できました。
テーブルとして使えるのも始めて知りました。
ありがとうございます。
No.1
- 回答日時:
vbは、特に最近の.netのvbは知らないのですが・・・。
vba風で良ければこんなのはどうでしょう。
内容が詳しくわからないのですが、
>エクセルに2つのシートには更新前と更新後のデータがあって、
とあるので、同じブック内の2つのシートだとして、比較結果のシートを作ります。
2つのシートの同じ位置のデータを比較するとします。
book1.xlsのsheet1とsheet2の(1,1)-(10,10)の範囲を比較するとします。
vbで、formにButton1を配置します。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'bookを開く
Dim wb As Object
wb = CreateObject("Excel.Application").Workbooks.Open(Filename:="c:\book1.xls")
'新しいシートを作って差分の計算式を代入(ここでは(1,1)-(10,10)の範囲
Dim ws As Object
ws = wb.Worksheets.Add()
ws.Range(ws.Cells(1, 1), ws.Cells(10, 10)).FormulaR1C1 = "=Sheet1!RC-Sheet2!RC"
'各種操作
'配列に入れても良いが、そのままws.Cells(row, col).valueでアクセスできる
'例えば結果表示
MessageBox.Show(ws.Cells(1, 1).value)
'後始末
ws = Nothing
wb.Close(savechanges:=False)
wb = Nothing
End Sub
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルVBAが途中で止まります
-
VBA シートをコピーする際に Co...
-
別ブックをダイアログボックス...
-
ワイルドカード「*」を使うとう...
-
VBA 別ブックからコピペしたい...
-
VBAで別ブックのシートを指定し...
-
マクロVBA別Excelブックにデー...
-
【Excel VBA】書き込み先ブック...
-
VBA コードを実行すると画面が...
-
vbaで他のブックに転記したい。...
-
エクセル vba ある検索値を別ブ...
-
ADOで複数のBookから抽出
-
VBAで別のブックにシートをコピ...
-
Excelマクロ 該当する値の行番...
-
【ExcelVBA】インデックスが有...
-
拡張メタファイルにて貼り付け
-
[Excel]ADODBでNull変換されて...
-
VBA 実行時エラー 2147024893
-
VBA 特定のユーザーのみパス...
-
【ExcelVBA】zip圧縮されたCSV...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA シートをコピーする際に Co...
-
エクセルVBAが途中で止まります
-
VBA 別ブックからコピペしたい...
-
別ブックをダイアログボックス...
-
ワイルドカード「*」を使うとう...
-
【マクロ】AブックからBブック...
-
【ExcelVBA】インデックスが有...
-
【ExcelVBA】zip圧縮されたCSV...
-
VBA コードを実行すると画面が...
-
VBA シート名が一致した場合の...
-
VBA 実行時エラー 2147024893
-
VBS Bookを閉じるコード
-
VBAで別のブックにシートをコピ...
-
VBAで別ブックのシートを指定し...
-
【マクロ】違うフォルダにある...
-
[Excel]ADODBでNull変換されて...
-
VBAで複数のブックを開かずに処...
-
【Excel VBA】書き込み先ブック...
-
Excelマクロ 該当する値の行番...
-
vbaでvbaProjectのパスワード解...
おすすめ情報