質問: Excelのマクロについて2つ教えてください。 <1> ボタンを押したら特定のセルに入力した値がcsvファイルの末尾に1行追記されるマクロを作っています。 csvファイルの一番最後の文字が改行コードでないと直前の行に続けて記入されてしまうのですが、これをチェックする場合 ・一度読み取りモードでcsvファイルを開く ・ファイルの最終行までよみこむ ・最後の文字を確認する ・ファイルを閉じる ・csvファイルを追記モードで開く ・最後が改行コードじゃなかった場合、改行コードを追記する ・入力値を追記する ・ファイルを閉じる という手順しかないのでしょうか? もっとスマートな方法、理想的な方法はありますか? FileSystemObjectにもTextStreamにもファイルの最後の文字を取得するなんて都合のいい関数は無いようでした。 <2> 複数のExcelファイルの差分を表示させるマクロを作る場合、使用者に分かりやすいのはどういった方法でしょうか。最新ファイルが他のファイルの内容とどう違うのかを分かりやすくさせたいです。 各Excelファイルのファイル名は「固定文字列_日付_時間」、シート数は1シート。 内容は列数、行数共に増減する可能性のある表です。 現時点では ・マクロブックと同階層にある当日日付のExcelファイルをDir関数で取得 ・マクロブックに各Excelファイルをシート別にCopyしてフィルタを解除 ・コピーしたシート名をコピー元ファイル名の時間にする ・最も列数のあるシート、行数のあるシートから比較範囲を決定 ・最も新しい時間のシートを基準に1セルずつ他のシートと比較 ・値が同じ場合は最新シートの該当セルを白くぬる ・値が違う場合は最新シートの該当セルを赤くぬり、対するシート名のコメントを付与 で考えています。 もっとスマートな方法、理想的な方法はありますか? Excelのバージョンは2010です。 他に必要な情報があれば聞いてください。 宜しくお願いします。
回答: <1> ファイルの最後の文字を取得するメソッドは単独ではありませんが、ファイルポインタを移動すればよいと思います。 ほとんど答えになってしまいますが、書いておきます。 ``` Const ForReading = 1, ForWriting = 2, ForAppending = 8 const fname = "C:\Temp\testfile.txt" Dim fso, stm Dim fsize, bAddCrlf Set fso = CreateObject("Scripting.FileSystemObject") fsize = 0 If (fso.FileExists(fname)) Then fsize = fso.GetFile(fname).Size End If bAddCrlf = (fsize > 0) If (fsize >= 2) Then Set stm = fso.OpenTextFile(fname, ForReading, True) ' 最後の2バイトがCRLFかどうかを読み込むため、ファイルサイズ-2バイトの位置に ' ファイルポインタを移動 Call stm.Skip(fsize - 2) Dim last last = stm.Read(2) bAddCrlf = (last <> vbCrLf) stm.Close End If Set stm = fso.OpenTextFile(fname, ForAppending, True) If (bAddCrlf) Then Call stm.WriteLine End If Call stm.Write("Append Value") stm.Close ``` ところで、この出力するCSVファイルは、最後の行に改行コードがあってはいけないのでしょうか? また、このファイルは他の人やシステムが編集することがあるのでしょうか? もし、両方クリアできるのであれば、WriteLineで出力しているだけでよいと思います。 (安全のためにロジックを組んでおくのは悪いことではないですが、プログラムは短いほうがバグが少ないです) なお、Excelで一度開いて、閉じるという方法でも、一見問題ないように見えますが、 Excelの欠点として、CSVを開くと、前ゼロが落ちるという問題があります。 つまり、 ``` 000001,1 ``` のようなデータは、 ``` 1,1 ``` になってしまいます。 他のシステムにデータを取り込もうとする場合など、これが問題になることも多いです。 <2> あまり良い方法は思いつかないですね。 ファイルの比較については、Office 2013にはツールが付属します。 元のロジックで、一度赤くしたセルは白く塗りなおしてはいけない気がします。 行の増減もあるということなので、かなり難しいかと思います。 行が途中で削除されたら、それ以降の行はすべて変更扱いになります。 なにか、キーとなる列があれば、行追加・削除もとらえることはできると思います。 あと、質問が複数のときは、分けたほうが良いと思いますよ。