エクセル幼稚園:テキストファイルから読み出す [コンピューター]
7/16の記事では、元データのセル範囲をSub aaa()の10-25行目に埋め込んでいましたが、
ファイル名: cell1.txt
01: d11,b14,c14:c15
02: d11,b16,c16:c18
03: d11,b19,c19:c20
04: d11,b21,c21:c22
というような、カンマで区切られたセル範囲のデータをテキストファイルから読み込んで処理するにはどうしたらよいでしょうか?
Sub aaa()の10-25行目を削除して、cell1.txtファイルから、元データのセル範囲を読み込むように変更しました。変更した行に(*)を示します。
01(_):Sub aaa()
02(_): ' 機能:エクセル上のデータを加工して、コマンドファイル(テキスト)を作成する
03(*): Dim myRange1() As String ' 元データのセル範囲
04(*): ReDim myRange1(2, 0) ' (x, y) x:opの番号(0-2) y:データの番号(可変)
05(_): Dim cmd2 As String ' コマンドの文字列
06(_): Dim file1 As String ' ファイル名
07(_): Dim nFNO As Integer 'ファイル番号
08(_): Dim str1(2) As String ' 文字列
09(_): Dim ans1 As Integer ' 答え
10(*): Dim i, j As Integer ' For文用
11(*): Dim buf As String ' テキスト読み出し用バッファ
12(*): Dim tmp As Variant ' テキスト分割用
13(_):
14(*): '元データのセル範囲を読み込む
15(*): ' ファイル名を作成
16(*): file1 = ThisWorkbook.Path & "\cell1.txt"
17(*): ' ファイルが存在しなかったら、終了
18(*): If Dir(file1) = "" Then
19(*): MsgBox file1 & vbCrLf & "が存在しません。"
20(*): Exit Sub
21(*): End If
22(*): ' 使用可能なファイル番号を調べる
23(*): nFNO = FreeFile()
24(*): ' ファイルを開く (読み出し)
25(*): Open file1 For Input As #nFNO
26(*): ' EOFまで1行ずつ読み出す
27(*): i = 0 ' データの番号
28(*): Do Until EOF(1)
29(*): ReDim Preserve myRange1(2, i) ' 配列をデータ方向に1つ拡大
30(*): Line Input #nFNO, buf ' 1行ずつ読み出す
31(*): tmp = Split(buf, ",") ' カンマで分割
32(*): For j = LBound(tmp) To UBound(tmp)
33(*): myRange1(j, i) = tmp(j) ' myRange1配列に格納
34(*): ' MsgBox "myRange1(" & j & "," & i & ")=" & myRange1(j, i) ' debug
35(*): Next
36(*): i = i + 1 ' 次のデータの番号
37(*): Loop
38(*): ' ファイルを閉じる
39(*): Close #nFNO
40(*): ' MsgBox " UBound(myRange1, 2)=" & UBound(myRange1, 2) ' debug
41(_): ' ファイル名を作成
42(_): file1 = ThisWorkbook.Path & "\" & Range("b11").Value & ".txt"
43(_): ' ファイルが存在する場合、上書きして良いか、確認する
44(_): If Dir(file1) <> "" Then
45(_): str1(0) = file1 & vbCrLf & "は存在します。" & vbCrLf
46(_): str1(0) = str1(0) & "上書きしますか?"
47(_): ' 上書きするか確認
48(_): ans1 = MsgBox(str1(0), vbYesNo + vbExclamation + vbDefaultButton2)
49(_): ' 場合分け
50(_): Select Case ans1
51(_): Case vbYes ' 「はい」
52(_): ' ファイル書込みする(End If以降を実行)
53(_): Case vbNo ' 「いいえ」
54(_): ' ファイル書込みせず、Subを抜ける
55(_): Exit Sub
56(_): Case Else '「はい」でも「いいえ」でもない
57(_): ' ファイル書込みせず、Subを抜ける
58(_): Exit Sub
59(_): End Select
60(_): Else
61(_): MsgBox (file1 & vbCrLf & "を作成します。")
62(_): End If
63(_): ' 使用可能なファイル番号を調べる
64(_): nFNO = FreeFile()
65(_): ' ファイルを開く
66(_): Open file1 For Output As #nFNO
67(_): ' ファイルへ書き込む
68(_): Print #nFNO, "hoge hoge"
69(*): For i = LBound(myRange1, 2) To UBound(myRange1, 2)
70(*): If myRange1(0, i) <> "" Then
71(*): cmd2 = UFCmd1(myRange1(0, i), myRange1(1, i), myRange1(2, i))
72(_): Print #nFNO, cmd2
73(_): End If
74(_): Next
75(_): ' ファイルを閉じる
76(_): Close #nFNO
77(_):End Sub
プログラムが長くなってしまいました。。
データが少ないときは、プログラムの中にデータを埋め込んだ方が楽ですが、
データが多くなると、データを別ファイルに分けた方が、管理が楽です。
変更した部分を説明します。
03-04行目:myRange1配列変数の宣言を変えています。03行目では配列の添字を入れず、04行目のReDimで配列の大きさを指定しています。
7/16のSub aaa()とは、添字の順番を入れ替えています。
理由は、最後の添字しか、ReDimで変更できないというVBAの制限によります。
ReDimを使って、配列の大きさを可変とすることを、動的配列と言います。
動的配列とした理由は、テキストファイルから読み込むデータ量で配列の大きさを変更したいからです。
10行目:j変数を追加。
11-12行目:テキストファイルからセル範囲のデータを読み込んでmyRange1配列に代入する処理のため、buf, tmp変数を追加。
14-40行目:元データのセル範囲をテキストファイルから読み込んで、myRange1配列に代入しています。
16行目:ファイル名をcell1.txtとして定義し、file1変数に代入。
18-20行目:cell1.txtファイルが無かったら、処理を中止。
23行目:使用可能なファイル番号を調べて、nFNO変数に代入。
25行目:cell1.txtファイルを読み出しモードで開く。
27行目:データ番号(i変数)を0に初期化。
28-37行目:cell1.txtファイルから1行ずつ読み出し、ファイルの最後(EOF)まで繰り返す。
29行目:myRange1配列をデータ方向に1つ拡大。ここで、Preserveを指定しているのは、今まで読み込んだデータを消去したくないから。
30行目:ファイルから1行読み出し、buf変数に代入。
31行目:読み出した内容をカンマで区切って、tmp配列に代入。
32-35行目:tmp配列の内容を、myRange1配列に転記。
36行目:データ番号(i)を1増やします。
39行目:cell1.txtファイルを閉じます。
69行目:LBound(配列の添字の最少), UBound(配列の添字の最大)でデータの数だけ、繰り返すようにしています。
myRange1配列の添字の順番を入れ替えたので、2次元を指定しています。
70行目:セル範囲(op1)の文字列が空文字列でなかったら、71-72行目を実行。
71行目:UFCmd1関数を呼んで、コマンド文字列をcmd2変数に代入。70-71行目でmyRange1配列の添字の順序が逆になっています。
(PS)この間、止まってしまった古い方の腕時計ですが、再度、電池を入れ替えてもらったところ、
今のところ、動いています。。お店の人曰く、腕時計の回路が故障により、電池の電圧が異常低下したのだとか。。
新しい時計を買ってしまったので、古い方は、そのまま、机の上に飾っておきます。。
The Rolling Stones - Bridges to Babylon - Too Tight
ファイル名: cell1.txt
01: d11,b14,c14:c15
02: d11,b16,c16:c18
03: d11,b19,c19:c20
04: d11,b21,c21:c22
というような、カンマで区切られたセル範囲のデータをテキストファイルから読み込んで処理するにはどうしたらよいでしょうか?
Sub aaa()の10-25行目を削除して、cell1.txtファイルから、元データのセル範囲を読み込むように変更しました。変更した行に(*)を示します。
01(_):Sub aaa()
02(_): ' 機能:エクセル上のデータを加工して、コマンドファイル(テキスト)を作成する
03(*): Dim myRange1() As String ' 元データのセル範囲
04(*): ReDim myRange1(2, 0) ' (x, y) x:opの番号(0-2) y:データの番号(可変)
05(_): Dim cmd2 As String ' コマンドの文字列
06(_): Dim file1 As String ' ファイル名
07(_): Dim nFNO As Integer 'ファイル番号
08(_): Dim str1(2) As String ' 文字列
09(_): Dim ans1 As Integer ' 答え
10(*): Dim i, j As Integer ' For文用
11(*): Dim buf As String ' テキスト読み出し用バッファ
12(*): Dim tmp As Variant ' テキスト分割用
13(_):
14(*): '元データのセル範囲を読み込む
15(*): ' ファイル名を作成
16(*): file1 = ThisWorkbook.Path & "\cell1.txt"
17(*): ' ファイルが存在しなかったら、終了
18(*): If Dir(file1) = "" Then
19(*): MsgBox file1 & vbCrLf & "が存在しません。"
20(*): Exit Sub
21(*): End If
22(*): ' 使用可能なファイル番号を調べる
23(*): nFNO = FreeFile()
24(*): ' ファイルを開く (読み出し)
25(*): Open file1 For Input As #nFNO
26(*): ' EOFまで1行ずつ読み出す
27(*): i = 0 ' データの番号
28(*): Do Until EOF(1)
29(*): ReDim Preserve myRange1(2, i) ' 配列をデータ方向に1つ拡大
30(*): Line Input #nFNO, buf ' 1行ずつ読み出す
31(*): tmp = Split(buf, ",") ' カンマで分割
32(*): For j = LBound(tmp) To UBound(tmp)
33(*): myRange1(j, i) = tmp(j) ' myRange1配列に格納
34(*): ' MsgBox "myRange1(" & j & "," & i & ")=" & myRange1(j, i) ' debug
35(*): Next
36(*): i = i + 1 ' 次のデータの番号
37(*): Loop
38(*): ' ファイルを閉じる
39(*): Close #nFNO
40(*): ' MsgBox " UBound(myRange1, 2)=" & UBound(myRange1, 2) ' debug
41(_): ' ファイル名を作成
42(_): file1 = ThisWorkbook.Path & "\" & Range("b11").Value & ".txt"
43(_): ' ファイルが存在する場合、上書きして良いか、確認する
44(_): If Dir(file1) <> "" Then
45(_): str1(0) = file1 & vbCrLf & "は存在します。" & vbCrLf
46(_): str1(0) = str1(0) & "上書きしますか?"
47(_): ' 上書きするか確認
48(_): ans1 = MsgBox(str1(0), vbYesNo + vbExclamation + vbDefaultButton2)
49(_): ' 場合分け
50(_): Select Case ans1
51(_): Case vbYes ' 「はい」
52(_): ' ファイル書込みする(End If以降を実行)
53(_): Case vbNo ' 「いいえ」
54(_): ' ファイル書込みせず、Subを抜ける
55(_): Exit Sub
56(_): Case Else '「はい」でも「いいえ」でもない
57(_): ' ファイル書込みせず、Subを抜ける
58(_): Exit Sub
59(_): End Select
60(_): Else
61(_): MsgBox (file1 & vbCrLf & "を作成します。")
62(_): End If
63(_): ' 使用可能なファイル番号を調べる
64(_): nFNO = FreeFile()
65(_): ' ファイルを開く
66(_): Open file1 For Output As #nFNO
67(_): ' ファイルへ書き込む
68(_): Print #nFNO, "hoge hoge"
69(*): For i = LBound(myRange1, 2) To UBound(myRange1, 2)
70(*): If myRange1(0, i) <> "" Then
71(*): cmd2 = UFCmd1(myRange1(0, i), myRange1(1, i), myRange1(2, i))
72(_): Print #nFNO, cmd2
73(_): End If
74(_): Next
75(_): ' ファイルを閉じる
76(_): Close #nFNO
77(_):End Sub
プログラムが長くなってしまいました。。
データが少ないときは、プログラムの中にデータを埋め込んだ方が楽ですが、
データが多くなると、データを別ファイルに分けた方が、管理が楽です。
変更した部分を説明します。
03-04行目:myRange1配列変数の宣言を変えています。03行目では配列の添字を入れず、04行目のReDimで配列の大きさを指定しています。
7/16のSub aaa()とは、添字の順番を入れ替えています。
理由は、最後の添字しか、ReDimで変更できないというVBAの制限によります。
ReDimを使って、配列の大きさを可変とすることを、動的配列と言います。
動的配列とした理由は、テキストファイルから読み込むデータ量で配列の大きさを変更したいからです。
10行目:j変数を追加。
11-12行目:テキストファイルからセル範囲のデータを読み込んでmyRange1配列に代入する処理のため、buf, tmp変数を追加。
14-40行目:元データのセル範囲をテキストファイルから読み込んで、myRange1配列に代入しています。
16行目:ファイル名をcell1.txtとして定義し、file1変数に代入。
18-20行目:cell1.txtファイルが無かったら、処理を中止。
23行目:使用可能なファイル番号を調べて、nFNO変数に代入。
25行目:cell1.txtファイルを読み出しモードで開く。
27行目:データ番号(i変数)を0に初期化。
28-37行目:cell1.txtファイルから1行ずつ読み出し、ファイルの最後(EOF)まで繰り返す。
29行目:myRange1配列をデータ方向に1つ拡大。ここで、Preserveを指定しているのは、今まで読み込んだデータを消去したくないから。
30行目:ファイルから1行読み出し、buf変数に代入。
31行目:読み出した内容をカンマで区切って、tmp配列に代入。
32-35行目:tmp配列の内容を、myRange1配列に転記。
36行目:データ番号(i)を1増やします。
39行目:cell1.txtファイルを閉じます。
69行目:LBound(配列の添字の最少), UBound(配列の添字の最大)でデータの数だけ、繰り返すようにしています。
myRange1配列の添字の順番を入れ替えたので、2次元を指定しています。
70行目:セル範囲(op1)の文字列が空文字列でなかったら、71-72行目を実行。
71行目:UFCmd1関数を呼んで、コマンド文字列をcmd2変数に代入。70-71行目でmyRange1配列の添字の順序が逆になっています。
(PS)この間、止まってしまった古い方の腕時計ですが、再度、電池を入れ替えてもらったところ、
今のところ、動いています。。お店の人曰く、腕時計の回路が故障により、電池の電圧が異常低下したのだとか。。
新しい時計を買ってしまったので、古い方は、そのまま、机の上に飾っておきます。。
The Rolling Stones - Bridges to Babylon - Too Tight
『続きを読む』を使ってみました。。
(^_0)ノ
by cheese999 (2012-07-22 07:31)
nice! ありがとうございます。
(^_0)ノ
by cheese999 (2012-07-22 08:42)
うちも、「続きを読む」をいつか使ってみたいと思っています♪
古い腕時計も復活したようで良かったですね^^
by hirochiki (2012-07-22 09:59)
hirochikiさん、
長い記事だと、、「続きを読む」重宝しますよね。
古い腕時計ですが、買ってくれた伯母さんは、とっくの昔に忘れてました。。(笑)
(^_0)ノ
by cheese999 (2012-07-22 12:26)
おニューの腕時計いいですねー。両方ともピカピカでカコイイです。古い腕時計も大事にしてあげて下さいね。w (^ω^)b
(^ー^)ノシ
by モッズパンツ (2012-07-22 17:44)
モッズパンツさん、
腕時計(古)は、私と一緒にロシア出張にも、UK出張にもついてきてくれました。もし、止まってしまったら、電池を抜いてもらって、永久保存したいかなあ、と思いますう。
(^_0)ノ
by cheese999 (2012-07-22 20:33)