ここから本文です

以下作業をvba若しくはvbsで行いたいです。 どなたかご指導(プログラムを書いて...

she********さん

2018/5/513:11:33

以下作業をvba若しくはvbsで行いたいです。
どなたかご指導(プログラムを書いて)いただけないでしょうか?

pc、cドライブ上の任意のフォルダの中に
エクセルの表(データ)と、テキストのフォーム(雛形)があります。

エクセルの指定列のデータを、
作成したテキストフォームの特定箇所に挿入したい。

エクセルのデータが10個以上の場合は次のテキストフォームに出力させたい。

指定したエクセルファイル数だけ、同じ作業を繰り返したい。

閲覧数:
75
回答数:
3
お礼:
100枚

違反報告

ベストアンサーに選ばれた回答

プロフィール画像

カテゴリマスター

lin********さん

2018/5/611:08:26

全く、ファイルの構造がどうなっているのか、また、「テキストのフォーム」が何を指すのか分かりませんが、一応、「テキストのフォーム」を「決まったテキストファイル」と解釈し、以下の「VBScript」を組みました。

参考になる部分があれば、使ってください。

とにかく、プログラムを組む、ということは、極めて具体的な情報が必要ですが、質問者の質問文では、何も分からないので、かってに想定して作っています。

あとで、できるだけ詳しく説明するので、あとは、自分で変更してください。

今回は、プログラムファイルが存在するフォルダ内のすべての「xlsx」ファイルを読み込み、私の環境である「D:\Programming」フォルダにある「Form.txt」ファイルを読み込み、エクセルのブックから10行ずつ「Form.txt」に書き込み、エクセルブックと同じフォルダ内(=プログラムファイルが存在するフォルダ)にブックと同じ名前のテキストファイルとして保存しています。

今は、「Form.txt」は「csv」ファイルと中身は同じ構造です。

「abc.xlsx」を処理したとき、「abc_1.txt」というファイルができます。

エクセルの方が10行を超えたときは、「abc_2.txt」、「abc_3.txt」と作成されてゆきます。

エクセルの列「A」の値(1行目は項目行という想定なので、2行目から)を使って、「Form.txt」ファイルの列「B」の値を書き換えています。

Option Explicit
Dim a, bk, c, ex, f, gf, i, j, k, n, r, sh, so, tr, tx, x, y, z
Set so = CreateObject("Scripting.FileSystemObject")
Set gf = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))
Set ex = CreateObject("Excel.Application")
ex.Application.DisplayAlerts = False
ex.Visible = False
For Each f In gf.Files
If LCase(so.GetExtensionName(f.Name)) = "xlsx" Then
Set bk = ex.Workbooks.Open(gf & "\" & f.Name)
Set sh = bk.ActiveSheet
x = sh.Range("A1").End(-4121).Row
y = Int((x - 1)/ 10) + 1
c = 0
r = 1
For i = 1 to y
Set tx = so.OpenTextFile("D:\Programming\Form.txt", 1)
n = gf & "\" & so.GetBaseName(f.Name) & "_"
c = c + 1
Set tr = so.OpenTextFile(n & CStr(c) & ".txt", 2, True)
For j = 1 to 10
If r >= x Then
Exit For
End If
r = r + 1
a = Split(tx.ReadLine, ",")
z = ""
For k = 0 to UBound(a) - 1
If k = 1 Then
a(k) = sh.Cells(r, 1).Value
End If
z = z & a(k) & ","
Next
z = z & a(UBound(a))
tr.WriteLine z
Next
Do Until tx.AtEndOfStream
z = tx.ReadLine
tr.WriteLine z
Loop
tr.Close
tx.Close
Set tr = Nothing
Set tx = Nothing
Next
bk.Close
Set sh = Nothing
Set bk = Nothing
End If
Next
ex.Quit
Set ex = Nothing
Set gf = Nothing
Set so = Nothing
MsgBox("Finished!")

説明です。

Option Explicit

「厳密に」とか「明確に」というような意味で、このオプションを設定すると、変数は、その使用の前に、必ず、「Dim」等によって「使いますよ!」と宣言しておかなければなりません。

Set so = CreateObject("Scripting.FileSystemObject")

ファイルやフォルダを扱えるようにしていますが、今回は特に、テキストファイルを扱うのにも必要です。

Set gf = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))

プログラムファイル(「~.vbs」ファイル)が存在するフォルダを取得しています。

Set ex = CreateObject("Excel.Application")

エクセルを扱えるようにしています。

ex.Application.DisplayAlerts = False
ex.Visible = False

「上書きしますか?」などと聞いてこないように、また、エクセルを表示しません。

For Each f In gf.Files

プログラムファイルが存在するフォルダ内のすべてのファイルを1つずつ処理。

If LCase(so.GetExtensionName(f.Name)) = "xlsx" Then

「LCase()」は、英字を小文字にする関数です。

「so.GetExtensionName()」は、「Scripting.FileSystemObject」の機能を使って(頭の「so.」)、拡張子を取得します。

これで「Xlsx」や「XLSX」なども、すべて「xlsx」になります。

したがって、「拡張子がxlsxなら」となります。

Set bk = ex.Workbooks.Open(gf & "\" & f.Name)

そのブックを開いています。

Set sh = bk.ActiveSheet

そのブックのアクティブシートを「sh」にセット。

x = sh.Range("A1").End(-4121).Row

列「A」についての最終行を「x」に入れています。

y = Int((x - 1)/ 10) + 1

「10行以下」なら「y = 1」、「11~20」なら「y = 2」、「21~30」なら「y = 3」という計算をしています。

c = 0

「abc_1.txt」の「1」をカウント用変数の初期化。

r = 1

エクセルの行カウント用変数の初期化。

For i = 1 to y

「y」の回数だけ処理します。

Set tx = so.OpenTextFile("D:\Programming\Form.txt", 1)

「D:\Programming」フォルダ内の「Form.txt」を「読み込み専用」(=「1」)で開いています。

n = gf & "\" & so.GetBaseName(f.Name) & "_"

「gf」はプログラムファイルの存在するフォルダ。

「so.GetBaseName()」は、「Scripting.FilesystemObject」の機能を使って(頭の「so.」)、ベースネーム(「abc.xlsx」→「abc」)を取得しています。

c = c + 1

1つカウント。

Set tr = so.OpenTextFile(n & CStr(c) & ".txt", 2, True)

「abc_1.txt」などという名前のテキストファイルを「書き込み専用」(=「2」)、で「新規作成を許可」(=「True」)しています。

For j = 1 to 10

10行ずつ処理。

If r >= x Then
Exit For
End If

もし、「r」の値が、そのブックの最終行以上になれば、「For j = 1 to 10~Next」を抜け出して、処理を終了します。

r = r + 1

1行カウント。

a = Split(tx.ReadLine, ",")

「Form.txt」から1行分読み込み。

「Split()」は、区切り記号を使って、配列変数に格納する関数です。

今回の区切り記号は「,」です。

たとえば、読み込んだ1行が「a,b,c」なら、「a(0) = "a"」、「a(1) = "b"」、「a(2) = "c"」となります。

z = ""

書き込み用変数の初期化。

For k = 0 to UBound(a) - 1

「UBound()」は、配列変数の添え字(「()」内の数字)の最大値を返します。

上記の例でしたら「a(2) = "c"」の「2」です。

「-1」していますので、最大値の1つ前まで処理します。

If k = 1 Then

「Form.txt」の列「B」(配列変数は「0」から始まるので、列「B」は「1」)なら、

a(k) = sh.Cells(r, 1).Value

その値をブックの列「A」の値にします。

z = z & a(k) & ","

「a,b,・・・」などという形を作っています。

Next

を、配列変数の添え字の最大値の1つ前まで繰り返します。

z = z & a(UBound(a))

最後のデータを「z」に書き込んでいます。

tr.WriteLine z

「abc_1.txt」の方に書き込んでいます。

Next

を、10行分繰り返しています。

Do Until tx.AtEndOfStream
z = tx.ReadLine
tr.WriteLine z
Loop

「Form.txt」ファイルの残りを「abc_1.txt」に書き込んでいます。

tr.Close
tx.Close
Set tr = Nothing
Set tx = Nothing

両ファイルを閉じています。

Next

必要回数繰り返しています。

bk.Close
Set sh = Nothing
Set bk = Nothing

ブックを閉じています。

End If
Next

を、ファイルの数だけ繰り返しています。

ex.Quit

エクセルそのものを終了しています。

Set ex = Nothing
Set gf = Nothing
Set so = Nothing
MsgBox("Finished!")

あとは、終了処理で、最後に「Finished!」と表示しています。

質問した人からのコメント

2018/5/7 00:37:24

回答ありがとうございます!

要領を得ない表現のお願いで申し訳ありません。

通関業に従事しています。
エクセルで送られてくる元資料(データ)の必要なところを、
通関用システム(NACCS)に取り込めるように
テキスト(タブ区切り)に変換しようと模索中です。
データの件数が多く、今回投稿させていただきました。
ありがとうございます。

ベストアンサー以外の回答

1〜2件/2件中

並び替え:回答日時の
新しい順
|古い順

yok********さん

2018/5/520:07:30

本当に勘違いが多いんですが
指導っていうのは使える様になりたい
のでしょうか?

もしそうなら貴方の質問は運転に
例えれば、免許は無いけど東京から大阪に行きたいみたいな話しで、説明されてもおそらく理解出来ません。
仮に助手席でそのドライブをしたって運転は身につかないでしょう?

ひとつづつ理解しないといっぺんに全部聞いても理解できるわけないです。逆に理解出来たらかなりの能力、類い稀な素質です。

まず任意のエクセルファイルをひとつ開く、そこから試して見ましょう。
ひとつづつ解決を図らないと結局貴方のスキルにならないと思います。

moo********さん

2018/5/513:39:41

作成依頼にしては仕様が曖昧過ぎますが、
>任意の、特定の、指定列の、特定個所に、

って実際はどこなんでしょうか。もし再回答する際は、回答削除の上回答するので、説明は補足へ記入ください。

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる