タグ:VBScript ( 57 ) タグの人気記事
[VBScript] 実行フォルダ内のYYYYMMDD…形式のファイルをYYYYMMフォルダに移動する
どーもボキです。

VBS実行フォルダにある、YYYYMMDD…形式のファイル名がつけられたファイルを、
YYYYMMってフォルダを作って移動するスクリプト。

N82の写真が、同じフォルダにすべて転送されてしまったから、スクリプトでフォルダ分け処理させた。
自分用の簡単なスクリプト(毎回、簡単だけど)なので、2000年からしか処理できない。
(If Left(file.Name,2) <> "20" Then の行ね。)

FileSystemObjectを利用すれば、YYYYMMDD…形式のファイルに限らず、
ファイルの更新日でフォルダを分けたり、
デジカメの時間設定ミスで更新日時がズレてしまったファイルの一括で修正したりもできる。
Set objFS = WScript.CreateObject("Scripting.FileSystemObject")

DPath_VBS = objFS.GetParentFolderName(WScript.ScriptFullName) & "\"

Set folder = objFS.GetFolder(DPath_VBS)

For Each file In folder.Files :Do
If Left(file.Name,2) <> "20" Then Exit Do ' 次のファイルへ

dname = Left(file.Name,6) ' フォルダ名:YYYYMM

DPath_To = DPath_VBS & dname & "\"

' YYYYMMフォルダがなければ作成
If Not objFS.FolderExists(DPath_To) Then objFS.CreateFolder(DPath_To)

' ファイル移動
objFS.MoveFile DPath_VBS & file.Name, DPath_To
Loop Until 1 :Next
a0021757_0243931.gif
動作イメージ



[PR]
by yozda | 2011-02-08 00:33 | プログラミング | Trackback | Comments(0)
[VBScript] デバッグ上手はプログラム上手 ~サンプルプログラム1~6~
どーもボキです。

サンプルプログラム
1~6で扱った内容を入れています。

[PR]
by yozda | 2010-12-03 22:32 | プログラミング | Trackback(1) | Comments(0)
[VBScript] デバッグ上手はプログラム上手6 ~おまけ:デバッガの起動方法~
どーもボキです。

これはオマケ。Excelをインストールしている場合、
スクリプトエディタ(といってもVBSのエディットには使えない)を使ってデバッグが出来る。

以下のソースをVBSファイルに保存して、デバッグしたいスクリプトをドロップすればいい。
このソースは、ホストの設定がWScriptでも、CScriptホスト上でスクリプトを実行させるってことも出来る。
その場合は、Mode = 1 にすること。

デバッガ起動.vbs
'使い方
' デバッグしたいVBSファイルを、このファイルにドロップする

Mode = 3
' 1:WScript.Echo をコンソールに出力
' 2:WScript.Echo をLOG出力
' 3:デバッガ起動

Set objWS = CreateObject("WScript.Shell")
Set objFS = CreateObject("Scripting.FileSystemObject")

If WScript.Arguments.count = 0 Then WScript.Quit

For i = 0 to WScript.Arguments.Count -1
ExecuteDebug(WScript.Arguments.Item(i))
Next



'--------------------------------------------------------------------------------
Sub ExecuteDebug(FPath)
fnam = Right(FPath, Len(FPath)-InStrRev(FPath,"\")) ' ファイル名
dpth = objFS.GetParentFolderName(FPath) & "\"

If LCase(Right(fnam,3)) <> "vbs" Then Exit Sub ' VBSファイルではない

Select Case Mode
Case 1
cmd1 = "cmd /k cscript"
cmd2 = ""
Case 2
cmd1 = "cmd /c cscript"
cmd2 = " > """ & dpth & Left(fnam, InStrRev(fnam,".")-1) & ".log"""
Case 3
cmd1 = "cscript //x //d"
cmd2 = ""
End Select

cmd = cmd1 & " //nologo """& FPath &"""" & cmd2
objWS.Run cmd
End Sub

デバッガでのデバッグイメージ
a0021757_1638386.gif

まぁこれでデバッグするより、
dprintf()を上手に使ったほうが効率的だと思うけどね。

[PR]
by yozda | 2010-11-20 16:39 | プログラミング | Trackback | Comments(0)
[VBScript] デバッグ上手はプログラム上手5 ~まとめ~
どーもボキです。

クラスの初期化&終了処理機能を利用したデバッグクラスを作成した。

このクラスは、
初期処理時には、スクリプトホストを判定
終了処理時には、デバッグモード時(CScriptホストでの実行時)のみ、ユーザの入力を待ち受ける。
(ユーザの入力を待ち受けなければ、デバッグメッセージを表示した黒い画面が、スクリプト終了時に閉じるため)

このdprintf()関数は、CScriptホストのときのみ、デバッグメッセージを表示する。
そのため、一般的なPC(デフォルトホストはWSCript)には、デバッグしたスクリプトをそのまま展開できる。

デバッグ用クラスの定義ファイル vbCommon.vbs
' デバッグクラスを作成
Dim DebugClass
Set DebugClass = New TDebug

' 共通定数
Dim bCScript


' -------------------------------------------------------------------------------
' cscriptホストのみ、Echo実行
Sub dprintf(v)
DebugClass.dprintf(v)
End Sub



Class TDebug
Private Sub Class_Initialize()
bCScript = InStr(LCase(WSCript.FullName),"cscript") > 0
End Sub

Private Sub Class_Terminate()
If Not bCScript Then Exit Sub

WScript.StdOut.WriteLine WScript.ScriptFullName & " [END]"
WScript.StdIn.ReadLine
End Sub


Public Sub dprintf(v)
Dim i,s
If Not bCScript Then Exit Sub

s = v
If VarType(v) >= vbArray Then
s = ""
For i = 0 to UBound(v)
s = s & "dprintf(" &i& ")=" & v(i) & vbCRLF
Next
End If
WScript.Echo s
End Sub
End Class


デバッグクラスを定義したvbCommon.vbsを読み込む方法は、その3で紹介した2つ。
以下を見れば、Executeの方を利用するほうがシンプルで管理しやすいことがわかる。

1.Executeメソッドを利用する方法
Execute CreateObject("Scripting.FileSystemObject").OpenTextFile("vbCommon.vbs").ReadAll()
'─────────────────────────────────────────────

dprintf("ど")
dprintf("│")
dprintf("も")
dprintf("ボ")
dprintf("キ")
dprintf("で")
dprintf("す")

wsfファイルなら、languageでスクリプトエンジンを指定できるから、
複数の言語を混在できるんだろうね。VBScriptとJScriptの混在とか。使わないけど。

2.wsfファイルを利用する方法
<job>
<script language="VBScript" src="vbCommon.vbs"/>
<script language="VBScript">
'───────────────────────────
dprintf("ど")
dprintf("│")
dprintf("も")
dprintf("ボ")
dprintf("キ")
dprintf("で")
dprintf("す")
'───────────────────────────
</script>
</job>

このvbCommon.vbsをデバッグだけに使うのではなく、汎用的な関数や、
頻繁に使うオブジェクトをあらかじめCreateObjectしておけば、メインスクリプトはシンプルに仕上げることが出来る。

色々と応用してほしい。

[PR]
by yozda | 2010-11-20 01:54 | プログラミング | Trackback(1) | Comments(2)
[VBScript] デバッグ上手はプログラム上手4 ~クラスの処理化処理・終了処理~
どーもボキです。

dprintf()関数をより使いやすくするための前提知識としてもうひとつだけ、
クラスを紹介する。

クラスとは、関数や変数をまとめて定義できる集合体だと思ってもらえばいい。
クラスを使えば、その関数や変数の集合体をいくつも作成することが出来る。

今回は、そのクラスの初期化処理(Class_Initialize)と終了処理(Class_Terminate)について理解する。

クラスの初期化処理&終了処理
WScript.Echo "VBS実行 開始"

WScript.Echo "クラス【A】を作成"
Set a = New TSampleClass
a.Name = "【A】"
WScript.Echo "クラス【A】を破棄"
Set a = Nothing

WScript.Echo "クラス【B】を作成"
Set b = New TSampleClass
b.Name = "【B】"

WScript.Echo "VBS実行 終了"


' ----------------------------------------
Class TSampleClass
Dim FName

' コンストラクタ
Private Sub Class_Initialize()
WScript.Echo "Class_Initialize"
End Sub

' プロパティ
Property Let Name(sName)
FName = sName
End Property

' デストラクタ
Private Sub Class_Terminate()
MsgBox FName & ".Class_Terminate"
End Sub

End Class


このサンプルをCScriptホストで実行すると、まず以下の画面が表示される。
クラスを作成したタイミングで、Class_Initializeが呼ばれることが分かる。
また、クラスを破棄したタイミング(Set a = Nothing)で、Class_Terminateが呼ばれることが分かる。
a0021757_135837.gif


スクリプトを最後まで実行すると、以下の画面が表示される。
この画面から、スクリプトが終了するタイミングで、クラスが破棄されたことが分かる。
a0021757_135484.gif
このように、クラスには作成・破棄時に、自動的に呼び出させる関数が用意されている。
このような機能をもったクラスを上手に活用し、次回、dprintf()を使いやすくしてみる。


[PR]
by yozda | 2010-11-20 01:39 | プログラミング | Trackback | Comments(0)
[VBScript] デバッグ上手はプログラム上手3 ~外部ファイルの読み込み方法~
どーもボキです。

前回はCScriptホストのときだけ、メッセージを表示するdprintf()関数を紹介した。
このdprintf()関数をより使いやすくするため、今回は外部ファイルの取り込み方法を2つ紹介する。

今回呼び出す外部ファイルは、echo.vbs。

echo.vbs
WScript.Echo("ど")
WScript.Echo("│")
WScript.Echo("も")
WScript.Echo("ボ")
WScript.Echo("キ")
WScript.Echo("で")
WScript.Echo("す")

WScript.Sleep(1000)


1.Executeメソッドを利用する方法
Execute Include("echo.vbs")   'echo.vbsの内容をテキストで読み込み実行

' -------------------------------------------------------
' 指定ファイルを読み出し実行
Function Include(FName)
Dim objFS,txtf,s

Set objFS = CreateObject("Scripting.FileSystemObject")
Set txtf = objFS.OpenTextFile(FName) ' FNameのファイルを開く
s = txtf.ReadAll() ' 指定ファイルの全内容を文字列で取得する

Include = s
End Function
' -------------------------------------------------------
シンプルに書けば、以下のように一行に収めることも出来る。

1’.Executeメソッドを利用する方法 (シンプル版)
Execute CreateObject("Scripting.FileSystemObject").OpenTextFile("echo.vbs").ReadAll


2.wsfファイルを利用する方法
<job>
<script language="VBScript" src="echo.vbs"/>
</job>


オススメしたいのは、1のExecuteメソッドを利用する方法。
vbsファイルのみで管理できるし、wsfのように<タグ>の知識がなくてもいいからね。

[PR]
by yozda | 2010-11-20 01:12 | プログラミング | Trackback | Comments(0)
[VBScript] デバッグ上手はプログラム上手2 ~dprintf():CScriptホストのみWScript.Echoを実行~
どーもボキです。

前回、CScriptホストでスクリプトを実行すれば、
WScript.Echoでデバッグメッセージを表示させても処理が中断されないことがわかった。

なら、ホストがCScriptのときだけ、
WScript.Echoを実行する関数を用意すれば、処理を中断せずデバッグできる。
あえて中断したいなら、そのときだけMsgBoxを使えばいい。

以下のdprintf()は、CScriptホストでの実行時のみWScript.Echoを実行する。
dprintf("ど")
dprintf("│")
dprintf("も")
dprintf("ボ")
dprintf("キ")
dprintf("で")
dprintf("す")



' -------------------------------------------------------------------------------
' 終了処理
If InStr(LCase(WSCript.FullName),"cscript") > 0 Then
WScript.StdOut.WriteLine WScript.ScriptFullName & " [終了]" ' メッセージ表示
WScript.StdIn.ReadLine ' ユーザの入力待ち
End If

' -------------------------------------------------------------------------------
' cscriptホストのみ、Echo実行
Sub dprintf(v)
Dim i,s
If InStr(LCase(WSCript.FullName),"cscript") = 0 Then Exit Sub ' WScriptなら出力なし

s = v
If VarType(v) >= vbArray Then
s = ""
For i = 0 to UBound(v)
s = s & "dprintf(" &i& ")=" & v(i) & vbCRLF
Next
End If
WScript.Echo s
End Sub
実行イメージ (WScriptホストの場合は、何も表示されない)
a0021757_0392745.gif



[PR]
by yozda | 2010-11-20 00:37 | プログラミング | Trackback | Comments(0)
[VBScript] デバッグ上手はプログラム上手1 ~WScriptホストとCScriptホストの違い~
どーもボキです。

上手上手って何回も書いてたら、土手に見えてくるね。どて。
デバッグ上手にしとるか?MsgBoxで確認しとるじゃぁ?このド素人が!

そんな「Buon giorno」もいえないようなチミでも、上手にデバッグできる方法教えちゃろう。
全3~7回くらい。まぁ適当に。

ちなみに「Buon giorno」はイタリア語で「こんにちは」ね。
一歩イタリアに近づいたね。


まず最初に言いたいことは、デバッグにはCScriptを使え!
PCの設定をなーんも変えてないなら、VBScriptはWScriptホスト上で実行されるんよ。

なんじゃそりゃ?って思う人は、このサンプルプログラム実行してみ。

心配せんでもええ。ウィルスやら変な処理やら仕込んどりゃぁせん。下の画面が出るだけよ。

このサンプルは、WScript.Echo でのメッセージ出力を、WScriptとCScriptで同時に実行させとるんよ。
メッセージってのは、「どーもボキです」ね。それを、WScriptとCScriptの両方で表示させとるんよ。

手前にあるウィンドウがWScript、後ろの黒い画面がCScript。
WScriptは[OK]を押すまで処理が止まっとるのがわかるよね。けど、CScriptは最後までメッセージ(どーもボキです)が出とるのがわかる?
a0021757_2329095.gif
じゃけどしたん?何がいいたいんって?最初に言ったやろ?デバッグにはCScriptを使え!ちゅうことよ。
[OK]押すまで止められたらたまらんやろ?WScriptのままでデバッグするのは素人がやることじゃ。

「止めたいときはどうすりゃいいんだ?」ってぇ?
じゃけ素人なんよ。そんなときはお得意のMsgBox使やええやろ。


スクリプトホストの変更方法は簡単で。
スタート > ファイル名を指定して実行で
cmd cscript /h:cscript
を実行するだけじゃ。元のWScriptホストに戻したいなら、
cmd cscript /h:wscript
簡単じゃろ?

サンプルプログラムのソースはこれじゃけぇ。
このサンプルは、WScriptとCScriptの違いを知ってもらうために作ったんじゃけど、
コマンドプロンプト使って、プログラムを引数付きで実行するってことやってるのよね。これも勉強になるで。
' プログラム実行 -----------------------------
Run_CScript("Echo.vbs")
Run_WScript("Echo.vbs")

'---------------------------------------------
' CScriptで実行
Sub Run_CScript(FName)
s = "cmd /k cscript """& FName &""""
Run_Command(s)
End Sub

'---------------------------------------------
' WScriptで実行
Sub Run_WScript(FName)
s = "cmd /k wscript """& FName &""""
Run_Command(s)
End Sub

'---------------------------------------------
' コマンドを実行
Sub Run_Command(s_cmd)
Set objWS = CreateObject("WScript.Shell")
objWS.Run(s_cmd)
End Sub
ほな、Arrivederci!

[PR]
by yozda | 2010-10-16 23:45 | プログラミング | Trackback | Comments(0)
[Delphi] スクリプト言語を利用し、ユーザによる処理実装を実現する方法 その4 : サンプルプログラム3
どーもボキです。

ScriptControl。知恵絞りあげて実装すりゃ相当使えるわ、コレは。

DelphiとVBScriptとの連携、VBScriptの関数に値渡したり、戻り値を受け取ったりするにあるように、
VBScript関数への引数や、VBScript関数の戻り値でデータをやり取りするのは、とても面倒。

正攻法でVBScriptと連携させる場合、つまり VBScript関数の引数でデータを渡す、戻りで処理結果を得る場合、
まず、引数として渡すデータはVariant型に変換する必要がある。配列データのやりとりとなるとVariant配列への変換がかなり面倒だ。
また、戻り値で配列を受け取る場合も、Variant配列で受け取る必要がある。
加えて、引数の数によってDelphi側の呼び出し処理の変更が必要。
その上、参照渡しは使えない。正確には、参照渡し(ByRef)での引数をVBScript内で変更しても、Delphi側の変数には反映されない。
これらから、VBScript関数への引数&VBScript関数からの戻り値 を使っての連携はかなり使い勝手が悪い。つうか、使い物にならない。

そこで、DelphiとVBScriptとのデータ中継にCoClassを使う。
Delphi ⇔ CoClass ⇔ VBScript ってな感じに。こうやることで、VBScriptとの連携が超簡単になる。やり方は以下
1.CoClassのPublicメンバにDelphi ⇔ VBScript間でやり取りしたいデータ用の変数を定義する
2.タイプライブラリにCoClassのPublicメンバを処理するプロパティ・メソッドを定義する
3.ScriptControl.AddObjectで、CoClassを指定する
Delphiから CoClass の Publicメンバに必要なデータを渡し、
VBScriptからは、CoClassのプロパティ・メソッドで渡されたデータにアクセスする。
Delphi ~ VBScriptの間を、CoClassが取り持つため、Variantへの変換は不要。
引数の数も考慮しないくていい。
(その代わり必要なデータは、CoClassに渡し、VBScriptからアクセスできるようにする必要がある)
CoClassにデータポインタを渡しておけば、VBScriptでの編集がそのままDelphi上のデータに反映される。

自前でスクリプト処理をサポートさせる場合は、逆ポーランド記法処理でスクリプトを解読したり、エラーチェックをしたりと超面倒。
ScriptControlを使えば、構文の解釈&エラーチェックはVBScriptエンジンがやってくれる。
VBScriptでの記述が出来るため、かなり複雑な処理も実装可能。超便利であり、超強力。試作ロジックの検証とかに使えそう。

サンプルプログラム

a0021757_1515247.gif
実行イメージ : 元データ(青)に対しての、スクリプト処理結果(赤)
移動平均処理で、赤グラフが平滑化されていることがわかる

uFM_Main.pasのソース (ScriptControl呼び出し側)
unit uFM_Main;

interface

uses
uAutoObject,
MSScriptControl_TLB,
Math,
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, TeeProcs, TeEngine, Chart, ExtCtrls, OleCtrls, Series;

type
TFM_Main = class(TForm)
Button: TButton;
Panel: TPanel;
Chart: TChart;
Memo: TMemo;
Splitter: TSplitter;
Line: TFastLineSeries;
ScriptControl: TScriptControl;
Line_out: TFastLineSeries;
procedure ButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
Data : TFltArr;
FCoClass : TExposingObjectsDemo;
public
{ Public declarations }
end;

var
FM_Main: TFM_Main;

implementation

uses
ActiveX;

{$R *.DFM}

{ TFM_Main }

procedure TFM_Main.FormCreate(Sender: TObject);
var
i : Integer;
begin
Memo.Align := alClient;

// サンプルデータ
for i := 0 to High(Data) do begin
Data[i] := Sin(2*PI*i/Length(Data)) + Random/7;
Line.AddXY(i,Data[i]);
end;

FCoClass := TExposingObjectsDemo.Create;
FCoClass.PData := @Data; // CoClassにデータのポインタを渡す
ScriptControl.AddObject('CoClass', FCoClass, False); // ScriptControlにCoClassをAddする
ScriptControl.SitehWnd := Self.Handle;
end;


procedure TFM_Main.ButtonClick(Sender: TObject);
var
i : Integer;
begin
Line_out.Clear;
for i := 0 to High(Data) do begin
FCoClass.DataIndex := i; // CoClassに現在のデータインデックスを渡す
ScriptControl.ExecuteStatement(Memo.Lines.Text); // VBScriptを実行
Line_out.AddXY(i,Data[i]); // VBScriptでの処理結果でグラフ描画
end;
end;


end.

uAutoObject.pasのソース (Delphi ~ VBScriptのデータ中継、VBScriptからのDelphiデータアクセス)
unit uAutoObject;

interface

uses
ExposingObjects_TLB,
ComObj, ActiveX, StdVcl, Forms;

type
PFltArr = ^TFltArr;
TFltArr = Array[0..99] of Single;

type
TExposingObjectsDemo = class(TAutoObject, IExposingObjectsDemo)
public
DataIndex : Integer;
PData : PFltArr;
protected
function Get_Data(Index: Integer): OleVariant; safecall;
procedure Set_Data(Index: Integer; Data: OleVariant); safecall;
{ Protected declarations }
end;

implementation

uses ComServ, uFM_Main;

// Dataプロパティ Get
function TExposingObjectsDemo.Get_Data(Index: Integer): OleVariant;
begin
Result := PData[DataIndex + Index];
end;

// Dataプロパティ Set
procedure TExposingObjectsDemo.Set_Data(Index: Integer; Data: OleVariant);
begin
PData[DataIndex + Index] := Data;
end;


initialization
TAutoObjectFactory.Create(ComServer, TExposingObjectsDemo, Class_ExposingObjectsDemo, ciMultiInstance, tmApartment);
end.

[PR]
by yozda | 2010-03-22 15:03 | プログラミング | Trackback | Comments(0)
[VBScript] 非同期処理(マルチスレッド) 参考ページ
どーもボキです。

More (長いので)
[PR]
by yozda | 2010-03-15 22:57 | プログラミング | Trackback | Comments(0)