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

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

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

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

Q&A

解決済

3回答

5855閲覧

VBScriptでvlookupのような処理を実施したい

amatsuno

総合スコア54

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

0グッド

0クリップ

投稿2019/03/19 11:59

VBSを使用して、VBAで言うVLOOKUPのような処理を実現したいと思っています
(VBAが使用できない理由は、マクロのタスク実行ができない(ログオフ状態で)ためです)
2つのcsvファイルを突き合わせて、指定の共通箇所をもとにファイルの結合をしたいと思っています

共通箇所は以下の通りです
・ファイルAの6カラム目の値
・ファイルBの1カラム目の値

・ファイルA:
AAA,BBB,CCC,DDD,EEE,FFF
SOS1,2019/3/10 10:15,〇,10:05,,1
SOS2,2019/3/10 10:18,〇,00:07,,2
SOS2,2019/3/10 10:11,〇,00:08,,2
SOS2,2019/3/10 10:03,〇,02:01,,2
SOS3,2019/3/10 10:15,〇,00:09,OK1,5
SOS4,2019/3/10 10:19,×,00:04,OK2,6
SOS4,2019/3/10 10:15,×,02:02,OK2,6

・ファイルB:
QQQ,WWW,TTT
1,東京,1位
2,神奈川,2位
3,埼玉,3位
4,千葉,4位
5,秋田,5位
6,青森,6位

⇒結合後は、以下の通りとしたいです
・ファイルC
AAA,BBB,CCC,DDD,EEE,FFF,WWW,TTT
SOS1,2019/3/10 10:15,〇,10:05,,1,東京,1位
SOS2,2019/3/10 10:18,〇,00:07,,2,神奈川,2位
SOS2,2019/3/10 10:11,〇,00:08,,2,神奈川,2位
SOS2,2019/3/10 10:03,〇,02:01,,2,神奈川,2位
SOS3,2019/3/10 10:15,〇,00:09,OK1,5,秋田,5位
SOS4,2019/3/10 10:19,×,00:04,OK2,6,青森,6位
SOS4,2019/3/10 10:15,×,02:02,OK2,6,青森,6位

VBAならば、vlookupでFFFとQQQを突き合せれば何とかなりそうなのですが、
VBSで実現する場合、どのようにすればよいのでしょうか?

お分かりになられる方、
申し訳ございませんがご教授いただけませんでしょうか

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

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

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

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

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

guest

回答3

0

ベストアンサー

SQLがわかるなら、ADOでCSVファイルに接続してSQLで突き合わせれば一発で希望の結果が取得できます。

参考リンク
ADOを使ってCSVファイルのデータを取得: rururuのブログ

2つのファイルが同じフォルダーにあるなら、ファイル名=テーブル名となりますので、下記のようなSQLをExecuteすればOKです。

sql

1SELECT A.*, B.WWW, B.TTT 2FROM FileA.csv AS A INNER JOIN FileB.csv AS B ON A.FFF = B.QQQ;

SELECT * INTO文(テーブル作成クエリ)を使えば、ファイルCへの出力までSQL一発でできますね。
コード書いてみました

vbs

1Option Explicit 2 3Dim objADO 4Dim strPath 5 6strPath = "C:\test\" 7 8Set objADO = CreateObject("ADODB.Connection") 9objADO.Open "Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=" & _ 10 strPath & ";ReadOnly=0" 11 12objADO.Execute "SELECT A.*, B.WWW, B.TTT INTO TableC.csv " & _ 13 "FROM FileA.csv AS A INNER JOIN FileB.csv AS B ON A.FFF = B.QQQ;" 14 15objADO.Close 16Set objADO = Nothing

注意点は、
ReadOnly=0 で更新可にすることがポイント。
あと、
ADOドライバーが32Bitだと、32BitのWScriptで実行しないとエラーになります。下記参照。

64bitOS、32bitOffice環境でのWSH(VBS)でAccessデータベースに接続する - hatena chips

投稿2019/03/20 02:26

編集2019/03/20 05:08
hatena19

総合スコア33620

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

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

amatsuno

2019/03/20 04:46

SQLは理解できます ただ、対象機にaccessが入っていないのですが、これは使えるのでしょうか?
hatena19

2019/03/20 04:50

ADOドライバーは最近のWindowsなら標準で入っていますので、使えます。AccessのないPCでエクセルからADOを使うのは普通にしています。
amatsuno

2019/03/20 05:05

ありがとうございます。 ADODB.Connection を使用して試してみたいと思います
amatsuno

2019/03/20 09:45

すいません。 SQLについて質問させてください。 SQLで実現しようとすると、 実際はそのSQLの中にwhere句を入れる想定です。 (csvファイルのうち、指定のカラムに指定の文字列がある行を抽出) この時、カラム名と指定文字列がともに日本語なのですが、 こちらはシングルクオートでしょうか?ダブルクオートでしょうか? objADO.Execute "SELECT * INTO fileD.csv " & _ " FROM fileC.csv where 'カラム名' = '指定カラム';"
hatena19

2019/03/20 10:17 編集

VBAのコード内ではSQL文は単なる文字列ですので、SQL文全体は、" で囲みます。SQLではテキストは'でも"でもどちらで囲んでもいいので、' で囲むといいでしょう。カラム名(フィールド名)はテキストではないので ’ で囲んではだめです。 objADO.Execute "SELECT * INTO fileD.csv " & _ " FROM fileC.csv where フィールド名 = '指定文字列';" フィールド名が日本語でもOKですが、空白や記号が含まれたり、予約語の場合は、[]で囲んでおく必要があります。 objADO.Execute "SELECT * INTO fileD.csv " & _ " FROM fileC.csv where [フィールド名] = '指定文字列';" 下記のリンク先で詳しく説明しています。(VBAですが、VBSも基本同じです。) https://hatenachips.blog.fc2.com/blog-entry-508.html
amatsuno

2019/03/22 03:18

ありがとうございます。 フィールド名のほうも''で記載いていたためにうまくいかなかったようです 非常に助かりました
guest

0

ファイルBがマスタファイル的な感じなので、こちらのQQQをキーに連想配列化するのがよろしいかと。
あとはファイルAを読みながらFFFで連想配列を参照して、引っ張ってきたものと一緒にファイルAを出力すればよいですね。
ただファイルBの中身を全部メモリに読み込むことになるので、メモリを圧迫するほどのデータ量だと実用的ではないです。

ざっくりですが、コードを書いてみました。
エラー処理等は省いています。

VBScript

1' ファイルBを連想配列化 2Set oFSO = WScript.CreateObject("Scripting.FileSystemObject") 3Set oFB = oFSO.OpenTextFile("fileB.csv") 4Set dicB = CreateObject("Scripting.Dictionary") 5Do While oFB.AtEndOfStream <> True 6 line = oFB.ReadLine 7 cols = Split(line, ",") 8 key = cols(0) 9 For i = 0 to Ubound(cols) - 2 10 cols(i) = cols(i+1) 11 Next 12 ReDim Preserve cols(Ubound(cols)-2) 13 cols2 = Join(cols, ",") 14 dicB.Add key, cols2 15Loop 16oFB.Close 17 18' ファイルAを読んでファイルCに出力 19Set oFA = oFSO.OpenTextFile("fileA.csv") 20Set oFC = oFSO.OpenTextFile("fileC.csv") 21Do While oFA.AtEndOfStream <> True 22 line = oFA.ReadLine 23 cols = Split(line, ",") 24 outline = line & "," & dicB.Item(cols(5)) 25 oFC.WriteLine outline 26Loop 27oFA.Close 28oFC.Close 29

投稿2019/03/20 00:21

編集2019/03/20 05:02
ttyp03

総合スコア16996

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

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

otn

2019/03/20 01:18

検索してみると"Scripting.Dictionary"というのがあるんですね。知らなかった。過去に書いたコードがずっと簡単になりそうです。ありがとうございます。
amatsuno

2019/03/20 04:52

上記を確認させていただきました。 cols = CommonSplit(line, " ", " ") の箇所でエラーが出まして、調べてみたのですが、 正確な理由がわかりませんでした。 ここはどのような処理なのでしょうか?
ttyp03

2019/03/20 04:58

失礼しました。 過去に作った関数が残ってました。 cols = Split(line, ",") に置き換えてください。
ttyp03

2019/03/20 04:59

もう一箇所のSplitも引数が足りていませんでした。 度々すみません。 元のコードを修正しておきました。
ttyp03

2019/03/20 05:00

あ~、他にもちょいちょい間違ってますな。 さすが動作未確認。 ちょっと見直します。
amatsuno

2019/03/20 05:06

了解しました。 よろしくお願いいたします。
ttyp03

2019/03/20 05:07

だいたい見直し修正しました。
amatsuno

2019/03/20 09:46

ありがとうございます。 希望の操作ができそうですので、 このコードを勉強させていただきます
ttyp03

2019/03/20 09:48

難しいことはやっていないのでがんばってみてください。 エラー処理とか1行目を読み飛ばす処理とか入れれば結構動くと思いますので。
guest

0

どちらかのファイル全体を2次元配列変数に記憶します。
他方のファイルを読みながら、変数をループで検索します。

カンマで区切られた文字列を、カンマで分割するにはSplit関数を使います。

#追記
ファイルBの1カラム目が小さい数字(3,4桁くらいまでか)なら、
1次元配列で、1カラム目の数字を添え字にして、そこに、カラム2以降を保存しておけば、

ファイルAを1行読む。
カンマで分割する。
6カラム目を添え字にしてさきほどの配列を参照する。
連結して表示する。

ということで出来るかと思います。

投稿2019/03/19 13:03

編集2019/03/20 02:16
otn

総合スコア84423

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

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

amatsuno

2019/03/20 02:07

すいません。 VBAだと以下のようなコードで作成していたのですが、 VBSだとどのようなコードになるのでしょうか? Const cFormula As String = "=VLOOKUP(@,ーーーー!A:C,3,FALSE)" With Worksheets("----") Worksheets("利XXXX").Range("A:C").Copy .Range("A:A") With .Range("A1").CurrentRegion.Columns(2) If Application.CountBlank(.Cells) > 0 Then With .SpecialCells(xlCellTypeBlanks) .Formula = Replace(cFormula, "@", .Cells(1).Offset(, -1).Address(False, False)) End With .Value = .Value End If End With End With
otn

2019/03/20 02:10

回答に書いた通りですが、何が分かりませんか?
otn

2019/03/20 02:12

ちょっと追記しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問