Last active
April 2, 2018 06:23
-
-
Save ginlime/d197aea58d7f97a82a44179fc856c9c4 to your computer and use it in GitHub Desktop.
vbac.wsf で出力されるコードが Shift_JIS で エディタによっては面倒なので、nkf で UTF-8 に変換するようにしてみた(要 nkf)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | |
<package> | |
<comment> | |
The vbac is not VBA compiler. | |
Instead, this unsophisticated script frees VBA code from binary files. | |
This script is distributed as part of the Ariawase library. | |
The Project Page: https://github.com/vbaidiot/Ariawase | |
Modified by: twitter:@ginlime | |
Added: charcode of source code will be converted to UTF-8 on exporting. | |
Added: charcode of source code also will be converted to Shift JIS on importing. | |
Requirement: nkf.exe | |
</comment> | |
<job id=""> | |
<?job error="true" debug="false" ?> | |
<runtime> | |
<description></description> | |
<example></example> | |
</runtime> | |
<resource id="HelpMessage"> | |
vbac (version 0.9.0) | |
Usage: cscript vbac.wsf <command> [<options>] | |
Commands: | |
combine Import all VBComponents | |
decombine Export all VBComponents | |
clear Remove all VBComponents | |
help Display this help message | |
Options: | |
/binary:<dir> Specify directory of macro-enabled Office files | |
(default: bin) | |
/source:<dir> Specify directory of source code files | |
(default: src) | |
/vbaproj Use .vbaproj file | |
/dbcompact With Access DB compaction | |
/charcodeconv Source file will be converted to UTF-8 | |
</resource> | |
<script language="JScript"> | |
<![CDATA[ | |
// Enumerations: | |
// Word - http://msdn.microsoft.com/en-us/library/office/jj684104.aspx | |
// Excel - http://msdn.microsoft.com/en-us/library/office/ff838815.aspx | |
// Access - http://msdn.microsoft.com/en-us/library/office/jj713155.aspx | |
// WdSaveFormat | |
var wdFormatDocument97 = 0 //.doc | |
var wdFormatTemplate97 = 1 //.dot | |
var wdFormatXMLDocumentMacroEnabled = 13 //.docm | |
var wdFormatXMLTemplateMacroEnabled = 15 //.dotm | |
// XlFileFormat | |
var xlExcel9795 = 43; //.xls 97-2003 format in Excel 2003 or prev | |
var xlExcel8 = 56; //.xls 97-2003 format in Excel 2007 | |
var xlExcel12 = 50; //.xlsb | |
var xlOpenXMLWorkbookMacroEnabled = 52; //.xlsm | |
// AcNewDatabaseFormat | |
var acNewDatabaseFormatAccess2000 = 9; //.mdb | |
var acNewDatabaseFormatAccess2002 = 10; //.mdb | |
var acNewDatabaseFormatAccess2007 = 12; //.accdb | |
// AcSysCmdAction | |
var acSysCmdAccessVer = 7; | |
// AcObjectType | |
var acTable = 0; | |
var acQuery = 1; | |
var acForm = 2; | |
var acReport = 3; | |
var acMacro = 4; | |
var acModule = 5; | |
// vbext_ct_* (ref: http://msdn.microsoft.com/en-us/library/office/gg264162.aspx) | |
var vbext_ct_StdModule = 1; | |
var vbext_ct_ClassModule = 2; | |
var vbext_ct_MSForm = 3; | |
var vbext_ct_Document = 100; | |
// FileSystemObject (ref: http://msdn.microsoft.com/en-us/library/hww8txat%28v=vs.84%29.aspx) | |
var fso = WScript.CreateObject("Scripting.FileSystemObject"); | |
// WshShell | |
var wshshell = WScript.CreateObject("WScript.Shell"); | |
var forReading = 1; | |
var forWriting = 2; | |
var forAppending = 8; | |
var scriptPath = WScript.ScriptFullName; | |
var args = (function() { | |
var a = new Array(WScript.Arguments.length); | |
for (var i = 0; i < a.length; i++) a[i] = WScript.Arguments.item(i); | |
return a; | |
}()); | |
var getResource = function(str) { | |
return scriptlet.getResource(str).replace(/^\s+|\s+$/g, ""); | |
}; | |
var println = function(str) { | |
WScript.Echo(str); | |
}; | |
var foreachEnum = function(collection, callback) { | |
for ( var xs=new Enumerator(collection), x=xs.item(), i=0; | |
!xs.atEnd(); | |
xs.moveNext(), x=xs.item(), i++ | |
) { | |
if (!!callback(x, i)) break; | |
} | |
} | |
var dateTimeString = function(dt) { | |
var g = function(y) { return (y < 2000) ? 1900 + y : y; }; | |
var f = function(n) { return (n < 10) ? "0" + n : n.toString(); }; | |
var ymd = g(dt.getYear()) + f(dt.getMonth() + 1) + f(dt.getDate()); | |
var hns = f(dt.getHours()) + f(dt.getMinutes()) + f(dt.getSeconds()); | |
return ymd + " " + hns; | |
}; | |
var typename = function(obj) { | |
if (obj === undefined) return 'Undefined'; | |
if (obj == null) return 'Null'; | |
return Object.prototype.toString.call(obj).slice(8, -1); | |
}; | |
var isPathRooted = function(path) { | |
if (!path) return false; | |
var p1 = path.substring(0, 1); | |
if (p1 == '\\' || p1 == '/') return true; | |
var p2 = path.substring(1, 2); | |
if (p2 == ':') return true; | |
return false; | |
}; | |
var Conditional = function(val) { | |
this.flag = false; | |
this.value = val; | |
}; | |
Conditional.prototype.change = function(val) { | |
this.flag = true; | |
if (val !== undefined) this.value = val; | |
}; | |
var CmdParam = function(paramObj) { | |
this.defaultParameterName = paramObj.defaultParameterName; | |
delete paramObj.defaultParameterName; | |
this.parameters = paramObj; | |
this.paramNames = {}; | |
for (var pname in this.parameters) | |
this.paramNames[pname.toLowerCase()] = pname; | |
}; | |
CmdParam.prototype.exists = function(paramName) { | |
return paramName.toLowerCase() in this.paramNames; | |
}; | |
CmdParam.prototype.get = function(paramName) { | |
var pname = this.paramNames[paramName.toLowerCase()]; | |
return this.parameters[pname]; | |
}; | |
CmdParam.prototype.set = function(paramName, value) { | |
var pname = this.paramNames[paramName.toLowerCase()]; | |
this.parameters[pname] = value; | |
}; | |
CmdParam.prototype.setParam = function(pname, arg) { | |
// the 'Object' assumed Conditional class | |
switch (typename(this.get(pname))) { | |
case 'Boolean': | |
if (arg === undefined) arg = true; | |
this.set(pname, Boolean(arg)); | |
break; | |
case 'Number': | |
this.set(pname, Number(arg)); | |
break; | |
//case 'Date': | |
// this.set(pname, Date.parse(arg)); | |
// break; | |
case 'Object': | |
this.get(pname).change(arg); //FIXME: type of value is string only? | |
break; | |
case 'Array': | |
this.get(pname).push(arg); //FIXME: type of value is string only? | |
break; | |
case 'Undefined': | |
break; | |
default: | |
this.set(pname, arg || ""); | |
break; | |
} | |
}; | |
CmdParam.prototype.parse = function(args) { | |
var pname = this.defaultParameterName; | |
for (var i = 0; i < args.length; i++) { | |
var value = undefined; | |
switch (args[i].charAt(0)) { | |
case '-': case '/': | |
pname = args[i].substring(1); | |
var j = -1; | |
if (j < 0) j = pname.indexOf(':'); | |
if (j < 0) j = pname.indexOf('='); | |
if (j > -1) { | |
value = pname.substring(j + 1); | |
pname = pname.substring(0, j); | |
} | |
break; | |
default: | |
value = args[i]; | |
break; | |
} | |
this.setParam(pname, value); | |
} | |
return this.parameters; | |
}; | |
var Config = function(binary, source, binbak) { | |
var root = fso.GetParentFolderName(scriptPath); | |
this.bin = (isPathRooted(binary)) ? binary : fso.BuildPath(root, binary); | |
this.src = (isPathRooted(source)) ? source : fso.BuildPath(root, source); | |
this.bak = (!binbak.flag) ? undefined | |
: (isPathRooted(binbak.value)) ? binbak.value | |
: fso.BuildPath(root, binbak.value); | |
}; | |
Config.prototype.getBins = function() { return fso.GetFolder(this.bin).Files; }; | |
Config.prototype.getSrcs = function() { return fso.GetFolder(this.src).SubFolders; }; | |
var VBAProjFile = function(vbproj, srcdir) { | |
this.vbproj = vbproj; | |
this.fileName = 'App.vbaproj'; | |
this.path = fso.BuildPath(srcdir, this.fileName); | |
}; | |
VBAProjFile.prototype.projPropName = { | |
'Name': 1, 'Description': 1, 'HelpFile': 1, 'HelpContextID': 1 | |
}; | |
VBAProjFile.prototype.removeAllRefs = function() { | |
var self = this; | |
foreachEnum(this.vbproj.References, function(ref) { | |
if (ref.BuiltIn) return false; | |
self.vbproj.References.Remove(ref); | |
}); | |
}; | |
VBAProjFile.prototype.read = function(is64BitOffice) { | |
var isSection = function(line) { return line.match(/^\[.*\]$/) != null; }; | |
var getParam = function(line) { | |
var i = line.indexOf('='); | |
return (i > -1) ? { key: line.substring(0, i), val: line.substring(i+1) } : null; | |
}; | |
if (!fso.FileExists(this.path)) return; | |
var fl = fso.OpenTextFile(this.path, forReading); | |
while (!fl.AtEndOfStream) { | |
var line = fl.ReadLine(); | |
var section = line; | |
switch (section) { | |
case '[General]': | |
while (!fl.AtEndOfStream) { | |
line = fl.ReadLine(); | |
if (isSection(line)) break; | |
var p = getParam(line); | |
// quick-fix solution | |
if (is64BitOffice && p.key == "HelpContextID") | |
println("! Warning: can not 'VBProject.HelpContextID = \"" + p.val + "\"'. probably 64-bit Office have a bug."); | |
else | |
this.vbproj[p.key] = p.val; | |
} | |
break; | |
case '[Reference]': | |
this.removeAllRefs(); | |
while (!fl.AtEndOfStream) { | |
line = fl.ReadLine(); | |
if (isSection(line)) break; | |
var p = getParam(line); | |
var refinf = p.key.split(" "); | |
this.vbproj.References.AddFromGuid(refinf[0], refinf[1], refinf[2]); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
}; | |
VBAProjFile.prototype.write = function() { | |
var fl = fso.OpenTextFile(this.path, forWriting, true); | |
fl.WriteLine('[General]'); | |
for (var prop in this.projPropName) | |
fl.WriteLine(prop + "=" + this.vbproj[prop]); | |
fl.WriteLine('[Reference]'); | |
foreachEnum(this.vbproj.References, function(ref) { | |
if (ref.BuiltIn) return false; | |
fl.WriteLine(ref.GUID + " " + ref.Major + " " + ref.Minor + "=" + ref.Description); | |
}); | |
fl.Close(); | |
}; | |
var Office = function() {}; | |
Office.prototype.progID1 = undefined; | |
Office.prototype.progID2 = "Application"; | |
Office.prototype.getProgID = function() { | |
return (this.progID1 !== undefined) ? this.progID1 + "." + this.progID2 : undefined; | |
}; | |
Office.prototype.setCmdParam = function(cmdParam) { | |
this.cmdParam = cmdParam; | |
}; | |
Office.prototype.isDirectiveOnly = function(codeModule) { | |
var ml = codeModule.CountOfLines; | |
var dl = codeModule.CountOfDeclarationLines; | |
if (ml > dl) return false; | |
if (ml < 1) return true; | |
for (var i=0,arr=codeModule.Lines(1, dl).split("\r\n"),len=arr.length; i<len; i++) { | |
var s = arr[i].replace(/^\s+|\s+$/g, ""); | |
if (s != "" && s.charAt(0).toLowerCase() != "o") return false; | |
} | |
return true; | |
}; | |
Office.prototype.isValidFileName = function(fname) { | |
return fname.match(/[\\/:\*\?"<>\|]/) == null; | |
}; | |
Office.prototype.loanOfOfficeDocument = function(path, isCreate, callback) { | |
throw "Not Implemented"; | |
}; | |
Office.prototype.checkMacroSecurity = function(ofDoc) { | |
try { | |
ofDoc.VBProject; | |
} | |
catch (ex) { | |
switch (ex.number) { | |
case -2146822220: | |
ex.description = [ex.description, "See also http://support.microsoft.com/kb/282830"].join("\n"); | |
break; | |
case -2146827284: | |
ex.description = [ex.description, "See also http://support.microsoft.com/kb/813969"].join("\n"); | |
break; | |
default: | |
break; | |
} | |
throw ex; | |
} | |
}; | |
Office.prototype.is64Bit = function(ofApp) { | |
// ref: http://support.microsoft.com/kb/2186281 | |
return parseInt(ofApp.Version) >= 14 | |
&& ofApp.ProductCode.substring(20, 21) == "1"; | |
}; | |
Office.prototype.extensionTypeTable = (function() { | |
var tbl = {}; | |
tbl['bas'] = vbext_ct_StdModule; | |
tbl['cls'] = vbext_ct_ClassModule; | |
tbl['frm'] = vbext_ct_MSForm; | |
tbl['frx'] = vbext_ct_MSForm; | |
tbl['dcm'] = vbext_ct_Document; | |
return tbl; | |
})(); | |
Office.prototype.typeExtensionTable = (function () { | |
var tbl = {}; | |
tbl[vbext_ct_StdModule] = 'bas'; | |
tbl[vbext_ct_ClassModule] = 'cls'; | |
tbl[vbext_ct_MSForm] = 'frm'; // with 'frx' | |
tbl[vbext_ct_Document] = 'dcm'; | |
return tbl; | |
})(); | |
Office.prototype.addTargetType = function(typ) { | |
}; | |
Office.prototype.cleanupBinary = function(ofDoc, verbose) { | |
var compos = ofDoc.VBProject.VBComponents; | |
var self = this; | |
foreachEnum(compos, function(compo) { | |
var bname = compo.Name; | |
//if (!(compo.Type.toString() in self.typeExtensionTable)) return false; | |
if (compo.Type == vbext_ct_Document) { | |
if (self.isDirectiveOnly(compo.CodeModule)) return false; | |
compo.CodeModule.DeleteLines(1, compo.CodeModule.CountOfLines); | |
} | |
else { | |
compos.Remove(compo); | |
} | |
if (!!verbose) println("- Remove: " + bname); | |
}); | |
}; | |
Office.prototype.cleanupSource = function(dir, verbose) { | |
if (!fso.FolderExists(dir)) { | |
fso.CreateFolder(dir); | |
return; | |
} | |
var self = this; | |
foreachEnum(fso.GetFolder(dir).Files, function(fl) { | |
var fname = fso.GetFileName(fl.Path); | |
var xname = fso.GetExtensionName(fl.Path); | |
if (!(xname in self.extensionTypeTable)) return false; | |
fl.Delete(); | |
if (!!verbose) println("- Remove: " + fname); | |
}); | |
}; | |
Office.prototype.importComponent = function(path, ofDoc) { | |
var compos = ofDoc.VBProject.VBComponents; | |
if (this.cmdParam.charcodeconv) { | |
wshshell.Run("cmd /c nkf -s -Lw -d --overwrite " + path,0,true); | |
} | |
compos.Import(path); | |
}; | |
Office.prototype.importDocument = function(path, ofDoc) { | |
throw "Not Implemented"; | |
}; | |
Office.prototype.importSource = function(impdir, ofDoc) { | |
var self = this; | |
foreachEnum(fso.GetFolder(impdir).Files, function(fl) { | |
var xname = fso.GetExtensionName(fl.Path); | |
var bname = fso.GetBaseName(fl.Path); | |
if (!(xname in self.extensionTypeTable)) return false; | |
if (xname == 'frx') return false; | |
if (xname != 'dcm') | |
self.importComponent(fl.Path, ofDoc); | |
else | |
self.importDocument(fl.Path, ofDoc); | |
println("- Import: " + fso.GetFileName(fl.Path)); | |
if (xname == 'frm') println("- Import: " + bname + ".frx"); | |
}); | |
}; | |
Office.prototype.importProject = function(impdir, vbproj, is64BitOffice) { | |
var proj = new VBAProjFile(vbproj, impdir); | |
if (fso.FileExists(proj.path)) { | |
proj.read(is64BitOffice); | |
println("- Import: " + proj.fileName); | |
} | |
}; | |
Office.prototype.exportSource = function(ofDoc, expdir) { | |
var self = this; | |
foreachEnum(ofDoc.VBProject.VBComponents, function(compo) { | |
//if (!(compo.Type.toString() in self.typeExtensionTable)) return false; | |
if (compo.Type == vbext_ct_Document) { | |
if (self.isDirectiveOnly(compo.CodeModule)) return false; | |
} | |
var xname = self.typeExtensionTable[compo.Type.toString()]; | |
var bname = compo.Name; | |
var fname = bname + "." + xname; | |
var path = fso.BuildPath(expdir, fname); | |
compo.Export(path); | |
if (self.cmdParam.charcodeconv) { | |
wshshell.Run("cmd /c nkf -w -Lu -d --overwrite " + path,0,true); | |
} | |
println("- Export: " + fname); | |
if (xname == 'frm') println("- Export: " + bname + ".frx"); | |
}); | |
}; | |
Office.prototype.exportProject = function(vbproj, expdir) { | |
var proj = new VBAProjFile(vbproj, expdir) | |
proj.write(); | |
println("- Export: " + proj.fileName); | |
}; | |
Office.prototype.combine = function(tsrc, tbin) { | |
println("> Target: " + fso.GetFileName(tbin)); | |
var self = this; | |
this.loanOfOfficeDocument(tbin, true, function(ofDoc) { | |
self.cleanupBinary(ofDoc); | |
if (self.cmdParam.vbaproj) { | |
var is64BitOffice = self.is64Bit(ofDoc.Application); | |
self.importProject(tsrc, ofDoc.VBProject, is64BitOffice); | |
} | |
self.importSource(tsrc, ofDoc); | |
ofDoc.Save(); | |
}); | |
println(); | |
}; | |
Office.prototype.decombine = function(tbin, tsrc) { | |
println("> Target: " + fso.GetFileName(tbin)); | |
var self = this; | |
this.loanOfOfficeDocument(tbin, false, function(ofDoc) { | |
self.cleanupSource(tsrc); | |
if (self.cmdParam.vbaproj) self.exportProject(ofDoc.VBProject, tsrc); | |
self.exportSource(ofDoc, tsrc); | |
}); | |
println(); | |
}; | |
Office.prototype.clear = function(tbin) { | |
println("> Target: " + fso.GetFileName(tbin)); | |
var self = this; | |
this.loanOfOfficeDocument(tbin, false, function(ofDoc) { | |
self.cleanupBinary(ofDoc, true); | |
ofDoc.Save(); | |
}); | |
println(); | |
}; | |
var Dummy = function() {}; | |
Dummy.prototype = new Office(); | |
Dummy.prototype.combine = function() {}; | |
Dummy.prototype.decombine = function() {}; | |
Dummy.prototype.clear = function() {}; | |
var Word = function() {}; | |
Word.prototype = new Office(); | |
Word.prototype.progID1 = "Word"; | |
Word.prototype.createOpenFile = function(wdApp, path) { | |
var wdSaveFormat; | |
var vernum = parseInt(wdApp.Version); | |
switch (fso.GetExtensionName(path)) { | |
case 'doc': wdSaveFormat = wdFormatDocument97; | |
break; | |
case 'dot': wdSaveFormat = wdFormatTemplate97; | |
break; | |
case 'docm': wdSaveFormat = wdFormatXMLDocumentMacroEnabled; | |
break; | |
case 'dotm': wdSaveFormat = wdFormatXMLTemplateMacroEnabled; | |
break; | |
default: wdSaveFormat = (vernum < 12) ? wdFormatDocument97 : wdFormatXMLDocumentMacroEnabled; | |
path += (vernum < 12) ? '.doc' : '.docm'; | |
break; | |
} | |
var wdDoc; | |
try { | |
if (fso.FileExists(path)) { | |
wdDoc = wdApp.Documents.Open(path) | |
} | |
else { | |
wdDoc = wdApp.Documents.Add(); | |
wdDoc.SaveAs(path, wdSaveFormat); | |
} | |
} | |
catch (ex) { | |
if (wdDoc != null) wdDoc.Close(); | |
throw ex; | |
} | |
return wdDoc; | |
}; | |
Word.prototype.loanOfOfficeDocument = function(path, isCreate, callback) { | |
var wdApp, wdDoc, ret; | |
try { | |
wdApp = new ActiveXObject(this.getProgID()); | |
wdApp.DisplayAlerts = false; | |
//wdApp.EnableEvents = false; //In Word, Application class does not have this property | |
try { | |
wdDoc = (isCreate) ? this.createOpenFile(wdApp, path) : wdApp.Documents.Open(path); | |
this.checkMacroSecurity(wdDoc); | |
ret = callback(wdDoc); | |
} finally { if (wdDoc != null) wdDoc.Close(); } | |
} finally { if (wdApp != null) wdApp.Quit(); } | |
return ret; | |
}; | |
Word.prototype.importDocument = function(path, wdDoc) { | |
var compos = wdDoc.VBProject.VBComponents; | |
var impCompo = compos.Import(path); | |
var origCompo; | |
var cname=impCompo.Name, bname=fso.GetBaseName(path); | |
if (cname != bname) { | |
origCompo = compos.item(bname); | |
} | |
else { | |
var doc = wdDoc.Documents.Add(); | |
compos = wdDoc.VBProject.VBComponents; // refresh Component collection | |
origCompo = compos.item(doc.CodeName); | |
var tmpname = "ImportTemp"; | |
var find = function(compos, name) { | |
var ret = false; | |
foreachEnum(compos, function(c) { return ret = (c.Name == name); }); | |
return ret; | |
}; | |
while (find(compos, tmpname)) tmpname += "1"; | |
impCompo.Name = tmpname; | |
origCompo.Name = cname; | |
} | |
var imod=impCompo.CodeModule, omod=origCompo.CodeModule; | |
omod.DeleteLines(1, omod.CountOfLines); | |
omod.AddFromString(imod.Lines(1, imod.CountOfLines)); | |
compos.Remove(impCompo); | |
}; | |
var Excel = function() {}; | |
Excel.prototype = new Office(); | |
Excel.prototype.progID1 = "Excel"; | |
Excel.prototype.createOpenFile = function(xlApp, path) { | |
var xlFileFormat; | |
var vernum = parseInt(xlApp.Version); | |
switch (fso.GetExtensionName(path)) { | |
case 'xls': case 'xla': case 'xlt': | |
xlFileFormat = (vernum < 12) ? xlExcel9795 : xlExcel8; | |
break; | |
case 'xlsb': | |
xlFileFormat = xlExcel12; | |
break; | |
case 'xlsm': case 'xlam': case 'xltm': | |
xlFileFormat = xlOpenXMLWorkbookMacroEnabled; | |
break; | |
default: | |
xlFileFormat = (vernum < 12) ? xlExcel9795 : xlOpenXMLWorkbookMacroEnabled; | |
path += (vernum < 12) ? '.xls' : '.xlsm'; | |
break; | |
} | |
var xlBook; | |
try { | |
if (fso.FileExists(path)) { | |
xlBook = xlApp.Workbooks.Open(path); | |
} | |
else { | |
xlBook = xlApp.Workbooks.Add(); | |
xlBook.SaveAs(path, xlFileFormat); | |
} | |
} | |
catch (ex) { | |
if (xlBook != null) xlBook.Close(); | |
throw ex; | |
} | |
return xlBook; | |
}; | |
Excel.prototype.loanOfOfficeDocument = function(path, isCreate, callback) { | |
var xlApp, xlBook, ret; | |
try { | |
xlApp = new ActiveXObject(this.getProgID()); | |
xlApp.DisplayAlerts = false; | |
xlApp.EnableEvents = false; | |
try { | |
xlBook = (isCreate) ? this.createOpenFile(xlApp, path) : xlApp.Workbooks.Open(path);; | |
this.checkMacroSecurity(xlBook); | |
ret = callback(xlBook); | |
} finally { if (xlBook != null) xlBook.Close(); } | |
} finally { if (xlApp != null) xlApp.Quit(); } | |
return ret; | |
}; | |
Excel.prototype.importDocument = function(path, xlBook) { | |
var compos = xlBook.VBProject.VBComponents; | |
var impCompo = compos.Import(path); | |
var origCompo; | |
var cname=impCompo.Name, bname=fso.GetBaseName(path); | |
if (cname != bname) { | |
origCompo = compos.item(bname); | |
} | |
else { | |
var sht = xlBook.Worksheets.Add(); | |
compos = xlBook.VBProject.VBComponents; // refreash Component collection | |
origCompo = compos.item(sht.CodeName); | |
var tmpname = "ImportTemp"; | |
var find = function(compos, name) { | |
var ret = false; | |
foreachEnum(compos, function(c) { return ret = (c.Name == name); }); | |
return ret; | |
}; | |
while (find(compos, tmpname)) tmpname += "1"; | |
impCompo.Name = tmpname; | |
origCompo.Name = cname; | |
} | |
var imod=impCompo.CodeModule, omod=origCompo.CodeModule; | |
omod.DeleteLines(1, omod.CountOfLines); | |
omod.AddFromString(imod.Lines(1, imod.CountOfLines)); | |
compos.Remove(impCompo); | |
}; | |
var Outlook = function() {}; | |
Outlook.prototype = new Office(); | |
Outlook.prototype.sadNews = function(tbin) { | |
var notSupported = | |
"Unfortunately, Outlook does not support access to VBA project from the outside.\n" | |
+ "See also http://support.microsoft.com/kb/290779."; | |
println("> Target: " + fso.GetFileName(tbin)); | |
println(notSupported); | |
println(); | |
}; | |
Outlook.prototype.combine = function(tsrc, tbin) { this.sadNews(tbin); }; | |
Outlook.prototype.decombine = function(tbin, tsrc) { this.sadNews(tbin); }; | |
Outlook.prototype.clear = function(tbin) { this.sadNews(tbin); }; | |
var Access = function() {}; | |
Access.prototype = new Office(); | |
Access.prototype.progID1 = "Access"; | |
Access.prototype.createOpenFile = function(acApp, path) { | |
var dbFormat; | |
var vernum = parseInt(acApp.SysCmd(acSysCmdAccessVer)); | |
switch (fso.GetExtensionName(path)) { | |
case 'mdb': dbFormat = acNewDatabaseFormatAccess2000; | |
break; | |
case 'accdb': dbFormat = acNewDatabaseFormatAccess2007; | |
break; | |
default: dbFormat = (vernum < 12) ? acNewDatabaseFormatAccess2002 : acNewDatabaseFormatAccess2007; | |
path += (vernum < 12) ? '.mdb' : '.accdb'; | |
break; | |
} | |
if (!fso.FileExists(path)) | |
acApp.NewCurrentDatabase(path, dbFormat); | |
else | |
acApp.OpenCurrentDatabase(path); | |
return path; | |
}; | |
Access.prototype.getDbProperty = function(db, propName) { | |
var prop = undefined; | |
try { prop = db.Properties(propName); } | |
catch (e) {} | |
return prop; | |
}; | |
Access.prototype.loanOfAcProj = function(path, isCreate, callback) { | |
var acApp, acDb, ret; | |
try { | |
acApp = new ActiveXObject(this.getProgID()); | |
acApp.Visible = false; | |
try { | |
if (!!path) { | |
if (isCreate) | |
this.createOpenFile(acApp, path); | |
else | |
acApp.OpenCurrentDatabase(path); | |
} | |
acDb = acApp.CurrentDB(); | |
var startUp = this.getDbProperty(acDb, "StartUpForm"); | |
if (startUp !== undefined) acApp.DoCmd.Close(acForm, startUp.Value); | |
ret = callback(acApp.CurrentProject); | |
} finally { if (acDb != null) acDb.Close(); } | |
} finally { if (acApp != null) { if (acDb != null) acApp.CloseCurrentDatabase(); acApp.Quit(); } } | |
return ret; | |
}; | |
Access.prototype.extensionTypeTable = (function() { | |
var tbl = {}; | |
tbl['mdl'] = acModule; | |
tbl['bas'] = acModule; | |
tbl['cls'] = acModule; | |
tbl['frm'] = acForm; | |
tbl['rpt'] = acReport; | |
tbl['mcr'] = acMacro; | |
return tbl; | |
})(); | |
Access.prototype.typeExtensionTable = (function() { | |
var tbl = {}; | |
tbl[acModule] = 'mdl'; // rename 'bas' or 'cls' | |
tbl[acForm] = 'frm'; | |
tbl[acReport] = 'rpt'; | |
tbl[acMacro] = 'mcr'; | |
return tbl; | |
})(); | |
Access.prototype.addTargetType = function(acTyp) { | |
var ext = undefined; | |
switch (acTyp) { | |
case acQuery: ext = 'qry'; break; | |
default: break; | |
} | |
if (ext !== undefined) { | |
this.extensionTypeTable[ext] = acTyp; | |
this.typeExtensionTable[acTyp] = ext; | |
} | |
}; | |
Access.prototype.iterAllObjects = function(acApp, action) { | |
var i; | |
var objs = new Array(); | |
var acProj = acApp.CurrentProject; | |
for (i = 0; i < acProj.AllModules.Count; i++) objs.push(acProj.AllModules.item(i)); | |
for (i = 0; i < acProj.AllForms.Count; i++) objs.push(acProj.AllForms.item(i)); | |
for (i = 0; i < acProj.AllReports.Count; i++) objs.push(acProj.AllReports.item(i)); | |
for (i = 0; i < acProj.AllMacros.Count; i++) objs.push(acProj.AllMacros.item(i)); | |
var acData = acApp.CurrentData; | |
for (i = 0; i < acData.AllQueries.Count; i++) objs.push(acData.AllQueries.item(i)); | |
for (i = 0; i < objs.length; i++) { | |
if (!!action(objs[i], i)) break; | |
} | |
}; | |
Access.prototype.getAcDocs = function(acApp) { | |
var acDb; | |
try { | |
acDb = acApp.CurrentDB(); | |
var docs = new Array(); | |
var conts = ['Modules', 'Forms', 'Reports', 'Scripts']; | |
var c2eTable = this.containerExtensionTable; | |
for (var i = 0; i < conts.length; i++) { | |
var cont = conts[i]; | |
foreachEnum(acDb.Containers(cont).Documents, function(doc) { | |
docs.push({ container: cont, name: doc.Name }); | |
}); | |
} | |
} finally { if (acDb != null) acDb.Close(); } | |
return docs; | |
}; | |
Access.prototype.cleanupBinary = function(acProj, verbose) { | |
var acApp = acProj.Application; | |
var self = this; | |
this.iterAllObjects(acApp, function(obj) { | |
var name = obj.Name; | |
if (!(obj.Type.toString() in self.typeExtensionTable)) return false; | |
acApp.DoCmd.DeleteObject(obj.Type, name); | |
if (!!verbose) println("- Remove: " + name); | |
}); | |
}; | |
Access.prototype.cleanupSource = function(dir, verbose) { | |
if (!fso.FolderExists(dir)) { | |
fso.CreateFolder(dir); | |
return; | |
} | |
var self = this; | |
foreachEnum(fso.GetFolder(dir).Files, function(fl) { | |
var fname = fso.GetFileName(fl.Path); | |
var xname = fso.GetExtensionName(fl.Path); | |
if (!(xname in self.extensionTypeTable)) return false; | |
fl.Delete(); | |
if (!!verbose) println("- Remove: " + fname); | |
}); | |
}; | |
Access.prototype.importSource = function(impdir, acProj) { | |
var acApp = acProj.Application; | |
var compos = acApp.VBE.ActiveVBProject.VBComponents; | |
var self = this; | |
foreachEnum(fso.GetFolder(impdir).Files, function(fl) { | |
var path = fl.Path; | |
var fname = fso.GetFileName(path); | |
var xname = fso.GetExtensionName(path); | |
var bname = fso.GetBaseName(path); | |
if (!(xname in self.extensionTypeTable)) return false; | |
var typ = self.extensionTypeTable[xname]; | |
if (typ == acModule) { | |
var c = compos.Import(path); | |
c.Name = bname; | |
acApp.DoCmd.Save(typ, bname); | |
} | |
else { | |
acApp.LoadFromText(typ, bname, path); | |
} | |
println("- Import: " + fname); | |
}); | |
}; | |
Access.prototype.exportSource = function(acProj, expdir) { | |
var acApp = acProj.Application; | |
var compos = acApp.VBE.ActiveVBProject.VBComponents; | |
var self = this; | |
this.iterAllObjects(acApp, function(obj) { | |
var bname = obj.Name; | |
if (!(obj.Type.toString() in self.typeExtensionTable)) return false; | |
if (!self.isValidFileName(bname)) { | |
println("! Warning: skip export. object '" + bname + "' is invalid file name"); | |
return false; | |
} | |
var xname = self.typeExtensionTable[obj.Type.toString()]; | |
if (obj.Type == acModule) { | |
switch (compos.item(bname).Type) { | |
case vbext_ct_StdModule: xname = 'bas'; break; | |
case vbext_ct_ClassModule: xname = 'cls'; break; | |
default: break; | |
} | |
} | |
var fname = bname + "." + xname; | |
var path = fso.BuildPath(expdir, fname); | |
if (obj.Type == acModule) | |
compos(obj.Name).Export(path); | |
else | |
acApp.SaveAsText(obj.Type, bname, path); | |
println("- Export: " + fname); | |
}); | |
}; | |
Access.prototype.compact = function(dbPath, acApp) { | |
var engine = (!!acApp) ? acApp.DBEngine : (function() { | |
var egname = "DAO.DBEngine"; | |
var egvers = ["120", "36", "35"]; | |
for (var i = 0; i < egvers.length; i++) { | |
try { return new ActiveXObject(egname + "." + egvers[i]); } | |
catch (e) {} | |
} | |
return undefined; | |
})(); | |
var tempPath = (function(dbPath) { | |
var d = fso.GetParentFolderName(dbPath); | |
var b = fso.GetBaseName(dbPath); | |
var x = fso.GetExtensionName(dbPath); | |
var tempExt = "tempdb"; | |
var tempPath = fso.BuildPath(d, [b, x, tempExt].join(".")); | |
var delim = "#"; | |
var i = 0; | |
while (fso.FileExists(tempPath)) | |
tempPath = fso.BuildPath(d, [b+delim+(++i), x, tempExt].join(".")); | |
return tempPath; | |
})(dbPath); | |
engine.CompactDatabase(dbPath, tempPath); | |
fso.DeleteFile(dbPath); | |
fso.MoveFile(tempPath, dbPath); | |
println("- Compact: " + fso.GetFileName(dbPath)); | |
}; | |
Access.prototype.combine = function(tsrc, tbin) { | |
println("> Target: " + fso.GetFileName(tbin)); | |
var self = this; | |
this.loanOfAcProj(tbin, true, function(acProj) { | |
self.cleanupBinary(acProj); | |
if (self.cmdParam.vbaproj) { | |
var is64BitOffice = self.is64Bit(acProj.Application); | |
self.importProject(tsrc, acProj.Application.VBE.ActiveVBProject, is64BitOffice); | |
} | |
self.importSource(tsrc, acProj); | |
}); | |
this.loanOfAcProj(undefined, false, function(acProj) { | |
if (self.cmdParam.dbCompact) self.compact(tbin, acProj.Application); | |
}); | |
println(); | |
}; | |
Access.prototype.decombine = function(tbin, tsrc) { | |
println("> Target: " + fso.GetFileName(tbin)); | |
var self = this; | |
this.loanOfAcProj(tbin, true, function(acProj) { | |
self.cleanupSource(tsrc); | |
if (self.cmdParam.vbaproj) self.exportProject(acProj.Application.VBE.ActiveVBProject, tsrc); | |
self.exportSource(acProj, tsrc); | |
}); | |
this.loanOfAcProj(undefined, false, function(acProj) { | |
if (self.cmdParam.dbCompact) self.compact(tbin, acProj.Application); | |
}); | |
println(); | |
}; | |
Access.prototype.clear = function(tbin) { | |
println("> Target: " + fso.GetFileName(tbin)); | |
var self = this; | |
this.loanOfAcProj(tbin, true, function(acProj) { | |
self.cleanupBinary(acProj, true); | |
}); | |
println(); | |
}; | |
var Command = function(helper) { | |
this.__helper = helper; | |
}; | |
Command.prototype.__helper = null; | |
Command.prototype.help = function() { | |
println(getResource('HelpMessage')); | |
}; | |
Command.prototype.combine = function() { | |
var hlp = this.__helper; | |
var conf = hlp.config; | |
if (conf.bak !== undefined && fso.FolderExists(conf.bin)) { | |
if (!fso.FolderExists(conf.bak)) fso.CreateFolder(conf.bak); | |
var bkdir = fso.BuildPath(conf.bak, dateTimeString(new Date())); | |
fso.CreateFolder(bkdir); | |
fso.CopyFile(fso.BuildPath(conf.bin, "*.*"), bkdir + "\\"); | |
} | |
hlp.combineImpl(conf.src, conf.bin, function() { return conf.getSrcs(); }); | |
}; | |
Command.prototype.decombine = function() { | |
var hlp = this.__helper; | |
var conf = hlp.config; | |
hlp.combineImpl(conf.bin, conf.src, function() { return conf.getBins(); }); | |
}; | |
Command.prototype.clear = function() { | |
var hlp = this.__helper; | |
var conf = hlp.config; | |
hlp.iterTarget( | |
function() { return conf.getBins(); }, | |
function(path) { | |
var office = hlp.createOffice(path); | |
office.clear(path); | |
}); | |
}; | |
Command.prototype.acdoc = function() { | |
var hlp = this.__helper; | |
var conf = hlp.config; | |
hlp.iterTarget( | |
function() { return conf.getBins(); }, | |
function(path) { | |
if (hlp.getAppName(path) != 'Access') return false; | |
println("> Target: " + fso.GetFileName(path)); | |
var docs; | |
var acc = hlp.createOffice(path); | |
acc.loanOfAcProj(path, true, function(acProj) { | |
var acApp = acProj.Application; | |
docs = acc.getAcDocs(acApp); | |
}); | |
for (var i = 0; i < docs.length; i++) { | |
var doc = docs[i]; | |
println("- " + doc.container + ": " + doc.name); | |
} | |
println(); | |
}); | |
}; | |
var CommandHelper = function(param) { | |
this.parameter = param; | |
this.config = new Config(param.binary, param.source, param.binbak); | |
this.command = new Command(this); | |
}; | |
CommandHelper.prototype.getAppName = function(fname) { | |
switch (fso.GetExtensionName(fname)) { | |
case 'doc': case 'dot': case 'docm': case 'dotm': | |
return 'Word'; | |
case 'xls': case 'xlsm': case 'xla': case 'xlam': case 'xlt': case 'xltm': case 'xlsb': | |
return 'Excel'; | |
case 'otm': | |
return 'Outlook'; | |
case 'mdb': case 'accdb': | |
return 'Access'; | |
default: | |
return undefined; | |
} | |
}; | |
CommandHelper.prototype.createOffice = function(fname) { | |
var office; | |
switch (this.getAppName(fname)) { | |
case 'Word': | |
office = new Word(); | |
break; | |
case 'Excel': | |
office = new Excel(); | |
break; | |
case 'Outlook': | |
office = new Outlook(); | |
break; | |
case 'Access': | |
office = new Access(); | |
if (this.parameter.incQuery) office.addTargetType(acQuery); | |
break; | |
default: | |
office = new Dummy(); | |
break; | |
} | |
office.setCmdParam(this.parameter); | |
return office; | |
}; | |
CommandHelper.prototype.isTempFile = function(fname) { | |
return fname.substring(0, 2) == '~$'; | |
}; | |
CommandHelper.prototype.iterTarget = function(getPaths, action) { | |
var self = this; | |
foreachEnum(getPaths(), function(fl) { | |
if (self.isTempFile(fl.Name)) return false; | |
return action(fl.Path); | |
}); | |
}; | |
CommandHelper.prototype.combineImpl = function(fromDir, toDir, getPaths) { | |
if (!fso.FolderExists(fromDir)) { | |
println("directory '" + fromDir + "' not exists."); | |
return; | |
} | |
if (!fso.FolderExists(toDir)) fso.CreateFolder(toDir); | |
var self = this; | |
this.iterTarget(getPaths, function(fromPath) { | |
var toPath = fso.BuildPath(toDir, fso.GetFileName(fromPath)); | |
var office = self.createOffice(fromPath); | |
var param = self.parameter; | |
// overwrite protection | |
var fromModified; | |
var toModified; | |
if (fso.FolderExists(fromPath)) { | |
fromModified = fso.GetFolder(fromPath).DateLastModified; | |
} | |
else if (fso.FileExists(fromPath)) { | |
fromModified = fso.GetFile(fromPath).DateLastModified; | |
} | |
if (fso.FolderExists(toPath)) { | |
toModified = fso.GetFolder(toPath).DateLastModified; | |
} | |
else if (fso.FileExists(toPath)) { | |
toModified = fso.GetFile(toPath).DateLastModified; | |
} | |
if (fromModified < toModified) { | |
println("Overwrite has blocked."); | |
println(); | |
return; | |
} | |
office[param.commandType](fromPath, toPath); | |
}); | |
}; | |
CommandHelper.prototype.hasCommand = function(cmdType) { | |
return cmdType in this.command | |
&& this.command[cmdType] != this; | |
}; | |
CommandHelper.prototype.runCommand = function() { | |
var cmd = this.command; | |
var cmdType = this.parameter.commandType; | |
if (!this.hasCommand(cmdType)) { | |
println("command '" + cmdType + "' is undefined."); | |
return; | |
} | |
var runner = function() { cmd[cmdType].apply(cmd, arguments); }; | |
if (cmdType == 'help') { | |
runner(); | |
} | |
else { | |
println("begin " + cmdType + "\n"); | |
runner(); | |
println("end"); | |
} | |
}; | |
function main(args) { | |
var param = | |
new CmdParam({ | |
defaultParameterName: "commandType", | |
commandType: "help", | |
binary: "bin", | |
source: "src", | |
binbak: new Conditional("bak"), | |
vbaproj: false, | |
charcodeconv: false, | |
// vbacGUI.exe で UTF-8 変換ありで使う場合、GUI 側に設定がないので true 固定にする。 | |
// charcodeconv: true, | |
incQuery: false, | |
dbCompact: false | |
}) | |
.parse(args); | |
// It's guard for internal impl. If necessary, you can comment out to enable this feature. | |
param.binbak.flag = false; | |
param.incQuery = false; | |
var h = new CommandHelper(param); | |
h.runCommand(); | |
} | |
main(args); | |
]]> | |
</script> | |
</job> | |
</package> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment