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

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

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

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

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Q&A

解決済

3回答

5827閲覧

【Excelマクロ】ファイルの最終文字取得・Excelの差分表示

forestfield

総合スコア14

VBA

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

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

0グッド

0クリップ

投稿2016/05/06 16:14

編集2016/05/07 04:12

Excelのマクロについて2つ教えてください。

<1>
ボタンを押したら特定のセルに入力した値がcsvファイルの末尾に1行追記されるマクロを作っています。
csvファイルの一番最後の文字が改行コードでないと直前の行に続けて記入されてしまうのですが、これをチェックする場合
・一度読み取りモードでcsvファイルを開く
・ファイルの最終行までよみこむ
・最後の文字を確認する
・ファイルを閉じる
・csvファイルを追記モードで開く
・最後が改行コードじゃなかった場合、改行コードを追記する
・入力値を追記する
・ファイルを閉じる
という手順しかないのでしょうか?
もっとスマートな方法、理想的な方法はありますか?
FileSystemObjectにもTextStreamにもファイルの最後の文字を取得するなんて都合のいい関数は無いようでした。

<2>
複数のExcelファイルの差分を表示させるマクロを作る場合、使用者に分かりやすいのはどういった方法でしょうか。最新ファイルが他のファイルの内容とどう違うのかを分かりやすくさせたいです。
各Excelファイルのファイル名は「固定文字列_日付_時間」、シート数は1シート。
内容は列数、行数共に増減する可能性のある表です。
現時点では
・マクロブックと同階層にある当日日付のExcelファイルをDir関数で取得
・マクロブックに各Excelファイルをシート別にCopyしてフィルタを解除
・コピーしたシート名をコピー元ファイル名の時間にする
・最も列数のあるシート、行数のあるシートから比較範囲を決定
・最も新しい時間のシートを基準に1セルずつ他のシートと比較
・値が同じ場合は最新シートの該当セルを白くぬる
・値が違う場合は最新シートの該当セルを赤くぬり、対するシート名のコメントを付与
で考えています。
もっとスマートな方法、理想的な方法はありますか?

Excelのバージョンは2010です。
他に必要な情報があれば聞いてください。
宜しくお願いします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

<1>
ファイルの最後の文字を取得するメソッドは単独ではありませんが、ファイルポインタを移動すればよいと思います。
ほとんど答えになってしまいますが、書いておきます。

VB

1Const ForReading = 1, ForWriting = 2, ForAppending = 8 2const fname = "C:\Temp\testfile.txt" 3Dim fso, stm 4Dim fsize, bAddCrlf 5 6Set fso = CreateObject("Scripting.FileSystemObject") 7fsize = 0 8If (fso.FileExists(fname)) Then 9 fsize = fso.GetFile(fname).Size 10End If 11bAddCrlf = (fsize > 0) 12If (fsize >= 2) Then 13 Set stm = fso.OpenTextFile(fname, ForReading, True) 14 ' 最後の2バイトがCRLFかどうかを読み込むため、ファイルサイズ-2バイトの位置に 15 ' ファイルポインタを移動 16 Call stm.Skip(fsize - 2) 17 Dim last 18 last = stm.Read(2) 19 bAddCrlf = (last <> vbCrLf) 20 stm.Close 21End If 22Set stm = fso.OpenTextFile(fname, ForAppending, True) 23If (bAddCrlf) Then 24 Call stm.WriteLine 25End If 26Call stm.Write("Append Value") 27stm.Close

ところで、この出力するCSVファイルは、最後の行に改行コードがあってはいけないのでしょうか?
また、このファイルは他の人やシステムが編集することがあるのでしょうか?
もし、両方クリアできるのであれば、WriteLineで出力しているだけでよいと思います。
(安全のためにロジックを組んでおくのは悪いことではないですが、プログラムは短いほうがバグが少ないです)

なお、Excelで一度開いて、閉じるという方法でも、一見問題ないように見えますが、
Excelの欠点として、CSVを開くと、前ゼロが落ちるという問題があります。
つまり、

CSV

1000001,1

のようなデータは、

CSV

11,1

になってしまいます。
他のシステムにデータを取り込もうとする場合など、これが問題になることも多いです。

<2>
あまり良い方法は思いつかないですね。
ファイルの比較については、Office 2013にはツールが付属します。
元のロジックで、一度赤くしたセルは白く塗りなおしてはいけない気がします。

行の増減もあるということなので、かなり難しいかと思います。
行が途中で削除されたら、それ以降の行はすべて変更扱いになります。
なにか、キーとなる列があれば、行追加・削除もとらえることはできると思います。

あと、質問が複数のときは、分けたほうが良いと思いますよ。

投稿2016/05/08 06:25

shiyavako

総合スコア49

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

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

forestfield

2016/05/09 11:06 編集

回答ありがとうございます。 Skipという関数は調べていた時に目にした事があるのですが、恥ずかしながらその名前のせいか末尾から先頭に向けて戻れるという発想に至りませんでした。参考になります。 csvファイルについてですが、最終行に改行コード(だけ)があってもいいのかという事ですよね?それは「だめ」です。 このcsvファイルを他のシステム(管轄外なので干渉不可)が読み込んで登録情報が更新(読み込んだcsvの内容に総入れ替え)されます。 なので少しでもシステムの仕様に合っていないと、読み込みに失敗して一時的に登録情報が全て消えてしまう事もあります。 csvファイルはやろうと思えば手動で編集出来てしまうので、万が一少し知識のある人によって手動で編集されてしまった場合を想定して少しでも対策をしておきたいです。 >ファイルの比較については、Office 2013にはツールが付属します。 他の回答者さんも教えてくれていましたが、実はExcelに比較機能的なものが(アドオン?が)あるのは目にしたことがあり、それは既に報告済みです。 しかし、社内の規定で申請が必要になるらしく大概その手の申請受理は長期間になる(機能していない?)との事で、皆こういう時は自分で作るという環境にあります。 比較ツールに関しては現状で利便性を求めるのは難しいという事を理解して貰っているので、 >元のロジックで、一度赤くしたセルは白く塗りなおしてはいけない気がします。 >なにか、キーとなる列があれば、行追加・削除もとらえることはできる こちらも参考にお伺いを立てながら質問文にある方式でゆっくり作っております。 >あと、質問が複数のときは、分けたほうが良いと思いますよ。 失礼しました! 同一人物の質問が同時にいくつも上がっているのは不快かと思い、まとめてしまいました。以後気を付けます。
guest

0

<1>
文章で書いたので、誤解をされたようですね。
私が言いましたのは下記のようなコードです。これで、csvの最後に(改行がなければ)改行が付加されると思います。

Workbooks.OpenText Filename:="C:\temp\test.csv" Application.DisplayAlerts = False ActiveWorkbook.SaveAs Filename:="C:\temp\test.csv", FileFormat:=xlCSV ActiveWindow.Close Application.DisplayAlerts = True

ここまでで、

・一度読み取りモードでcsvファイルを開く
・ファイルの最終行までよみこむ
・最後の文字を確認する
・ファイルを閉じる
・最後が改行コードじゃなかった場合、改行コードを追記する

が可能です。

あと、改行の有無を判断するのであれば、(私なら)line inputして、最後の行がlen()=0ならば改行ありと判断して、(そうでない場合には)改行を付けてもいいかもです。

<2>
最近のExcelには、(私は使ったことがないのですが)どこかに、対照比較する機能があったと思います。それを使うのがスマートだとは思います。(これは、マクロでなく、ユーザー教育の範疇になってしまいますが。)

(2010にもその機能があるかは、不詳です。すみません。)

が、<1>もですが、『スマート』とか『理想的』と考えていらっしゃるのが、どういうことかによるかと思います。

ほかにも、こういう手もあるよ~みたいな回答が付くといいですね!

投稿2016/05/07 10:27

編集2016/05/07 10:38
aki.aki.

総合スコア58

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

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

forestfield

2016/05/09 10:44 編集

引き続きの回答ありがとうございます。 完全に誤解をしておりました。 後出しになってしまい大変申し訳ないのですが今回は「電話番号」を扱うため、他の回答者さんも指摘されている「先頭0抜け」になってしまうので参考までに止めさせて頂きます。 回答を頂く前に自分なりに考えた結果・・・詳細な関数名などは忘れてしまったのですが、追記モードでcsvファイルを開いてファイルポインタの位置が0かどうかで判断しました。 >『スマート』とか『理想的』と考えていらっしゃるのが、どういうことかによるか これは人によって考え方が違うだろうなと思い、色んな方法・拘り・知識を聞けたらなぁと思って書きました。 例えば今回でいうと理論を尊重して一度「読取」で開くのか、結果が同じであれば「追記」で開いて対応するのか等もきになっていた所の一つです。
guest

0

<1>
csvファイルをExcelで開いて『上書き保存』しますと、最後に改行がない場合は、最後に改行が付いたと思います。それが一番手っ取り早いような感じがします。(違っていたらご容赦)

投稿2016/05/07 02:00

aki.aki.

総合スコア58

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

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

forestfield

2016/05/07 04:11

回答ありがとうございます。 使用者さんには色々と難しい方が多く、できれば「値を入れてボタンを押すだけですよ~」という方式で行きたいと考えております。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問