ON-BLOG

CGのこと、あれこれ書いてます。

ファイル、フォルダコピー(同期)をエクセル参照して

エクセルで指定したフォルダ間をコピーするツールです。
※エクセルを使用したWSHツールです。
おそらく今後必要になりそうだったので、先行して作成しました。
あとエラー処理、オープンオフィスの対応がありますが
とりあえずこれで色々試してみたいです。

こちらは往々にこちらを参考させて頂きました。

JScriptでのScripting.FileSystemObjectオブジェクト TIPS - Qiita

まずはコード

//指定ファイルのエクセル、セルB2[コピー元]H2[コピー先]に記載されているパスを元に
//フォルダをコピーするツール。
//現在はコピー先のフォルダ、ファイルを一旦削除しています。
//要はフォルダ間を同期する感じです。
//エクセルのセルを増やせばコピーするフォルダが増えます。
//フォルダがなければ、強制的にフォルダを作成します。
//以下注意事項があります。
//1.B2、H2のセルは必ず列で埋めて下さい。間があるとエラーになります。
//2.列に空白は作らないください。これもエラーになります。
//3.一個上のフォルダまで有無は確認しますが、それ以上はエラーとなります。

var fso = new ActiveXObject("Scripting.FileSystemObject");
var Shell = new ActiveXObject("Shell.Application");
var excelApp = WScript.CreateObject("Excel.Application");
var Book = excelApp.Workbooks.Open("C:\\Users\\tommy_on\\Desktop\\Copypath.xls");
var Sheet = Book.WorkSheets("Sheet1");
var usedRange	= Sheet.UsedRange;
var bottom	= usedRange.Rows(usedRange.Rows.Count).Row;//列の一番下取得

for (var i=2; i<bottom+1; i++)
{
	var end_B_cells = Sheet.Cells(i,2).value;
	var end_H_cells = Sheet.Cells(i,8).value;
	var Floder = Shell.NameSpace(end_H_cells);
	if(!fso.FolderExists(end_H_cells))
		{
			ParentFolder(end_H_cells);
		}
	else
		{
		var DelItems = Floder.Items();
		for(var j = 0 ; j<DelItems.count; j++)
			{
				var SetItem = DelItems.Item(j);
				if(SetItem.IsFolder == true)
					{
					fso.DeleteFolder(SetItem,true);
					}
				else if(SetItem.IsFile == true)
					{
					fso.DeleteFile(SetItem,true);
					}
			}
		}
	fso.CopyFolder(end_B_cells, end_H_cells);
}

function ParentFolder(end_H_cells) 
	{
    if (!fso.FolderExists(end_H_cells))
    	{
			if (fso.GetParentFolderName(end_H_cells))
				{
				// フォルダが存在しなかったので、親フォルダ生成
				createFolder(fso.GetParentFolderName(end_H_cells));
				fso.CreateFolder(end_H_cells);
				}
        }
    }
Book.Close();
fso = null;
excelApp.Quit();
excelApp = null;

こんな感じです。
流れとしては、
まずはコピー元とコピー先を記入したエクセルが必要です。
こんな感じ
f:id:tommy_on:20150125001249p:plain
フォルダ的はこんな感じです。
f:id:tommy_on:20150125001929p:plain
エクセルのセル【B1以降】【H1以降】を参照して
コピーする感じです。

この環境ができれば、あとは上記コードのエクセルパスを変更後
JSで保存して実行すれば、BパスからHパスへフォルダ、ファイルがコピーされてると思います。
コードのコメント欄に書いてますが
注意事項があります。
1.B2、H2のセルは必ず列で埋めて下さい。間があるとエラーになります。
→BとHに必ずセルが埋まっている事が前提になっています。ないとエラーで止まりますので・・

2.列に空白は作らないください。これもエラーになります。
→使用している、列を取得している為、間に空白があるとそこが最後の列として扱われます。

3.一個上のフォルダまで有無は確認しますが、それ以上はエラーとなります。
→これは仕様です。もっと親を伸ばすことはできますが、しません。

こんな感じでした。
ではコードで手こずった部分をメモ変わりに書いていきます。

まずは、列の取得。
今回はB,Hで使用している列数ですね。

var usedRange	= Sheet.UsedRange;
var bottom	= usedRange.Rows(usedRange.Rows.Count).Row;//列の一番下取得

「UsedRange」で使用しているセルを取得し、「Rows.Count」で一番までカウントしてます。
これによって一番のセルまで取れてる訳ですね。
これはめちゃくちゃハマりました。
ってかこれであってるか未だに自信ありません。

あとFolderExitで親フォルダも無い時の挙動です。
これはおもっきり上記リンクを参考にさせてもらってます。

function ParentFolder(end_H_cells) 
	{
    if (!fso.FolderExists(end_H_cells))
    	{
			if (fso.GetParentFolderName(end_H_cells))
				{
				// フォルダが存在しなかったので、親フォルダ生成
				createFolder(fso.GetParentFolderName(end_H_cells));
				fso.CreateFolder(end_H_cells);
				}
        }
    }

SIでも同様のことやってたんですが
なぜか上手くいかなったので参考にさせてもらってます。
内容は非常に簡単で
「親フォルダ取得」→「無かった作成」→「フォルダを取得」
を繰り返しているだけ。

まぁ一応苦戦したので、忘れないように・・・


とまぁこんな感じで作成しました。
今後はエラー処理を入れ込みがいるかな?
あと、この手のツールC#でアプリケーションとして作成したいですね。

以上です。